| .. | .. |
|---|
| 33 | 33 | #include <linux/vfs.h> |
|---|
| 34 | 34 | |
|---|
| 35 | 35 | #include <linux/coda.h> |
|---|
| 36 | | -#include <linux/coda_psdev.h> |
|---|
| 36 | +#include "coda_psdev.h" |
|---|
| 37 | 37 | #include "coda_linux.h" |
|---|
| 38 | 38 | #include "coda_cache.h" |
|---|
| 39 | 39 | |
|---|
| .. | .. |
|---|
| 46 | 46 | { |
|---|
| 47 | 47 | union inputArgs *inp; |
|---|
| 48 | 48 | |
|---|
| 49 | | - CODA_ALLOC(inp, union inputArgs *, size); |
|---|
| 49 | + inp = kvzalloc(size, GFP_KERNEL); |
|---|
| 50 | 50 | if (!inp) |
|---|
| 51 | 51 | return ERR_PTR(-ENOMEM); |
|---|
| 52 | 52 | |
|---|
| .. | .. |
|---|
| 85 | 85 | if (!error) |
|---|
| 86 | 86 | *fidp = outp->coda_root.VFid; |
|---|
| 87 | 87 | |
|---|
| 88 | | - CODA_FREE(inp, insize); |
|---|
| 88 | + kvfree(inp); |
|---|
| 89 | 89 | return error; |
|---|
| 90 | 90 | } |
|---|
| 91 | 91 | |
|---|
| .. | .. |
|---|
| 104 | 104 | if (!error) |
|---|
| 105 | 105 | *attr = outp->coda_getattr.attr; |
|---|
| 106 | 106 | |
|---|
| 107 | | - CODA_FREE(inp, insize); |
|---|
| 107 | + kvfree(inp); |
|---|
| 108 | 108 | return error; |
|---|
| 109 | 109 | } |
|---|
| 110 | 110 | |
|---|
| .. | .. |
|---|
| 123 | 123 | |
|---|
| 124 | 124 | error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); |
|---|
| 125 | 125 | |
|---|
| 126 | | - CODA_FREE(inp, insize); |
|---|
| 126 | + kvfree(inp); |
|---|
| 127 | 127 | return error; |
|---|
| 128 | 128 | } |
|---|
| 129 | 129 | |
|---|
| .. | .. |
|---|
| 153 | 153 | *type = outp->coda_lookup.vtype; |
|---|
| 154 | 154 | } |
|---|
| 155 | 155 | |
|---|
| 156 | | - CODA_FREE(inp, insize); |
|---|
| 156 | + kvfree(inp); |
|---|
| 157 | 157 | return error; |
|---|
| 158 | 158 | } |
|---|
| 159 | 159 | |
|---|
| .. | .. |
|---|
| 173 | 173 | |
|---|
| 174 | 174 | error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); |
|---|
| 175 | 175 | |
|---|
| 176 | | - CODA_FREE(inp, insize); |
|---|
| 176 | + kvfree(inp); |
|---|
| 177 | 177 | return error; |
|---|
| 178 | 178 | } |
|---|
| 179 | 179 | |
|---|
| .. | .. |
|---|
| 194 | 194 | if (!error) |
|---|
| 195 | 195 | *fh = outp->coda_open_by_fd.fh; |
|---|
| 196 | 196 | |
|---|
| 197 | | - CODA_FREE(inp, insize); |
|---|
| 197 | + kvfree(inp); |
|---|
| 198 | 198 | return error; |
|---|
| 199 | 199 | } |
|---|
| 200 | 200 | |
|---|
| .. | .. |
|---|
| 224 | 224 | *newfid = outp->coda_mkdir.VFid; |
|---|
| 225 | 225 | } |
|---|
| 226 | 226 | |
|---|
| 227 | | - CODA_FREE(inp, insize); |
|---|
| 227 | + kvfree(inp); |
|---|
| 228 | 228 | return error; |
|---|
| 229 | 229 | } |
|---|
| 230 | 230 | |
|---|
| .. | .. |
|---|
| 262 | 262 | |
|---|
| 263 | 263 | error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); |
|---|
| 264 | 264 | |
|---|
| 265 | | - CODA_FREE(inp, insize); |
|---|
| 265 | + kvfree(inp); |
|---|
| 266 | 266 | return error; |
|---|
| 267 | 267 | } |
|---|
| 268 | 268 | |
|---|
| .. | .. |
|---|
| 295 | 295 | *newfid = outp->coda_create.VFid; |
|---|
| 296 | 296 | } |
|---|
| 297 | 297 | |
|---|
| 298 | | - CODA_FREE(inp, insize); |
|---|
| 298 | + kvfree(inp); |
|---|
| 299 | 299 | return error; |
|---|
| 300 | 300 | } |
|---|
| 301 | 301 | |
|---|
| .. | .. |
|---|
| 318 | 318 | |
|---|
| 319 | 319 | error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); |
|---|
| 320 | 320 | |
|---|
| 321 | | - CODA_FREE(inp, insize); |
|---|
| 321 | + kvfree(inp); |
|---|
| 322 | 322 | return error; |
|---|
| 323 | 323 | } |
|---|
| 324 | 324 | |
|---|
| .. | .. |
|---|
| 340 | 340 | |
|---|
| 341 | 341 | error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); |
|---|
| 342 | 342 | |
|---|
| 343 | | - CODA_FREE(inp, insize); |
|---|
| 343 | + kvfree(inp); |
|---|
| 344 | 344 | return error; |
|---|
| 345 | 345 | } |
|---|
| 346 | 346 | |
|---|
| .. | .. |
|---|
| 370 | 370 | *(buffer + retlen) = '\0'; |
|---|
| 371 | 371 | } |
|---|
| 372 | 372 | |
|---|
| 373 | | - CODA_FREE(inp, insize); |
|---|
| 373 | + kvfree(inp); |
|---|
| 374 | 374 | return error; |
|---|
| 375 | 375 | } |
|---|
| 376 | 376 | |
|---|
| .. | .. |
|---|
| 398 | 398 | |
|---|
| 399 | 399 | error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); |
|---|
| 400 | 400 | |
|---|
| 401 | | - CODA_FREE(inp, insize); |
|---|
| 401 | + kvfree(inp); |
|---|
| 402 | 402 | return error; |
|---|
| 403 | 403 | } |
|---|
| 404 | 404 | |
|---|
| .. | .. |
|---|
| 433 | 433 | |
|---|
| 434 | 434 | error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); |
|---|
| 435 | 435 | |
|---|
| 436 | | - CODA_FREE(inp, insize); |
|---|
| 436 | + kvfree(inp); |
|---|
| 437 | 437 | return error; |
|---|
| 438 | 438 | } |
|---|
| 439 | 439 | |
|---|
| .. | .. |
|---|
| 449 | 449 | inp->coda_fsync.VFid = *fid; |
|---|
| 450 | 450 | error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); |
|---|
| 451 | 451 | |
|---|
| 452 | | - CODA_FREE(inp, insize); |
|---|
| 452 | + kvfree(inp); |
|---|
| 453 | 453 | return error; |
|---|
| 454 | 454 | } |
|---|
| 455 | 455 | |
|---|
| .. | .. |
|---|
| 467 | 467 | |
|---|
| 468 | 468 | error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); |
|---|
| 469 | 469 | |
|---|
| 470 | | - CODA_FREE(inp, insize); |
|---|
| 470 | + kvfree(inp); |
|---|
| 471 | 471 | return error; |
|---|
| 472 | 472 | } |
|---|
| 473 | 473 | |
|---|
| .. | .. |
|---|
| 543 | 543 | } |
|---|
| 544 | 544 | |
|---|
| 545 | 545 | exit: |
|---|
| 546 | | - CODA_FREE(inp, insize); |
|---|
| 546 | + kvfree(inp); |
|---|
| 547 | 547 | return error; |
|---|
| 548 | 548 | } |
|---|
| 549 | 549 | |
|---|
| .. | .. |
|---|
| 553 | 553 | union outputArgs *outp; |
|---|
| 554 | 554 | int insize, outsize, error; |
|---|
| 555 | 555 | |
|---|
| 556 | | - insize = max_t(unsigned int, INSIZE(statfs), OUTSIZE(statfs)); |
|---|
| 556 | + insize = SIZE(statfs); |
|---|
| 557 | 557 | UPARG(CODA_STATFS); |
|---|
| 558 | 558 | |
|---|
| 559 | 559 | error = coda_upcall(coda_vcp(dentry->d_sb), insize, &outsize, inp); |
|---|
| .. | .. |
|---|
| 565 | 565 | sfs->f_ffree = outp->coda_statfs.stat.f_ffree; |
|---|
| 566 | 566 | } |
|---|
| 567 | 567 | |
|---|
| 568 | | - CODA_FREE(inp, insize); |
|---|
| 568 | + kvfree(inp); |
|---|
| 569 | 569 | return error; |
|---|
| 570 | +} |
|---|
| 571 | + |
|---|
| 572 | +int venus_access_intent(struct super_block *sb, struct CodaFid *fid, |
|---|
| 573 | + bool *access_intent_supported, |
|---|
| 574 | + size_t count, loff_t ppos, int type) |
|---|
| 575 | +{ |
|---|
| 576 | + union inputArgs *inp; |
|---|
| 577 | + union outputArgs *outp; |
|---|
| 578 | + int insize, outsize, error; |
|---|
| 579 | + bool finalizer = |
|---|
| 580 | + type == CODA_ACCESS_TYPE_READ_FINISH || |
|---|
| 581 | + type == CODA_ACCESS_TYPE_WRITE_FINISH; |
|---|
| 582 | + |
|---|
| 583 | + if (!*access_intent_supported && !finalizer) |
|---|
| 584 | + return 0; |
|---|
| 585 | + |
|---|
| 586 | + insize = SIZE(access_intent); |
|---|
| 587 | + UPARG(CODA_ACCESS_INTENT); |
|---|
| 588 | + |
|---|
| 589 | + inp->coda_access_intent.VFid = *fid; |
|---|
| 590 | + inp->coda_access_intent.count = count; |
|---|
| 591 | + inp->coda_access_intent.pos = ppos; |
|---|
| 592 | + inp->coda_access_intent.type = type; |
|---|
| 593 | + |
|---|
| 594 | + error = coda_upcall(coda_vcp(sb), insize, |
|---|
| 595 | + finalizer ? NULL : &outsize, inp); |
|---|
| 596 | + |
|---|
| 597 | + /* |
|---|
| 598 | + * we have to free the request buffer for synchronous upcalls |
|---|
| 599 | + * or when asynchronous upcalls fail, but not when asynchronous |
|---|
| 600 | + * upcalls succeed |
|---|
| 601 | + */ |
|---|
| 602 | + if (!finalizer || error) |
|---|
| 603 | + kvfree(inp); |
|---|
| 604 | + |
|---|
| 605 | + /* Chunked access is not supported or an old Coda client */ |
|---|
| 606 | + if (error == -EOPNOTSUPP) { |
|---|
| 607 | + *access_intent_supported = false; |
|---|
| 608 | + error = 0; |
|---|
| 609 | + } |
|---|
| 610 | + return error; |
|---|
| 570 | 611 | } |
|---|
| 571 | 612 | |
|---|
| 572 | 613 | /* |
|---|
| .. | .. |
|---|
| 598 | 639 | * has seen them, |
|---|
| 599 | 640 | * - CODA_CLOSE or CODA_RELEASE upcall (to avoid reference count problems) |
|---|
| 600 | 641 | * - CODA_STORE (to avoid data loss) |
|---|
| 642 | + * - CODA_ACCESS_INTENT (to avoid reference count problems) |
|---|
| 601 | 643 | */ |
|---|
| 602 | 644 | #define CODA_INTERRUPTIBLE(r) (!coda_hard && \ |
|---|
| 603 | 645 | (((r)->uc_opcode != CODA_CLOSE && \ |
|---|
| 604 | 646 | (r)->uc_opcode != CODA_STORE && \ |
|---|
| 647 | + (r)->uc_opcode != CODA_ACCESS_INTENT && \ |
|---|
| 605 | 648 | (r)->uc_opcode != CODA_RELEASE) || \ |
|---|
| 606 | 649 | (r)->uc_flags & CODA_REQ_READ)) |
|---|
| 607 | 650 | |
|---|
| .. | .. |
|---|
| 687 | 730 | goto exit; |
|---|
| 688 | 731 | } |
|---|
| 689 | 732 | |
|---|
| 690 | | - req->uc_data = (void *)buffer; |
|---|
| 691 | | - req->uc_flags = 0; |
|---|
| 692 | | - req->uc_inSize = inSize; |
|---|
| 693 | | - req->uc_outSize = *outSize ? *outSize : inSize; |
|---|
| 694 | | - req->uc_opcode = ((union inputArgs *)buffer)->ih.opcode; |
|---|
| 695 | | - req->uc_unique = ++vcp->vc_seq; |
|---|
| 696 | | - init_waitqueue_head(&req->uc_sleep); |
|---|
| 733 | + buffer->ih.unique = ++vcp->vc_seq; |
|---|
| 697 | 734 | |
|---|
| 698 | | - /* Fill in the common input args. */ |
|---|
| 699 | | - ((union inputArgs *)buffer)->ih.unique = req->uc_unique; |
|---|
| 735 | + req->uc_data = (void *)buffer; |
|---|
| 736 | + req->uc_flags = outSize ? 0 : CODA_REQ_ASYNC; |
|---|
| 737 | + req->uc_inSize = inSize; |
|---|
| 738 | + req->uc_outSize = (outSize && *outSize) ? *outSize : inSize; |
|---|
| 739 | + req->uc_opcode = buffer->ih.opcode; |
|---|
| 740 | + req->uc_unique = buffer->ih.unique; |
|---|
| 741 | + init_waitqueue_head(&req->uc_sleep); |
|---|
| 700 | 742 | |
|---|
| 701 | 743 | /* Append msg to pending queue and poke Venus. */ |
|---|
| 702 | 744 | list_add_tail(&req->uc_chain, &vcp->vc_pending); |
|---|
| 703 | | - |
|---|
| 704 | 745 | wake_up_interruptible(&vcp->vc_waitq); |
|---|
| 746 | + |
|---|
| 747 | + if (req->uc_flags & CODA_REQ_ASYNC) { |
|---|
| 748 | + mutex_unlock(&vcp->vc_mutex); |
|---|
| 749 | + return 0; |
|---|
| 750 | + } |
|---|
| 751 | + |
|---|
| 705 | 752 | /* We can be interrupted while we wait for Venus to process |
|---|
| 706 | 753 | * our request. If the interrupt occurs before Venus has read |
|---|
| 707 | 754 | * the request, we dequeue and return. If it occurs after the |
|---|
| .. | .. |
|---|
| 743 | 790 | sig_req = kmalloc(sizeof(struct upc_req), GFP_KERNEL); |
|---|
| 744 | 791 | if (!sig_req) goto exit; |
|---|
| 745 | 792 | |
|---|
| 746 | | - CODA_ALLOC((sig_req->uc_data), char *, sizeof(struct coda_in_hdr)); |
|---|
| 747 | | - if (!sig_req->uc_data) { |
|---|
| 793 | + sig_inputArgs = kvzalloc(sizeof(struct coda_in_hdr), GFP_KERNEL); |
|---|
| 794 | + if (!sig_inputArgs) { |
|---|
| 748 | 795 | kfree(sig_req); |
|---|
| 749 | 796 | goto exit; |
|---|
| 750 | 797 | } |
|---|
| 751 | 798 | |
|---|
| 752 | 799 | error = -EINTR; |
|---|
| 753 | | - sig_inputArgs = (union inputArgs *)sig_req->uc_data; |
|---|
| 754 | 800 | sig_inputArgs->ih.opcode = CODA_SIGNAL; |
|---|
| 755 | 801 | sig_inputArgs->ih.unique = req->uc_unique; |
|---|
| 756 | 802 | |
|---|
| 757 | 803 | sig_req->uc_flags = CODA_REQ_ASYNC; |
|---|
| 758 | 804 | sig_req->uc_opcode = sig_inputArgs->ih.opcode; |
|---|
| 759 | 805 | sig_req->uc_unique = sig_inputArgs->ih.unique; |
|---|
| 806 | + sig_req->uc_data = (void *)sig_inputArgs; |
|---|
| 760 | 807 | sig_req->uc_inSize = sizeof(struct coda_in_hdr); |
|---|
| 761 | 808 | sig_req->uc_outSize = sizeof(struct coda_in_hdr); |
|---|
| 762 | 809 | |
|---|
| .. | .. |
|---|
| 804 | 851 | * |
|---|
| 805 | 852 | * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */ |
|---|
| 806 | 853 | |
|---|
| 807 | | -int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out) |
|---|
| 854 | +int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out, |
|---|
| 855 | + size_t nbytes) |
|---|
| 808 | 856 | { |
|---|
| 809 | 857 | struct inode *inode = NULL; |
|---|
| 810 | 858 | struct CodaFid *fid = NULL, *newfid; |
|---|
| 811 | 859 | struct super_block *sb; |
|---|
| 860 | + |
|---|
| 861 | + /* |
|---|
| 862 | + * Make sure we have received enough data from the cache |
|---|
| 863 | + * manager to populate the necessary fields in the buffer |
|---|
| 864 | + */ |
|---|
| 865 | + switch (opcode) { |
|---|
| 866 | + case CODA_PURGEUSER: |
|---|
| 867 | + if (nbytes < sizeof(struct coda_purgeuser_out)) |
|---|
| 868 | + return -EINVAL; |
|---|
| 869 | + break; |
|---|
| 870 | + |
|---|
| 871 | + case CODA_ZAPDIR: |
|---|
| 872 | + if (nbytes < sizeof(struct coda_zapdir_out)) |
|---|
| 873 | + return -EINVAL; |
|---|
| 874 | + break; |
|---|
| 875 | + |
|---|
| 876 | + case CODA_ZAPFILE: |
|---|
| 877 | + if (nbytes < sizeof(struct coda_zapfile_out)) |
|---|
| 878 | + return -EINVAL; |
|---|
| 879 | + break; |
|---|
| 880 | + |
|---|
| 881 | + case CODA_PURGEFID: |
|---|
| 882 | + if (nbytes < sizeof(struct coda_purgefid_out)) |
|---|
| 883 | + return -EINVAL; |
|---|
| 884 | + break; |
|---|
| 885 | + |
|---|
| 886 | + case CODA_REPLACE: |
|---|
| 887 | + if (nbytes < sizeof(struct coda_replace_out)) |
|---|
| 888 | + return -EINVAL; |
|---|
| 889 | + break; |
|---|
| 890 | + } |
|---|
| 812 | 891 | |
|---|
| 813 | 892 | /* Handle invalidation requests. */ |
|---|
| 814 | 893 | mutex_lock(&vcp->vc_mutex); |
|---|
| .. | .. |
|---|
| 879 | 958 | iput(inode); |
|---|
| 880 | 959 | return 0; |
|---|
| 881 | 960 | } |
|---|
| 882 | | - |
|---|