~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/afs/fsclient.c

Version: ~ [ linux-5.4-rc3 ] ~ [ linux-5.3.6 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.79 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.149 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.196 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.196 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.75 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* AFS File Server client stubs
  2  *
  3  * Copyright (C) 2002, 2007 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/init.h>
 13 #include <linux/slab.h>
 14 #include <linux/sched.h>
 15 #include <linux/circ_buf.h>
 16 #include "internal.h"
 17 #include "afs_fs.h"
 18 
 19 /*
 20  * We need somewhere to discard into in case the server helpfully returns more
 21  * than we asked for in FS.FetchData{,64}.
 22  */
 23 static u8 afs_discard_buffer[64];
 24 
 25 /*
 26  * decode an AFSFid block
 27  */
 28 static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid)
 29 {
 30         const __be32 *bp = *_bp;
 31 
 32         fid->vid                = ntohl(*bp++);
 33         fid->vnode              = ntohl(*bp++);
 34         fid->unique             = ntohl(*bp++);
 35         *_bp = bp;
 36 }
 37 
 38 /*
 39  * decode an AFSFetchStatus block
 40  */
 41 static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
 42                                       struct afs_file_status *status,
 43                                       struct afs_vnode *vnode,
 44                                       afs_dataversion_t *store_version)
 45 {
 46         afs_dataversion_t expected_version;
 47         const __be32 *bp = *_bp;
 48         umode_t mode;
 49         u64 data_version, size;
 50         u32 changed = 0; /* becomes non-zero if ctime-type changes seen */
 51         kuid_t owner;
 52         kgid_t group;
 53 
 54 #define EXTRACT(DST)                            \
 55         do {                                    \
 56                 u32 x = ntohl(*bp++);           \
 57                 changed |= DST - x;             \
 58                 DST = x;                        \
 59         } while (0)
 60 
 61         status->if_version = ntohl(*bp++);
 62         EXTRACT(status->type);
 63         EXTRACT(status->nlink);
 64         size = ntohl(*bp++);
 65         data_version = ntohl(*bp++);
 66         EXTRACT(status->author);
 67         owner = make_kuid(&init_user_ns, ntohl(*bp++));
 68         changed |= !uid_eq(owner, status->owner);
 69         status->owner = owner;
 70         EXTRACT(status->caller_access); /* call ticket dependent */
 71         EXTRACT(status->anon_access);
 72         EXTRACT(status->mode);
 73         EXTRACT(status->parent.vnode);
 74         EXTRACT(status->parent.unique);
 75         bp++; /* seg size */
 76         status->mtime_client = ntohl(*bp++);
 77         status->mtime_server = ntohl(*bp++);
 78         group = make_kgid(&init_user_ns, ntohl(*bp++));
 79         changed |= !gid_eq(group, status->group);
 80         status->group = group;
 81         bp++; /* sync counter */
 82         data_version |= (u64) ntohl(*bp++) << 32;
 83         EXTRACT(status->lock_count);
 84         size |= (u64) ntohl(*bp++) << 32;
 85         bp++; /* spare 4 */
 86         *_bp = bp;
 87 
 88         if (size != status->size) {
 89                 status->size = size;
 90                 changed |= true;
 91         }
 92         status->mode &= S_IALLUGO;
 93 
 94         _debug("vnode time %lx, %lx",
 95                status->mtime_client, status->mtime_server);
 96 
 97         if (vnode) {
 98                 status->parent.vid = vnode->fid.vid;
 99                 if (changed && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
100                         _debug("vnode changed");
101                         i_size_write(&vnode->vfs_inode, size);
102                         vnode->vfs_inode.i_uid = status->owner;
103                         vnode->vfs_inode.i_gid = status->group;
104                         vnode->vfs_inode.i_generation = vnode->fid.unique;
105                         set_nlink(&vnode->vfs_inode, status->nlink);
106 
107                         mode = vnode->vfs_inode.i_mode;
108                         mode &= ~S_IALLUGO;
109                         mode |= status->mode;
110                         barrier();
111                         vnode->vfs_inode.i_mode = mode;
112                 }
113 
114                 vnode->vfs_inode.i_ctime.tv_sec = status->mtime_client;
115                 vnode->vfs_inode.i_mtime        = vnode->vfs_inode.i_ctime;
116                 vnode->vfs_inode.i_atime        = vnode->vfs_inode.i_ctime;
117                 vnode->vfs_inode.i_version      = data_version;
118         }
119 
120         expected_version = status->data_version;
121         if (store_version)
122                 expected_version = *store_version;
123 
124         if (expected_version != data_version) {
125                 status->data_version = data_version;
126                 if (vnode && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
127                         _debug("vnode modified %llx on {%x:%u}",
128                                (unsigned long long) data_version,
129                                vnode->fid.vid, vnode->fid.vnode);
130                         set_bit(AFS_VNODE_MODIFIED, &vnode->flags);
131                         set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
132                 }
133         } else if (store_version) {
134                 status->data_version = data_version;
135         }
136 }
137 
138 /*
139  * decode an AFSCallBack block
140  */
141 static void xdr_decode_AFSCallBack(const __be32 **_bp, struct afs_vnode *vnode)
142 {
143         const __be32 *bp = *_bp;
144 
145         vnode->cb_version       = ntohl(*bp++);
146         vnode->cb_expiry        = ntohl(*bp++);
147         vnode->cb_type          = ntohl(*bp++);
148         vnode->cb_expires       = vnode->cb_expiry + ktime_get_real_seconds();
149         *_bp = bp;
150 }
151 
152 static void xdr_decode_AFSCallBack_raw(const __be32 **_bp,
153                                        struct afs_callback *cb)
154 {
155         const __be32 *bp = *_bp;
156 
157         cb->version     = ntohl(*bp++);
158         cb->expiry      = ntohl(*bp++);
159         cb->type        = ntohl(*bp++);
160         *_bp = bp;
161 }
162 
163 /*
164  * decode an AFSVolSync block
165  */
166 static void xdr_decode_AFSVolSync(const __be32 **_bp,
167                                   struct afs_volsync *volsync)
168 {
169         const __be32 *bp = *_bp;
170 
171         volsync->creation = ntohl(*bp++);
172         bp++; /* spare2 */
173         bp++; /* spare3 */
174         bp++; /* spare4 */
175         bp++; /* spare5 */
176         bp++; /* spare6 */
177         *_bp = bp;
178 }
179 
180 /*
181  * encode the requested attributes into an AFSStoreStatus block
182  */
183 static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
184 {
185         __be32 *bp = *_bp;
186         u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;
187 
188         mask = 0;
189         if (attr->ia_valid & ATTR_MTIME) {
190                 mask |= AFS_SET_MTIME;
191                 mtime = attr->ia_mtime.tv_sec;
192         }
193 
194         if (attr->ia_valid & ATTR_UID) {
195                 mask |= AFS_SET_OWNER;
196                 owner = from_kuid(&init_user_ns, attr->ia_uid);
197         }
198 
199         if (attr->ia_valid & ATTR_GID) {
200                 mask |= AFS_SET_GROUP;
201                 group = from_kgid(&init_user_ns, attr->ia_gid);
202         }
203 
204         if (attr->ia_valid & ATTR_MODE) {
205                 mask |= AFS_SET_MODE;
206                 mode = attr->ia_mode & S_IALLUGO;
207         }
208 
209         *bp++ = htonl(mask);
210         *bp++ = htonl(mtime);
211         *bp++ = htonl(owner);
212         *bp++ = htonl(group);
213         *bp++ = htonl(mode);
214         *bp++ = 0;              /* segment size */
215         *_bp = bp;
216 }
217 
218 /*
219  * decode an AFSFetchVolumeStatus block
220  */
221 static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
222                                             struct afs_volume_status *vs)
223 {
224         const __be32 *bp = *_bp;
225 
226         vs->vid                 = ntohl(*bp++);
227         vs->parent_id           = ntohl(*bp++);
228         vs->online              = ntohl(*bp++);
229         vs->in_service          = ntohl(*bp++);
230         vs->blessed             = ntohl(*bp++);
231         vs->needs_salvage       = ntohl(*bp++);
232         vs->type                = ntohl(*bp++);
233         vs->min_quota           = ntohl(*bp++);
234         vs->max_quota           = ntohl(*bp++);
235         vs->blocks_in_use       = ntohl(*bp++);
236         vs->part_blocks_avail   = ntohl(*bp++);
237         vs->part_max_blocks     = ntohl(*bp++);
238         *_bp = bp;
239 }
240 
241 /*
242  * deliver reply data to an FS.FetchStatus
243  */
244 static int afs_deliver_fs_fetch_status(struct afs_call *call)
245 {
246         struct afs_vnode *vnode = call->reply;
247         const __be32 *bp;
248         int ret;
249 
250         _enter("");
251 
252         ret = afs_transfer_reply(call);
253         if (ret < 0)
254                 return ret;
255 
256         /* unmarshall the reply once we've received all of it */
257         bp = call->buffer;
258         xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
259         xdr_decode_AFSCallBack(&bp, vnode);
260         if (call->reply2)
261                 xdr_decode_AFSVolSync(&bp, call->reply2);
262 
263         _leave(" = 0 [done]");
264         return 0;
265 }
266 
267 /*
268  * FS.FetchStatus operation type
269  */
270 static const struct afs_call_type afs_RXFSFetchStatus = {
271         .name           = "FS.FetchStatus",
272         .deliver        = afs_deliver_fs_fetch_status,
273         .abort_to_error = afs_abort_to_error,
274         .destructor     = afs_flat_call_destructor,
275 };
276 
277 /*
278  * fetch the status information for a file
279  */
280 int afs_fs_fetch_file_status(struct afs_server *server,
281                              struct key *key,
282                              struct afs_vnode *vnode,
283                              struct afs_volsync *volsync,
284                              bool async)
285 {
286         struct afs_call *call;
287         __be32 *bp;
288 
289         _enter(",%x,{%x:%u},,",
290                key_serial(key), vnode->fid.vid, vnode->fid.vnode);
291 
292         call = afs_alloc_flat_call(&afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
293         if (!call)
294                 return -ENOMEM;
295 
296         call->key = key;
297         call->reply = vnode;
298         call->reply2 = volsync;
299         call->service_id = FS_SERVICE;
300         call->port = htons(AFS_FS_PORT);
301 
302         /* marshall the parameters */
303         bp = call->request;
304         bp[0] = htonl(FSFETCHSTATUS);
305         bp[1] = htonl(vnode->fid.vid);
306         bp[2] = htonl(vnode->fid.vnode);
307         bp[3] = htonl(vnode->fid.unique);
308 
309         return afs_make_call(&server->addr, call, GFP_NOFS, async);
310 }
311 
312 /*
313  * deliver reply data to an FS.FetchData
314  */
315 static int afs_deliver_fs_fetch_data(struct afs_call *call)
316 {
317         struct afs_vnode *vnode = call->reply;
318         struct afs_read *req = call->reply3;
319         const __be32 *bp;
320         unsigned int size;
321         void *buffer;
322         int ret;
323 
324         _enter("{%u,%zu/%u;%llu/%llu}",
325                call->unmarshall, call->offset, call->count,
326                req->remain, req->actual_len);
327 
328         switch (call->unmarshall) {
329         case 0:
330                 req->actual_len = 0;
331                 call->offset = 0;
332                 call->unmarshall++;
333                 if (call->operation_ID != FSFETCHDATA64) {
334                         call->unmarshall++;
335                         goto no_msw;
336                 }
337 
338                 /* extract the upper part of the returned data length of an
339                  * FSFETCHDATA64 op (which should always be 0 using this
340                  * client) */
341         case 1:
342                 _debug("extract data length (MSW)");
343                 ret = afs_extract_data(call, &call->tmp, 4, true);
344                 if (ret < 0)
345                         return ret;
346 
347                 req->actual_len = ntohl(call->tmp);
348                 req->actual_len <<= 32;
349                 call->offset = 0;
350                 call->unmarshall++;
351 
352         no_msw:
353                 /* extract the returned data length */
354         case 2:
355                 _debug("extract data length");
356                 ret = afs_extract_data(call, &call->tmp, 4, true);
357                 if (ret < 0)
358                         return ret;
359 
360                 req->actual_len |= ntohl(call->tmp);
361                 _debug("DATA length: %llu", req->actual_len);
362 
363                 req->remain = req->actual_len;
364                 call->offset = req->pos & (PAGE_SIZE - 1);
365                 req->index = 0;
366                 if (req->actual_len == 0)
367                         goto no_more_data;
368                 call->unmarshall++;
369 
370         begin_page:
371                 ASSERTCMP(req->index, <, req->nr_pages);
372                 if (req->remain > PAGE_SIZE - call->offset)
373                         size = PAGE_SIZE - call->offset;
374                 else
375                         size = req->remain;
376                 call->count = call->offset + size;
377                 ASSERTCMP(call->count, <=, PAGE_SIZE);
378                 req->remain -= size;
379 
380                 /* extract the returned data */
381         case 3:
382                 _debug("extract data %llu/%llu %zu/%u",
383                        req->remain, req->actual_len, call->offset, call->count);
384 
385                 buffer = kmap(req->pages[req->index]);
386                 ret = afs_extract_data(call, buffer, call->count, true);
387                 kunmap(req->pages[req->index]);
388                 if (ret < 0)
389                         return ret;
390                 if (call->offset == PAGE_SIZE) {
391                         if (req->page_done)
392                                 req->page_done(call, req);
393                         req->index++;
394                         if (req->remain > 0) {
395                                 call->offset = 0;
396                                 if (req->index >= req->nr_pages) {
397                                         call->unmarshall = 4;
398                                         goto begin_discard;
399                                 }
400                                 goto begin_page;
401                         }
402                 }
403                 goto no_more_data;
404 
405                 /* Discard any excess data the server gave us */
406         begin_discard:
407         case 4:
408                 size = min_t(loff_t, sizeof(afs_discard_buffer), req->remain);
409                 call->count = size;
410                 _debug("extract discard %llu/%llu %zu/%u",
411                        req->remain, req->actual_len, call->offset, call->count);
412 
413                 call->offset = 0;
414                 ret = afs_extract_data(call, afs_discard_buffer, call->count, true);
415                 req->remain -= call->offset;
416                 if (ret < 0)
417                         return ret;
418                 if (req->remain > 0)
419                         goto begin_discard;
420 
421         no_more_data:
422                 call->offset = 0;
423                 call->unmarshall = 5;
424 
425                 /* extract the metadata */
426         case 5:
427                 ret = afs_extract_data(call, call->buffer,
428                                        (21 + 3 + 6) * 4, false);
429                 if (ret < 0)
430                         return ret;
431 
432                 bp = call->buffer;
433                 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
434                 xdr_decode_AFSCallBack(&bp, vnode);
435                 if (call->reply2)
436                         xdr_decode_AFSVolSync(&bp, call->reply2);
437 
438                 call->offset = 0;
439                 call->unmarshall++;
440 
441         case 6:
442                 break;
443         }
444 
445         for (; req->index < req->nr_pages; req->index++) {
446                 if (call->count < PAGE_SIZE)
447                         zero_user_segment(req->pages[req->index],
448                                           call->count, PAGE_SIZE);
449                 if (req->page_done)
450                         req->page_done(call, req);
451                 call->count = 0;
452         }
453 
454         _leave(" = 0 [done]");
455         return 0;
456 }
457 
458 static void afs_fetch_data_destructor(struct afs_call *call)
459 {
460         struct afs_read *req = call->reply3;
461 
462         afs_put_read(req);
463         afs_flat_call_destructor(call);
464 }
465 
466 /*
467  * FS.FetchData operation type
468  */
469 static const struct afs_call_type afs_RXFSFetchData = {
470         .name           = "FS.FetchData",
471         .deliver        = afs_deliver_fs_fetch_data,
472         .abort_to_error = afs_abort_to_error,
473         .destructor     = afs_fetch_data_destructor,
474 };
475 
476 static const struct afs_call_type afs_RXFSFetchData64 = {
477         .name           = "FS.FetchData64",
478         .deliver        = afs_deliver_fs_fetch_data,
479         .abort_to_error = afs_abort_to_error,
480         .destructor     = afs_fetch_data_destructor,
481 };
482 
483 /*
484  * fetch data from a very large file
485  */
486 static int afs_fs_fetch_data64(struct afs_server *server,
487                                struct key *key,
488                                struct afs_vnode *vnode,
489                                struct afs_read *req,
490                                bool async)
491 {
492         struct afs_call *call;
493         __be32 *bp;
494 
495         _enter("");
496 
497         call = afs_alloc_flat_call(&afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
498         if (!call)
499                 return -ENOMEM;
500 
501         call->key = key;
502         call->reply = vnode;
503         call->reply2 = NULL; /* volsync */
504         call->reply3 = req;
505         call->service_id = FS_SERVICE;
506         call->port = htons(AFS_FS_PORT);
507         call->operation_ID = FSFETCHDATA64;
508 
509         /* marshall the parameters */
510         bp = call->request;
511         bp[0] = htonl(FSFETCHDATA64);
512         bp[1] = htonl(vnode->fid.vid);
513         bp[2] = htonl(vnode->fid.vnode);
514         bp[3] = htonl(vnode->fid.unique);
515         bp[4] = htonl(upper_32_bits(req->pos));
516         bp[5] = htonl(lower_32_bits(req->pos));
517         bp[6] = 0;
518         bp[7] = htonl(lower_32_bits(req->len));
519 
520         atomic_inc(&req->usage);
521         return afs_make_call(&server->addr, call, GFP_NOFS, async);
522 }
523 
524 /*
525  * fetch data from a file
526  */
527 int afs_fs_fetch_data(struct afs_server *server,
528                       struct key *key,
529                       struct afs_vnode *vnode,
530                       struct afs_read *req,
531                       bool async)
532 {
533         struct afs_call *call;
534         __be32 *bp;
535 
536         if (upper_32_bits(req->pos) ||
537             upper_32_bits(req->len) ||
538             upper_32_bits(req->pos + req->len))
539                 return afs_fs_fetch_data64(server, key, vnode, req, async);
540 
541         _enter("");
542 
543         call = afs_alloc_flat_call(&afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
544         if (!call)
545                 return -ENOMEM;
546 
547         call->key = key;
548         call->reply = vnode;
549         call->reply2 = NULL; /* volsync */
550         call->reply3 = req;
551         call->service_id = FS_SERVICE;
552         call->port = htons(AFS_FS_PORT);
553         call->operation_ID = FSFETCHDATA;
554 
555         /* marshall the parameters */
556         bp = call->request;
557         bp[0] = htonl(FSFETCHDATA);
558         bp[1] = htonl(vnode->fid.vid);
559         bp[2] = htonl(vnode->fid.vnode);
560         bp[3] = htonl(vnode->fid.unique);
561         bp[4] = htonl(lower_32_bits(req->pos));
562         bp[5] = htonl(lower_32_bits(req->len));
563 
564         atomic_inc(&req->usage);
565         return afs_make_call(&server->addr, call, GFP_NOFS, async);
566 }
567 
568 /*
569  * deliver reply data to an FS.GiveUpCallBacks
570  */
571 static int afs_deliver_fs_give_up_callbacks(struct afs_call *call)
572 {
573         _enter("");
574 
575         /* shouldn't be any reply data */
576         return afs_extract_data(call, NULL, 0, false);
577 }
578 
579 /*
580  * FS.GiveUpCallBacks operation type
581  */
582 static const struct afs_call_type afs_RXFSGiveUpCallBacks = {
583         .name           = "FS.GiveUpCallBacks",
584         .deliver        = afs_deliver_fs_give_up_callbacks,
585         .abort_to_error = afs_abort_to_error,
586         .destructor     = afs_flat_call_destructor,
587 };
588 
589 /*
590  * give up a set of callbacks
591  * - the callbacks are held in the server->cb_break ring
592  */
593 int afs_fs_give_up_callbacks(struct afs_server *server,
594                              bool async)
595 {
596         struct afs_call *call;
597         size_t ncallbacks;
598         __be32 *bp, *tp;
599         int loop;
600 
601         ncallbacks = CIRC_CNT(server->cb_break_head, server->cb_break_tail,
602                               ARRAY_SIZE(server->cb_break));
603 
604         _enter("{%zu},", ncallbacks);
605 
606         if (ncallbacks == 0)
607                 return 0;
608         if (ncallbacks > AFSCBMAX)
609                 ncallbacks = AFSCBMAX;
610 
611         _debug("break %zu callbacks", ncallbacks);
612 
613         call = afs_alloc_flat_call(&afs_RXFSGiveUpCallBacks,
614                                    12 + ncallbacks * 6 * 4, 0);
615         if (!call)
616                 return -ENOMEM;
617 
618         call->service_id = FS_SERVICE;
619         call->port = htons(AFS_FS_PORT);
620 
621         /* marshall the parameters */
622         bp = call->request;
623         tp = bp + 2 + ncallbacks * 3;
624         *bp++ = htonl(FSGIVEUPCALLBACKS);
625         *bp++ = htonl(ncallbacks);
626         *tp++ = htonl(ncallbacks);
627 
628         atomic_sub(ncallbacks, &server->cb_break_n);
629         for (loop = ncallbacks; loop > 0; loop--) {
630                 struct afs_callback *cb =
631                         &server->cb_break[server->cb_break_tail];
632 
633                 *bp++ = htonl(cb->fid.vid);
634                 *bp++ = htonl(cb->fid.vnode);
635                 *bp++ = htonl(cb->fid.unique);
636                 *tp++ = htonl(cb->version);
637                 *tp++ = htonl(cb->expiry);
638                 *tp++ = htonl(cb->type);
639                 smp_mb();
640                 server->cb_break_tail =
641                         (server->cb_break_tail + 1) &
642                         (ARRAY_SIZE(server->cb_break) - 1);
643         }
644 
645         ASSERT(ncallbacks > 0);
646         wake_up_nr(&server->cb_break_waitq, ncallbacks);
647 
648         return afs_make_call(&server->addr, call, GFP_NOFS, async);
649 }
650 
651 /*
652  * deliver reply data to an FS.CreateFile or an FS.MakeDir
653  */
654 static int afs_deliver_fs_create_vnode(struct afs_call *call)
655 {
656         struct afs_vnode *vnode = call->reply;
657         const __be32 *bp;
658         int ret;
659 
660         _enter("{%u}", call->unmarshall);
661 
662         ret = afs_transfer_reply(call);
663         if (ret < 0)
664                 return ret;
665 
666         /* unmarshall the reply once we've received all of it */
667         bp = call->buffer;
668         xdr_decode_AFSFid(&bp, call->reply2);
669         xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL, NULL);
670         xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
671         xdr_decode_AFSCallBack_raw(&bp, call->reply4);
672         /* xdr_decode_AFSVolSync(&bp, call->replyX); */
673 
674         _leave(" = 0 [done]");
675         return 0;
676 }
677 
678 /*
679  * FS.CreateFile and FS.MakeDir operation type
680  */
681 static const struct afs_call_type afs_RXFSCreateXXXX = {
682         .name           = "FS.CreateXXXX",
683         .deliver        = afs_deliver_fs_create_vnode,
684         .abort_to_error = afs_abort_to_error,
685         .destructor     = afs_flat_call_destructor,
686 };
687 
688 /*
689  * create a file or make a directory
690  */
691 int afs_fs_create(struct afs_server *server,
692                   struct key *key,
693                   struct afs_vnode *vnode,
694                   const char *name,
695                   umode_t mode,
696                   struct afs_fid *newfid,
697                   struct afs_file_status *newstatus,
698                   struct afs_callback *newcb,
699                   bool async)
700 {
701         struct afs_call *call;
702         size_t namesz, reqsz, padsz;
703         __be32 *bp;
704 
705         _enter("");
706 
707         namesz = strlen(name);
708         padsz = (4 - (namesz & 3)) & 3;
709         reqsz = (5 * 4) + namesz + padsz + (6 * 4);
710 
711         call = afs_alloc_flat_call(&afs_RXFSCreateXXXX, reqsz,
712                                    (3 + 21 + 21 + 3 + 6) * 4);
713         if (!call)
714                 return -ENOMEM;
715 
716         call->key = key;
717         call->reply = vnode;
718         call->reply2 = newfid;
719         call->reply3 = newstatus;
720         call->reply4 = newcb;
721         call->service_id = FS_SERVICE;
722         call->port = htons(AFS_FS_PORT);
723 
724         /* marshall the parameters */
725         bp = call->request;
726         *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE);
727         *bp++ = htonl(vnode->fid.vid);
728         *bp++ = htonl(vnode->fid.vnode);
729         *bp++ = htonl(vnode->fid.unique);
730         *bp++ = htonl(namesz);
731         memcpy(bp, name, namesz);
732         bp = (void *) bp + namesz;
733         if (padsz > 0) {
734                 memset(bp, 0, padsz);
735                 bp = (void *) bp + padsz;
736         }
737         *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
738         *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
739         *bp++ = 0; /* owner */
740         *bp++ = 0; /* group */
741         *bp++ = htonl(mode & S_IALLUGO); /* unix mode */
742         *bp++ = 0; /* segment size */
743 
744         return afs_make_call(&server->addr, call, GFP_NOFS, async);
745 }
746 
747 /*
748  * deliver reply data to an FS.RemoveFile or FS.RemoveDir
749  */
750 static int afs_deliver_fs_remove(struct afs_call *call)
751 {
752         struct afs_vnode *vnode = call->reply;
753         const __be32 *bp;
754         int ret;
755 
756         _enter("{%u}", call->unmarshall);
757 
758         ret = afs_transfer_reply(call);
759         if (ret < 0)
760                 return ret;
761 
762         /* unmarshall the reply once we've received all of it */
763         bp = call->buffer;
764         xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
765         /* xdr_decode_AFSVolSync(&bp, call->replyX); */
766 
767         _leave(" = 0 [done]");
768         return 0;
769 }
770 
771 /*
772  * FS.RemoveDir/FS.RemoveFile operation type
773  */
774 static const struct afs_call_type afs_RXFSRemoveXXXX = {
775         .name           = "FS.RemoveXXXX",
776         .deliver        = afs_deliver_fs_remove,
777         .abort_to_error = afs_abort_to_error,
778         .destructor     = afs_flat_call_destructor,
779 };
780 
781 /*
782  * remove a file or directory
783  */
784 int afs_fs_remove(struct afs_server *server,
785                   struct key *key,
786                   struct afs_vnode *vnode,
787                   const char *name,
788                   bool isdir,
789                   bool async)
790 {
791         struct afs_call *call;
792         size_t namesz, reqsz, padsz;
793         __be32 *bp;
794 
795         _enter("");
796 
797         namesz = strlen(name);
798         padsz = (4 - (namesz & 3)) & 3;
799         reqsz = (5 * 4) + namesz + padsz;
800 
801         call = afs_alloc_flat_call(&afs_RXFSRemoveXXXX, reqsz, (21 + 6) * 4);
802         if (!call)
803                 return -ENOMEM;
804 
805         call->key = key;
806         call->reply = vnode;
807         call->service_id = FS_SERVICE;
808         call->port = htons(AFS_FS_PORT);
809 
810         /* marshall the parameters */
811         bp = call->request;
812         *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE);
813         *bp++ = htonl(vnode->fid.vid);
814         *bp++ = htonl(vnode->fid.vnode);
815         *bp++ = htonl(vnode->fid.unique);
816         *bp++ = htonl(namesz);
817         memcpy(bp, name, namesz);
818         bp = (void *) bp + namesz;
819         if (padsz > 0) {
820                 memset(bp, 0, padsz);
821                 bp = (void *) bp + padsz;
822         }
823 
824         return afs_make_call(&server->addr, call, GFP_NOFS, async);
825 }
826 
827 /*
828  * deliver reply data to an FS.Link
829  */
830 static int afs_deliver_fs_link(struct afs_call *call)
831 {
832         struct afs_vnode *dvnode = call->reply, *vnode = call->reply2;
833         const __be32 *bp;
834         int ret;
835 
836         _enter("{%u}", call->unmarshall);
837 
838         ret = afs_transfer_reply(call);
839         if (ret < 0)
840                 return ret;
841 
842         /* unmarshall the reply once we've received all of it */
843         bp = call->buffer;
844         xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
845         xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode, NULL);
846         /* xdr_decode_AFSVolSync(&bp, call->replyX); */
847 
848         _leave(" = 0 [done]");
849         return 0;
850 }
851 
852 /*
853  * FS.Link operation type
854  */
855 static const struct afs_call_type afs_RXFSLink = {
856         .name           = "FS.Link",
857         .deliver        = afs_deliver_fs_link,
858         .abort_to_error = afs_abort_to_error,
859         .destructor     = afs_flat_call_destructor,
860 };
861 
862 /*
863  * make a hard link
864  */
865 int afs_fs_link(struct afs_server *server,
866                 struct key *key,
867                 struct afs_vnode *dvnode,
868                 struct afs_vnode *vnode,
869                 const char *name,
870                 bool async)
871 {
872         struct afs_call *call;
873         size_t namesz, reqsz, padsz;
874         __be32 *bp;
875 
876         _enter("");
877 
878         namesz = strlen(name);
879         padsz = (4 - (namesz & 3)) & 3;
880         reqsz = (5 * 4) + namesz + padsz + (3 * 4);
881 
882         call = afs_alloc_flat_call(&afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
883         if (!call)
884                 return -ENOMEM;
885 
886         call->key = key;
887         call->reply = dvnode;
888         call->reply2 = vnode;
889         call->service_id = FS_SERVICE;
890         call->port = htons(AFS_FS_PORT);
891 
892         /* marshall the parameters */
893         bp = call->request;
894         *bp++ = htonl(FSLINK);
895         *bp++ = htonl(dvnode->fid.vid);
896         *bp++ = htonl(dvnode->fid.vnode);
897         *bp++ = htonl(dvnode->fid.unique);
898         *bp++ = htonl(namesz);
899         memcpy(bp, name, namesz);
900         bp = (void *) bp + namesz;
901         if (padsz > 0) {
902                 memset(bp, 0, padsz);
903                 bp = (void *) bp + padsz;
904         }
905         *bp++ = htonl(vnode->fid.vid);
906         *bp++ = htonl(vnode->fid.vnode);
907         *bp++ = htonl(vnode->fid.unique);
908 
909         return afs_make_call(&server->addr, call, GFP_NOFS, async);
910 }
911 
912 /*
913  * deliver reply data to an FS.Symlink
914  */
915 static int afs_deliver_fs_symlink(struct afs_call *call)
916 {
917         struct afs_vnode *vnode = call->reply;
918         const __be32 *bp;
919         int ret;
920 
921         _enter("{%u}", call->unmarshall);
922 
923         ret = afs_transfer_reply(call);
924         if (ret < 0)
925                 return ret;
926 
927         /* unmarshall the reply once we've received all of it */
928         bp = call->buffer;
929         xdr_decode_AFSFid(&bp, call->reply2);
930         xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL, NULL);
931         xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
932         /* xdr_decode_AFSVolSync(&bp, call->replyX); */
933 
934         _leave(" = 0 [done]");
935         return 0;
936 }
937 
938 /*
939  * FS.Symlink operation type
940  */
941 static const struct afs_call_type afs_RXFSSymlink = {
942         .name           = "FS.Symlink",
943         .deliver        = afs_deliver_fs_symlink,
944         .abort_to_error = afs_abort_to_error,
945         .destructor     = afs_flat_call_destructor,
946 };
947 
948 /*
949  * create a symbolic link
950  */
951 int afs_fs_symlink(struct afs_server *server,
952                    struct key *key,
953                    struct afs_vnode *vnode,
954                    const char *name,
955                    const char *contents,
956                    struct afs_fid *newfid,
957                    struct afs_file_status *newstatus,
958                    bool async)
959 {
960         struct afs_call *call;
961         size_t namesz, reqsz, padsz, c_namesz, c_padsz;
962         __be32 *bp;
963 
964         _enter("");
965 
966         namesz = strlen(name);
967         padsz = (4 - (namesz & 3)) & 3;
968 
969         c_namesz = strlen(contents);
970         c_padsz = (4 - (c_namesz & 3)) & 3;
971 
972         reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
973 
974         call = afs_alloc_flat_call(&afs_RXFSSymlink, reqsz,
975                                    (3 + 21 + 21 + 6) * 4);
976         if (!call)
977                 return -ENOMEM;
978 
979         call->key = key;
980         call->reply = vnode;
981         call->reply2 = newfid;
982         call->reply3 = newstatus;
983         call->service_id = FS_SERVICE;
984         call->port = htons(AFS_FS_PORT);
985 
986         /* marshall the parameters */
987         bp = call->request;
988         *bp++ = htonl(FSSYMLINK);
989         *bp++ = htonl(vnode->fid.vid);
990         *bp++ = htonl(vnode->fid.vnode);
991         *bp++ = htonl(vnode->fid.unique);
992         *bp++ = htonl(namesz);
993         memcpy(bp, name, namesz);
994         bp = (void *) bp + namesz;
995         if (padsz > 0) {
996                 memset(bp, 0, padsz);
997                 bp = (void *) bp + padsz;
998         }
999         *bp++ = htonl(c_namesz);
1000         memcpy(bp, contents, c_namesz);
1001         bp = (void *) bp + c_namesz;
1002         if (c_padsz > 0) {
1003                 memset(bp, 0, c_padsz);
1004                 bp = (void *) bp + c_padsz;
1005         }
1006         *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
1007         *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
1008         *bp++ = 0; /* owner */
1009         *bp++ = 0; /* group */
1010         *bp++ = htonl(S_IRWXUGO); /* unix mode */
1011         *bp++ = 0; /* segment size */
1012 
1013         return afs_make_call(&server->addr, call, GFP_NOFS, async);
1014 }
1015 
1016 /*
1017  * deliver reply data to an FS.Rename
1018  */
1019 static int afs_deliver_fs_rename(struct afs_call *call)
1020 {
1021         struct afs_vnode *orig_dvnode = call->reply, *new_dvnode = call->reply2;
1022         const __be32 *bp;
1023         int ret;
1024 
1025         _enter("{%u}", call->unmarshall);
1026 
1027         ret = afs_transfer_reply(call);
1028         if (ret < 0)
1029                 return ret;
1030 
1031         /* unmarshall the reply once we've received all of it */
1032         bp = call->buffer;
1033         xdr_decode_AFSFetchStatus(&bp, &orig_dvnode->status, orig_dvnode, NULL);
1034         if (new_dvnode != orig_dvnode)
1035                 xdr_decode_AFSFetchStatus(&bp, &new_dvnode->status, new_dvnode,
1036                                           NULL);
1037         /* xdr_decode_AFSVolSync(&bp, call->replyX); */
1038 
1039         _leave(" = 0 [done]");
1040         return 0;
1041 }
1042 
1043 /*
1044  * FS.Rename operation type
1045  */
1046 static const struct afs_call_type afs_RXFSRename = {
1047         .name           = "FS.Rename",
1048         .deliver        = afs_deliver_fs_rename,
1049         .abort_to_error = afs_abort_to_error,
1050         .destructor     = afs_flat_call_destructor,
1051 };
1052 
1053 /*
1054  * create a symbolic link
1055  */
1056 int afs_fs_rename(struct afs_server *server,
1057                   struct key *key,
1058                   struct afs_vnode *orig_dvnode,
1059                   const char *orig_name,
1060                   struct afs_vnode *new_dvnode,
1061                   const char *new_name,
1062                   bool async)
1063 {
1064         struct afs_call *call;
1065         size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
1066         __be32 *bp;
1067 
1068         _enter("");
1069 
1070         o_namesz = strlen(orig_name);
1071         o_padsz = (4 - (o_namesz & 3)) & 3;
1072 
1073         n_namesz = strlen(new_name);
1074         n_padsz = (4 - (n_namesz & 3)) & 3;
1075 
1076         reqsz = (4 * 4) +
1077                 4 + o_namesz + o_padsz +
1078                 (3 * 4) +
1079                 4 + n_namesz + n_padsz;
1080 
1081         call = afs_alloc_flat_call(&afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
1082         if (!call)
1083                 return -ENOMEM;
1084 
1085         call->key = key;
1086         call->reply = orig_dvnode;
1087         call->reply2 = new_dvnode;
1088         call->service_id = FS_SERVICE;
1089         call->port = htons(AFS_FS_PORT);
1090 
1091         /* marshall the parameters */
1092         bp = call->request;
1093         *bp++ = htonl(FSRENAME);
1094         *bp++ = htonl(orig_dvnode->fid.vid);
1095         *bp++ = htonl(orig_dvnode->fid.vnode);
1096         *bp++ = htonl(orig_dvnode->fid.unique);
1097         *bp++ = htonl(o_namesz);
1098         memcpy(bp, orig_name, o_namesz);
1099         bp = (void *) bp + o_namesz;
1100         if (o_padsz > 0) {
1101                 memset(bp, 0, o_padsz);
1102                 bp = (void *) bp + o_padsz;
1103         }
1104 
1105         *bp++ = htonl(new_dvnode->fid.vid);
1106         *bp++ = htonl(new_dvnode->fid.vnode);
1107         *bp++ = htonl(new_dvnode->fid.unique);
1108         *bp++ = htonl(n_namesz);
1109         memcpy(bp, new_name, n_namesz);
1110         bp = (void *) bp + n_namesz;
1111         if (n_padsz > 0) {
1112                 memset(bp, 0, n_padsz);
1113                 bp = (void *) bp + n_padsz;
1114         }
1115 
1116         return afs_make_call(&server->addr, call, GFP_NOFS, async);
1117 }
1118 
1119 /*
1120  * deliver reply data to an FS.StoreData
1121  */
1122 static int afs_deliver_fs_store_data(struct afs_call *call)
1123 {
1124         struct afs_vnode *vnode = call->reply;
1125         const __be32 *bp;
1126         int ret;
1127 
1128         _enter("");
1129 
1130         ret = afs_transfer_reply(call);
1131         if (ret < 0)
1132                 return ret;
1133 
1134         /* unmarshall the reply once we've received all of it */
1135         bp = call->buffer;
1136         xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
1137                                   &call->store_version);
1138         /* xdr_decode_AFSVolSync(&bp, call->replyX); */
1139 
1140         afs_pages_written_back(vnode, call);
1141 
1142         _leave(" = 0 [done]");
1143         return 0;
1144 }
1145 
1146 /*
1147  * FS.StoreData operation type
1148  */
1149 static const struct afs_call_type afs_RXFSStoreData = {
1150         .name           = "FS.StoreData",
1151         .deliver        = afs_deliver_fs_store_data,
1152         .abort_to_error = afs_abort_to_error,
1153         .destructor     = afs_flat_call_destructor,
1154 };
1155 
1156 static const struct afs_call_type afs_RXFSStoreData64 = {
1157         .name           = "FS.StoreData64",
1158         .deliver        = afs_deliver_fs_store_data,
1159         .abort_to_error = afs_abort_to_error,
1160         .destructor     = afs_flat_call_destructor,
1161 };
1162 
1163 /*
1164  * store a set of pages to a very large file
1165  */
1166 static int afs_fs_store_data64(struct afs_server *server,
1167                                struct afs_writeback *wb,
1168                                pgoff_t first, pgoff_t last,
1169                                unsigned offset, unsigned to,
1170                                loff_t size, loff_t pos, loff_t i_size,
1171                                bool async)
1172 {
1173         struct afs_vnode *vnode = wb->vnode;
1174         struct afs_call *call;
1175         __be32 *bp;
1176 
1177         _enter(",%x,{%x:%u},,",
1178                key_serial(wb->key), vnode->fid.vid, vnode->fid.vnode);
1179 
1180         call = afs_alloc_flat_call(&afs_RXFSStoreData64,
1181                                    (4 + 6 + 3 * 2) * 4,
1182                                    (21 + 6) * 4);
1183         if (!call)
1184                 return -ENOMEM;
1185 
1186         call->wb = wb;
1187         call->key = wb->key;
1188         call->reply = vnode;
1189         call->service_id = FS_SERVICE;
1190         call->port = htons(AFS_FS_PORT);
1191         call->mapping = vnode->vfs_inode.i_mapping;
1192         call->first = first;
1193         call->last = last;
1194         call->first_offset = offset;
1195         call->last_to = to;
1196         call->send_pages = true;
1197         call->store_version = vnode->status.data_version + 1;
1198 
1199         /* marshall the parameters */
1200         bp = call->request;
1201         *bp++ = htonl(FSSTOREDATA64);
1202         *bp++ = htonl(vnode->fid.vid);
1203         *bp++ = htonl(vnode->fid.vnode);
1204         *bp++ = htonl(vnode->fid.unique);
1205 
1206         *bp++ = htonl(AFS_SET_MTIME); /* mask */
1207         *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
1208         *bp++ = 0; /* owner */
1209         *bp++ = 0; /* group */
1210         *bp++ = 0; /* unix mode */
1211         *bp++ = 0; /* segment size */
1212 
1213         *bp++ = htonl(pos >> 32);
1214         *bp++ = htonl((u32) pos);
1215         *bp++ = htonl(size >> 32);
1216         *bp++ = htonl((u32) size);
1217         *bp++ = htonl(i_size >> 32);
1218         *bp++ = htonl((u32) i_size);
1219 
1220         return afs_make_call(&server->addr, call, GFP_NOFS, async);
1221 }
1222 
1223 /*
1224  * store a set of pages
1225  */
1226 int afs_fs_store_data(struct afs_server *server, struct afs_writeback *wb,
1227                       pgoff_t first, pgoff_t last,
1228                       unsigned offset, unsigned to,
1229                       bool async)
1230 {
1231         struct afs_vnode *vnode = wb->vnode;
1232         struct afs_call *call;
1233         loff_t size, pos, i_size;
1234         __be32 *bp;
1235 
1236         _enter(",%x,{%x:%u},,",
1237                key_serial(wb->key), vnode->fid.vid, vnode->fid.vnode);
1238 
1239         size = (loff_t)to - (loff_t)offset;
1240         if (first != last)
1241                 size += (loff_t)(last - first) << PAGE_SHIFT;
1242         pos = (loff_t)first << PAGE_SHIFT;
1243         pos += offset;
1244 
1245         i_size = i_size_read(&vnode->vfs_inode);
1246         if (pos + size > i_size)
1247                 i_size = size + pos;
1248 
1249         _debug("size %llx, at %llx, i_size %llx",
1250                (unsigned long long) size, (unsigned long long) pos,
1251                (unsigned long long) i_size);
1252 
1253         if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
1254                 return afs_fs_store_data64(server, wb, first, last, offset, to,
1255                                            size, pos, i_size, async);
1256 
1257         call = afs_alloc_flat_call(&afs_RXFSStoreData,
1258                                    (4 + 6 + 3) * 4,
1259                                    (21 + 6) * 4);
1260         if (!call)
1261                 return -ENOMEM;
1262 
1263         call->wb = wb;
1264         call->key = wb->key;
1265         call->reply = vnode;
1266         call->service_id = FS_SERVICE;
1267         call->port = htons(AFS_FS_PORT);
1268         call->mapping = vnode->vfs_inode.i_mapping;
1269         call->first = first;
1270         call->last = last;
1271         call->first_offset = offset;
1272         call->last_to = to;
1273         call->send_pages = true;
1274         call->store_version = vnode->status.data_version + 1;
1275 
1276         /* marshall the parameters */
1277         bp = call->request;
1278         *bp++ = htonl(FSSTOREDATA);
1279         *bp++ = htonl(vnode->fid.vid);
1280         *bp++ = htonl(vnode->fid.vnode);
1281         *bp++ = htonl(vnode->fid.unique);
1282 
1283         *bp++ = htonl(AFS_SET_MTIME); /* mask */
1284         *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
1285         *bp++ = 0; /* owner */
1286         *bp++ = 0; /* group */
1287         *bp++ = 0; /* unix mode */
1288         *bp++ = 0; /* segment size */
1289 
1290         *bp++ = htonl(pos);
1291         *bp++ = htonl(size);
1292         *bp++ = htonl(i_size);
1293 
1294         return afs_make_call(&server->addr, call, GFP_NOFS, async);
1295 }
1296 
1297 /*
1298  * deliver reply data to an FS.StoreStatus
1299  */
1300 static int afs_deliver_fs_store_status(struct afs_call *call)
1301 {
1302         afs_dataversion_t *store_version;
1303         struct afs_vnode *vnode = call->reply;
1304         const __be32 *bp;
1305         int ret;
1306 
1307         _enter("");
1308 
1309         ret = afs_transfer_reply(call);
1310         if (ret < 0)
1311                 return ret;
1312 
1313         /* unmarshall the reply once we've received all of it */
1314         store_version = NULL;
1315         if (call->operation_ID == FSSTOREDATA)
1316                 store_version = &call->store_version;
1317 
1318         bp = call->buffer;
1319         xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, store_version);
1320         /* xdr_decode_AFSVolSync(&bp, call->replyX); */
1321 
1322         _leave(" = 0 [done]");
1323         return 0;
1324 }
1325 
1326 /*
1327  * FS.StoreStatus operation type
1328  */
1329 static const struct afs_call_type afs_RXFSStoreStatus = {
1330         .name           = "FS.StoreStatus",
1331         .deliver        = afs_deliver_fs_store_status,
1332         .abort_to_error = afs_abort_to_error,
1333         .destructor     = afs_flat_call_destructor,
1334 };
1335 
1336 static const struct afs_call_type afs_RXFSStoreData_as_Status = {
1337         .name           = "FS.StoreData",
1338         .deliver        = afs_deliver_fs_store_status,
1339         .abort_to_error = afs_abort_to_error,
1340         .destructor     = afs_flat_call_destructor,
1341 };
1342 
1343 static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
1344         .name           = "FS.StoreData64",
1345         .deliver        = afs_deliver_fs_store_status,
1346         .abort_to_error = afs_abort_to_error,
1347         .destructor     = afs_flat_call_destructor,
1348 };
1349 
1350 /*
1351  * set the attributes on a very large file, using FS.StoreData rather than
1352  * FS.StoreStatus so as to alter the file size also
1353  */
1354 static int afs_fs_setattr_size64(struct afs_server *server, struct key *key,
1355                                  struct afs_vnode *vnode, struct iattr *attr,
1356                                  bool async)
1357 {
1358         struct afs_call *call;
1359         __be32 *bp;
1360 
1361         _enter(",%x,{%x:%u},,",
1362                key_serial(key), vnode->fid.vid, vnode->fid.vnode);
1363 
1364         ASSERT(attr->ia_valid & ATTR_SIZE);
1365 
1366         call = afs_alloc_flat_call(&afs_RXFSStoreData64_as_Status,
1367                                    (4 + 6 + 3 * 2) * 4,
1368                                    (21 + 6) * 4);
1369         if (!call)
1370                 return -ENOMEM;
1371 
1372         call->key = key;
1373         call->reply = vnode;
1374         call->service_id = FS_SERVICE;
1375         call->port = htons(AFS_FS_PORT);
1376         call->store_version = vnode->status.data_version + 1;
1377         call->operation_ID = FSSTOREDATA;
1378 
1379         /* marshall the parameters */
1380         bp = call->request;
1381         *bp++ = htonl(FSSTOREDATA64);
1382         *bp++ = htonl(vnode->fid.vid);
1383         *bp++ = htonl(vnode->fid.vnode);
1384         *bp++ = htonl(vnode->fid.unique);
1385 
1386         xdr_encode_AFS_StoreStatus(&bp, attr);
1387 
1388         *bp++ = 0;                              /* position of start of write */
1389         *bp++ = 0;
1390         *bp++ = 0;                              /* size of write */
1391         *bp++ = 0;
1392         *bp++ = htonl(attr->ia_size >> 32);     /* new file length */
1393         *bp++ = htonl((u32) attr->ia_size);
1394 
1395         return afs_make_call(&server->addr, call, GFP_NOFS, async);
1396 }
1397 
1398 /*
1399  * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1400  * so as to alter the file size also
1401  */
1402 static int afs_fs_setattr_size(struct afs_server *server, struct key *key,
1403                                struct afs_vnode *vnode, struct iattr *attr,
1404                                bool async)
1405 {
1406         struct afs_call *call;
1407         __be32 *bp;
1408 
1409         _enter(",%x,{%x:%u},,",
1410                key_serial(key), vnode->fid.vid, vnode->fid.vnode);
1411 
1412         ASSERT(attr->ia_valid & ATTR_SIZE);
1413         if (attr->ia_size >> 32)
1414                 return afs_fs_setattr_size64(server, key, vnode, attr,
1415                                              async);
1416 
1417         call = afs_alloc_flat_call(&afs_RXFSStoreData_as_Status,
1418                                    (4 + 6 + 3) * 4,
1419                                    (21 + 6) * 4);
1420         if (!call)
1421                 return -ENOMEM;
1422 
1423         call->key = key;
1424         call->reply = vnode;
1425         call->service_id = FS_SERVICE;
1426         call->port = htons(AFS_FS_PORT);
1427         call->store_version = vnode->status.data_version + 1;
1428         call->operation_ID = FSSTOREDATA;
1429 
1430         /* marshall the parameters */
1431         bp = call->request;
1432         *bp++ = htonl(FSSTOREDATA);
1433         *bp++ = htonl(vnode->fid.vid);
1434         *bp++ = htonl(vnode->fid.vnode);
1435         *bp++ = htonl(vnode->fid.unique);
1436 
1437         xdr_encode_AFS_StoreStatus(&bp, attr);
1438 
1439         *bp++ = 0;                              /* position of start of write */
1440         *bp++ = 0;                              /* size of write */
1441         *bp++ = htonl(attr->ia_size);           /* new file length */
1442 
1443         return afs_make_call(&server->addr, call, GFP_NOFS, async);
1444 }
1445 
1446 /*
1447  * set the attributes on a file, using FS.StoreData if there's a change in file
1448  * size, and FS.StoreStatus otherwise
1449  */
1450 int afs_fs_setattr(struct afs_server *server, struct key *key,
1451                    struct afs_vnode *vnode, struct iattr *attr,
1452                    bool async)
1453 {
1454         struct afs_call *call;
1455         __be32 *bp;
1456 
1457         if (attr->ia_valid & ATTR_SIZE)
1458                 return afs_fs_setattr_size(server, key, vnode, attr,
1459                                            async);
1460 
1461         _enter(",%x,{%x:%u},,",
1462                key_serial(key), vnode->fid.vid, vnode->fid.vnode);
1463 
1464         call = afs_alloc_flat_call(&afs_RXFSStoreStatus,
1465                                    (4 + 6) * 4,
1466                                    (21 + 6) * 4);
1467         if (!call)
1468                 return -ENOMEM;
1469 
1470         call->key = key;
1471         call->reply = vnode;
1472         call->service_id = FS_SERVICE;
1473         call->port = htons(AFS_FS_PORT);
1474         call->operation_ID = FSSTORESTATUS;
1475 
1476         /* marshall the parameters */
1477         bp = call->request;
1478         *bp++ = htonl(FSSTORESTATUS);
1479         *bp++ = htonl(vnode->fid.vid);
1480         *bp++ = htonl(vnode->fid.vnode);
1481         *bp++ = htonl(vnode->fid.unique);
1482 
1483         xdr_encode_AFS_StoreStatus(&bp, attr);
1484 
1485         return afs_make_call(&server->addr, call, GFP_NOFS, async);
1486 }
1487 
1488 /*
1489  * deliver reply data to an FS.GetVolumeStatus
1490  */
1491 static int afs_deliver_fs_get_volume_status(struct afs_call *call)
1492 {
1493         const __be32 *bp;
1494         char *p;
1495         int ret;
1496 
1497         _enter("{%u}", call->unmarshall);
1498 
1499         switch (call->unmarshall) {
1500         case 0:
1501                 call->offset = 0;
1502                 call->unmarshall++;
1503 
1504                 /* extract the returned status record */
1505         case 1:
1506                 _debug("extract status");
1507                 ret = afs_extract_data(call, call->buffer,
1508                                        12 * 4, true);
1509                 if (ret < 0)
1510                         return ret;
1511 
1512                 bp = call->buffer;
1513                 xdr_decode_AFSFetchVolumeStatus(&bp, call->reply2);
1514                 call->offset = 0;
1515                 call->unmarshall++;
1516 
1517                 /* extract the volume name length */
1518         case 2:
1519                 ret = afs_extract_data(call, &call->tmp, 4, true);
1520                 if (ret < 0)
1521                         return ret;
1522 
1523                 call->count = ntohl(call->tmp);
1524                 _debug("volname length: %u", call->count);
1525                 if (call->count >= AFSNAMEMAX)
1526                         return -EBADMSG;
1527                 call->offset = 0;
1528                 call->unmarshall++;
1529 
1530                 /* extract the volume name */
1531         case 3:
1532                 _debug("extract volname");
1533                 if (call->count > 0) {
1534                         ret = afs_extract_data(call, call->reply3,
1535                                                call->count, true);
1536                         if (ret < 0)
1537                                 return ret;
1538                 }
1539 
1540                 p = call->reply3;
1541                 p[call->count] = 0;
1542                 _debug("volname '%s'", p);
1543 
1544                 call->offset = 0;
1545                 call->unmarshall++;
1546 
1547                 /* extract the volume name padding */
1548                 if ((call->count & 3) == 0) {
1549                         call->unmarshall++;
1550                         goto no_volname_padding;
1551                 }
1552                 call->count = 4 - (call->count & 3);
1553 
1554         case 4:
1555                 ret = afs_extract_data(call, call->buffer,
1556                                        call->count, true);
1557                 if (ret < 0)
1558                         return ret;
1559 
1560                 call->offset = 0;
1561                 call->unmarshall++;
1562         no_volname_padding:
1563 
1564                 /* extract the offline message length */
1565         case 5:
1566                 ret = afs_extract_data(call, &call->tmp, 4, true);
1567                 if (ret < 0)
1568                         return ret;
1569 
1570                 call->count = ntohl(call->tmp);
1571                 _debug("offline msg length: %u", call->count);
1572                 if (call->count >= AFSNAMEMAX)
1573                         return -EBADMSG;
1574                 call->offset = 0;
1575                 call->unmarshall++;
1576 
1577                 /* extract the offline message */
1578         case 6:
1579                 _debug("extract offline");
1580                 if (call->count > 0) {
1581                         ret = afs_extract_data(call, call->reply3,
1582                                                call->count, true);
1583                         if (ret < 0)
1584                                 return ret;
1585                 }
1586 
1587                 p = call->reply3;
1588                 p[call->count] = 0;
1589                 _debug("offline '%s'", p);
1590 
1591                 call->offset = 0;
1592                 call->unmarshall++;
1593 
1594                 /* extract the offline message padding */
1595                 if ((call->count & 3) == 0) {
1596                         call->unmarshall++;
1597                         goto no_offline_padding;
1598                 }
1599                 call->count = 4 - (call->count & 3);
1600 
1601         case 7:
1602                 ret = afs_extract_data(call, call->buffer,
1603                                        call->count, true);
1604                 if (ret < 0)
1605                         return ret;
1606 
1607                 call->offset = 0;
1608                 call->unmarshall++;
1609         no_offline_padding:
1610 
1611                 /* extract the message of the day length */
1612         case 8:
1613                 ret = afs_extract_data(call, &call->tmp, 4, true);
1614                 if (ret < 0)
1615                         return ret;
1616 
1617                 call->count = ntohl(call->tmp);
1618                 _debug("motd length: %u", call->count);
1619                 if (call->count >= AFSNAMEMAX)
1620                         return -EBADMSG;
1621                 call->offset = 0;
1622                 call->unmarshall++;
1623 
1624                 /* extract the message of the day */
1625         case 9:
1626                 _debug("extract motd");
1627                 if (call->count > 0) {
1628                         ret = afs_extract_data(call, call->reply3,
1629                                                call->count, true);
1630                         if (ret < 0)
1631                                 return ret;
1632                 }
1633 
1634                 p = call->reply3;
1635                 p[call->count] = 0;
1636                 _debug("motd '%s'", p);
1637 
1638                 call->offset = 0;
1639                 call->unmarshall++;
1640 
1641                 /* extract the message of the day padding */
1642                 call->count = (4 - (call->count & 3)) & 3;
1643 
1644         case 10:
1645                 ret = afs_extract_data(call, call->buffer,
1646                                        call->count, false);
1647                 if (ret < 0)
1648                         return ret;
1649 
1650                 call->offset = 0;
1651                 call->unmarshall++;
1652         case 11:
1653                 break;
1654         }
1655 
1656         _leave(" = 0 [done]");
1657         return 0;
1658 }
1659 
1660 /*
1661  * destroy an FS.GetVolumeStatus call
1662  */
1663 static void afs_get_volume_status_call_destructor(struct afs_call *call)
1664 {
1665         kfree(call->reply3);
1666         call->reply3 = NULL;
1667         afs_flat_call_destructor(call);
1668 }
1669 
1670 /*
1671  * FS.GetVolumeStatus operation type
1672  */
1673 static const struct afs_call_type afs_RXFSGetVolumeStatus = {
1674         .name           = "FS.GetVolumeStatus",
1675         .deliver        = afs_deliver_fs_get_volume_status,
1676         .abort_to_error = afs_abort_to_error,
1677         .destructor     = afs_get_volume_status_call_destructor,
1678 };
1679 
1680 /*
1681  * fetch the status of a volume
1682  */
1683 int afs_fs_get_volume_status(struct afs_server *server,
1684                              struct key *key,
1685                              struct afs_vnode *vnode,
1686                              struct afs_volume_status *vs,
1687                              bool async)
1688 {
1689         struct afs_call *call;
1690         __be32 *bp;
1691         void *tmpbuf;
1692 
1693         _enter("");
1694 
1695         tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
1696         if (!tmpbuf)
1697                 return -ENOMEM;
1698 
1699         call = afs_alloc_flat_call(&afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4);
1700         if (!call) {
1701                 kfree(tmpbuf);
1702                 return -ENOMEM;
1703         }
1704 
1705         call->key = key;
1706         call->reply = vnode;
1707         call->reply2 = vs;
1708         call->reply3 = tmpbuf;
1709         call->service_id = FS_SERVICE;
1710         call->port = htons(AFS_FS_PORT);
1711 
1712         /* marshall the parameters */
1713         bp = call->request;
1714         bp[0] = htonl(FSGETVOLUMESTATUS);
1715         bp[1] = htonl(vnode->fid.vid);
1716 
1717         return afs_make_call(&server->addr, call, GFP_NOFS, async);
1718 }
1719 
1720 /*
1721  * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
1722  */
1723 static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
1724 {
1725         const __be32 *bp;
1726         int ret;
1727 
1728         _enter("{%u}", call->unmarshall);
1729 
1730         ret = afs_transfer_reply(call);
1731         if (ret < 0)
1732                 return ret;
1733 
1734         /* unmarshall the reply once we've received all of it */
1735         bp = call->buffer;
1736         /* xdr_decode_AFSVolSync(&bp, call->replyX); */
1737 
1738         _leave(" = 0 [done]");
1739         return 0;
1740 }
1741 
1742 /*
1743  * FS.SetLock operation type
1744  */
1745 static const struct afs_call_type afs_RXFSSetLock = {
1746         .name           = "FS.SetLock",
1747         .deliver        = afs_deliver_fs_xxxx_lock,
1748         .abort_to_error = afs_abort_to_error,
1749         .destructor     = afs_flat_call_destructor,
1750 };
1751 
1752 /*
1753  * FS.ExtendLock operation type
1754  */
1755 static const struct afs_call_type afs_RXFSExtendLock = {
1756         .name           = "FS.ExtendLock",
1757         .deliver        = afs_deliver_fs_xxxx_lock,
1758         .abort_to_error = afs_abort_to_error,
1759         .destructor     = afs_flat_call_destructor,
1760 };
1761 
1762 /*
1763  * FS.ReleaseLock operation type
1764  */
1765 static const struct afs_call_type afs_RXFSReleaseLock = {
1766         .name           = "FS.ReleaseLock",
1767         .deliver        = afs_deliver_fs_xxxx_lock,
1768         .abort_to_error = afs_abort_to_error,
1769         .destructor     = afs_flat_call_destructor,
1770 };
1771 
1772 /*
1773  * get a lock on a file
1774  */
1775 int afs_fs_set_lock(struct afs_server *server,
1776                     struct key *key,
1777                     struct afs_vnode *vnode,
1778                     afs_lock_type_t type,
1779                     bool async)
1780 {
1781         struct afs_call *call;
1782         __be32 *bp;
1783 
1784         _enter("");
1785 
1786         call = afs_alloc_flat_call(&afs_RXFSSetLock, 5 * 4, 6 * 4);
1787         if (!call)
1788                 return -ENOMEM;
1789 
1790         call->key = key;
1791         call->reply = vnode;
1792         call->service_id = FS_SERVICE;
1793         call->port = htons(AFS_FS_PORT);
1794 
1795         /* marshall the parameters */
1796         bp = call->request;
1797         *bp++ = htonl(FSSETLOCK);
1798         *bp++ = htonl(vnode->fid.vid);
1799         *bp++ = htonl(vnode->fid.vnode);
1800         *bp++ = htonl(vnode->fid.unique);
1801         *bp++ = htonl(type);
1802 
1803         return afs_make_call(&server->addr, call, GFP_NOFS, async);
1804 }
1805 
1806 /*
1807  * extend a lock on a file
1808  */
1809 int afs_fs_extend_lock(struct afs_server *server,
1810                        struct key *key,
1811                        struct afs_vnode *vnode,
1812                        bool async)
1813 {
1814         struct afs_call *call;
1815         __be32 *bp;
1816 
1817         _enter("");
1818 
1819         call = afs_alloc_flat_call(&afs_RXFSExtendLock, 4 * 4, 6 * 4);
1820         if (!call)
1821                 return -ENOMEM;
1822 
1823         call->key = key;
1824         call->reply = vnode;
1825         call->service_id = FS_SERVICE;
1826         call->port = htons(AFS_FS_PORT);
1827 
1828         /* marshall the parameters */
1829         bp = call->request;
1830         *bp++ = htonl(FSEXTENDLOCK);
1831         *bp++ = htonl(vnode->fid.vid);
1832         *bp++ = htonl(vnode->fid.vnode);
1833         *bp++ = htonl(vnode->fid.unique);
1834 
1835         return afs_make_call(&server->addr, call, GFP_NOFS, async);
1836 }
1837 
1838 /*
1839  * release a lock on a file
1840  */
1841 int afs_fs_release_lock(struct afs_server *server,
1842                         struct key *key,
1843                         struct afs_vnode *vnode,
1844                         bool async)
1845 {
1846         struct afs_call *call;
1847         __be32 *bp;
1848 
1849         _enter("");
1850 
1851         call = afs_alloc_flat_call(&afs_RXFSReleaseLock, 4 * 4, 6 * 4);
1852         if (!call)
1853                 return -ENOMEM;
1854 
1855         call->key = key;
1856         call->reply = vnode;
1857         call->service_id = FS_SERVICE;
1858         call->port = htons(AFS_FS_PORT);
1859 
1860         /* marshall the parameters */
1861         bp = call->request;
1862         *bp++ = htonl(FSRELEASELOCK);
1863         *bp++ = htonl(vnode->fid.vid);
1864         *bp++ = htonl(vnode->fid.vnode);
1865         *bp++ = htonl(vnode->fid.unique);
1866 
1867         return afs_make_call(&server->addr, call, GFP_NOFS, async);
1868 }
1869 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp