diff -u --recursive --new-file linux-2.4.3-write_inode/fs/exec.c linux-2.4.3-cto/fs/exec.c --- linux-2.4.3-write_inode/fs/exec.c Thu Mar 22 18:26:18 2001 +++ linux-2.4.3-cto/fs/exec.c Fri Mar 30 13:19:04 2001 @@ -341,7 +341,7 @@ struct file *file; int err = 0; - if (path_init(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd)) + if (path_init(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE|LOOKUP_REVAL, &nd)) err = path_walk(name, &nd); file = ERR_PTR(err); if (!err) { diff -u --recursive --new-file linux-2.4.3-write_inode/fs/namei.c linux-2.4.3-cto/fs/namei.c --- linux-2.4.3-write_inode/fs/namei.c Thu Mar 22 20:07:58 2001 +++ linux-2.4.3-cto/fs/namei.c Fri Mar 30 13:19:04 2001 @@ -429,7 +429,7 @@ while (*name=='/') name++; if (!*name) - goto return_base; + goto return_reval; inode = nd->dentry->d_inode; if (current->link_count) @@ -548,14 +548,14 @@ inode = nd->dentry->d_inode; /* fallthrough */ case 1: - goto return_base; + goto return_reval; } if (nd->dentry->d_op && nd->dentry->d_op->d_hash) { err = nd->dentry->d_op->d_hash(nd->dentry, &this); if (err < 0) break; } - dentry = cached_lookup(nd->dentry, &this, 0); + dentry = cached_lookup(nd->dentry, &this, nd->flags); if (!dentry) { dentry = real_lookup(nd->dentry, &this, 0); err = PTR_ERR(dentry); @@ -599,6 +599,10 @@ nd->last_type = LAST_DOT; else if (this.len == 2 && this.name[1] == '.') nd->last_type = LAST_DOTDOT; +return_reval: + dentry = nd->dentry; + if (dentry && dentry->d_op && dentry->d_op->d_revalidate) + dentry->d_op->d_revalidate(dentry, nd->flags); return_base: return 0; out_dput: @@ -881,7 +885,7 @@ */ static inline int lookup_flags(unsigned int f) { - unsigned long retval = LOOKUP_FOLLOW; + unsigned long retval = LOOKUP_FOLLOW|LOOKUP_REVAL; if (f & O_NOFOLLOW) retval &= ~LOOKUP_FOLLOW; diff -u --recursive --new-file linux-2.4.3-write_inode/fs/nfs/dir.c linux-2.4.3-cto/fs/nfs/dir.c --- linux-2.4.3-write_inode/fs/nfs/dir.c Fri Mar 30 13:16:15 2001 +++ linux-2.4.3-cto/fs/nfs/dir.c Tue Apr 3 19:46:12 2001 @@ -455,22 +455,17 @@ unsigned long timeout = NFS_ATTRTIMEO(inode); /* - * If it's the last lookup in a series, we use a stricter - * cache consistency check by looking at the parent mtime. - * - * If it's been modified in the last hour, be really strict. - * (This still means that we can avoid doing unnecessary - * work on directories like /usr/share/bin etc which basically - * never change). + * Force an immediate revalidation if LOOKUP_REVAL is set. + * This is necessary to ensure close-to-open cache consistency, + * and is set for all "open" calls, to refresh our attributes. */ - if (!(flags & LOOKUP_CONTINUE)) { - long diff = CURRENT_TIME - dentry->d_parent->d_inode->i_mtime; + if ((flags & LOOKUP_REVAL) && !(NFS_SERVER(inode)->flags & NFS_MOUNT_NOCTO)) + return 1; - if (diff < 15*60) - timeout = 0; - } - - return time_after(jiffies,dentry->d_time + timeout); + if (time_after(jiffies, NFS_READTIME(inode) + timeout)) + return 1; + + return time_after(jiffies, dentry->d_time + timeout); } /* @@ -480,15 +475,13 @@ * 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) +static inline int nfs_neg_need_reval(struct dentry *dentry, int flags) { 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 > NFS_REVALIDATE_NEGATIVE) - timeout = NFS_REVALIDATE_NEGATIVE; + if ((flags & (LOOKUP_REVAL|LOOKUP_POSITIVE)) && !(NFS_SERVER(dir)->flags & NFS_MOUNT_NOCTO)) + return 1; return time_after(jiffies, dentry->d_time + timeout); } @@ -522,7 +515,7 @@ * should validate things.. */ if (!inode) { - if (nfs_neg_need_reval(dentry)) + if (nfs_neg_need_reval(dentry, flags)) goto out_bad; goto out_valid; } @@ -548,14 +541,8 @@ if (error) goto out_bad; - /* Inode number matches? */ - if (!(fattr.valid & NFS_ATTR_FATTR) || - NFS_FSID(inode) != fattr.fsid || - NFS_FILEID(inode) != fattr.fileid) + if ((error = nfs_refresh_inode(inode, &fattr)) != 0) goto out_bad; - - /* Ok, remember that we successfully checked it.. */ - nfs_refresh_inode(inode, &fattr); if (nfs_inode_is_stale(inode, &fhandle, &fattr)) goto out_bad; diff -u --recursive --new-file linux-2.4.3-write_inode/fs/nfs/inode.c linux-2.4.3-cto/fs/nfs/inode.c --- linux-2.4.3-write_inode/fs/nfs/inode.c Fri Mar 30 13:18:29 2001 +++ linux-2.4.3-cto/fs/nfs/inode.c Tue Apr 3 23:06:24 2001 @@ -916,40 +916,29 @@ __u64 new_size, new_mtime; loff_t new_isize; int invalid = 0; - int error = -EIO; - - if (!inode || !fattr) { - printk(KERN_ERR "nfs_refresh_inode: inode or fattr is NULL\n"); - goto out; - } - if (inode->i_mode == 0) { - printk(KERN_ERR "nfs_refresh_inode: empty inode\n"); - goto out; - } + int error; if ((fattr->valid & NFS_ATTR_FATTR) == 0) goto out; - if (is_bad_inode(inode)) - goto out; - dfprintk(VFS, "NFS: refresh_inode(%x/%ld ct=%d info=0x%x)\n", inode->i_dev, inode->i_ino, atomic_read(&inode->i_count), fattr->valid); - + error = -ESTALE; if (NFS_FSID(inode) != fattr->fsid || NFS_FILEID(inode) != fattr->fileid) { - printk(KERN_ERR "nfs_refresh_inode: inode number mismatch\n" + dfprintk(VFS, "nfs_refresh_inode: inode number mismatch\n" "expected (0x%Lx/0x%Lx), got (0x%Lx/0x%Lx)\n", (long long)NFS_FSID(inode), (long long)NFS_FILEID(inode), (long long)fattr->fsid, (long long)fattr->fileid); - goto out; + goto out_error; } /* * Make sure the inode's type hasn't changed. */ + error = -EIO; if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) goto out_changed; @@ -957,8 +946,6 @@ new_size = fattr->size; new_isize = nfs_size_to_loff_t(fattr->size); - error = 0; - /* * Update the read time so we don't revalidate too often. */ @@ -1049,8 +1036,8 @@ if (invalid) nfs_zap_caches(inode); -out: - return error; + out: + return 0; out_changed: /* @@ -1066,7 +1053,8 @@ * (But we fall through to invalidate the caches.) */ nfs_invalidate_inode(inode); - goto out; + out_error: + return error; } /* diff -u --recursive --new-file linux-2.4.3-write_inode/fs/nfs/nfs3proc.c linux-2.4.3-cto/fs/nfs/nfs3proc.c --- linux-2.4.3-write_inode/fs/nfs/nfs3proc.c Mon Dec 4 03:01:01 2000 +++ linux-2.4.3-cto/fs/nfs/nfs3proc.c Tue Apr 3 18:41:34 2001 @@ -80,7 +80,8 @@ status = rpc_call(NFS_CLIENT(dir), NFS3PROC_GETATTR, fhandle, fattr, 0); dprintk("NFS reply lookup: %d\n", status); - nfs_refresh_inode(dir, &dir_attr); + if (status >= 0) + status = nfs_refresh_inode(dir, &dir_attr); return status; } diff -u --recursive --new-file linux-2.4.3-write_inode/include/linux/fs.h linux-2.4.3-cto/include/linux/fs.h --- linux-2.4.3-write_inode/include/linux/fs.h Tue Mar 27 01:48:11 2001 +++ linux-2.4.3-cto/include/linux/fs.h Fri Mar 30 13:31:06 2001 @@ -1158,6 +1158,7 @@ * - require a directory * - ending slashes ok even for nonexistent files * - internal "there are more path compnents" flag + * - force an immediate revalidation of the dcache entry */ #define LOOKUP_FOLLOW (1) #define LOOKUP_DIRECTORY (2) @@ -1165,6 +1166,7 @@ #define LOOKUP_POSITIVE (8) #define LOOKUP_PARENT (16) #define LOOKUP_NOALT (32) +#define LOOKUP_REVAL (64) /* * Type of the last component on LOOKUP_PARENT */