patch-2.1.75 linux/fs/coda/upcall.c

Next file: linux/fs/ext2/acl.c
Previous file: linux/fs/coda/sysctl.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.74/linux/fs/coda/upcall.c linux/fs/coda/upcall.c
@@ -35,33 +35,53 @@
 #include <linux/coda_linux.h>
 #include <linux/coda_psdev.h>
 #include <linux/coda_cnode.h>
-#include <linux/coda_namecache.h>
+#include <linux/coda_cache.h>
 
+#define UPARG(op)\
+do {\
+  	CODA_ALLOC(inp, union inputArgs *, insize);\
+	outp = (union outputArgs *) (inp);\
+        inp->ih.opcode = (op);\
+	inp->ih.pid = current->pid;\
+	inp->ih.pgid = current->pgrp;\
+	coda_load_creds(&(inp->ih.cred));\
+        outsize = insize;\
+} while (0)
+
+static inline int max(int a, int b) 
+{
+	if ( a > b )
+		return a; 
+	else
+		return b;
+}
+
+#define INSIZE(tag) sizeof(struct cfs_ ## tag ## _in)
+#define OUTSIZE(tag) sizeof(struct cfs_ ## tag ## _out)
+#define SIZE(tag)  max(INSIZE(tag), OUTSIZE(tag))
 
-static vcsize = (sizeof(struct inputArgs) > sizeof(struct outputArgs)) ?
-		 sizeof(struct inputArgs): sizeof(struct outputArgs);
 
 /* the upcalls */
 int venus_rootfid(struct super_block *sb, ViceFid *fidp)
 {
-        struct inputArgs *inp;
-	struct outputArgs *outp;
-	int error=0;
-	int size;
+        union inputArgs *inp;
+        union outputArgs *outp;
+        int insize, outsize, error;
 ENTRY;
 
-        UPARG(vcsize, CFS_ROOT);
-	error = coda_upcall(coda_sbp(sb), VC_IN_NO_DATA, &size, inp);
+        insize = SIZE(root);
+        UPARG(CFS_ROOT);
+	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 	
 	if (error) {
 	        printk("coda_get_rootfid: error %d\n", error);
 	} else {
-	        *fidp = (ViceFid) outp->d.cfs_root.VFid;
+	        *fidp = (ViceFid) outp->cfs_root.VFid;
 		CDEBUG(D_SUPER, "VolumeId: %lx, VnodeId: %lx.\n",
 		       fidp->Volume, fidp->Vnode);
 	}
 
-	if (inp)  CODA_FREE(inp, VC_IN_NO_DATA);
+	if (inp)  CODA_FREE(inp, insize);
         EXIT;
 	return -error;
 }
@@ -69,19 +89,19 @@
 int venus_getattr(struct super_block *sb, struct ViceFid *fid, 
 		     struct coda_vattr *attr) 
 {
-        struct inputArgs *inp;
-        struct outputArgs *outp;
-        int size, error;
+        union inputArgs *inp;
+        union outputArgs *outp;
+        int insize, outsize, error;
 ENTRY;
-
-	UPARG(vcsize, CFS_GETATTR);
-        inp->d.cfs_getattr.VFid = *fid;
-        error = coda_upcall(coda_sbp(sb), vcsize, &size, inp);
+        insize = SIZE(getattr); 
+	UPARG(CFS_GETATTR);
+        inp->cfs_getattr.VFid = *fid;
+        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 	
 	if ( !error )
-	        *attr = (struct coda_vattr) outp->d.cfs_getattr.attr;
+	        *attr = outp->cfs_getattr.attr;
 
-        if (inp) CODA_FREE(inp, sizeof(struct inputArgs));
+        if (inp) CODA_FREE(inp, insize);
         EXIT;
         return -error;
 }
@@ -89,19 +109,20 @@
 int  venus_setattr(struct super_block *sb, struct ViceFid *fid, 
 		      struct coda_vattr *vattr)
 {
-        struct inputArgs *inp;
-        struct outputArgs *outp;
-        int error, size;
+        union inputArgs *inp;
+        union outputArgs *outp;
+        int insize, outsize, error;
 	
-	UPARG(vcsize, CFS_SETATTR);
+	insize= SIZE(setattr);
+	UPARG(CFS_SETATTR);
 
-        inp->d.cfs_setattr.VFid = *fid;
-	inp->d.cfs_setattr.attr = *vattr;
+        inp->cfs_setattr.VFid = *fid;
+	inp->cfs_setattr.attr = *vattr;
 
-        error = coda_upcall(coda_sbp(sb), vcsize, &size, inp);
+        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
-        CDEBUG(D_SUPER, " result %ld\n", outp->result); 
-        if ( inp ) CODA_FREE(inp, vcsize);
+        CDEBUG(D_SUPER, " result %d\n", error); 
+        if ( inp ) CODA_FREE(inp, insize);
         return -error;
 }
 
@@ -109,26 +130,26 @@
 		    const char *name, int length, int * type, 
 		    struct ViceFid *resfid)
 {
-        struct inputArgs *inp;
-	struct outputArgs *outp;
-	int insize, size, error=0, payload_offset;
-
-        insize =  VC_INSIZE(cfs_lookup_in) + CFS_MAXNAMLEN +1;
-	UPARG(insize, CFS_LOOKUP);
+        union inputArgs *inp;
+        union outputArgs *outp;
+        int insize, outsize, error;
+	int offset;
+
+	offset = INSIZE(lookup);
+        insize =  max(offset + length +1, OUTSIZE(lookup));
+	UPARG(CFS_LOOKUP);
 
-        inp->d.cfs_lookup.VFid = *fid;
+        inp->cfs_lookup.VFid = *fid;
+	inp->cfs_lookup.name = offset;
         /* send Venus a null terminated string */
-        payload_offset = VC_INSIZE(cfs_lookup_in);
-        inp->d.cfs_lookup.name = (char *) payload_offset;
-        memcpy((char *)inp + payload_offset, name, length);
-        *((char *)inp + payload_offset + length) = '\0';
+        memcpy((char *)(inp) + offset, name, length);
+        *((char *)inp + offset + length) = '\0';
 
-        size = payload_offset + length + 1;
-        error = coda_upcall(coda_sbp(sb), size, &size, inp);
+        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
 	if ( !error ) {
-	        *resfid = outp->d.cfs_lookup.VFid;
-		*type = outp->d.cfs_lookup.vtype;
+	        *resfid = outp->cfs_lookup.VFid;
+		*type = outp->cfs_lookup.vtype;
 	}
 	if (inp) CODA_FREE(inp, insize);
 		
@@ -138,53 +159,48 @@
 
 int venus_release(struct super_block *sb, struct ViceFid *fid, int flags)
 {
-        struct inputArgs *inp;
-	struct outputArgs *outp;
-	int size = sizeof(struct outputArgs);
-	int error = 0;
-
-	CODA_ALLOC(inp, struct inputArgs *, sizeof(struct inputArgs));
-        outp = (struct outputArgs *)inp;
-        INIT_IN(inp, CFS_CLOSE);
-        coda_load_creds(&(inp->cred));
+        union inputArgs *inp;
+        union outputArgs *outp;
+        int insize, outsize, error;
+	
+	insize = SIZE(close);
+	UPARG(CFS_CLOSE);
 
-        inp->d.cfs_close.VFid = *fid;
-        inp->d.cfs_close.flags = flags;
+        inp->cfs_close.VFid = *fid;
+        inp->cfs_close.flags = flags;
 
-        error = coda_upcall(coda_sbp(sb), size, &size, inp);
+        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
-        if (inp) CODA_FREE(inp, sizeof(struct inputArgs));
+        if (inp) 
+		CODA_FREE(inp, insize);
         return -error;
 }
 
 int venus_open(struct super_block *sb, struct ViceFid *fid,
 		  int flags, ino_t *ino, dev_t *dev)
 {
-        struct inputArgs *inp = NULL;
-	struct outputArgs *outp = NULL;
-	int size = sizeof(struct inputArgs);
-	int error = 0;
-
-        CODA_ALLOC(inp, struct inputArgs *, sizeof(struct inputArgs));
-        outp = (struct outputArgs *)inp;
-        INIT_IN(inp, CFS_OPEN);
-        coda_load_creds(&(inp->cred));
+        union inputArgs *inp;
+        union outputArgs *outp;
+        int insize, outsize, error;
+       
+	insize = SIZE(open);
+	UPARG(CFS_OPEN);
 
-        inp->d.cfs_open.VFid = *fid;
-        inp->d.cfs_open.flags = flags;
+        inp->cfs_open.VFid = *fid;
+        inp->cfs_open.flags = flags;
 
-        error = coda_upcall(coda_sbp(sb), size, &size, inp);
+        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
 	if ( !error ) {
-	        *ino = outp->d.cfs_open.inode;
-	        *dev = outp->d.cfs_open.dev;
+	        *ino = outp->cfs_open.inode;
+	        *dev = outp->cfs_open.dev;
 	} else {
 	        *ino = 0;
 		*dev = 0;
 	}
 
         if (inp) 
-                CODA_FREE(inp, sizeof(struct inputArgs));
+                CODA_FREE(inp, insize);
 
 	return -error;
 }	
@@ -193,69 +209,69 @@
 		   const char *name, int length, 
 		   struct ViceFid *newfid, struct coda_vattr *attrs)
 {
-        struct inputArgs *inp;
-        struct outputArgs *outp;
-        int error=0, size, payload_offset;
-
-        payload_offset = VC_INSIZE(cfs_mkdir_in);
-	size = CFS_MAXNAMLEN + payload_offset;
-	UPARG(size, CFS_MKDIR);
-
-        inp->d.cfs_mkdir.VFid = *dirfid;
-        inp->d.cfs_mkdir.attr = *attrs;
-        inp->d.cfs_mkdir.name = (char *) payload_offset;
-
+        union inputArgs *inp;
+        union outputArgs *outp;
+        int insize, outsize, error;
+        int offset;
+
+	offset = INSIZE(mkdir);
+	insize = max(offset + length + 1, OUTSIZE(mkdir));
+	UPARG(CFS_MKDIR);
+
+        inp->cfs_mkdir.VFid = *dirfid;
+        inp->cfs_mkdir.attr = *attrs;
+	inp->cfs_mkdir.name = offset;
         /* Venus must get null terminated string */
-        memcpy((char *)inp + payload_offset, name, length);
-        *((char *)inp + payload_offset + length) = '\0';
-        size = payload_offset + length + 1;
+        memcpy((char *)(inp) + offset, name, length);
+        *((char *)inp + offset + length) = '\0';
         
-        error = coda_upcall(coda_sbp(sb), size, &size, inp);
+        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
-	*attrs = outp->d.cfs_mkdir.attr;
-	*newfid = outp->d.cfs_mkdir.VFid;
+	*attrs = outp->cfs_mkdir.attr;
+	*newfid = outp->cfs_mkdir.VFid;
 
 	if (inp) 
-	        CODA_FREE(inp, size);
+	        CODA_FREE(inp, insize);
 	return -error;        
 }
 
 
 int venus_rename(struct super_block *sb, struct ViceFid *old_fid, 
 		 struct ViceFid *new_fid, size_t old_length, 
-		 size_t new_length, const char *old_name, const char *new_name)
+		 size_t new_length, const char *old_name, 
+		 const char *new_name)
 {
-        struct inputArgs *inp;
-        struct outputArgs *outp;
-	int error, offset, size, s;
+	union inputArgs *inp;
+        union outputArgs *outp;
+        int insize, outsize, error; 
+	int offset, s;
 	
-	size = 2*CFS_MAXNAMLEN + VC_INSIZE(cfs_rename_in) +8;
-	UPARG(size, CFS_RENAME);
-
-        inp->d.cfs_rename.sourceFid = *old_fid;
-        inp->d.cfs_rename.destFid =  *new_fid;
-
-        offset = VC_INSIZE(cfs_rename_in);
+	offset = INSIZE(rename);
+	insize = max(offset + new_length + old_length + 8,
+		     OUTSIZE(rename)); 
+ 	UPARG(CFS_RENAME);
+
+        inp->cfs_rename.sourceFid = *old_fid;
+        inp->cfs_rename.destFid =  *new_fid;
+        inp->cfs_rename.srcname = offset;
 
         /* Venus must receive an null terminated string */
-        inp->d.cfs_rename.srcname = (char *)offset;
         s = ( old_length & ~0x3) +4; /* round up to word boundary */
-        memcpy((char *)inp + offset, old_name, old_length);
+        memcpy((char *)(inp) + offset, old_name, old_length);
         *((char *)inp + offset + old_length) = '\0';
 
         /* another null terminated string for Venus */
         offset += s;
-        inp->d.cfs_rename.destname = (char *)offset;
+        inp->cfs_rename.destname = offset;
         s = ( new_length & ~0x3) +4; /* round up to word boundary */
-        memcpy((char *)inp + offset, new_name, new_length);
+        memcpy((char *)(inp) + offset, new_name, new_length);
         *((char *)inp + offset + new_length) = '\0';
 
-        size += s;
         CDEBUG(D_INODE, "destname in packet: %s\n", 
-              (char *)inp + (int) inp->d.cfs_rename.destname);
-        error = coda_upcall(coda_sbp(sb), size, &size, inp);
+              (char *)inp + (int) inp->cfs_rename.destname);
+        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
-	if (inp) CODA_FREE(inp, size);
+	if (inp) CODA_FREE(inp, insize);
 	return -error;
 }
 
@@ -263,131 +279,138 @@
 		    const char *name, int length, int excl, int mode, 
 		    struct ViceFid *newfid, struct coda_vattr *attrs) 
 {
-        struct inputArgs *inp;
-        struct outputArgs *outp;
-        int error=0, size, payload_offset;
-
-        payload_offset = VC_INSIZE(cfs_create_in);
-	size = CFS_MAXNAMLEN + payload_offset;
-	UPARG(size, CFS_CREATE);
-
-        inp->d.cfs_create.VFid = *dirfid;
-        inp->d.cfs_create.attr.va_mode = mode;
-	inp->d.cfs_create.excl = excl;
-        inp->d.cfs_create.mode = mode;
-        inp->d.cfs_create.name = (char *) payload_offset;
+        union inputArgs *inp;
+        union outputArgs *outp;
+        int insize, outsize, error;
+        int offset;
+
+        offset = INSIZE(create);
+	insize = max(offset + length + 1, OUTSIZE(create));
+	UPARG(CFS_CREATE);
+
+        inp->cfs_create.VFid = *dirfid;
+        inp->cfs_create.attr.va_mode = mode;
+	inp->cfs_create.excl = excl;
+        inp->cfs_create.mode = mode;
+        inp->cfs_create.name = offset;
 
         /* Venus must get null terminated string */
-        memcpy((char *)inp + payload_offset, name, length);
-        *((char *)inp + payload_offset + length) = '\0';
-        size = payload_offset + length + 1;
-        
-        error = coda_upcall(coda_sbp(sb), size, &size, inp);
+        memcpy((char *)(inp) + offset, name, length);
+        *((char *)inp + offset + length) = '\0';
+                
+        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
-	*attrs = outp->d.cfs_create.attr;
-	*newfid = outp->d.cfs_create.VFid;
+	*attrs = outp->cfs_create.attr;
+	*newfid = outp->cfs_create.VFid;
 
 	if (inp) 
-	        CODA_FREE(inp, size);
+	        CODA_FREE(inp, insize);
 	return -error;        
 }
 
 int venus_rmdir(struct super_block *sb, struct ViceFid *dirfid, 
 		    const char *name, int length)
 {
-        struct inputArgs *inp;
-        struct outputArgs *outp;
-        int error=0, size, payload_offset;
-
-        payload_offset = VC_INSIZE(cfs_rmdir_in);
-	size = CFS_MAXNAMLEN + payload_offset;
-	UPARG(size, CFS_RMDIR);
-
-        inp->d.cfs_rmdir.VFid = *dirfid;
-        inp->d.cfs_rmdir.name = (char *) payload_offset;
-        memcpy((char *)inp + payload_offset, name, size);
+        union inputArgs *inp;
+        union outputArgs *outp;
+        int insize, outsize, error;
+        int offset;
+
+        offset = INSIZE(rmdir);
+	insize = max(offset + length + 1, OUTSIZE(rmdir));
+	UPARG(CFS_RMDIR);
+
+        inp->cfs_rmdir.VFid = *dirfid;
+        inp->cfs_rmdir.name = offset;
+        memcpy((char *)(inp) + offset, name, length);
+	*((char *)inp + offset + length) = '\0';
         
-        error = coda_upcall(coda_sbp(sb), size, &size, inp);
+        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 	if ( inp ) 
-	        CODA_FREE(inp, size);
+	        CODA_FREE(inp, insize);
 	return -error;
 }
 
 int venus_remove(struct super_block *sb, struct ViceFid *dirfid, 
 		    const char *name, int length)
 {
-        struct inputArgs *inp;
-        struct outputArgs *outp;
-        int error=0, size, payload_offset;
-
-        payload_offset = VC_INSIZE(cfs_remove_in);
-	size = CFS_MAXNAMLEN + payload_offset;
-	UPARG(size, CFS_REMOVE);
-
-        inp->d.cfs_remove.VFid = *dirfid;
-        inp->d.cfs_remove.name = (char *)payload_offset;
-        memcpy((char *)inp + payload_offset, name, size);
+        union inputArgs *inp;
+        union outputArgs *outp;
+        int error=0, insize, outsize, offset;
+
+        offset = INSIZE(remove);
+	insize = max(offset + length + 1, OUTSIZE(remove));
+	UPARG(CFS_REMOVE);
+
+        inp->cfs_remove.VFid = *dirfid;
+        inp->cfs_remove.name = offset;
+        memcpy((char *)(inp) + offset, name, length);
+	*((char *)inp + offset + length) = '\0';
         
-        error = coda_upcall(coda_sbp(sb), size, &size, inp);
+        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 	if ( inp ) 
-	        CODA_FREE(inp, size);
+	        CODA_FREE(inp, insize);
 	return -error;
 }
 
 int venus_readlink(struct super_block *sb, struct ViceFid *fid, 
 		      char *buffer, int *length)
 { 
-        int error, size, retlen;
+        union inputArgs *inp;
+        union outputArgs *outp;
+        int insize, outsize, error;
+        int retlen;
         char *result;
-        struct inputArgs *inp;
-        struct outputArgs *outp;
-        char *buf=NULL; /*[CFS_MAXNAMLEN + VC_INSIZE(cfs_readlink_in)];*/
         
-	size = CFS_MAXPATHLEN + VC_INSIZE(cfs_readlink_in);
-	UPARG(size, CFS_READLINK);
-        inp->d.cfs_readlink.VFid = *fid;
+	insize = max(INSIZE(readlink), OUTSIZE(readlink)+ *length + 1);
+	UPARG(CFS_READLINK);
+
+        inp->cfs_readlink.VFid = *fid;
     
-        error =  coda_upcall(coda_sbp(sb), size, &size, inp);
+        error =  coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 	
 	if (! error) {
-                retlen = outp->d.cfs_readlink.count;
+                retlen = outp->cfs_readlink.count;
 		if ( retlen > *length )
 		        retlen = *length;
 		*length = retlen;
-		result =  (char *)outp + (int)outp->d.cfs_readlink.data;
+		result =  (char *)outp + (int)outp->cfs_readlink.data;
 		memcpy(buffer, result, retlen);
+		*(buffer + retlen) = '\0';
 	}
         
-        if (inp) CODA_FREE(buf, size);
+        if (inp) CODA_FREE(inp, insize);
         CDEBUG(D_INODE, " result %d\n",error);
         EXIT;
         return -error;
 }
 
+
+
 int venus_link(struct super_block *sb, struct ViceFid *fid, 
 		  struct ViceFid *dirfid, const char *name, int len )
 {
-        int error, payload_offset, size;
-        struct inputArgs *inp;
-        struct outputArgs *outp;
-
-	size = CFS_MAXNAMLEN + sizeof(struct inputArgs);
-        UPARG(size, CFS_LINK);
-
-        payload_offset = (VC_INSIZE(cfs_link_in));
-        inp->d.cfs_link.sourceFid = *fid;
-        inp->d.cfs_link.destFid = *dirfid;
-        inp->d.cfs_link.tname = (char *)payload_offset;
+        union inputArgs *inp;
+        union outputArgs *outp;
+        int insize, outsize, error;
+        int offset;
+
+	offset = INSIZE(link);
+	insize = max(offset  + len + 1, OUTSIZE(link));
+        UPARG(CFS_LINK);
+
+        inp->cfs_link.sourceFid = *fid;
+        inp->cfs_link.destFid = *dirfid;
+        inp->cfs_link.tname = offset;
 
         /* make sure strings are null terminated */
-        memcpy((char *)inp + payload_offset, name, len);
-        *((char *)inp + payload_offset + len) = '\0';
-        size = payload_offset + len + 1;
+        memcpy((char *)(inp) + offset, name, len);
+        *((char *)inp + offset + len) = '\0';
         
-        error = coda_upcall(coda_sbp(sb), size, &size, inp);
+        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
         if (inp) 
-	        CODA_FREE(inp, size);
+	        CODA_FREE(inp, insize);
         CDEBUG(D_INODE, " result %d\n",error);
         EXIT;
         return -error;
@@ -397,62 +420,73 @@
 		     const char *name, int len,
 		     const char *symname, int symlen)
 {
-        int error, payload_offset, size, s;
-        struct inputArgs *inp;
-        struct outputArgs *outp;
-        
-
-        /* 
-         * allocate space for regular input, 
-         * plus 1 path and 1 name, plus padding 
-         */        
-	size = sizeof(struct inputArgs) + CFS_MAXNAMLEN + CFS_MAXNAMLEN + 8;
-	UPARG(size, CFS_SYMLINK);
-        
-        /*        inp->d.cfs_symlink.attr = *tva; XXXXXX */ 
-        inp->d.cfs_symlink.VFid = *fid;
-
-        payload_offset = VC_INSIZE(cfs_symlink_in);
-        inp->d.cfs_symlink.srcname =(char*) payload_offset;
-    
-        s = ( symlen  & ~0x3 ) + 4; /* Round up to word boundary. */
-    
-        /* don't forget to copy out the null termination */
-        memcpy((char *)inp + payload_offset, symname, symlen);
-        *((char *)inp + payload_offset + symlen) = '\0';
+        union inputArgs *inp;
+        union outputArgs *outp;
+        int insize, outsize, error;
+        int offset, s;
+
+        offset = INSIZE(symlink);
+	insize = max(offset + len + symlen + 8, OUTSIZE(symlink));
+	UPARG(CFS_SYMLINK);
+        
+        /*        inp->cfs_symlink.attr = *tva; XXXXXX */ 
+        inp->cfs_symlink.VFid = *fid;
+
+	/* Round up to word boundary and null terminate */
+        inp->cfs_symlink.srcname = offset;
+        s = ( symlen  & ~0x3 ) + 4; 
+        memcpy((char *)(inp) + offset, symname, symlen);
+        *((char *)inp + offset + symlen) = '\0';
         
-        payload_offset += s;
-        inp->d.cfs_symlink.tname = (char *) payload_offset;
-        s = (len & ~0x3) + 4;	/* Round up to word boundary. */
-        memcpy((char *)inp + payload_offset, name, len);
-        *((char *)inp + payload_offset + len) = '\0';
+	/* Round up to word boundary and null terminate */
+        offset += s;
+        inp->cfs_symlink.tname = offset;
+        s = (len & ~0x3) + 4;
+        memcpy((char *)(inp) + offset, name, len);
+        *((char *)inp + offset + len) = '\0';
 
-        size = payload_offset + s;
-        error = coda_upcall(coda_sbp(sb), size, &size, inp);
+	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
         if (inp) 
-	        CODA_FREE(inp, size);
+	        CODA_FREE(inp, insize);
         CDEBUG(D_INODE, " result %d\n",error);
         EXIT;
         return -error;
 }
 
+int venus_fsync(struct super_block *sb, struct ViceFid *fid)
+{
+        union inputArgs *inp;
+        union outputArgs *outp;
+        int insize, outsize, error;
+	
+	insize=SIZE(fsync);
+	UPARG(CFS_FSYNC);
+
+        inp->cfs_fsync.VFid = *fid;
+        error = coda_upcall(coda_sbp(sb), sizeof(union inputArgs), 
+                            &outsize, inp);
+
+	if ( inp ) 
+		CODA_FREE(inp, insize);
+	return -error;
+}
+
 int venus_access(struct super_block *sb, struct ViceFid *fid, int mask)
 {
-        struct inputArgs *inp;
-        struct outputArgs *outp;
-        int size;
-        int error;
+        union inputArgs *inp;
+        union outputArgs *outp;
+        int insize, outsize, error;
 
-	size = sizeof(struct inputArgs);
-	UPARG(size, CFS_ACCESS);
+	insize = SIZE(access);
+	UPARG(CFS_ACCESS);
 
-        inp->d.cfs_access.VFid = *fid;
-        inp->d.cfs_access.flags = mask << 6;
+        inp->cfs_access.VFid = *fid;
+        inp->cfs_access.flags = mask;
 
-	error = coda_upcall(coda_sbp(sb), size, &size, inp);
+	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
-	if (inp) CODA_FREE(inp, sizeof(struct inputArgs));
+	if (inp) CODA_FREE(inp, insize);
         EXIT;
 	return -error;
 }
@@ -461,41 +495,46 @@
 int venus_pioctl(struct super_block *sb, struct ViceFid *fid,
 		 unsigned int cmd, struct PioctlData *data)
 {
-        struct inputArgs *inp;
-	struct outputArgs *outp;
-	int size, error = 0;
+        union inputArgs *inp;
+        union outputArgs *outp;
+        int insize, outsize, error;
 	int iocsize;
 	char str[50];
 
-	size = VC_MAXMSGSIZE;
-	UPARG(size, CFS_IOCTL);
+	insize = VC_MAXMSGSIZE;
+	UPARG(CFS_IOCTL);
 
         /* build packet for Venus */
-        if (data->vi.in_size > VC_DATASIZE) {
+        if (data->vi.in_size > VC_MAXDATASIZE) {
 	        error = EINVAL;
 		goto exit;
         }
 
-        inp->d.cfs_ioctl.VFid = *fid;
+        inp->cfs_ioctl.VFid = *fid;
     
         /* the cmd field was mutated by increasing its size field to
          * reflect the path and follow args. We need to subtract that
          * out before sending the command to Venus.  */
-        inp->d.cfs_ioctl.cmd = (cmd & ~(IOCPARM_MASK << 16));	
-        iocsize = ((cmd >> 16) & IOCPARM_MASK) - sizeof(char *) - sizeof(int);
-        inp->d.cfs_ioctl.cmd |= (iocsize & IOCPARM_MASK) <<	16;	
+        inp->cfs_ioctl.cmd = (cmd & ~(PIOCPARM_MASK << 16));	
+        iocsize = ((cmd >> 16) & PIOCPARM_MASK) - sizeof(char *) - sizeof(int);
+        inp->cfs_ioctl.cmd |= (iocsize & PIOCPARM_MASK) <<	16;	
     
-        /* in->d.cfs_ioctl.rwflag = flag; */
-        inp->d.cfs_ioctl.len = data->vi.in_size;
-        inp->d.cfs_ioctl.data = (char *)(VC_INSIZE(cfs_ioctl_in));
+        /* in->cfs_ioctl.rwflag = flag; */
+        inp->cfs_ioctl.len = data->vi.in_size;
+        inp->cfs_ioctl.data = (char *)(INSIZE(ioctl));
      
         /* get the data out of user space */
-        if ( copy_from_user((char*)inp + (int)inp->d.cfs_ioctl.data,
+#ifdef L20
+        memcpy_fromfs((char*)inp + (int)inp->cfs_ioctl.data,
+                      data->vi.in, data->vi.in_size);
+#else
+        if ( copy_from_user((char*)inp + (int)inp->cfs_ioctl.data,
 			    data->vi.in, data->vi.in_size) ) {
 	        error = EINVAL;
 	        goto exit;
 	}
-        error = coda_upcall(coda_sbp(sb), size, &size, inp);
+#endif
+        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
         
         if (error) {
 	        printk("coda_pioctl: Venus returns: %d for %s\n", 
@@ -504,23 +543,32 @@
 	}
         
 	/* Copy out the OUT buffer. */
-        if (outp->d.cfs_ioctl.len > data->vi.out_size) {
+        if (outp->cfs_ioctl.len > data->vi.out_size) {
                 CDEBUG(D_FILE, "return len %d <= request len %d\n",
-                      outp->d.cfs_ioctl.len, 
+                      outp->cfs_ioctl.len, 
                       data->vi.out_size);
                 error = EINVAL;
         } else {
-                if (copy_to_user(data->vi.out, 
-				 (char *)outp + (int)outp->d.cfs_ioctl.data, 
+		error = verify_area(VERIFY_WRITE, data->vi.out, 
+                                    data->vi.out_size);
+		if ( error ) goto exit;
+#ifdef L20
+                memcpy_tofs(data->vi.out, 
+                            (char *)outp + (int)outp->cfs_ioctl.data, 
+                            data->vi.out_size);                
+#else
+		if (copy_to_user(data->vi.out, 
+				 (char *)outp + (int)outp->cfs_ioctl.data, 
 				 data->vi.out_size)) {
 		        error = EINVAL;
 			goto exit;
 		}
+#endif
         }
 
  exit:
         if (inp) 
-	        CODA_FREE(inp, VC_MAXMSGSIZE);
+	        CODA_FREE(inp, insize);
 	return -error;
 }
 
@@ -535,11 +583,38 @@
  * reply and return Venus' error, also POSITIVE. 
  * 
  */
+static inline void coda_waitfor_upcall(struct vmsg *vmp)
+{
+	struct wait_queue	wait = { current, NULL };
+
+	vmp->vm_posttime = jiffies;
+
+	add_wait_queue(&vmp->vm_sleep, &wait);
+	for (;;) {
+		if ( coda_hard == 0 ) 
+			current->state = TASK_INTERRUPTIBLE;
+		else
+			current->state = TASK_UNINTERRUPTIBLE;
+
+		if ( vmp->vm_flags & VM_WRITE )
+			break;
+		if (signal_pending(current) &&
+		    (jiffies > vmp->vm_posttime + coda_timeout * HZ) )
+			break;
+		schedule();
+	}
+	remove_wait_queue(&vmp->vm_sleep, &wait);
+	current->state = TASK_RUNNING;
+
+	return;
+}
+
+
 int coda_upcall(struct coda_sb_info *sbi, int inSize, int *outSize, 
-		struct inputArgs *buffer) 
+		union inputArgs *buffer) 
 {
 	struct vcomm *vcommp;
-	struct outputArgs *out;
+	union outputArgs *out;
 	struct vmsg *vmp;
 	int error = 0;
 
@@ -550,7 +625,7 @@
 	}
 	vcommp = sbi->sbi_vcomm;
 
-	clstats(((struct inputArgs *)buffer)->opcode);
+	clstats(((union inputArgs *)buffer)->ih.opcode);
 
 	if (!vcomm_open(vcommp))
                 return(ENODEV);
@@ -561,16 +636,15 @@
 	vmp->vm_flags = 0;
 	vmp->vm_inSize = inSize;
 	vmp->vm_outSize = *outSize ? *outSize : inSize;
-	vmp->vm_opcode = ((struct inputArgs *)buffer)->opcode;
+	vmp->vm_opcode = ((union inputArgs *)buffer)->ih.opcode;
 	vmp->vm_unique = ++vcommp->vc_seq;
         vmp->vm_sleep = NULL;
 	
 	/* Fill in the common input args. */
-	((struct inputArgs *)buffer)->unique = vmp->vm_unique;
+	((union inputArgs *)buffer)->ih.unique = vmp->vm_unique;
 
 	/* Append msg to pending queue and poke Venus. */
-
-	INSQUE(vmp->vm_chain, vcommp->vc_pending);
+	coda_q_insert(&(vmp->vm_chain), &(vcommp->vc_pending));
 	CDEBUG(D_UPCALL, 
 	       "Proc %d wake Venus for(opc,uniq) =(%d,%d) msg at %x.zzz.\n",
 	       current->pid, vmp->vm_opcode, vmp->vm_unique, (int)vmp);
@@ -582,13 +656,15 @@
 	 * read but before the reply, we dequeue, send a signal
 	 * message, and return. If it occurs after the reply we ignore
 	 * it. In no case do we want to restart the syscall.  If it
-	 * was interrupted by a venus shutdown (vcclose), return
+	 * was interrupted by a venus shutdown (psdev_close), return
 	 * ENODEV.  */
 
-	/* Ignore return, We have to check anyway */
-
+	/* Go to sleep.  Wake up on signals only after the timeout. */
+	coda_waitfor_upcall(vmp);
 
-	interruptible_sleep_on(&vmp->vm_sleep);
+	CDEBUG(D_TIMING, "opc: %d time: %ld uniq: %d size: %d\n",
+	       vmp->vm_opcode, jiffies - vmp->vm_posttime, 
+	       vmp->vm_unique, vmp->vm_outSize);
 	CDEBUG(D_UPCALL, 
 	       "..process %d woken up by Venus for vmp at 0x%x, data at %x\n", 
 	       current->pid, (int)vmp, (int)vmp->vm_data);
@@ -596,60 +672,61 @@
 	    /* Op went through, interrupt or not... */
 	    if (vmp->vm_flags & VM_WRITE) {
 		error = 0;
-		out = (struct outputArgs *)vmp->vm_data;
-		error = out->result;
+		out = (union outputArgs *)vmp->vm_data;
+		error = out->oh.result;
 		CDEBUG(D_UPCALL, 
-		       "upcall: (u,o,r) (%ld, %ld, %ld) out at %x\n", 
-		       out->unique, out->opcode, out->result, (int)out);
+		       "upcall: (u,o,r) (%ld, %ld, %ld) out at %p\n", 
+		       out->oh.unique, out->oh.opcode, out->oh.result, out);
 		*outSize = vmp->vm_outSize;
 		goto exit;
-	    } 
-	    if (!(vmp->vm_flags & VM_READ)) { 
+	    }
+	    if ( !(vmp->vm_flags & VM_READ) && signal_pending(current)) { 
 		/* Interrupted before venus read it. */
 		CDEBUG(D_UPCALL, 
 		       "Interrupted before read:(op,un) (%d.%d), flags = %x\n",
 		       vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags);
-		REMQUE(vmp->vm_chain);
-		error = ERESTARTSYS;
+		coda_q_remove(&(vmp->vm_chain));
+		error = ERESTARTNOHAND;
 		goto exit;
 	    } 
-	    if ( vmp->vm_flags & VM_READ) { 	
+	    if ( (vmp->vm_flags & VM_READ) && signal_pending(current) ) {
 		/* interrupted after Venus did its read, send signal */
-		struct inputArgs *dog;
+		union inputArgs *dog;
 		struct vmsg *svmp;
 		
 		CDEBUG(D_UPCALL, 
 		       "Sending Venus a signal: op = %d.%d, flags = %x\n",
 		       vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags);
 		
-		REMQUE(vmp->vm_chain);
-		error = ERESTARTSYS;
+		coda_q_remove(&(vmp->vm_chain));
+		error = ERESTARTNOHAND;
 		
 		CODA_ALLOC(svmp, struct vmsg *, sizeof (struct vmsg));
-		CODA_ALLOC((svmp->vm_data), char *, VC_IN_NO_DATA);
+		CODA_ALLOC((svmp->vm_data), char *, sizeof(struct cfs_in_hdr));
 
+		dog = (union inputArgs *)svmp->vm_data;
+		dog->ih.opcode = CFS_SIGNAL;
+		dog->ih.unique = vmp->vm_unique;
+		
+		svmp->vm_flags = 0;
+		svmp->vm_opcode = dog->ih.opcode;
+		svmp->vm_unique = dog->ih.unique;
+		svmp->vm_inSize = sizeof(struct cfs_in_hdr);
+		svmp->vm_outSize = sizeof(struct cfs_in_hdr);
 		CDEBUG(D_UPCALL, 
 		       "coda_upcall: enqueing signal msg (%d, %d)\n",
 		       svmp->vm_opcode, svmp->vm_unique);
-		dog = (struct inputArgs *)svmp->vm_data;
-		dog->opcode = CFS_SIGNAL;
-		dog->unique = vmp->vm_unique;
-		
-		svmp->vm_flags = 0;
-		svmp->vm_opcode = dog->opcode;
-		svmp->vm_unique = dog->unique;
-		svmp->vm_inSize = VC_IN_NO_DATA;
-		svmp->vm_outSize = VC_IN_NO_DATA;
 		
 		/* insert at head of queue! */
-		INSQUE(svmp->vm_chain, vcommp->vc_pending);
+		coda_q_insert(&(svmp->vm_chain), vcommp->vc_pending.forw);
 		wake_up_interruptible(&vcommp->vc_waitq);
+	    } else {
+		    printk("Coda: Strange interruption..\n");
+		    error = EINTR;
 	    }
 	} else {	/* If venus died i.e. !VC_OPEN(vcommp) */
-	        printk("coda_upcall: Venus dead upon (op,un) (%d.%d) flags %d\n",
+	        printk("coda_upcall: Venus dead on (op,un) (%d.%d) flags %d\n",
 		       vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags);
-		
-		/* if (! (vmp->vm_flags & VM_WRITE) ) */
 		error = ENODEV;
 	}
 
@@ -670,78 +747,106 @@
  * CFS_FLUSH     -- flush all entries from the name cache and the cnode cache.
  * CFS_PURGEUSER -- flush all entries from the name cache for a specific user
  *                  This call is a result of token expiration.
- *                  Linux does a cfsnc_flush since cred's are not maintained.
  *
  * The next arise as the result of callbacks on a file or directory.
  * CFS_ZAPDIR    -- flush the attributes for the dir from its cnode.
  *                  Zap all children of this directory from the namecache.
  * CFS_ZAPFILE   -- flush the cached attributes for a file.
- * CFS_ZAPVNODE  -- in linux the same as zap file (no creds).
+ * CFS_ZAPVNODE  -- intended to be a zapfile for just one cred. Not used?
  *
  * The next is a result of Venus detecting an inconsistent file.
  * CFS_PURGEFID  -- flush the attribute for the file
- *                  If it is a dir (odd vnode), purge its 
- *                  children from the namecache
- *                  remove the file from the namecache.
+ *                  purge it and its children from the dcache
  *
  * The last  allows Venus to replace local fids with global ones
  * during reintegration.
  *
  * CFS_REPLACE -- replace one ViceFid with another throughout the name cache */
 
-int coda_downcall(int opcode, struct outputArgs * out)
+int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
 {
 
     /* Handle invalidate requests. */
     switch (opcode) {
-      case CFS_FLUSH : {
-	      clstats(CFS_FLUSH);
-	      cfsnc_flush();
-	      return(0);
-      }
-      case CFS_PURGEUSER : {
-	      clstats(CFS_PURGEUSER);
-	      cfsnc_flush();
-	      return(0);
-      }
-      case CFS_ZAPDIR : {
-	      ViceFid *fid = &out->d.cfs_zapdir.CodaFid;
-	      clstats(CFS_ZAPDIR);
-	      cfsnc_zapfid(fid);
-	      cfsnc_zapParentfid(fid);     
-	      CDEBUG(D_UPCALL, "zapdir: fid = (%lx.%lx.%lx), \n",fid->Volume, 
-					  fid->Vnode, 
-					  fid->Unique);
-	      return(0);
-      }
-      case CFS_ZAPVNODE : {
-              clstats(CFS_ZAPVNODE);
-	      cfsnc_zapfid(&out->d.cfs_zapvnode.VFid);
-	      return(0);
-      }	
-      case CFS_ZAPFILE : {
-              clstats(CFS_ZAPFILE);
-	      cfsnc_zapfid(&out->d.cfs_zapfile.CodaFid);
-	      return 0;
-      }
-      case CFS_PURGEFID : {
-	      ViceFid *fid = &out->d.cfs_purgefid.CodaFid;
-              clstats(CFS_PURGEFID);
-	      cfsnc_zapfid(fid);
-	      cfsnc_zapParentfid(fid);     
-	      CDEBUG(D_UPCALL, "purgefid: fid = (%lx.%lx.%lx)\n", 
-                                            fid->Volume, fid->Vnode,
-                                            fid->Unique);
-	      return 0;
-      }
-      case CFS_REPLACE : {
-              clstats(CFS_REPLACE);
-	      cfsnc_replace(&out->d.cfs_replace.OldFid, 
-			    &out->d.cfs_replace.NewFid);
-	      return (0);
-      }			   
+    case CFS_FLUSH : {
+	    clstats(CFS_FLUSH);
+	    CDEBUG(D_DOWNCALL, "CFS_FLUSH\n");
+	    coda_cache_clear_all(sb);
+	    shrink_dcache_sb(sb);
+	    return(0);
+    }
+    case CFS_PURGEUSER : {
+	    struct coda_cred *cred = &out->cfs_purgeuser.cred;
+	    CDEBUG(D_DOWNCALL, "CFS_PURGEUSER\n");
+	    if ( !cred ) {
+		    printk("PURGEUSER: null cred!\n");
+		    return 0;
+	    }
+	    clstats(CFS_PURGEUSER);
+	    coda_cache_clear_cred(sb, cred);
+	    return(0);
+    }
+    case CFS_ZAPDIR : {
+	    ViceFid *fid = &out->cfs_zapdir.CodaFid;
+	    char str[50];
+	    if ( !fid ) {
+		    printk("ZAPDIR: Null fid\n");
+		    return 0;
+	    }
+	    CDEBUG(D_DOWNCALL, "zapdir: fid = %s\n", coda_f2s(fid, str));
+	    clstats(CFS_ZAPDIR);
+	    coda_zapfid(fid, sb, C_ZAPDIR);
+	    return(0);
+    }
+    case CFS_ZAPVNODE : {
+	    ViceFid *fid = &out->cfs_zapvnode.VFid;
+	    char str[50];
+	    struct coda_cred *cred = &out->cfs_zapvnode.cred;
+	    if ( !fid || !cred ) {
+		    printk("ZAPVNODE: Null fid or cred\n");
+		    return 0;
+	    }
+	    CDEBUG(D_DOWNCALL, "zapvnode: fid = %s\n", coda_f2s(fid, str));
+	    coda_zapfid(fid, sb, C_ZAPFID);
+	    coda_cache_clear_cred(sb, cred);
+	    clstats(CFS_ZAPVNODE);
+	    return(0);
+    }
+    case CFS_ZAPFILE : {
+	    struct ViceFid *fid = &out->cfs_zapfile.CodaFid;
+	    char str[50];
+	    clstats(CFS_ZAPFILE);
+	    if ( !fid ) {
+		    printk("ZAPFILE: Null fid\n");
+		    return 0;
+	    }
+	    CDEBUG(D_DOWNCALL, "zapfile: fid = %s\n", coda_f2s(fid, str));
+	    coda_zapfid(fid, sb, C_ZAPFID);
+	    return 0;
+    }
+    case CFS_PURGEFID : {
+	    ViceFid *fid = &out->cfs_purgefid.CodaFid;
+	    char str[50];
+	    if ( !fid ) {
+		    printk("PURGEFID: Null fid\n");
+		    return 0;
+	    }
+	    CDEBUG(D_DOWNCALL, "purgefid: fid = %s\n", coda_f2s(fid, str));
+	    clstats(CFS_PURGEFID);
+	    coda_zapfid(fid, sb, C_ZAPDIR);
+	    return 0;
+    }
+    case CFS_REPLACE : {
+	    printk("CFS_REPLACCE\n");
+	    clstats(CFS_REPLACE);
+	    CDEBUG(D_DOWNCALL, "CFS_REPLACE\n");
+	    coda_cache_clear_all(sb);
+	    shrink_dcache_sb(sb);
+	    return (0);
+    }			   
     }
       return 0;
 }
 
 
+                

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov