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/sched.h> 14 #include <linux/circ_buf.h> 15 #include "internal.h" 16 #include "afs_fs.h" 17 18 /* 19 * decode an AFSFid block 20 */ 21 static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid) 22 { 23 const __be32 *bp = *_bp; 24 25 fid->vid = ntohl(*bp++); 26 fid->vnode = ntohl(*bp++); 27 fid->unique = ntohl(*bp++); 28 *_bp = bp; 29 } 30 31 /* 32 * decode an AFSFetchStatus block 33 */ 34 static void xdr_decode_AFSFetchStatus(const __be32 **_bp, 35 struct afs_file_status *status, 36 struct afs_vnode *vnode) 37 { 38 const __be32 *bp = *_bp; 39 umode_t mode; 40 u64 data_version, size; 41 u32 changed = 0; /* becomes non-zero if ctime-type changes seen */ 42 43 #define EXTRACT(DST) \ 44 do { \ 45 u32 x = ntohl(*bp++); \ 46 changed |= DST - x; \ 47 DST = x; \ 48 } while (0) 49 50 status->if_version = ntohl(*bp++); 51 EXTRACT(status->type); 52 EXTRACT(status->nlink); 53 size = ntohl(*bp++); 54 data_version = ntohl(*bp++); 55 EXTRACT(status->author); 56 EXTRACT(status->owner); 57 EXTRACT(status->caller_access); /* call ticket dependent */ 58 EXTRACT(status->anon_access); 59 EXTRACT(status->mode); 60 EXTRACT(status->parent.vnode); 61 EXTRACT(status->parent.unique); 62 bp++; /* seg size */ 63 status->mtime_client = ntohl(*bp++); 64 status->mtime_server = ntohl(*bp++); 65 EXTRACT(status->group); 66 bp++; /* sync counter */ 67 data_version |= (u64) ntohl(*bp++) << 32; 68 bp++; /* lock count */ 69 size |= (u64) ntohl(*bp++) << 32; 70 bp++; /* spare 4 */ 71 *_bp = bp; 72 73 if (size != status->size) { 74 status->size = size; 75 changed |= true; 76 } 77 status->mode &= S_IALLUGO; 78 79 _debug("vnode time %lx, %lx", 80 status->mtime_client, status->mtime_server); 81 82 if (vnode) { 83 status->parent.vid = vnode->fid.vid; 84 if (changed && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) { 85 _debug("vnode changed"); 86 i_size_write(&vnode->vfs_inode, size); 87 vnode->vfs_inode.i_uid = status->owner; 88 vnode->vfs_inode.i_gid = status->group; 89 vnode->vfs_inode.i_version = vnode->fid.unique; 90 vnode->vfs_inode.i_nlink = status->nlink; 91 92 mode = vnode->vfs_inode.i_mode; 93 mode &= ~S_IALLUGO; 94 mode |= status->mode; 95 barrier(); 96 vnode->vfs_inode.i_mode = mode; 97 } 98 99 vnode->vfs_inode.i_ctime.tv_sec = status->mtime_server; 100 vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime; 101 vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime; 102 } 103 104 if (status->data_version != data_version) { 105 status->data_version = data_version; 106 if (vnode && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) { 107 _debug("vnode modified %llx on {%x:%u}", 108 (unsigned long long) data_version, 109 vnode->fid.vid, vnode->fid.vnode); 110 set_bit(AFS_VNODE_MODIFIED, &vnode->flags); 111 set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags); 112 } 113 } 114 } 115 116 /* 117 * decode an AFSCallBack block 118 */ 119 static void xdr_decode_AFSCallBack(const __be32 **_bp, struct afs_vnode *vnode) 120 { 121 const __be32 *bp = *_bp; 122 123 vnode->cb_version = ntohl(*bp++); 124 vnode->cb_expiry = ntohl(*bp++); 125 vnode->cb_type = ntohl(*bp++); 126 vnode->cb_expires = vnode->cb_expiry + get_seconds(); 127 *_bp = bp; 128 } 129 130 static void xdr_decode_AFSCallBack_raw(const __be32 **_bp, 131 struct afs_callback *cb) 132 { 133 const __be32 *bp = *_bp; 134 135 cb->version = ntohl(*bp++); 136 cb->expiry = ntohl(*bp++); 137 cb->type = ntohl(*bp++); 138 *_bp = bp; 139 } 140 141 /* 142 * decode an AFSVolSync block 143 */ 144 static void xdr_decode_AFSVolSync(const __be32 **_bp, 145 struct afs_volsync *volsync) 146 { 147 const __be32 *bp = *_bp; 148 149 volsync->creation = ntohl(*bp++); 150 bp++; /* spare2 */ 151 bp++; /* spare3 */ 152 bp++; /* spare4 */ 153 bp++; /* spare5 */ 154 bp++; /* spare6 */ 155 *_bp = bp; 156 } 157 158 /* 159 * deliver reply data to an FS.FetchStatus 160 */ 161 static int afs_deliver_fs_fetch_status(struct afs_call *call, 162 struct sk_buff *skb, bool last) 163 { 164 struct afs_vnode *vnode = call->reply; 165 const __be32 *bp; 166 167 _enter(",,%u", last); 168 169 afs_transfer_reply(call, skb); 170 if (!last) 171 return 0; 172 173 if (call->reply_size != call->reply_max) 174 return -EBADMSG; 175 176 /* unmarshall the reply once we've received all of it */ 177 bp = call->buffer; 178 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); 179 xdr_decode_AFSCallBack(&bp, vnode); 180 if (call->reply2) 181 xdr_decode_AFSVolSync(&bp, call->reply2); 182 183 _leave(" = 0 [done]"); 184 return 0; 185 } 186 187 /* 188 * FS.FetchStatus operation type 189 */ 190 static const struct afs_call_type afs_RXFSFetchStatus = { 191 .name = "FS.FetchStatus", 192 .deliver = afs_deliver_fs_fetch_status, 193 .abort_to_error = afs_abort_to_error, 194 .destructor = afs_flat_call_destructor, 195 }; 196 197 /* 198 * fetch the status information for a file 199 */ 200 int afs_fs_fetch_file_status(struct afs_server *server, 201 struct key *key, 202 struct afs_vnode *vnode, 203 struct afs_volsync *volsync, 204 const struct afs_wait_mode *wait_mode) 205 { 206 struct afs_call *call; 207 __be32 *bp; 208 209 _enter(",%x,{%x:%d},,", 210 key_serial(key), vnode->fid.vid, vnode->fid.vnode); 211 212 call = afs_alloc_flat_call(&afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4); 213 if (!call) 214 return -ENOMEM; 215 216 call->key = key; 217 call->reply = vnode; 218 call->reply2 = volsync; 219 call->service_id = FS_SERVICE; 220 call->port = htons(AFS_FS_PORT); 221 222 /* marshall the parameters */ 223 bp = call->request; 224 bp[0] = htonl(FSFETCHSTATUS); 225 bp[1] = htonl(vnode->fid.vid); 226 bp[2] = htonl(vnode->fid.vnode); 227 bp[3] = htonl(vnode->fid.unique); 228 229 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); 230 } 231 232 /* 233 * deliver reply data to an FS.FetchData 234 */ 235 static int afs_deliver_fs_fetch_data(struct afs_call *call, 236 struct sk_buff *skb, bool last) 237 { 238 struct afs_vnode *vnode = call->reply; 239 const __be32 *bp; 240 struct page *page; 241 void *buffer; 242 int ret; 243 244 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); 245 246 switch (call->unmarshall) { 247 case 0: 248 call->offset = 0; 249 call->unmarshall++; 250 251 /* extract the returned data length */ 252 case 1: 253 _debug("extract data length"); 254 ret = afs_extract_data(call, skb, last, &call->tmp, 4); 255 switch (ret) { 256 case 0: break; 257 case -EAGAIN: return 0; 258 default: return ret; 259 } 260 261 call->count = ntohl(call->tmp); 262 _debug("DATA length: %u", call->count); 263 if (call->count > PAGE_SIZE) 264 return -EBADMSG; 265 call->offset = 0; 266 call->unmarshall++; 267 268 if (call->count < PAGE_SIZE) { 269 page = call->reply3; 270 buffer = kmap_atomic(page, KM_USER0); 271 memset(buffer + PAGE_SIZE - call->count, 0, 272 call->count); 273 kunmap_atomic(buffer, KM_USER0); 274 } 275 276 /* extract the returned data */ 277 case 2: 278 _debug("extract data"); 279 page = call->reply3; 280 buffer = kmap_atomic(page, KM_USER0); 281 ret = afs_extract_data(call, skb, last, buffer, call->count); 282 kunmap_atomic(buffer, KM_USER0); 283 switch (ret) { 284 case 0: break; 285 case -EAGAIN: return 0; 286 default: return ret; 287 } 288 289 call->offset = 0; 290 call->unmarshall++; 291 292 /* extract the metadata */ 293 case 3: 294 ret = afs_extract_data(call, skb, last, call->buffer, 295 (21 + 3 + 6) * 4); 296 switch (ret) { 297 case 0: break; 298 case -EAGAIN: return 0; 299 default: return ret; 300 } 301 302 bp = call->buffer; 303 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); 304 xdr_decode_AFSCallBack(&bp, vnode); 305 if (call->reply2) 306 xdr_decode_AFSVolSync(&bp, call->reply2); 307 308 call->offset = 0; 309 call->unmarshall++; 310 311 case 4: 312 _debug("trailer"); 313 if (skb->len != 0) 314 return -EBADMSG; 315 break; 316 } 317 318 if (!last) 319 return 0; 320 321 _leave(" = 0 [done]"); 322 return 0; 323 } 324 325 /* 326 * FS.FetchData operation type 327 */ 328 static const struct afs_call_type afs_RXFSFetchData = { 329 .name = "FS.FetchData", 330 .deliver = afs_deliver_fs_fetch_data, 331 .abort_to_error = afs_abort_to_error, 332 .destructor = afs_flat_call_destructor, 333 }; 334 335 /* 336 * fetch data from a file 337 */ 338 int afs_fs_fetch_data(struct afs_server *server, 339 struct key *key, 340 struct afs_vnode *vnode, 341 off_t offset, size_t length, 342 struct page *buffer, 343 const struct afs_wait_mode *wait_mode) 344 { 345 struct afs_call *call; 346 __be32 *bp; 347 348 _enter(""); 349 350 call = afs_alloc_flat_call(&afs_RXFSFetchData, 24, (21 + 3 + 6) * 4); 351 if (!call) 352 return -ENOMEM; 353 354 call->key = key; 355 call->reply = vnode; 356 call->reply2 = NULL; /* volsync */ 357 call->reply3 = buffer; 358 call->service_id = FS_SERVICE; 359 call->port = htons(AFS_FS_PORT); 360 361 /* marshall the parameters */ 362 bp = call->request; 363 bp[0] = htonl(FSFETCHDATA); 364 bp[1] = htonl(vnode->fid.vid); 365 bp[2] = htonl(vnode->fid.vnode); 366 bp[3] = htonl(vnode->fid.unique); 367 bp[4] = htonl(offset); 368 bp[5] = htonl(length); 369 370 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); 371 } 372 373 /* 374 * deliver reply data to an FS.GiveUpCallBacks 375 */ 376 static int afs_deliver_fs_give_up_callbacks(struct afs_call *call, 377 struct sk_buff *skb, bool last) 378 { 379 _enter(",{%u},%d", skb->len, last); 380 381 if (skb->len > 0) 382 return -EBADMSG; /* shouldn't be any reply data */ 383 return 0; 384 } 385 386 /* 387 * FS.GiveUpCallBacks operation type 388 */ 389 static const struct afs_call_type afs_RXFSGiveUpCallBacks = { 390 .name = "FS.GiveUpCallBacks", 391 .deliver = afs_deliver_fs_give_up_callbacks, 392 .abort_to_error = afs_abort_to_error, 393 .destructor = afs_flat_call_destructor, 394 }; 395 396 /* 397 * give up a set of callbacks 398 * - the callbacks are held in the server->cb_break ring 399 */ 400 int afs_fs_give_up_callbacks(struct afs_server *server, 401 const struct afs_wait_mode *wait_mode) 402 { 403 struct afs_call *call; 404 size_t ncallbacks; 405 __be32 *bp, *tp; 406 int loop; 407 408 ncallbacks = CIRC_CNT(server->cb_break_head, server->cb_break_tail, 409 ARRAY_SIZE(server->cb_break)); 410 411 _enter("{%zu},", ncallbacks); 412 413 if (ncallbacks == 0) 414 return 0; 415 if (ncallbacks > AFSCBMAX) 416 ncallbacks = AFSCBMAX; 417 418 _debug("break %zu callbacks", ncallbacks); 419 420 call = afs_alloc_flat_call(&afs_RXFSGiveUpCallBacks, 421 12 + ncallbacks * 6 * 4, 0); 422 if (!call) 423 return -ENOMEM; 424 425 call->service_id = FS_SERVICE; 426 call->port = htons(AFS_FS_PORT); 427 428 /* marshall the parameters */ 429 bp = call->request; 430 tp = bp + 2 + ncallbacks * 3; 431 *bp++ = htonl(FSGIVEUPCALLBACKS); 432 *bp++ = htonl(ncallbacks); 433 *tp++ = htonl(ncallbacks); 434 435 atomic_sub(ncallbacks, &server->cb_break_n); 436 for (loop = ncallbacks; loop > 0; loop--) { 437 struct afs_callback *cb = 438 &server->cb_break[server->cb_break_tail]; 439 440 *bp++ = htonl(cb->fid.vid); 441 *bp++ = htonl(cb->fid.vnode); 442 *bp++ = htonl(cb->fid.unique); 443 *tp++ = htonl(cb->version); 444 *tp++ = htonl(cb->expiry); 445 *tp++ = htonl(cb->type); 446 smp_mb(); 447 server->cb_break_tail = 448 (server->cb_break_tail + 1) & 449 (ARRAY_SIZE(server->cb_break) - 1); 450 } 451 452 ASSERT(ncallbacks > 0); 453 wake_up_nr(&server->cb_break_waitq, ncallbacks); 454 455 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); 456 } 457 458 /* 459 * deliver reply data to an FS.CreateFile or an FS.MakeDir 460 */ 461 static int afs_deliver_fs_create_vnode(struct afs_call *call, 462 struct sk_buff *skb, bool last) 463 { 464 struct afs_vnode *vnode = call->reply; 465 const __be32 *bp; 466 467 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); 468 469 afs_transfer_reply(call, skb); 470 if (!last) 471 return 0; 472 473 if (call->reply_size != call->reply_max) 474 return -EBADMSG; 475 476 /* unmarshall the reply once we've received all of it */ 477 bp = call->buffer; 478 xdr_decode_AFSFid(&bp, call->reply2); 479 xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL); 480 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); 481 xdr_decode_AFSCallBack_raw(&bp, call->reply4); 482 /* xdr_decode_AFSVolSync(&bp, call->replyX); */ 483 484 _leave(" = 0 [done]"); 485 return 0; 486 } 487 488 /* 489 * FS.CreateFile and FS.MakeDir operation type 490 */ 491 static const struct afs_call_type afs_RXFSCreateXXXX = { 492 .name = "FS.CreateXXXX", 493 .deliver = afs_deliver_fs_create_vnode, 494 .abort_to_error = afs_abort_to_error, 495 .destructor = afs_flat_call_destructor, 496 }; 497 498 /* 499 * create a file or make a directory 500 */ 501 int afs_fs_create(struct afs_server *server, 502 struct key *key, 503 struct afs_vnode *vnode, 504 const char *name, 505 umode_t mode, 506 struct afs_fid *newfid, 507 struct afs_file_status *newstatus, 508 struct afs_callback *newcb, 509 const struct afs_wait_mode *wait_mode) 510 { 511 struct afs_call *call; 512 size_t namesz, reqsz, padsz; 513 __be32 *bp; 514 515 _enter(""); 516 517 namesz = strlen(name); 518 padsz = (4 - (namesz & 3)) & 3; 519 reqsz = (5 * 4) + namesz + padsz + (6 * 4); 520 521 call = afs_alloc_flat_call(&afs_RXFSCreateXXXX, reqsz, 522 (3 + 21 + 21 + 3 + 6) * 4); 523 if (!call) 524 return -ENOMEM; 525 526 call->key = key; 527 call->reply = vnode; 528 call->reply2 = newfid; 529 call->reply3 = newstatus; 530 call->reply4 = newcb; 531 call->service_id = FS_SERVICE; 532 call->port = htons(AFS_FS_PORT); 533 534 /* marshall the parameters */ 535 bp = call->request; 536 *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE); 537 *bp++ = htonl(vnode->fid.vid); 538 *bp++ = htonl(vnode->fid.vnode); 539 *bp++ = htonl(vnode->fid.unique); 540 *bp++ = htonl(namesz); 541 memcpy(bp, name, namesz); 542 bp = (void *) bp + namesz; 543 if (padsz > 0) { 544 memset(bp, 0, padsz); 545 bp = (void *) bp + padsz; 546 } 547 *bp++ = htonl(AFS_SET_MODE); 548 *bp++ = 0; /* mtime */ 549 *bp++ = 0; /* owner */ 550 *bp++ = 0; /* group */ 551 *bp++ = htonl(mode & S_IALLUGO); /* unix mode */ 552 *bp++ = 0; /* segment size */ 553 554 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); 555 } 556 557 /* 558 * deliver reply data to an FS.RemoveFile or FS.RemoveDir 559 */ 560 static int afs_deliver_fs_remove(struct afs_call *call, 561 struct sk_buff *skb, bool last) 562 { 563 struct afs_vnode *vnode = call->reply; 564 const __be32 *bp; 565 566 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); 567 568 afs_transfer_reply(call, skb); 569 if (!last) 570 return 0; 571 572 if (call->reply_size != call->reply_max) 573 return -EBADMSG; 574 575 /* unmarshall the reply once we've received all of it */ 576 bp = call->buffer; 577 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); 578 /* xdr_decode_AFSVolSync(&bp, call->replyX); */ 579 580 _leave(" = 0 [done]"); 581 return 0; 582 } 583 584 /* 585 * FS.RemoveDir/FS.RemoveFile operation type 586 */ 587 static const struct afs_call_type afs_RXFSRemoveXXXX = { 588 .name = "FS.RemoveXXXX", 589 .deliver = afs_deliver_fs_remove, 590 .abort_to_error = afs_abort_to_error, 591 .destructor = afs_flat_call_destructor, 592 }; 593 594 /* 595 * remove a file or directory 596 */ 597 int afs_fs_remove(struct afs_server *server, 598 struct key *key, 599 struct afs_vnode *vnode, 600 const char *name, 601 bool isdir, 602 const struct afs_wait_mode *wait_mode) 603 { 604 struct afs_call *call; 605 size_t namesz, reqsz, padsz; 606 __be32 *bp; 607 608 _enter(""); 609 610 namesz = strlen(name); 611 padsz = (4 - (namesz & 3)) & 3; 612 reqsz = (5 * 4) + namesz + padsz; 613 614 call = afs_alloc_flat_call(&afs_RXFSRemoveXXXX, reqsz, (21 + 6) * 4); 615 if (!call) 616 return -ENOMEM; 617 618 call->key = key; 619 call->reply = vnode; 620 call->service_id = FS_SERVICE; 621 call->port = htons(AFS_FS_PORT); 622 623 /* marshall the parameters */ 624 bp = call->request; 625 *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE); 626 *bp++ = htonl(vnode->fid.vid); 627 *bp++ = htonl(vnode->fid.vnode); 628 *bp++ = htonl(vnode->fid.unique); 629 *bp++ = htonl(namesz); 630 memcpy(bp, name, namesz); 631 bp = (void *) bp + namesz; 632 if (padsz > 0) { 633 memset(bp, 0, padsz); 634 bp = (void *) bp + padsz; 635 } 636 637 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); 638 } 639 640 /* 641 * deliver reply data to an FS.Link 642 */ 643 static int afs_deliver_fs_link(struct afs_call *call, 644 struct sk_buff *skb, bool last) 645 { 646 struct afs_vnode *dvnode = call->reply, *vnode = call->reply2; 647 const __be32 *bp; 648 649 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); 650 651 afs_transfer_reply(call, skb); 652 if (!last) 653 return 0; 654 655 if (call->reply_size != call->reply_max) 656 return -EBADMSG; 657 658 /* unmarshall the reply once we've received all of it */ 659 bp = call->buffer; 660 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); 661 xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode); 662 /* xdr_decode_AFSVolSync(&bp, call->replyX); */ 663 664 _leave(" = 0 [done]"); 665 return 0; 666 } 667 668 /* 669 * FS.Link operation type 670 */ 671 static const struct afs_call_type afs_RXFSLink = { 672 .name = "FS.Link", 673 .deliver = afs_deliver_fs_link, 674 .abort_to_error = afs_abort_to_error, 675 .destructor = afs_flat_call_destructor, 676 }; 677 678 /* 679 * make a hard link 680 */ 681 int afs_fs_link(struct afs_server *server, 682 struct key *key, 683 struct afs_vnode *dvnode, 684 struct afs_vnode *vnode, 685 const char *name, 686 const struct afs_wait_mode *wait_mode) 687 { 688 struct afs_call *call; 689 size_t namesz, reqsz, padsz; 690 __be32 *bp; 691 692 _enter(""); 693 694 namesz = strlen(name); 695 padsz = (4 - (namesz & 3)) & 3; 696 reqsz = (5 * 4) + namesz + padsz + (3 * 4); 697 698 call = afs_alloc_flat_call(&afs_RXFSLink, reqsz, (21 + 21 + 6) * 4); 699 if (!call) 700 return -ENOMEM; 701 702 call->key = key; 703 call->reply = dvnode; 704 call->reply2 = vnode; 705 call->service_id = FS_SERVICE; 706 call->port = htons(AFS_FS_PORT); 707 708 /* marshall the parameters */ 709 bp = call->request; 710 *bp++ = htonl(FSLINK); 711 *bp++ = htonl(dvnode->fid.vid); 712 *bp++ = htonl(dvnode->fid.vnode); 713 *bp++ = htonl(dvnode->fid.unique); 714 *bp++ = htonl(namesz); 715 memcpy(bp, name, namesz); 716 bp = (void *) bp + namesz; 717 if (padsz > 0) { 718 memset(bp, 0, padsz); 719 bp = (void *) bp + padsz; 720 } 721 *bp++ = htonl(vnode->fid.vid); 722 *bp++ = htonl(vnode->fid.vnode); 723 *bp++ = htonl(vnode->fid.unique); 724 725 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); 726 } 727 728 /* 729 * deliver reply data to an FS.Symlink 730 */ 731 static int afs_deliver_fs_symlink(struct afs_call *call, 732 struct sk_buff *skb, bool last) 733 { 734 struct afs_vnode *vnode = call->reply; 735 const __be32 *bp; 736 737 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); 738 739 afs_transfer_reply(call, skb); 740 if (!last) 741 return 0; 742 743 if (call->reply_size != call->reply_max) 744 return -EBADMSG; 745 746 /* unmarshall the reply once we've received all of it */ 747 bp = call->buffer; 748 xdr_decode_AFSFid(&bp, call->reply2); 749 xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL); 750 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); 751 /* xdr_decode_AFSVolSync(&bp, call->replyX); */ 752 753 _leave(" = 0 [done]"); 754 return 0; 755 } 756 757 /* 758 * FS.Symlink operation type 759 */ 760 static const struct afs_call_type afs_RXFSSymlink = { 761 .name = "FS.Symlink", 762 .deliver = afs_deliver_fs_symlink, 763 .abort_to_error = afs_abort_to_error, 764 .destructor = afs_flat_call_destructor, 765 }; 766 767 /* 768 * create a symbolic link 769 */ 770 int afs_fs_symlink(struct afs_server *server, 771 struct key *key, 772 struct afs_vnode *vnode, 773 const char *name, 774 const char *contents, 775 struct afs_fid *newfid, 776 struct afs_file_status *newstatus, 777 const struct afs_wait_mode *wait_mode) 778 { 779 struct afs_call *call; 780 size_t namesz, reqsz, padsz, c_namesz, c_padsz; 781 __be32 *bp; 782 783 _enter(""); 784 785 namesz = strlen(name); 786 padsz = (4 - (namesz & 3)) & 3; 787 788 c_namesz = strlen(contents); 789 c_padsz = (4 - (c_namesz & 3)) & 3; 790 791 reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4); 792 793 call = afs_alloc_flat_call(&afs_RXFSSymlink, reqsz, 794 (3 + 21 + 21 + 6) * 4); 795 if (!call) 796 return -ENOMEM; 797 798 call->key = key; 799 call->reply = vnode; 800 call->reply2 = newfid; 801 call->reply3 = newstatus; 802 call->service_id = FS_SERVICE; 803 call->port = htons(AFS_FS_PORT); 804 805 /* marshall the parameters */ 806 bp = call->request; 807 *bp++ = htonl(FSSYMLINK); 808 *bp++ = htonl(vnode->fid.vid); 809 *bp++ = htonl(vnode->fid.vnode); 810 *bp++ = htonl(vnode->fid.unique); 811 *bp++ = htonl(namesz); 812 memcpy(bp, name, namesz); 813 bp = (void *) bp + namesz; 814 if (padsz > 0) { 815 memset(bp, 0, padsz); 816 bp = (void *) bp + padsz; 817 } 818 *bp++ = htonl(c_namesz); 819 memcpy(bp, contents, c_namesz); 820 bp = (void *) bp + c_namesz; 821 if (c_padsz > 0) { 822 memset(bp, 0, c_padsz); 823 bp = (void *) bp + c_padsz; 824 } 825 *bp++ = htonl(AFS_SET_MODE); 826 *bp++ = 0; /* mtime */ 827 *bp++ = 0; /* owner */ 828 *bp++ = 0; /* group */ 829 *bp++ = htonl(S_IRWXUGO); /* unix mode */ 830 *bp++ = 0; /* segment size */ 831 832 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); 833 } 834 835 /* 836 * deliver reply data to an FS.Rename 837 */ 838 static int afs_deliver_fs_rename(struct afs_call *call, 839 struct sk_buff *skb, bool last) 840 { 841 struct afs_vnode *orig_dvnode = call->reply, *new_dvnode = call->reply2; 842 const __be32 *bp; 843 844 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); 845 846 afs_transfer_reply(call, skb); 847 if (!last) 848 return 0; 849 850 if (call->reply_size != call->reply_max) 851 return -EBADMSG; 852 853 /* unmarshall the reply once we've received all of it */ 854 bp = call->buffer; 855 xdr_decode_AFSFetchStatus(&bp, &orig_dvnode->status, orig_dvnode); 856 if (new_dvnode != orig_dvnode) 857 xdr_decode_AFSFetchStatus(&bp, &new_dvnode->status, new_dvnode); 858 /* xdr_decode_AFSVolSync(&bp, call->replyX); */ 859 860 _leave(" = 0 [done]"); 861 return 0; 862 } 863 864 /* 865 * FS.Rename operation type 866 */ 867 static const struct afs_call_type afs_RXFSRename = { 868 .name = "FS.Rename", 869 .deliver = afs_deliver_fs_rename, 870 .abort_to_error = afs_abort_to_error, 871 .destructor = afs_flat_call_destructor, 872 }; 873 874 /* 875 * create a symbolic link 876 */ 877 int afs_fs_rename(struct afs_server *server, 878 struct key *key, 879 struct afs_vnode *orig_dvnode, 880 const char *orig_name, 881 struct afs_vnode *new_dvnode, 882 const char *new_name, 883 const struct afs_wait_mode *wait_mode) 884 { 885 struct afs_call *call; 886 size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz; 887 __be32 *bp; 888 889 _enter(""); 890 891 o_namesz = strlen(orig_name); 892 o_padsz = (4 - (o_namesz & 3)) & 3; 893 894 n_namesz = strlen(new_name); 895 n_padsz = (4 - (n_namesz & 3)) & 3; 896 897 reqsz = (4 * 4) + 898 4 + o_namesz + o_padsz + 899 (3 * 4) + 900 4 + n_namesz + n_padsz; 901 902 call = afs_alloc_flat_call(&afs_RXFSRename, reqsz, (21 + 21 + 6) * 4); 903 if (!call) 904 return -ENOMEM; 905 906 call->key = key; 907 call->reply = orig_dvnode; 908 call->reply2 = new_dvnode; 909 call->service_id = FS_SERVICE; 910 call->port = htons(AFS_FS_PORT); 911 912 /* marshall the parameters */ 913 bp = call->request; 914 *bp++ = htonl(FSRENAME); 915 *bp++ = htonl(orig_dvnode->fid.vid); 916 *bp++ = htonl(orig_dvnode->fid.vnode); 917 *bp++ = htonl(orig_dvnode->fid.unique); 918 *bp++ = htonl(o_namesz); 919 memcpy(bp, orig_name, o_namesz); 920 bp = (void *) bp + o_namesz; 921 if (o_padsz > 0) { 922 memset(bp, 0, o_padsz); 923 bp = (void *) bp + o_padsz; 924 } 925 926 *bp++ = htonl(new_dvnode->fid.vid); 927 *bp++ = htonl(new_dvnode->fid.vnode); 928 *bp++ = htonl(new_dvnode->fid.unique); 929 *bp++ = htonl(n_namesz); 930 memcpy(bp, new_name, n_namesz); 931 bp = (void *) bp + n_namesz; 932 if (n_padsz > 0) { 933 memset(bp, 0, n_padsz); 934 bp = (void *) bp + n_padsz; 935 } 936 937 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); 938 } 939