summaryrefslogtreecommitdiffstats
path: root/fs/coda/upcall.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/coda/upcall.c')
-rw-r--r--fs/coda/upcall.c146
1 files changed, 112 insertions, 34 deletions
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index 1175a1722411..eb3b1898da46 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -33,7 +33,7 @@
33#include <linux/vfs.h> 33#include <linux/vfs.h>
34 34
35#include <linux/coda.h> 35#include <linux/coda.h>
36#include <linux/coda_psdev.h> 36#include "coda_psdev.h"
37#include "coda_linux.h" 37#include "coda_linux.h"
38#include "coda_cache.h" 38#include "coda_cache.h"
39 39
@@ -46,7 +46,7 @@ static void *alloc_upcall(int opcode, int size)
46{ 46{
47 union inputArgs *inp; 47 union inputArgs *inp;
48 48
49 CODA_ALLOC(inp, union inputArgs *, size); 49 inp = kvzalloc(size, GFP_KERNEL);
50 if (!inp) 50 if (!inp)
51 return ERR_PTR(-ENOMEM); 51 return ERR_PTR(-ENOMEM);
52 52
@@ -85,7 +85,7 @@ int venus_rootfid(struct super_block *sb, struct CodaFid *fidp)
85 if (!error) 85 if (!error)
86 *fidp = outp->coda_root.VFid; 86 *fidp = outp->coda_root.VFid;
87 87
88 CODA_FREE(inp, insize); 88 kvfree(inp);
89 return error; 89 return error;
90} 90}
91 91
@@ -104,7 +104,7 @@ int venus_getattr(struct super_block *sb, struct CodaFid *fid,
104 if (!error) 104 if (!error)
105 *attr = outp->coda_getattr.attr; 105 *attr = outp->coda_getattr.attr;
106 106
107 CODA_FREE(inp, insize); 107 kvfree(inp);
108 return error; 108 return error;
109} 109}
110 110
@@ -123,7 +123,7 @@ int venus_setattr(struct super_block *sb, struct CodaFid *fid,
123 123
124 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); 124 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
125 125
126 CODA_FREE(inp, insize); 126 kvfree(inp);
127 return error; 127 return error;
128} 128}
129 129
@@ -153,7 +153,7 @@ int venus_lookup(struct super_block *sb, struct CodaFid *fid,
153 *type = outp->coda_lookup.vtype; 153 *type = outp->coda_lookup.vtype;
154 } 154 }
155 155
156 CODA_FREE(inp, insize); 156 kvfree(inp);
157 return error; 157 return error;
158} 158}
159 159
@@ -173,7 +173,7 @@ int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
173 173
174 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); 174 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
175 175
176 CODA_FREE(inp, insize); 176 kvfree(inp);
177 return error; 177 return error;
178} 178}
179 179
@@ -194,7 +194,7 @@ int venus_open(struct super_block *sb, struct CodaFid *fid,
194 if (!error) 194 if (!error)
195 *fh = outp->coda_open_by_fd.fh; 195 *fh = outp->coda_open_by_fd.fh;
196 196
197 CODA_FREE(inp, insize); 197 kvfree(inp);
198 return error; 198 return error;
199} 199}
200 200
@@ -224,7 +224,7 @@ int venus_mkdir(struct super_block *sb, struct CodaFid *dirfid,
224 *newfid = outp->coda_mkdir.VFid; 224 *newfid = outp->coda_mkdir.VFid;
225 } 225 }
226 226
227 CODA_FREE(inp, insize); 227 kvfree(inp);
228 return error; 228 return error;
229} 229}
230 230
@@ -262,7 +262,7 @@ int venus_rename(struct super_block *sb, struct CodaFid *old_fid,
262 262
263 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); 263 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
264 264
265 CODA_FREE(inp, insize); 265 kvfree(inp);
266 return error; 266 return error;
267} 267}
268 268
@@ -295,7 +295,7 @@ int venus_create(struct super_block *sb, struct CodaFid *dirfid,
295 *newfid = outp->coda_create.VFid; 295 *newfid = outp->coda_create.VFid;
296 } 296 }
297 297
298 CODA_FREE(inp, insize); 298 kvfree(inp);
299 return error; 299 return error;
300} 300}
301 301
@@ -318,7 +318,7 @@ int venus_rmdir(struct super_block *sb, struct CodaFid *dirfid,
318 318
319 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); 319 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
320 320
321 CODA_FREE(inp, insize); 321 kvfree(inp);
322 return error; 322 return error;
323} 323}
324 324
@@ -340,7 +340,7 @@ int venus_remove(struct super_block *sb, struct CodaFid *dirfid,
340 340
341 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); 341 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
342 342
343 CODA_FREE(inp, insize); 343 kvfree(inp);
344 return error; 344 return error;
345} 345}
346 346
@@ -370,7 +370,7 @@ int venus_readlink(struct super_block *sb, struct CodaFid *fid,
370 *(buffer + retlen) = '\0'; 370 *(buffer + retlen) = '\0';
371 } 371 }
372 372
373 CODA_FREE(inp, insize); 373 kvfree(inp);
374 return error; 374 return error;
375} 375}
376 376
@@ -398,7 +398,7 @@ int venus_link(struct super_block *sb, struct CodaFid *fid,
398 398
399 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); 399 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
400 400
401 CODA_FREE(inp, insize); 401 kvfree(inp);
402 return error; 402 return error;
403} 403}
404 404
@@ -433,7 +433,7 @@ int venus_symlink(struct super_block *sb, struct CodaFid *fid,
433 433
434 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); 434 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
435 435
436 CODA_FREE(inp, insize); 436 kvfree(inp);
437 return error; 437 return error;
438} 438}
439 439
@@ -449,7 +449,7 @@ int venus_fsync(struct super_block *sb, struct CodaFid *fid)
449 inp->coda_fsync.VFid = *fid; 449 inp->coda_fsync.VFid = *fid;
450 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); 450 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
451 451
452 CODA_FREE(inp, insize); 452 kvfree(inp);
453 return error; 453 return error;
454} 454}
455 455
@@ -467,7 +467,7 @@ int venus_access(struct super_block *sb, struct CodaFid *fid, int mask)
467 467
468 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); 468 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
469 469
470 CODA_FREE(inp, insize); 470 kvfree(inp);
471 return error; 471 return error;
472} 472}
473 473
@@ -543,7 +543,7 @@ int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
543 } 543 }
544 544
545 exit: 545 exit:
546 CODA_FREE(inp, insize); 546 kvfree(inp);
547 return error; 547 return error;
548} 548}
549 549
@@ -553,7 +553,7 @@ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs)
553 union outputArgs *outp; 553 union outputArgs *outp;
554 int insize, outsize, error; 554 int insize, outsize, error;
555 555
556 insize = max_t(unsigned int, INSIZE(statfs), OUTSIZE(statfs)); 556 insize = SIZE(statfs);
557 UPARG(CODA_STATFS); 557 UPARG(CODA_STATFS);
558 558
559 error = coda_upcall(coda_vcp(dentry->d_sb), insize, &outsize, inp); 559 error = coda_upcall(coda_vcp(dentry->d_sb), insize, &outsize, inp);
@@ -565,10 +565,51 @@ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs)
565 sfs->f_ffree = outp->coda_statfs.stat.f_ffree; 565 sfs->f_ffree = outp->coda_statfs.stat.f_ffree;
566 } 566 }
567 567
568 CODA_FREE(inp, insize); 568 kvfree(inp);
569 return error; 569 return error;
570} 570}
571 571
572int 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;
611}
612
572/* 613/*
573 * coda_upcall and coda_downcall routines. 614 * coda_upcall and coda_downcall routines.
574 */ 615 */
@@ -598,10 +639,12 @@ static void coda_unblock_signals(sigset_t *old)
598 * has seen them, 639 * has seen them,
599 * - CODA_CLOSE or CODA_RELEASE upcall (to avoid reference count problems) 640 * - CODA_CLOSE or CODA_RELEASE upcall (to avoid reference count problems)
600 * - CODA_STORE (to avoid data loss) 641 * - CODA_STORE (to avoid data loss)
642 * - CODA_ACCESS_INTENT (to avoid reference count problems)
601 */ 643 */
602#define CODA_INTERRUPTIBLE(r) (!coda_hard && \ 644#define CODA_INTERRUPTIBLE(r) (!coda_hard && \
603 (((r)->uc_opcode != CODA_CLOSE && \ 645 (((r)->uc_opcode != CODA_CLOSE && \
604 (r)->uc_opcode != CODA_STORE && \ 646 (r)->uc_opcode != CODA_STORE && \
647 (r)->uc_opcode != CODA_ACCESS_INTENT && \
605 (r)->uc_opcode != CODA_RELEASE) || \ 648 (r)->uc_opcode != CODA_RELEASE) || \
606 (r)->uc_flags & CODA_REQ_READ)) 649 (r)->uc_flags & CODA_REQ_READ))
607 650
@@ -687,21 +730,25 @@ static int coda_upcall(struct venus_comm *vcp,
687 goto exit; 730 goto exit;
688 } 731 }
689 732
733 buffer->ih.unique = ++vcp->vc_seq;
734
690 req->uc_data = (void *)buffer; 735 req->uc_data = (void *)buffer;
691 req->uc_flags = 0; 736 req->uc_flags = outSize ? 0 : CODA_REQ_ASYNC;
692 req->uc_inSize = inSize; 737 req->uc_inSize = inSize;
693 req->uc_outSize = *outSize ? *outSize : inSize; 738 req->uc_outSize = (outSize && *outSize) ? *outSize : inSize;
694 req->uc_opcode = ((union inputArgs *)buffer)->ih.opcode; 739 req->uc_opcode = buffer->ih.opcode;
695 req->uc_unique = ++vcp->vc_seq; 740 req->uc_unique = buffer->ih.unique;
696 init_waitqueue_head(&req->uc_sleep); 741 init_waitqueue_head(&req->uc_sleep);
697 742
698 /* Fill in the common input args. */
699 ((union inputArgs *)buffer)->ih.unique = req->uc_unique;
700
701 /* Append msg to pending queue and poke Venus. */ 743 /* Append msg to pending queue and poke Venus. */
702 list_add_tail(&req->uc_chain, &vcp->vc_pending); 744 list_add_tail(&req->uc_chain, &vcp->vc_pending);
703
704 wake_up_interruptible(&vcp->vc_waitq); 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 /* We can be interrupted while we wait for Venus to process 752 /* We can be interrupted while we wait for Venus to process
706 * our request. If the interrupt occurs before Venus has read 753 * our request. If the interrupt occurs before Venus has read
707 * the request, we dequeue and return. If it occurs after the 754 * the request, we dequeue and return. If it occurs after the
@@ -743,20 +790,20 @@ static int coda_upcall(struct venus_comm *vcp,
743 sig_req = kmalloc(sizeof(struct upc_req), GFP_KERNEL); 790 sig_req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
744 if (!sig_req) goto exit; 791 if (!sig_req) goto exit;
745 792
746 CODA_ALLOC((sig_req->uc_data), char *, sizeof(struct coda_in_hdr)); 793 sig_inputArgs = kvzalloc(sizeof(struct coda_in_hdr), GFP_KERNEL);
747 if (!sig_req->uc_data) { 794 if (!sig_inputArgs) {
748 kfree(sig_req); 795 kfree(sig_req);
749 goto exit; 796 goto exit;
750 } 797 }
751 798
752 error = -EINTR; 799 error = -EINTR;
753 sig_inputArgs = (union inputArgs *)sig_req->uc_data;
754 sig_inputArgs->ih.opcode = CODA_SIGNAL; 800 sig_inputArgs->ih.opcode = CODA_SIGNAL;
755 sig_inputArgs->ih.unique = req->uc_unique; 801 sig_inputArgs->ih.unique = req->uc_unique;
756 802
757 sig_req->uc_flags = CODA_REQ_ASYNC; 803 sig_req->uc_flags = CODA_REQ_ASYNC;
758 sig_req->uc_opcode = sig_inputArgs->ih.opcode; 804 sig_req->uc_opcode = sig_inputArgs->ih.opcode;
759 sig_req->uc_unique = sig_inputArgs->ih.unique; 805 sig_req->uc_unique = sig_inputArgs->ih.unique;
806 sig_req->uc_data = (void *)sig_inputArgs;
760 sig_req->uc_inSize = sizeof(struct coda_in_hdr); 807 sig_req->uc_inSize = sizeof(struct coda_in_hdr);
761 sig_req->uc_outSize = sizeof(struct coda_in_hdr); 808 sig_req->uc_outSize = sizeof(struct coda_in_hdr);
762 809
@@ -804,12 +851,44 @@ exit:
804 * 851 *
805 * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */ 852 * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */
806 853
807int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out) 854int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out,
855 size_t nbytes)
808{ 856{
809 struct inode *inode = NULL; 857 struct inode *inode = NULL;
810 struct CodaFid *fid = NULL, *newfid; 858 struct CodaFid *fid = NULL, *newfid;
811 struct super_block *sb; 859 struct super_block *sb;
812 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 }
891
813 /* Handle invalidation requests. */ 892 /* Handle invalidation requests. */
814 mutex_lock(&vcp->vc_mutex); 893 mutex_lock(&vcp->vc_mutex);
815 sb = vcp->vc_sb; 894 sb = vcp->vc_sb;
@@ -879,4 +958,3 @@ unlock_out:
879 iput(inode); 958 iput(inode);
880 return 0; 959 return 0;
881} 960}
882