.. | .. |
---|
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(*sig_inputArgs), 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 | | - |
---|