Merge tag 'iio-for-4.17a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23...
[linux-2.6-block.git] / fs / afs / vlclient.c
1 /* AFS Volume Location Service client
2  *
3  * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
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 "afs_fs.h"
16 #include "internal.h"
17
18 /*
19  * Deliver reply data to a VL.GetEntryByNameU call.
20  */
21 static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call)
22 {
23         struct afs_uvldbentry__xdr *uvldb;
24         struct afs_vldb_entry *entry;
25         bool new_only = false;
26         u32 tmp, nr_servers;
27         int i, ret;
28
29         _enter("");
30
31         ret = afs_transfer_reply(call);
32         if (ret < 0)
33                 return ret;
34
35         /* unmarshall the reply once we've received all of it */
36         uvldb = call->buffer;
37         entry = call->reply[0];
38
39         nr_servers = ntohl(uvldb->nServers);
40         if (nr_servers > AFS_NMAXNSERVERS)
41                 nr_servers = AFS_NMAXNSERVERS;
42
43         for (i = 0; i < ARRAY_SIZE(uvldb->name) - 1; i++)
44                 entry->name[i] = (u8)ntohl(uvldb->name[i]);
45         entry->name[i] = 0;
46         entry->name_len = strlen(entry->name);
47
48         /* If there is a new replication site that we can use, ignore all the
49          * sites that aren't marked as new.
50          */
51         for (i = 0; i < nr_servers; i++) {
52                 tmp = ntohl(uvldb->serverFlags[i]);
53                 if (!(tmp & AFS_VLSF_DONTUSE) &&
54                     (tmp & AFS_VLSF_NEWREPSITE))
55                         new_only = true;
56         }
57
58         for (i = 0; i < nr_servers; i++) {
59                 struct afs_uuid__xdr *xdr;
60                 struct afs_uuid *uuid;
61                 int j;
62
63                 tmp = ntohl(uvldb->serverFlags[i]);
64                 if (tmp & AFS_VLSF_DONTUSE ||
65                     (new_only && !(tmp & AFS_VLSF_NEWREPSITE)))
66                         continue;
67                 if (tmp & AFS_VLSF_RWVOL)
68                         entry->fs_mask[i] |= AFS_VOL_VTM_RW;
69                 if (tmp & AFS_VLSF_ROVOL)
70                         entry->fs_mask[i] |= AFS_VOL_VTM_RO;
71                 if (tmp & AFS_VLSF_BACKVOL)
72                         entry->fs_mask[i] |= AFS_VOL_VTM_BAK;
73                 if (!entry->fs_mask[i])
74                         continue;
75
76                 xdr = &uvldb->serverNumber[i];
77                 uuid = (struct afs_uuid *)&entry->fs_server[i];
78                 uuid->time_low                  = xdr->time_low;
79                 uuid->time_mid                  = htons(ntohl(xdr->time_mid));
80                 uuid->time_hi_and_version       = htons(ntohl(xdr->time_hi_and_version));
81                 uuid->clock_seq_hi_and_reserved = (u8)ntohl(xdr->clock_seq_hi_and_reserved);
82                 uuid->clock_seq_low             = (u8)ntohl(xdr->clock_seq_low);
83                 for (j = 0; j < 6; j++)
84                         uuid->node[j] = (u8)ntohl(xdr->node[j]);
85
86                 entry->nr_servers++;
87         }
88
89         for (i = 0; i < AFS_MAXTYPES; i++)
90                 entry->vid[i] = ntohl(uvldb->volumeId[i]);
91
92         tmp = ntohl(uvldb->flags);
93         if (tmp & AFS_VLF_RWEXISTS)
94                 __set_bit(AFS_VLDB_HAS_RW, &entry->flags);
95         if (tmp & AFS_VLF_ROEXISTS)
96                 __set_bit(AFS_VLDB_HAS_RO, &entry->flags);
97         if (tmp & AFS_VLF_BACKEXISTS)
98                 __set_bit(AFS_VLDB_HAS_BAK, &entry->flags);
99
100         if (!(tmp & (AFS_VLF_RWEXISTS | AFS_VLF_ROEXISTS | AFS_VLF_BACKEXISTS))) {
101                 entry->error = -ENOMEDIUM;
102                 __set_bit(AFS_VLDB_QUERY_ERROR, &entry->flags);
103         }
104
105         __set_bit(AFS_VLDB_QUERY_VALID, &entry->flags);
106         _leave(" = 0 [done]");
107         return 0;
108 }
109
110 static void afs_destroy_vl_get_entry_by_name_u(struct afs_call *call)
111 {
112         kfree(call->reply[0]);
113         afs_flat_call_destructor(call);
114 }
115
116 /*
117  * VL.GetEntryByNameU operation type.
118  */
119 static const struct afs_call_type afs_RXVLGetEntryByNameU = {
120         .name           = "VL.GetEntryByNameU",
121         .op             = afs_VL_GetEntryByNameU,
122         .deliver        = afs_deliver_vl_get_entry_by_name_u,
123         .destructor     = afs_destroy_vl_get_entry_by_name_u,
124 };
125
126 /*
127  * Dispatch a get volume entry by name or ID operation (uuid variant).  If the
128  * volname is a decimal number then it's a volume ID not a volume name.
129  */
130 struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_net *net,
131                                                   struct afs_addr_cursor *ac,
132                                                   struct key *key,
133                                                   const char *volname,
134                                                   int volnamesz)
135 {
136         struct afs_vldb_entry *entry;
137         struct afs_call *call;
138         size_t reqsz, padsz;
139         __be32 *bp;
140
141         _enter("");
142
143         padsz = (4 - (volnamesz & 3)) & 3;
144         reqsz = 8 + volnamesz + padsz;
145
146         entry = kzalloc(sizeof(struct afs_vldb_entry), GFP_KERNEL);
147         if (!entry)
148                 return ERR_PTR(-ENOMEM);
149
150         call = afs_alloc_flat_call(net, &afs_RXVLGetEntryByNameU, reqsz,
151                                    sizeof(struct afs_uvldbentry__xdr));
152         if (!call) {
153                 kfree(entry);
154                 return ERR_PTR(-ENOMEM);
155         }
156
157         call->key = key;
158         call->reply[0] = entry;
159         call->ret_reply0 = true;
160
161         /* Marshall the parameters */
162         bp = call->request;
163         *bp++ = htonl(VLGETENTRYBYNAMEU);
164         *bp++ = htonl(volnamesz);
165         memcpy(bp, volname, volnamesz);
166         if (padsz > 0)
167                 memset((void *)bp + volnamesz, 0, padsz);
168
169         trace_afs_make_vl_call(call);
170         return (struct afs_vldb_entry *)afs_make_call(ac, call, GFP_KERNEL, false);
171 }
172
173 /*
174  * Deliver reply data to a VL.GetAddrsU call.
175  *
176  *      GetAddrsU(IN ListAddrByAttributes *inaddr,
177  *                OUT afsUUID *uuidp1,
178  *                OUT uint32_t *uniquifier,
179  *                OUT uint32_t *nentries,
180  *                OUT bulkaddrs *blkaddrs);
181  */
182 static int afs_deliver_vl_get_addrs_u(struct afs_call *call)
183 {
184         struct afs_addr_list *alist;
185         __be32 *bp;
186         u32 uniquifier, nentries, count;
187         int i, ret;
188
189         _enter("{%u,%zu/%u}", call->unmarshall, call->offset, call->count);
190
191 again:
192         switch (call->unmarshall) {
193         case 0:
194                 call->offset = 0;
195                 call->unmarshall++;
196
197                 /* Extract the returned uuid, uniquifier, nentries and blkaddrs size */
198         case 1:
199                 ret = afs_extract_data(call, call->buffer,
200                                        sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32),
201                                        true);
202                 if (ret < 0)
203                         return ret;
204
205                 bp = call->buffer + sizeof(struct afs_uuid__xdr);
206                 uniquifier      = ntohl(*bp++);
207                 nentries        = ntohl(*bp++);
208                 count           = ntohl(*bp);
209
210                 nentries = min(nentries, count);
211                 alist = afs_alloc_addrlist(nentries, FS_SERVICE, AFS_FS_PORT);
212                 if (!alist)
213                         return -ENOMEM;
214                 alist->version = uniquifier;
215                 call->reply[0] = alist;
216                 call->count = count;
217                 call->count2 = nentries;
218                 call->offset = 0;
219                 call->unmarshall++;
220
221                 /* Extract entries */
222         case 2:
223                 count = min(call->count, 4U);
224                 ret = afs_extract_data(call, call->buffer,
225                                        count * sizeof(__be32),
226                                        call->count > 4);
227                 if (ret < 0)
228                         return ret;
229
230                 alist = call->reply[0];
231                 bp = call->buffer;
232                 for (i = 0; i < count; i++)
233                         if (alist->nr_addrs < call->count2)
234                                 afs_merge_fs_addr4(alist, *bp++, AFS_FS_PORT);
235
236                 call->count -= count;
237                 if (call->count > 0)
238                         goto again;
239                 call->offset = 0;
240                 call->unmarshall++;
241                 break;
242         }
243
244         _leave(" = 0 [done]");
245         return 0;
246 }
247
248 static void afs_vl_get_addrs_u_destructor(struct afs_call *call)
249 {
250         afs_put_server(call->net, (struct afs_server *)call->reply[0]);
251         kfree(call->reply[1]);
252         return afs_flat_call_destructor(call);
253 }
254
255 /*
256  * VL.GetAddrsU operation type.
257  */
258 static const struct afs_call_type afs_RXVLGetAddrsU = {
259         .name           = "VL.GetAddrsU",
260         .op             = afs_VL_GetAddrsU,
261         .deliver        = afs_deliver_vl_get_addrs_u,
262         .destructor     = afs_vl_get_addrs_u_destructor,
263 };
264
265 /*
266  * Dispatch an operation to get the addresses for a server, where the server is
267  * nominated by UUID.
268  */
269 struct afs_addr_list *afs_vl_get_addrs_u(struct afs_net *net,
270                                          struct afs_addr_cursor *ac,
271                                          struct key *key,
272                                          const uuid_t *uuid)
273 {
274         struct afs_ListAddrByAttributes__xdr *r;
275         const struct afs_uuid *u = (const struct afs_uuid *)uuid;
276         struct afs_call *call;
277         __be32 *bp;
278         int i;
279
280         _enter("");
281
282         call = afs_alloc_flat_call(net, &afs_RXVLGetAddrsU,
283                                    sizeof(__be32) + sizeof(struct afs_ListAddrByAttributes__xdr),
284                                    sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32));
285         if (!call)
286                 return ERR_PTR(-ENOMEM);
287
288         call->key = key;
289         call->reply[0] = NULL;
290         call->ret_reply0 = true;
291
292         /* Marshall the parameters */
293         bp = call->request;
294         *bp++ = htonl(VLGETADDRSU);
295         r = (struct afs_ListAddrByAttributes__xdr *)bp;
296         r->Mask         = htonl(AFS_VLADDR_UUID);
297         r->ipaddr       = 0;
298         r->index        = 0;
299         r->spare        = 0;
300         r->uuid.time_low                        = u->time_low;
301         r->uuid.time_mid                        = htonl(ntohs(u->time_mid));
302         r->uuid.time_hi_and_version             = htonl(ntohs(u->time_hi_and_version));
303         r->uuid.clock_seq_hi_and_reserved       = htonl(u->clock_seq_hi_and_reserved);
304         r->uuid.clock_seq_low                   = htonl(u->clock_seq_low);
305         for (i = 0; i < 6; i++)
306                 r->uuid.node[i] = ntohl(u->node[i]);
307
308         trace_afs_make_vl_call(call);
309         return (struct afs_addr_list *)afs_make_call(ac, call, GFP_KERNEL, false);
310 }
311
312 /*
313  * Deliver reply data to an VL.GetCapabilities operation.
314  */
315 static int afs_deliver_vl_get_capabilities(struct afs_call *call)
316 {
317         u32 count;
318         int ret;
319
320         _enter("{%u,%zu/%u}", call->unmarshall, call->offset, call->count);
321
322 again:
323         switch (call->unmarshall) {
324         case 0:
325                 call->offset = 0;
326                 call->unmarshall++;
327
328                 /* Extract the capabilities word count */
329         case 1:
330                 ret = afs_extract_data(call, &call->tmp,
331                                        1 * sizeof(__be32),
332                                        true);
333                 if (ret < 0)
334                         return ret;
335
336                 count = ntohl(call->tmp);
337
338                 call->count = count;
339                 call->count2 = count;
340                 call->offset = 0;
341                 call->unmarshall++;
342
343                 /* Extract capabilities words */
344         case 2:
345                 count = min(call->count, 16U);
346                 ret = afs_extract_data(call, call->buffer,
347                                        count * sizeof(__be32),
348                                        call->count > 16);
349                 if (ret < 0)
350                         return ret;
351
352                 /* TODO: Examine capabilities */
353
354                 call->count -= count;
355                 if (call->count > 0)
356                         goto again;
357                 call->offset = 0;
358                 call->unmarshall++;
359                 break;
360         }
361
362         call->reply[0] = (void *)(unsigned long)call->service_id;
363
364         _leave(" = 0 [done]");
365         return 0;
366 }
367
368 /*
369  * VL.GetCapabilities operation type
370  */
371 static const struct afs_call_type afs_RXVLGetCapabilities = {
372         .name           = "VL.GetCapabilities",
373         .op             = afs_VL_GetCapabilities,
374         .deliver        = afs_deliver_vl_get_capabilities,
375         .destructor     = afs_flat_call_destructor,
376 };
377
378 /*
379  * Probe a fileserver for the capabilities that it supports.  This can
380  * return up to 196 words.
381  *
382  * We use this to probe for service upgrade to determine what the server at the
383  * other end supports.
384  */
385 int afs_vl_get_capabilities(struct afs_net *net,
386                             struct afs_addr_cursor *ac,
387                             struct key *key)
388 {
389         struct afs_call *call;
390         __be32 *bp;
391
392         _enter("");
393
394         call = afs_alloc_flat_call(net, &afs_RXVLGetCapabilities, 1 * 4, 16 * 4);
395         if (!call)
396                 return -ENOMEM;
397
398         call->key = key;
399         call->upgrade = true; /* Let's see if this is a YFS server */
400         call->reply[0] = (void *)VLGETCAPABILITIES;
401         call->ret_reply0 = true;
402
403         /* marshall the parameters */
404         bp = call->request;
405         *bp++ = htonl(VLGETCAPABILITIES);
406
407         /* Can't take a ref on server */
408         trace_afs_make_vl_call(call);
409         return afs_make_call(ac, call, GFP_KERNEL, false);
410 }
411
412 /*
413  * Deliver reply data to a YFSVL.GetEndpoints call.
414  *
415  *      GetEndpoints(IN yfsServerAttributes *attr,
416  *                   OUT opr_uuid *uuid,
417  *                   OUT afs_int32 *uniquifier,
418  *                   OUT endpoints *fsEndpoints,
419  *                   OUT endpoints *volEndpoints)
420  */
421 static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
422 {
423         struct afs_addr_list *alist;
424         __be32 *bp;
425         u32 uniquifier, size;
426         int ret;
427
428         _enter("{%u,%zu/%u,%u}", call->unmarshall, call->offset, call->count, call->count2);
429
430 again:
431         switch (call->unmarshall) {
432         case 0:
433                 call->offset = 0;
434                 call->unmarshall = 1;
435
436                 /* Extract the returned uuid, uniquifier, fsEndpoints count and
437                  * either the first fsEndpoint type or the volEndpoints
438                  * count if there are no fsEndpoints. */
439         case 1:
440                 ret = afs_extract_data(call, call->buffer,
441                                        sizeof(uuid_t) +
442                                        3 * sizeof(__be32),
443                                        true);
444                 if (ret < 0)
445                         return ret;
446
447                 bp = call->buffer + sizeof(uuid_t);
448                 uniquifier      = ntohl(*bp++);
449                 call->count     = ntohl(*bp++);
450                 call->count2    = ntohl(*bp); /* Type or next count */
451
452                 if (call->count > YFS_MAXENDPOINTS)
453                         return -EBADMSG;
454
455                 alist = afs_alloc_addrlist(call->count, FS_SERVICE, AFS_FS_PORT);
456                 if (!alist)
457                         return -ENOMEM;
458                 alist->version = uniquifier;
459                 call->reply[0] = alist;
460                 call->offset = 0;
461
462                 if (call->count == 0)
463                         goto extract_volendpoints;
464
465                 call->unmarshall = 2;
466
467                 /* Extract fsEndpoints[] entries */
468         case 2:
469                 switch (call->count2) {
470                 case YFS_ENDPOINT_IPV4:
471                         size = sizeof(__be32) * (1 + 1 + 1);
472                         break;
473                 case YFS_ENDPOINT_IPV6:
474                         size = sizeof(__be32) * (1 + 4 + 1);
475                         break;
476                 default:
477                         return -EBADMSG;
478                 }
479
480                 size += sizeof(__be32);
481                 ret = afs_extract_data(call, call->buffer, size, true);
482                 if (ret < 0)
483                         return ret;
484
485                 alist = call->reply[0];
486                 bp = call->buffer;
487                 switch (call->count2) {
488                 case YFS_ENDPOINT_IPV4:
489                         if (ntohl(bp[0]) != sizeof(__be32) * 2)
490                                 return -EBADMSG;
491                         afs_merge_fs_addr4(alist, bp[1], ntohl(bp[2]));
492                         bp += 3;
493                         break;
494                 case YFS_ENDPOINT_IPV6:
495                         if (ntohl(bp[0]) != sizeof(__be32) * 5)
496                                 return -EBADMSG;
497                         afs_merge_fs_addr6(alist, bp + 1, ntohl(bp[5]));
498                         bp += 6;
499                         break;
500                 default:
501                         return -EBADMSG;
502                 }
503
504                 /* Got either the type of the next entry or the count of
505                  * volEndpoints if no more fsEndpoints.
506                  */
507                 call->count2 = htonl(*bp++);
508
509                 call->offset = 0;
510                 call->count--;
511                 if (call->count > 0)
512                         goto again;
513
514         extract_volendpoints:
515                 /* Extract the list of volEndpoints. */
516                 call->count = call->count2;
517                 if (!call->count)
518                         goto end;
519                 if (call->count > YFS_MAXENDPOINTS)
520                         return -EBADMSG;
521
522                 call->unmarshall = 3;
523
524                 /* Extract the type of volEndpoints[0].  Normally we would
525                  * extract the type of the next endpoint when we extract the
526                  * data of the current one, but this is the first...
527                  */
528         case 3:
529                 ret = afs_extract_data(call, call->buffer, sizeof(__be32), true);
530                 if (ret < 0)
531                         return ret;
532
533                 bp = call->buffer;
534                 call->count2 = htonl(*bp++);
535                 call->offset = 0;
536                 call->unmarshall = 4;
537
538                 /* Extract volEndpoints[] entries */
539         case 4:
540                 switch (call->count2) {
541                 case YFS_ENDPOINT_IPV4:
542                         size = sizeof(__be32) * (1 + 1 + 1);
543                         break;
544                 case YFS_ENDPOINT_IPV6:
545                         size = sizeof(__be32) * (1 + 4 + 1);
546                         break;
547                 default:
548                         return -EBADMSG;
549                 }
550
551                 if (call->count > 1)
552                         size += sizeof(__be32);
553                 ret = afs_extract_data(call, call->buffer, size, true);
554                 if (ret < 0)
555                         return ret;
556
557                 bp = call->buffer;
558                 switch (call->count2) {
559                 case YFS_ENDPOINT_IPV4:
560                         if (ntohl(bp[0]) != sizeof(__be32) * 2)
561                                 return -EBADMSG;
562                         bp += 3;
563                         break;
564                 case YFS_ENDPOINT_IPV6:
565                         if (ntohl(bp[0]) != sizeof(__be32) * 5)
566                                 return -EBADMSG;
567                         bp += 6;
568                         break;
569                 default:
570                         return -EBADMSG;
571                 }
572
573                 /* Got either the type of the next entry or the count of
574                  * volEndpoints if no more fsEndpoints.
575                  */
576                 call->offset = 0;
577                 call->count--;
578                 if (call->count > 0) {
579                         call->count2 = htonl(*bp++);
580                         goto again;
581                 }
582
583         end:
584                 call->unmarshall = 5;
585
586                 /* Done */
587         case 5:
588                 ret = afs_extract_data(call, call->buffer, 0, false);
589                 if (ret < 0)
590                         return ret;
591                 call->unmarshall = 6;
592
593         case 6:
594                 break;
595         }
596
597         alist = call->reply[0];
598
599         /* Start with IPv6 if available. */
600         if (alist->nr_ipv4 < alist->nr_addrs)
601                 alist->index = alist->nr_ipv4;
602
603         _leave(" = 0 [done]");
604         return 0;
605 }
606
607 /*
608  * YFSVL.GetEndpoints operation type.
609  */
610 static const struct afs_call_type afs_YFSVLGetEndpoints = {
611         .name           = "YFSVL.GetEndpoints",
612         .op             = afs_YFSVL_GetEndpoints,
613         .deliver        = afs_deliver_yfsvl_get_endpoints,
614         .destructor     = afs_vl_get_addrs_u_destructor,
615 };
616
617 /*
618  * Dispatch an operation to get the addresses for a server, where the server is
619  * nominated by UUID.
620  */
621 struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_net *net,
622                                               struct afs_addr_cursor *ac,
623                                               struct key *key,
624                                               const uuid_t *uuid)
625 {
626         struct afs_call *call;
627         __be32 *bp;
628
629         _enter("");
630
631         call = afs_alloc_flat_call(net, &afs_YFSVLGetEndpoints,
632                                    sizeof(__be32) * 2 + sizeof(*uuid),
633                                    sizeof(struct in6_addr) + sizeof(__be32) * 3);
634         if (!call)
635                 return ERR_PTR(-ENOMEM);
636
637         call->key = key;
638         call->reply[0] = NULL;
639         call->ret_reply0 = true;
640
641         /* Marshall the parameters */
642         bp = call->request;
643         *bp++ = htonl(YVLGETENDPOINTS);
644         *bp++ = htonl(YFS_SERVER_UUID);
645         memcpy(bp, uuid, sizeof(*uuid)); /* Type opr_uuid */
646
647         trace_afs_make_vl_call(call);
648         return (struct afs_addr_list *)afs_make_call(ac, call, GFP_KERNEL, false);
649 }