patch-2.2.17 linux/fs/coda/dir.c

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

diff -u --recursive --new-file v2.2.16/fs/coda/dir.c linux/fs/coda/dir.c
@@ -37,8 +37,8 @@
 			const char *symname);
 static int coda_mkdir(struct inode *dir_inode, struct dentry *entry, int mode);
 static int coda_rmdir(struct inode *dir_inode, struct dentry *entry);
-static int coda_rename(struct inode *old_inode, struct dentry *old_dentry, 
-                       struct inode *new_inode, struct dentry *new_dentry);
+static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, 
+                       struct inode *new_dir, struct dentry *new_dentry);
 
 /* dir file-ops */
 static int coda_readdir(struct file *file, void *dirent, filldir_t filldir);
@@ -52,7 +52,6 @@
 			      filldir_t filldir);
 int coda_fsync(struct file *, struct dentry *dentry);
 
-int coda_crossvol_rename = 0;
 int coda_hasmknod = 0;
 
 struct dentry_operations coda_dentry_operations =
@@ -111,9 +110,9 @@
 {
         struct coda_inode_info *dircnp;
 	struct inode *res_inode = NULL;
-	struct ViceFid resfid;
+	struct ViceFid resfid = {0,0,0};
 	int dropme = 0; /* to indicate entry should not be cached */
-	int type;
+	int type = 0;
 	int error = 0;
 	const char *name = entry->d_name.name;
 	size_t length = entry->d_name.len;
@@ -137,6 +136,7 @@
 		CDEBUG(D_SPECIAL, 
 		       "Lookup on CTL object; dir ino %ld, count %d\n", 
 		       dir->i_ino, dir->i_count);
+		dropme = 1;
                 goto exit;
         }
 
@@ -151,9 +151,14 @@
 			       coda_f2s(&resfid));
 			dropme = 1;
 		}
+
 	    	error = coda_cnode_make(&res_inode, &resfid, dir->i_sb);
-		if (error)
-			return ERR_PTR(error);
+		if (error) return ERR_PTR(error);
+
+		/* make sure we drop unexpected non-hashable fids */
+		if (coda_f2i(&resfid) != res_inode->i_ino &&
+		    !coda_fid_is_weird(&resfid))
+			dropme = 1;
 	} else if (error != -ENOENT) {
 	        CDEBUG(D_INODE, "error for %s(%*s)%d\n",
 		       coda_f2s(&dircnp->c_fid), (int)length, name, error);
@@ -168,7 +173,7 @@
 	d_add(entry, res_inode);
 	if ( dropme ) {
 		d_drop(entry);
-		ITOC(res_inode)->c_flags |= C_VATTR;
+		coda_flag_inode(res_inode, C_VATTR);
 	}
         EXIT;
         return NULL;
@@ -184,9 +189,8 @@
 	coda_vfs_stat.permission++;
 	coda_permission_stat.count++;
 
-        if ( mask == 0 ) {
+        if ( mask == 0 )
                 return 0;
-        }
 
 	if ( coda_access_cache == 1 ) {
 		if ( coda_cache_check(inode, mask) ) {
@@ -203,17 +207,29 @@
         CDEBUG(D_INODE, "fid: %s, ino: %ld (mask: %o) error: %d\n", 
 	       coda_f2s(&(cp->c_fid)), inode->i_ino, mask, error);
 
-	if ( error == 0 ) {
+	if (!error)
 		coda_cache_enter(inode, mask);
-	}
 
         return error; 
 }
 
-
+static inline void coda_dir_changed(struct inode *dir, int link)
+{
+#ifdef REQUERY_VENUS_FOR_MTIME
+	/* invalidate the directory cnode's attributes to refetch the
+	 * attributes from venus next time the inode is referenced */
+	coda_flag_inode(dir, C_VATTR);
+#else
+	/* optimistically we can also act as if our nose bleeds. The
+	 * granularity of the mtime is coarse anyways so we might actually be
+	 * right most of the time. Note: we only do this for directories. */
+	dir->i_mtime = CURRENT_TIME;
+#endif
+	if (link)
+		dir->i_nlink += link;
+}
 
 /* creation routines: create, mknod, mkdir, link, symlink */
-
 static int coda_create(struct inode *dir, struct dentry *de, int mode)
 {
         int error=0;
@@ -252,10 +268,10 @@
 	}
 
 	/* invalidate the directory cnode's attributes */
-	dircnp->c_flags |= C_VATTR;
+	coda_dir_changed(dir, 0);
 	d_instantiate(de, result);
         return 0;
-}			     
+}
 
 static int coda_mknod(struct inode *dir, struct dentry *de, int mode, int rdev)
 {
@@ -297,7 +313,7 @@
 	}
 
 	/* invalidate the directory cnode's attributes */
-	dircnp->c_flags |= C_VATTR;
+	coda_dir_changed(dir, 0);
 	d_instantiate(de, result);
         return 0;
 }			     
@@ -344,8 +360,7 @@
 	}
 	
 	/* invalidate the directory cnode's attributes */
-	dircnp->c_flags |= C_VATTR;
-	dir->i_nlink++;
+	coda_dir_changed(dir, 1);
 	d_instantiate(de, inode);
         return 0;
 }
@@ -375,16 +390,17 @@
         error = venus_link(dir_inode->i_sb,&(cnp->c_fid), &(dir_cnp->c_fid), 
 			   (const char *)name, len);
 
-	if (  ! error ) { 
-		dir_cnp->c_flags |= C_VATTR;
-		++inode->i_count;
-		d_instantiate(de, inode);
-		inode->i_nlink++;
-	} else  {
+	if (error) { 
 		d_drop(de);
-		return error;
+		goto out;	
 	}
 
+	coda_dir_changed(dir_inode, 0);
+	inode->i_count++;
+	d_instantiate(de, inode);
+	inode->i_nlink++;
+
+out:
         CDEBUG(D_INODE, "link result %d\n",error);
 	EXIT;
         return(error);
@@ -421,9 +437,8 @@
 			      symname, symlen);
 
 	/* mtime is no good anymore */
-	if ( !error ) {
-		dir_cnp->c_flags |= C_VATTR;
-	}
+	if ( !error )
+		coda_dir_changed(dir_inode, 0);
 
         CDEBUG(D_INODE, "in symlink result %d\n",error);
         EXIT;
@@ -451,7 +466,7 @@
         }
 
         /* cache management: mtime has changed, ask Venus */
-	dircnp->c_flags |= C_VATTR;
+	coda_dir_changed(dir, 0);
 	de->d_inode->i_nlink--;
 	d_delete(de);
 
@@ -479,8 +494,9 @@
                 return error;
         }
 
-	if (de->d_inode->i_nlink)
-		de->d_inode->i_nlink --;
+	coda_dir_changed(dir, -1);
+	de->d_inode->i_nlink--;
+	d_delete(de);
 
         return 0;
 }
@@ -493,7 +509,6 @@
         const char *new_name = new_dentry->d_name.name;
 	int old_length = old_dentry->d_name.len;
 	int new_length = new_dentry->d_name.len;
-	struct inode *new_inode = new_dentry->d_inode;
         struct coda_inode_info *new_cnp, *old_cnp;
         int error;
 
@@ -508,28 +523,29 @@
 	       old_name, old_length, (long)strlen(old_name), new_name, new_length, 
 	       (long)strlen(new_name),old_dentry->d_count, new_dentry->d_count);
 
-	/* the C library will do unlink/create etc */
-	if ( coda_crossvol_rename == 0 && 
-	     old_cnp->c_fid.Volume != new_cnp->c_fid.Volume )
-		return -EXDEV;
-
         error = venus_rename(old_dir->i_sb, &(old_cnp->c_fid), 
 			     &(new_cnp->c_fid), old_length, new_length, 
 			     (const char *) old_name, (const char *)new_name);
 
-        if ( error ) {
-                CDEBUG(D_INODE, "returned error %d\n", error);
-                return error;
+        if ( !error ) {
+		if ( new_dentry->d_inode ) {
+			if ( S_ISDIR(new_dentry->d_inode->i_mode) ) {
+				old_dir->i_nlink--;
+				new_dir->i_nlink++;
+			}
+			coda_flag_inode(new_dentry->d_inode, C_VATTR);
+		}
+
+		/* coda_flag_inode(old_dir, C_VATTR); */
+		/* coda_flag_inode(new_dir, C_VATTR); */
+		old_dir->i_mtime = new_dir->i_mtime = CURRENT_TIME;
         }
 
-	coda_flag_inode(new_inode, C_VATTR);
-	coda_flag_inode(old_dir, C_VATTR);
-	coda_flag_inode(new_dir, C_VATTR);
 
 	CDEBUG(D_INODE, "result %d\n", error); 
 
 	EXIT;
-	return 0;
+	return error;
 }
 
 
@@ -589,7 +605,6 @@
 
         cnp = ITOC(i);
 
-
 	error = venus_open(i->i_sb, &(cnp->c_fid), coda_flags, &ino, &dev); 
 	if (error) {
 	        CDEBUG(D_FILE, "venus: dev %d, inode %ld, out->result %d\n",
@@ -617,7 +632,7 @@
 		cnp->c_ovp = NULL;
 	}
 	cnp->c_ovp = cont_inode; 
-        cnp->c_ocount++;
+	cnp->c_contcount++;
 
         CDEBUG(D_FILE, "result %d, coda i->i_count is %d for ino %ld\n", 
 	       error, i->i_count, i->i_ino);
@@ -642,24 +657,16 @@
 	cred = (struct coda_cred *)f->private_data;
 
         cnp =ITOC(i);
-        CHECK_CNODE(cnp);
         CDEBUG(D_FILE,  
-	       "RELEASE coda (ino %ld, ct %d) cache (ino %ld, ct %d)\n",
-               i->i_ino, i->i_count, (cnp->c_ovp ? cnp->c_ovp->i_ino : 0),
+	       "RELEASE coda (ino %ld, ct %d, ref %d) cache (ino %ld, ct %d)\n",
+               i->i_ino, i->i_count, cnp->c_contcount,
+	       (cnp->c_ovp ? cnp->c_ovp->i_ino : 0),
                (cnp->c_ovp ? cnp->c_ovp->i_count : -99));
 
-
-        /* even when c_ocount=0 we cannot put c_ovp to
-         * NULL since the file may be mmapped.
-	 * See code in inode.c (coda_put_inode) for
-	 * further handling of close.
-	 */
-
-        --cnp->c_ocount;
-
-        if (flags & (O_WRONLY | O_RDWR)) {
-                --cnp->c_owrite;
-        }
+	if (--cnp->c_contcount == 0) {
+		iput(cnp->c_ovp);
+		cnp->c_ovp = NULL;
+	}
 
 	error = venus_release(i->i_sb, &(cnp->c_fid), cflags, cred);
 
@@ -780,7 +787,6 @@
 /* called when a cache lookup succeeds */
 static int coda_dentry_revalidate(struct dentry *de, int flags)
 {
-	int valid = 1;
 	struct inode *inode = de->d_inode;
 	struct coda_inode_info *cii;
 	ENTRY;
@@ -788,14 +794,14 @@
 	if (!inode)
 		return 1;
 
-	cii = ITOC(de->d_inode);
 	if (coda_isroot(inode))
 		return 1;
 	if (is_bad_inode(inode))
 		return 0;
 
+	cii = ITOC(de->d_inode);
 	if (! (cii->c_flags & (C_PURGE | C_FLUSH)) )
-		return valid;
+		return 1;
 
 	shrink_dcache_parent(de);
 
@@ -825,9 +831,9 @@
 	int flags;
 
 	if (!dentry->d_inode) 
-		return ;
+		return;
 
-	flags =  (ITOC(dentry->d_inode)->c_flags) & C_PURGE;
+	flags = (ITOC(dentry->d_inode)->c_flags) & C_PURGE;
 	if (is_bad_inode(dentry->d_inode) || flags) {
 		CDEBUG(D_DOWNCALL, "bad inode, unhashing %s/%s, %ld\n", 
 		       dentry->d_parent->d_name.name, dentry->d_name.name,
@@ -862,19 +868,10 @@
 	if ( cii->c_flags == 0 )
 		return 0;
 
-	/* Venus closed the device .... */
-	if ( cii->c_flags & C_DYING ) { 
-		make_bad_inode(inode);
-		return -EIO;
-	}
-
-	
 	if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
 		error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
-		if ( error ) { 
-			make_bad_inode(inode);
+		if ( error )
 			return -EIO;
-		}
 
 		/* this inode may be lost if:
 		   - it's ino changed 
@@ -885,17 +882,15 @@
 		old_ino = inode->i_ino;
 		coda_vattr_to_iattr(inode, &attr);
 
-
 		if ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT)) {
 			printk("Coda: inode %ld, fid %s changed type!\n",
 			       inode->i_ino, coda_f2s(&(cii->c_fid)));
 		}
 
 		/* the following can happen when a local fid is replaced 
-		   with a global one, here we lose and declar the inode bad */
+		   with a global one, here we lose and declare the inode bad */
 		if (inode->i_ino != old_ino) {
 			make_bad_inode(inode);
-			inode->i_mode = old_mode;
 			return -EIO;
 		}
 		

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)