Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vlclient.c
Go to the documentation of this file.
1 /* AFS Volume Location Service client
2  *
3  * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells ([email protected])
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version
9  * 2 of the License, or (at your option) any later version.
10  */
11 
12 #include <linux/gfp.h>
13 #include <linux/init.h>
14 #include <linux/sched.h>
15 #include "internal.h"
16 
17 /*
18  * map volume locator abort codes to error codes
19  */
20 static int afs_vl_abort_to_error(u32 abort_code)
21 {
22  _enter("%u", abort_code);
23 
24  switch (abort_code) {
25  case AFSVL_IDEXIST: return -EEXIST;
26  case AFSVL_IO: return -EREMOTEIO;
27  case AFSVL_NAMEEXIST: return -EEXIST;
28  case AFSVL_CREATEFAIL: return -EREMOTEIO;
29  case AFSVL_NOENT: return -ENOMEDIUM;
30  case AFSVL_EMPTY: return -ENOMEDIUM;
31  case AFSVL_ENTDELETED: return -ENOMEDIUM;
32  case AFSVL_BADNAME: return -EINVAL;
33  case AFSVL_BADINDEX: return -EINVAL;
34  case AFSVL_BADVOLTYPE: return -EINVAL;
35  case AFSVL_BADSERVER: return -EINVAL;
36  case AFSVL_BADPARTITION: return -EINVAL;
37  case AFSVL_REPSFULL: return -EFBIG;
38  case AFSVL_NOREPSERVER: return -ENOENT;
39  case AFSVL_DUPREPSERVER: return -EEXIST;
40  case AFSVL_RWNOTFOUND: return -ENOENT;
41  case AFSVL_BADREFCOUNT: return -EINVAL;
42  case AFSVL_SIZEEXCEEDED: return -EINVAL;
43  case AFSVL_BADENTRY: return -EINVAL;
44  case AFSVL_BADVOLIDBUMP: return -EINVAL;
45  case AFSVL_IDALREADYHASHED: return -EINVAL;
46  case AFSVL_ENTRYLOCKED: return -EBUSY;
47  case AFSVL_BADVOLOPER: return -EBADRQC;
48  case AFSVL_BADRELLOCKTYPE: return -EINVAL;
49  case AFSVL_RERELEASE: return -EREMOTEIO;
50  case AFSVL_BADSERVERFLAG: return -EINVAL;
51  case AFSVL_PERM: return -EACCES;
52  case AFSVL_NOMEM: return -EREMOTEIO;
53  default:
54  return afs_abort_to_error(abort_code);
55  }
56 }
57 
58 /*
59  * deliver reply data to a VL.GetEntryByXXX call
60  */
61 static int afs_deliver_vl_get_entry_by_xxx(struct afs_call *call,
62  struct sk_buff *skb, bool last)
63 {
64  struct afs_cache_vlocation *entry;
65  __be32 *bp;
66  u32 tmp;
67  int loop;
68 
69  _enter(",,%u", last);
70 
71  afs_transfer_reply(call, skb);
72  if (!last)
73  return 0;
74 
75  if (call->reply_size != call->reply_max)
76  return -EBADMSG;
77 
78  /* unmarshall the reply once we've received all of it */
79  entry = call->reply;
80  bp = call->buffer;
81 
82  for (loop = 0; loop < 64; loop++)
83  entry->name[loop] = ntohl(*bp++);
84  entry->name[loop] = 0;
85  bp++; /* final NUL */
86 
87  bp++; /* type */
88  entry->nservers = ntohl(*bp++);
89 
90  for (loop = 0; loop < 8; loop++)
91  entry->servers[loop].s_addr = *bp++;
92 
93  bp += 8; /* partition IDs */
94 
95  for (loop = 0; loop < 8; loop++) {
96  tmp = ntohl(*bp++);
97  entry->srvtmask[loop] = 0;
98  if (tmp & AFS_VLSF_RWVOL)
99  entry->srvtmask[loop] |= AFS_VOL_VTM_RW;
100  if (tmp & AFS_VLSF_ROVOL)
101  entry->srvtmask[loop] |= AFS_VOL_VTM_RO;
102  if (tmp & AFS_VLSF_BACKVOL)
103  entry->srvtmask[loop] |= AFS_VOL_VTM_BAK;
104  }
105 
106  entry->vid[0] = ntohl(*bp++);
107  entry->vid[1] = ntohl(*bp++);
108  entry->vid[2] = ntohl(*bp++);
109 
110  bp++; /* clone ID */
111 
112  tmp = ntohl(*bp++); /* flags */
113  entry->vidmask = 0;
114  if (tmp & AFS_VLF_RWEXISTS)
115  entry->vidmask |= AFS_VOL_VTM_RW;
116  if (tmp & AFS_VLF_ROEXISTS)
117  entry->vidmask |= AFS_VOL_VTM_RO;
118  if (tmp & AFS_VLF_BACKEXISTS)
119  entry->vidmask |= AFS_VOL_VTM_BAK;
120  if (!entry->vidmask)
121  return -EBADMSG;
122 
123  _leave(" = 0 [done]");
124  return 0;
125 }
126 
127 /*
128  * VL.GetEntryByName operation type
129  */
130 static const struct afs_call_type afs_RXVLGetEntryByName = {
131  .name = "VL.GetEntryByName",
132  .deliver = afs_deliver_vl_get_entry_by_xxx,
133  .abort_to_error = afs_vl_abort_to_error,
134  .destructor = afs_flat_call_destructor,
135 };
136 
137 /*
138  * VL.GetEntryById operation type
139  */
140 static const struct afs_call_type afs_RXVLGetEntryById = {
141  .name = "VL.GetEntryById",
142  .deliver = afs_deliver_vl_get_entry_by_xxx,
143  .abort_to_error = afs_vl_abort_to_error,
144  .destructor = afs_flat_call_destructor,
145 };
146 
147 /*
148  * dispatch a get volume entry by name operation
149  */
151  struct key *key,
152  const char *volname,
153  struct afs_cache_vlocation *entry,
154  const struct afs_wait_mode *wait_mode)
155 {
156  struct afs_call *call;
157  size_t volnamesz, reqsz, padsz;
158  __be32 *bp;
159 
160  _enter("");
161 
162  volnamesz = strlen(volname);
163  padsz = (4 - (volnamesz & 3)) & 3;
164  reqsz = 8 + volnamesz + padsz;
165 
166  call = afs_alloc_flat_call(&afs_RXVLGetEntryByName, reqsz, 384);
167  if (!call)
168  return -ENOMEM;
169 
170  call->key = key;
171  call->reply = entry;
172  call->service_id = VL_SERVICE;
173  call->port = htons(AFS_VL_PORT);
174 
175  /* marshall the parameters */
176  bp = call->request;
177  *bp++ = htonl(VLGETENTRYBYNAME);
178  *bp++ = htonl(volnamesz);
179  memcpy(bp, volname, volnamesz);
180  if (padsz > 0)
181  memset((void *) bp + volnamesz, 0, padsz);
182 
183  /* initiate the call */
184  return afs_make_call(addr, call, GFP_KERNEL, wait_mode);
185 }
186 
187 /*
188  * dispatch a get volume entry by ID operation
189  */
191  struct key *key,
193  afs_voltype_t voltype,
194  struct afs_cache_vlocation *entry,
195  const struct afs_wait_mode *wait_mode)
196 {
197  struct afs_call *call;
198  __be32 *bp;
199 
200  _enter("");
201 
202  call = afs_alloc_flat_call(&afs_RXVLGetEntryById, 12, 384);
203  if (!call)
204  return -ENOMEM;
205 
206  call->key = key;
207  call->reply = entry;
208  call->service_id = VL_SERVICE;
209  call->port = htons(AFS_VL_PORT);
210 
211  /* marshall the parameters */
212  bp = call->request;
213  *bp++ = htonl(VLGETENTRYBYID);
214  *bp++ = htonl(volid);
215  *bp = htonl(voltype);
216 
217  /* initiate the call */
218  return afs_make_call(addr, call, GFP_KERNEL, wait_mode);
219 }