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

Next file: linux/fs/namei.c
Previous file: linux/fs/coda/psdev.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.108/linux/fs/coda/upcall.c linux/fs/coda/upcall.c
@@ -46,7 +46,8 @@
 #define UPARG(op)\
 do {\
   	CODA_ALLOC(inp, union inputArgs *, insize);\
-	outp = (union outputArgs *) (inp);\
+        if ( !inp ) { return -ENOMEM; }\
+        outp = (union outputArgs *) (inp);\
         inp->ih.opcode = (op);\
 	inp->ih.pid = current->pid;\
 	inp->ih.pgid = current->pgrp;\
@@ -90,7 +91,7 @@
 
 	if (inp)  CODA_FREE(inp, insize);
         EXIT;
-	return -error;
+	return error;
 }
 
 int venus_getattr(struct super_block *sb, struct ViceFid *fid, 
@@ -98,19 +99,22 @@
 {
         union inputArgs *inp;
         union outputArgs *outp;
-	        int insize, outsize, error;
-ENTRY;
+        int insize, outsize, error;
+	ENTRY;
+
         insize = SIZE(getattr); 
 	UPARG(CFS_GETATTR);
         inp->cfs_getattr.VFid = *fid;
+
         error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 	
 	if ( !error )
 	        *attr = outp->cfs_getattr.attr;
 
-        if (inp) CODA_FREE(inp, insize);
+        if (inp) 
+		CODA_FREE(inp, insize);
         EXIT;
-        return -error;
+        return error;
 }
 
 int  venus_setattr(struct super_block *sb, struct ViceFid *fid, 
@@ -130,7 +134,7 @@
 
         CDEBUG(D_SUPER, " result %d\n", error); 
         if ( inp ) CODA_FREE(inp, insize);
-        return -error;
+        return error;
 }
 
 int venus_lookup(struct super_block *sb, struct ViceFid *fid, 
@@ -160,7 +164,7 @@
 	}
 	if (inp) CODA_FREE(inp, insize);
 		
-	return -error;
+	return error;
 }
 
 
@@ -180,7 +184,7 @@
 
         if (inp) 
 		CODA_FREE(inp, insize);
-        return -error;
+        return error;
 }
 
 int venus_open(struct super_block *sb, struct ViceFid *fid,
@@ -209,7 +213,7 @@
         if (inp) 
                 CODA_FREE(inp, insize);
 
-	return -error;
+	return error;
 }	
 
 int venus_mkdir(struct super_block *sb, struct ViceFid *dirfid, 
@@ -239,7 +243,7 @@
 
 	if (inp) 
 	        CODA_FREE(inp, insize);
-	return -error;        
+	return error;        
 }
 
 
@@ -279,11 +283,11 @@
         error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
 	if (inp) CODA_FREE(inp, insize);
-	return -error;
+	return error;
 }
 
 int venus_create(struct super_block *sb, struct ViceFid *dirfid, 
-		    const char *name, int length, int excl, int mode, 
+		    const char *name, int length, int excl, int mode, int rdev,
 		    struct ViceFid *newfid, struct coda_vattr *attrs) 
 {
         union inputArgs *inp;
@@ -297,6 +301,7 @@
 
         inp->cfs_create.VFid = *dirfid;
         inp->cfs_create.attr.va_mode = mode;
+        inp->cfs_create.attr.va_rdev = rdev;
 	inp->cfs_create.excl = excl;
         inp->cfs_create.mode = mode;
         inp->cfs_create.name = offset;
@@ -312,7 +317,7 @@
 
 	if (inp) 
 	        CODA_FREE(inp, insize);
-	return -error;        
+	return error;        
 }
 
 int venus_rmdir(struct super_block *sb, struct ViceFid *dirfid, 
@@ -335,7 +340,7 @@
         error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 	if ( inp ) 
 	        CODA_FREE(inp, insize);
-	return -error;
+	return error;
 }
 
 int venus_remove(struct super_block *sb, struct ViceFid *dirfid, 
@@ -357,7 +362,7 @@
         error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 	if ( inp ) 
 	        CODA_FREE(inp, insize);
-	return -error;
+	return error;
 }
 
 int venus_readlink(struct super_block *sb, struct ViceFid *fid, 
@@ -389,7 +394,7 @@
         if (inp) CODA_FREE(inp, insize);
         CDEBUG(D_INODE, " result %d\n",error);
         EXIT;
-        return -error;
+        return error;
 }
 
 
@@ -420,7 +425,7 @@
 	        CODA_FREE(inp, insize);
         CDEBUG(D_INODE, " result %d\n",error);
         EXIT;
-        return -error;
+        return error;
 }
 
 int venus_symlink(struct super_block *sb, struct ViceFid *fid,
@@ -458,7 +463,7 @@
 	        CODA_FREE(inp, insize);
         CDEBUG(D_INODE, " result %d\n",error);
         EXIT;
-        return -error;
+        return error;
 }
 
 int venus_fsync(struct super_block *sb, struct ViceFid *fid)
@@ -476,7 +481,7 @@
 
 	if ( inp ) 
 		CODA_FREE(inp, insize);
-	return -error;
+	return error;
 }
 
 int venus_access(struct super_block *sb, struct ViceFid *fid, int mask)
@@ -495,7 +500,7 @@
 
 	if (inp) CODA_FREE(inp, insize);
         EXIT;
-	return -error;
+	return error;
 }
 
 
@@ -575,7 +580,7 @@
  exit:
         if (inp) 
 	        CODA_FREE(inp, insize);
-	return -error;
+	return error;
 }
 
 /*
@@ -583,12 +588,6 @@
  * 
  */
 
-/* 
- * coda_upcall will return a POSITIVE error in the case of 
- * failed communication with Venus _or_ will peek at Venus
- * reply and return Venus' error, also POSITIVE. 
- * 
- */
 static inline unsigned long coda_waitfor_upcall(struct vmsg *vmp)
 {
 	struct wait_queue	wait = { current, NULL };
@@ -608,18 +607,18 @@
 		if ( vmp->vm_flags & VM_WRITE )
 			break;
 
-		if ( ! signal_pending(current) )
-			schedule();
-		/* signal is present: after timeout always return */
-		if ( jiffies > vmp->vm_posttime + coda_timeout * HZ )
-			break; 
-				
-		/* if this process really wants to die, let it go */
-		if ( sigismember(&current->signal, SIGKILL) ||
-		     sigismember(&current->signal, SIGINT) )
-			break;
-		else 
-			schedule();
+		if ( !coda_hard && signal_pending(current) ) {
+			/* if this process really wants to die, let it go */
+			if ( sigismember(&(current->signal), SIGKILL) ||
+			     sigismember(&(current->signal), SIGINT) )
+				break;
+			/* signal is present: after timeout always return 
+			   really smart idea, probably useless ... */
+			if ( jiffies > vmp->vm_posttime + coda_timeout * HZ )
+				break; 
+		}
+		schedule();
+
 	}
 	remove_wait_queue(&vmp->vm_sleep, &wait);
 	current->state = TASK_RUNNING;
@@ -630,6 +629,16 @@
 }
 
 
+/* 
+ * coda_upcall will return an error in the case of 
+ * failed communication with Venus _or_ will peek at Venus
+ * reply and return Venus' error.
+ *
+ * As venus has 2 types of errors, normal errors (positive) and internal
+ * errors (negative), normal errors are negated, while internal errors
+ * are all mapped to -EINTR, while showing a nice warning message. (jh)
+ * 
+ */
 static int coda_upcall(struct coda_sb_info *sbi, 
 		int inSize, int *outSize, 
 		union inputArgs *buffer) 
@@ -643,13 +652,13 @@
 ENTRY;
 
 	if (sbi->sbi_vcomm == NULL) {
-                return ENODEV;
+                return -ENODEV;
 	}
 	vcommp = sbi->sbi_vcomm;
 
 
 	if (!vcomm_open(vcommp))
-                return(ENODEV);
+                return -ENXIO;
 
 	/* Format the request message. */
 	CODA_ALLOC(vmp,struct vmsg *,sizeof(struct vmsg));
@@ -693,9 +702,14 @@
 	if (vcomm_open(vcommp)) {      /* i.e. Venus is still alive */
 	    /* Op went through, interrupt or not... */
 	    if (vmp->vm_flags & VM_WRITE) {
-		error = 0;
 		out = (union outputArgs *)vmp->vm_data;
-		error = out->oh.result;
+		/* here we map positive Venus errors to kernel errors */
+		if ( out->oh.result < 0 ) {
+			printk("Tell Peter: Venus returns negative error %ld, for oc %ld!\n",
+			       out->oh.result, out->oh.opcode);
+			out->oh.result = EINTR;
+		}
+		error = -out->oh.result;
 		CDEBUG(D_UPCALL, 
 		       "upcall: (u,o,r) (%ld, %ld, %ld) out at %p\n", 
 		       out->oh.unique, out->oh.opcode, out->oh.result, out);
@@ -708,48 +722,49 @@
 		       "Interrupted before read:(op,un) (%d.%d), flags = %x\n",
 		       vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags);
 		coda_q_remove(&(vmp->vm_chain));
-		error = ERESTARTNOHAND;
+		/* perhaps the best way to convince the app to
+		   give up? */
+		error = -EINTR;
 		goto exit;
 	    } 
 	    if ( (vmp->vm_flags & VM_READ) && signal_pending(current) ) {
-		/* interrupted after Venus did its read, send signal */
-		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);
-		
-		coda_q_remove(&(vmp->vm_chain));
-		error = ERESTARTNOHAND;
-		
-		CODA_ALLOC(svmp, struct vmsg *, sizeof (struct vmsg));
-		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);
-		
-		/* insert at head of queue! */
-		coda_q_insert(&(svmp->vm_chain), vcommp->vc_pending.forw);
-		wake_up_interruptible(&vcommp->vc_waitq);
+		    /* interrupted after Venus did its read, send signal */
+		    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);
+		    
+		    coda_q_remove(&(vmp->vm_chain));
+		    error = -EINTR;
+		    CODA_ALLOC(svmp, struct vmsg *, sizeof (struct vmsg));
+		    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);
+		    
+		    /* insert at head of queue! */
+		    coda_q_insert(&(svmp->vm_chain), vcommp->vc_pending.forw);
+		    wake_up_interruptible(&vcommp->vc_waitq);
 	    } else {
 		    printk("Coda: Strange interruption..\n");
-		    error = EINTR;
+		    error = -EINTR;
 	    }
 	} else {	/* If venus died i.e. !VC_OPEN(vcommp) */
 	        printk("coda_upcall: Venus dead on (op,un) (%d.%d) flags %d\n",
 		       vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags);
-		error = ENODEV;
+		error = -ENODEV;
 	}
 
  exit:
@@ -759,7 +774,13 @@
 	return error;
 }
 
-
+/*  
+    The statements below are part of the Coda opportunistic
+    programming -- taken from the Mach/BSD kernel code for Coda. 
+    You don't get correct semantics by stating what needs to be
+    done without guaranteeing the invariants needed for it to happen.
+    When will be have time to find out what exactly is going on?  (pjb)
+*/
 
 
 /* 
@@ -790,7 +811,7 @@
 int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
 {
 
-    /* Handle invalidation requests. */
+	/* Handle invalidation requests. */
           if ( !sb ) { 
 	          printk("coda_downcall: opcode %d, no sb!\n", opcode);
 		  return 0; 
@@ -821,15 +842,19 @@
 	  case CFS_ZAPDIR : {
 	          struct inode *inode;
 		  ViceFid *fid = &out->cfs_zapdir.CodaFid;
-		  CDEBUG(D_DOWNCALL, "zapdir: fid = %s\n", coda_f2s(fid));
+		  CDEBUG(D_DOWNCALL, "zapdir: fid = %s...\n", coda_f2s(fid));
 		  clstats(CFS_ZAPDIR);
 
 		  inode = coda_fid_to_inode(fid, sb);
-		  if ( inode ) {
+		  if (inode) {
+			  CDEBUG(D_DOWNCALL, "zapdir: inode = %ld children flagged\n", 
+				 inode->i_ino);
+			  coda_purge_children(inode);
+			  CDEBUG(D_DOWNCALL, "zapdir: inode = %ld cache cleared\n", inode->i_ino);
 	                  coda_flag_inode(inode, C_VATTR);
-			  coda_cache_clear_inode(inode);
-			  coda_flag_alias_children(inode, C_PURGE);
-		  }
+		  } else 
+			  CDEBUG(D_DOWNCALL, "zapdir: no inode\n");
+		  
 		  return(0);
 	  }
 
@@ -840,9 +865,10 @@
 		  CDEBUG(D_DOWNCALL, "zapfile: fid = %s\n", coda_f2s(fid));
 		  inode = coda_fid_to_inode(fid, sb);
 		  if ( inode ) {
+			  CDEBUG(D_DOWNCALL, "zapfile: inode = %ld\n", inode->i_ino);
 	                  coda_flag_inode(inode, C_VATTR);
-			  coda_cache_clear_inode(inode);
-		  }
+		  } else 
+			  CDEBUG(D_DOWNCALL, "zapfile: no inode\n");
 		  return 0;
 	  }
 
@@ -853,19 +879,26 @@
 		  clstats(CFS_PURGEFID);
 		  inode = coda_fid_to_inode(fid, sb);
 		  if ( inode ) { 
-                          coda_flag_inode(inode, C_PURGE);
-			  coda_cache_clear_inode(inode);
-		  }
+			  CDEBUG(D_DOWNCALL, "purgefid: inode = %ld\n", inode->i_ino);
+			  coda_purge_children(inode);
+			  coda_purge_dentries(inode);
+		  }else 
+			  CDEBUG(D_DOWNCALL, "purgefid: no inode\n");
 		  return 0;
 	  }
 
 	  case CFS_REPLACE : {
-	          printk("CFS_REPLACCE\n");
+	          struct inode *inode;
+		  ViceFid *fid = &out->cfs_replace.OldFid;
 		  clstats(CFS_REPLACE);
 		  CDEBUG(D_DOWNCALL, "CFS_REPLACE\n");
-		  coda_cache_clear_all(sb);
-		  shrink_dcache_sb(sb);
-		  return (0);
+		  inode = coda_fid_to_inode(fid, sb);
+		  if ( inode ) { 
+			  CDEBUG(D_DOWNCALL, "replacefid: inode = %ld\n", inode->i_ino);
+                          coda_purge_dentries(inode);
+		  }else 
+			  CDEBUG(D_DOWNCALL, "purgefid: no inode\n");
+		  return 0;
 	  }			   
 	  }
 	  return 0;

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