patch-2.3.23 linux/fs/nfs/dir.c

Next file: linux/fs/nfs/inode.c
Previous file: linux/fs/minix/truncate.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.22/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
@@ -308,8 +308,7 @@
 	struct nfs_readdirres rd_res;
 	struct dentry *dentry = file->f_dentry;
 	struct inode *inode = dentry->d_inode;
-	struct page *page, **hash;
-	unsigned long page_cache;
+	struct page *page, **hash, *page_cache;
 	long offset;
 	__u32 *cookiep;
 
@@ -341,14 +340,14 @@
 		goto unlock_out;
 	}
 
-	page = page_cache_entry(page_cache);
+	page = page_cache;
 	if (add_to_page_cache_unique(page, inode, offset, hash)) {
 		page_cache_release(page);
 		goto repeat;
 	}
 
 	rd_args.fh = NFS_FH(dentry);
-	rd_res.buffer = (char *)page_cache;
+	rd_res.buffer = (char *)page_address(page_cache);
 	rd_res.bufsiz = PAGE_CACHE_SIZE;
 	rd_res.cookie = *cookiep;
 	do {
@@ -533,13 +532,15 @@
  * If mtime is close to present time, we revalidate
  * more often.
  */
+#define NFS_REVALIDATE_NEGATIVE (1 * HZ)
 static inline int nfs_neg_need_reval(struct dentry *dentry)
 {
-	unsigned long timeout = 30 * HZ;
-	long diff = CURRENT_TIME - dentry->d_parent->d_inode->i_mtime;
+	struct inode *dir = dentry->d_parent->d_inode;
+	unsigned long timeout = NFS_ATTRTIMEO(dir);
+	long diff = CURRENT_TIME - dir->i_mtime;
 
-	if (diff < 5*60)
-		timeout = 1 * HZ;
+	if (diff < 5*60 && timeout > NFS_REVALIDATE_NEGATIVE)
+		timeout = NFS_REVALIDATE_NEGATIVE;
 
 	return time_after(jiffies, dentry->d_time + timeout);
 }
@@ -581,12 +582,14 @@
 		goto out_bad;
 	}
 
-	if (IS_ROOT(dentry))
-		goto out_valid;
-
 	if (!nfs_dentry_force_reval(dentry, flags))
 		goto out_valid;
 
+	if (IS_ROOT(dentry)) {
+		__nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+		goto out_valid_renew;
+	}
+
 	/*
 	 * Do a new lookup and check the dentry attributes.
 	 */
@@ -596,32 +599,29 @@
 		goto out_bad;
 
 	/* Inode number matches? */
-	if (fattr.fileid != inode->i_ino)
+	if (NFS_FSID(inode) != fattr.fsid ||
+	    NFS_FILEID(inode) != fattr.fileid)
 		goto out_bad;
 
 	/* Filehandle matches? */
-	if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh))) {
-		if (!list_empty(&dentry->d_subdirs))
-			shrink_dcache_parent(dentry);
-		if (dentry->d_count < 2)
-			goto out_bad;
-	}
+	if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh)))
+		goto out_bad;
 
 	/* Ok, remeber that we successfully checked it.. */
-	nfs_renew_times(dentry);
 	nfs_refresh_inode(inode, &fattr);
 
+ out_valid_renew:
+	nfs_renew_times(dentry);
 out_valid:
 	return 1;
 out_bad:
+	d_drop(dentry);
+	if (!list_empty(&dentry->d_subdirs))
+		shrink_dcache_parent(dentry);
 	/* Purge readdir caches. */
 	if (dentry->d_parent->d_inode) {
-		invalidate_inode_pages(dentry->d_parent->d_inode);
-		nfs_flush_dircache(dentry->d_parent->d_inode);
-	}
-	if (inode && S_ISDIR(inode->i_mode)) {
-		invalidate_inode_pages(inode);
-		nfs_flush_dircache(inode);
+		nfs_zap_caches(dentry->d_parent->d_inode);
+		NFS_CACHEINV(dentry->d_parent->d_inode);
 	}
 	return 0;
 }
@@ -649,21 +649,6 @@
 				dentry->d_name.name, error);
 	}
 
-#ifdef NFS_PARANOIA
-	/*
-	 * Sanity check: if the dentry has been unhashed and the
-	 * inode still has users, we could have problems ...
-	 */
-	if (list_empty(&dentry->d_hash) && dentry->d_inode) {
-		struct inode *inode = dentry->d_inode;
-		int max_count = (S_ISDIR(inode->i_mode) ? 1 : inode->i_nlink);
-		if (inode->i_count > max_count) {
-printk("nfs_dentry_delete: %s/%s: ino=%ld, count=%d, nlink=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name,
-inode->i_ino, inode->i_count, inode->i_nlink);
-		}
-	}
-#endif
 }
 
 static kmem_cache_t *nfs_fh_cachep;
@@ -750,14 +735,6 @@
 		error = -EACCES;
 		inode = nfs_fhget(dentry, &fhandle, &fattr);
 		if (inode) {
-#ifdef NFS_PARANOIA
-if (inode->i_count > (S_ISDIR(inode->i_mode) ? 1 : inode->i_nlink)) {
-printk("nfs_lookup: %s/%s ino=%ld in use, count=%d, nlink=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name,
-inode->i_ino, inode->i_count, inode->i_nlink);
-show_dentry(&inode->i_dentry);
-}
-#endif
 	    no_entry:
 			d_add(dentry, inode);
 			nfs_renew_times(dentry);
@@ -779,14 +756,6 @@
 
 	inode = nfs_fhget(dentry, fhandle, fattr);
 	if (inode) {
-#ifdef NFS_PARANOIA
-if (inode->i_count > (S_ISDIR(inode->i_mode) ? 1 : inode->i_nlink)) {
-printk("nfs_instantiate: %s/%s ino=%ld in use, count=%d, nlink=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name,
-inode->i_ino, inode->i_count, inode->i_nlink);
-show_dentry(&inode->i_dentry);
-}
-#endif
 		d_instantiate(dentry, inode);
 		nfs_renew_times(dentry);
 		error = 0;
@@ -803,16 +772,15 @@
 static int nfs_create(struct inode *dir, struct dentry *dentry, int mode)
 {
 	int error;
-	struct nfs_sattr sattr;
+	struct iattr attr;
 	struct nfs_fattr fattr;
 	struct nfs_fh fhandle;
 
 	dfprintk(VFS, "NFS: create(%x/%ld, %s\n",
 		dir->i_dev, dir->i_ino, dentry->d_name.name);
 
-	sattr.mode = mode;
-	sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
-	sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
+	attr.ia_mode = mode;
+	attr.ia_valid = ATTR_MODE;
 
 	/*
 	 * Invalidate the dir cache before the operation to avoid a race.
@@ -820,7 +788,7 @@
 	invalidate_inode_pages(dir);
 	nfs_flush_dircache(dir);
 	error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
-			dentry->d_name.name, &sattr, &fhandle, &fattr);
+			dentry->d_name.name, &attr, &fhandle, &fattr);
 	if (!error)
 		error = nfs_instantiate(dentry, &fhandle, &fattr);
 	if (error)
@@ -834,23 +802,25 @@
 static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
 {
 	int error;
-	struct nfs_sattr sattr;
+	struct iattr attr;
 	struct nfs_fattr fattr;
 	struct nfs_fh fhandle;
 
 	dfprintk(VFS, "NFS: mknod(%x/%ld, %s\n",
 		dir->i_dev, dir->i_ino, dentry->d_name.name);
 
-	sattr.mode = mode;
-	sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
-	if (S_ISCHR(mode) || S_ISBLK(mode))
-		sattr.size = rdev; /* get out your barf bag */
-	sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
+	attr.ia_mode = mode;
+	attr.ia_valid = ATTR_MODE;
+	/* FIXME: move this to a special nfs_proc_mknod() */
+	if (S_ISCHR(mode) || S_ISBLK(mode)) {
+		attr.ia_size = rdev; /* get out your barf bag */
+		attr.ia_valid |= ATTR_SIZE;
+	}
 
 	invalidate_inode_pages(dir);
 	nfs_flush_dircache(dir);
 	error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
-				dentry->d_name.name, &sattr, &fhandle, &fattr);
+				dentry->d_name.name, &attr, &fhandle, &fattr);
 	if (!error)
 		error = nfs_instantiate(dentry, &fhandle, &fattr);
 	if (error)
@@ -864,16 +834,15 @@
 static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
 	int error;
-	struct nfs_sattr sattr;
+	struct iattr attr;
 	struct nfs_fattr fattr;
 	struct nfs_fh fhandle;
 
 	dfprintk(VFS, "NFS: mkdir(%x/%ld, %s\n",
 		dir->i_dev, dir->i_ino, dentry->d_name.name);
 
-	sattr.mode = mode | S_IFDIR;
-	sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
-	sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
+	attr.ia_valid = ATTR_MODE;
+	attr.ia_mode = mode | S_IFDIR;
 
 	/*
 	 * Always drop the dentry, we can't always depend on
@@ -885,7 +854,7 @@
 	invalidate_inode_pages(dir);
 	nfs_flush_dircache(dir);
 	error = nfs_proc_mkdir(NFS_DSERVER(dentry), NFS_FH(dentry->d_parent),
-				dentry->d_name.name, &sattr, &fhandle, &fattr);
+				dentry->d_name.name, &attr, &fhandle, &fattr);
 	if (!error)
 		dir->i_nlink++;
 	return error;
@@ -898,13 +867,6 @@
 	dfprintk(VFS, "NFS: rmdir(%x/%ld, %s\n",
 		dir->i_dev, dir->i_ino, dentry->d_name.name);
 
-#ifdef NFS_PARANOIA
-if (dentry->d_inode->i_count > 1)
-printk("nfs_rmdir: %s/%s inode busy?? i_count=%d, i_nlink=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name,
-dentry->d_inode->i_count, dentry->d_inode->i_nlink);
-#endif
-
 	invalidate_inode_pages(dir);
 	nfs_flush_dircache(dir);
 	error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
@@ -1082,12 +1044,6 @@
 #endif
 		goto out;
 	}
-#ifdef NFS_PARANOIA
-if (inode && inode->i_count > inode->i_nlink)
-printk("nfs_safe_remove: %s/%s inode busy?? i_count=%d, i_nlink=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name,
-inode->i_count, inode->i_nlink);
-#endif
 	/*
 	 * Unhash the dentry while we remove the file ...
 	 */
@@ -1141,7 +1097,7 @@
 static int
 nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 {
-	struct nfs_sattr sattr;
+	struct iattr attr;
 	int error;
 
 	dfprintk(VFS, "NFS: symlink(%x/%ld, %s, %s)\n",
@@ -1160,9 +1116,8 @@
 	 * Fill in the sattr for the call.
  	 * Note: SunOS 4.1.2 crashes if the mode isn't initialized!
 	 */
-	sattr.mode = S_IFLNK | S_IRWXUGO;
-	sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
-	sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
+	attr.ia_valid = ATTR_MODE;
+	attr.ia_mode = S_IFLNK | S_IRWXUGO;
 
 	/*
 	 * Drop the dentry in advance to force a new lookup.
@@ -1173,7 +1128,7 @@
 	invalidate_inode_pages(dir);
 	nfs_flush_dircache(dir);
 	error = nfs_proc_symlink(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
-				dentry->d_name.name, symname, &sattr);
+				dentry->d_name.name, symname, &attr);
 	if (!error) {
 		nfs_renew_times(dentry->d_parent);
 	} else if (error == -EEXIST) {
@@ -1332,13 +1287,6 @@
 	 * To prevent any new references to the target during the rename,
 	 * we unhash the dentry and free the inode in advance.
 	 */
-#ifdef NFS_PARANOIA
-if (new_inode && 
-    new_inode->i_count > (S_ISDIR(new_inode->i_mode) ? 1 : new_inode->i_nlink))
-printk("nfs_rename: %s/%s inode busy?? i_count=%d, i_nlink=%d\n",
-new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
-new_inode->i_count, new_inode->i_nlink);
-#endif
 	if (!list_empty(&new_dentry->d_hash)) {
 		d_drop(new_dentry);
 		rehash = update;

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