patch-2.2.7 linux/fs/nfs/inode.c
Next file: linux/fs/nls/Config.in
Previous file: linux/fs/nfs/dir.c
Back to the patch index
Back to the overall index
- Lines: 232
- Date:
Sat Apr 24 12:45:37 1999
- Orig file:
v2.2.6/linux/fs/nfs/inode.c
- Orig date:
Fri Apr 16 14:47:31 1999
diff -u --recursive --new-file v2.2.6/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
@@ -37,6 +37,8 @@
#define NFS_PARANOIA 1
static struct inode * __nfs_fhget(struct super_block *, struct nfs_fattr *);
+static void nfs_zap_caches(struct inode *);
+static void nfs_invalidate_inode(struct inode *);
static void nfs_read_inode(struct inode *);
static void nfs_put_inode(struct inode *);
@@ -234,6 +236,11 @@
server->rsize = nfs_block_size(data->rsize, NULL);
server->wsize = nfs_block_size(data->wsize, NULL);
server->flags = data->flags;
+
+ if (data->flags & NFS_MOUNT_NOAC) {
+ data->acregmin = data->acregmax = 0;
+ data->acdirmin = data->acdirmax = 0;
+ }
server->acregmin = data->acregmin*HZ;
server->acregmax = data->acregmax*HZ;
server->acdirmin = data->acdirmin*HZ;
@@ -388,25 +395,61 @@
* could cause file corruption. But since the dentry
* count is 0 and all pending IO for a dentry has been
* flushed when the count went to 0, we're safe here.
+ * Also returns the number of unhashed dentries
*/
-void nfs_free_dentries(struct inode *inode)
+static int
+nfs_free_dentries(struct inode *inode)
{
struct list_head *tmp, *head = &inode->i_dentry;
+ int unhashed;
restart:
tmp = head;
+ unhashed = 0;
while ((tmp = tmp->next) != head) {
struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
-printk("nfs_free_dentries: found %s/%s, d_count=%d, hashed=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name,
-dentry->d_count, !list_empty(&dentry->d_hash));
+ dprintk("nfs_free_dentries: found %s/%s, d_count=%d, hashed=%d\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name,
+ dentry->d_count, !list_empty(&dentry->d_hash));
if (!dentry->d_count) {
dget(dentry);
d_drop(dentry);
dput(dentry);
goto restart;
}
+ if (!list_empty(&dentry->d_hash))
+ unhashed++;
}
+ return unhashed;
+}
+
+/*
+ * Invalidate the local caches
+ */
+static void
+nfs_zap_caches(struct inode *inode)
+{
+ NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
+ NFS_CACHEINV(inode);
+
+ if (S_ISDIR(inode->i_mode))
+ nfs_invalidate_dircache(inode);
+ else
+ invalidate_inode_pages(inode);
+}
+
+/*
+ * Invalidate, but do not unhash, the inode
+ */
+static void
+nfs_invalidate_inode(struct inode *inode)
+{
+ umode_t save_mode = inode->i_mode;
+
+ make_bad_inode(inode);
+ inode->i_mode = save_mode;
+ nfs_inval(inode);
+ nfs_zap_caches(inode);
}
/*
@@ -508,7 +551,7 @@
__nfs_fhget(struct super_block *sb, struct nfs_fattr *fattr)
{
struct inode *inode;
- int max_count;
+ int max_count, stale_inode, unhashed = 0;
retry:
inode = iget(sb, fattr->fileid);
@@ -527,27 +570,30 @@
* as the inode may have become a different object.
* (We can probably handle modes changes here, too.)
*/
+ stale_inode = inode->i_mode &&
+ ((fattr->mode ^ inode->i_mode) & S_IFMT);
+ stale_inode |= inode->i_count && inode->i_count == unhashed;
max_count = S_ISDIR(fattr->mode) ? 1 : fattr->nlink;
- if (inode->i_count > max_count) {
-printk("__nfs_fhget: inode %ld busy, i_count=%d, i_nlink=%d\n",
-inode->i_ino, inode->i_count, inode->i_nlink);
- nfs_free_dentries(inode);
- if (inode->i_count > max_count) {
-printk("__nfs_fhget: inode %ld still busy, i_count=%d\n",
-inode->i_ino, inode->i_count);
+ if (stale_inode || inode->i_count > max_count + unhashed) {
+ dprintk("__nfs_fhget: inode %ld busy, i_count=%d, i_nlink=%d\n",
+ inode->i_ino, inode->i_count, inode->i_nlink);
+ unhashed = nfs_free_dentries(inode);
+ if (stale_inode || inode->i_count > max_count + unhashed) {
+ printk("__nfs_fhget: inode %ld still busy, i_count=%d\n",
+ inode->i_ino, inode->i_count);
if (!list_empty(&inode->i_dentry)) {
struct dentry *dentry;
dentry = list_entry(inode->i_dentry.next,
struct dentry, d_alias);
-printk("__nfs_fhget: killing %s/%s filehandle\n",
-dentry->d_parent->d_name.name, dentry->d_name.name);
- memset(dentry->d_fsdata, 0,
+ printk("__nfs_fhget: killing %s/%s filehandle\n",
+ dentry->d_parent->d_name.name,
+ dentry->d_name.name);
+ memset(dentry->d_fsdata, 0,
sizeof(struct nfs_fh));
- } else
- printk("NFS: inode %ld busy, no aliases?\n",
- inode->i_ino);
- make_bad_inode(inode);
+ }
remove_inode_hash(inode);
+ nfs_invalidate_inode(inode);
+ unhashed = 0;
}
iput(inode);
goto retry;
@@ -660,10 +706,6 @@
int status = 0;
struct nfs_fattr fattr;
- /* Don't bother revalidating if we've done it recently */
- if (jiffies - NFS_READTIME(inode) < NFS_ATTRTIMEO(inode))
- goto out;
-
dfprintk(PAGECACHE, "NFS: revalidating %s/%s, ino=%ld\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
inode->i_ino);
@@ -672,10 +714,9 @@
int error;
u32 *fh;
struct nfs_fh fhandle;
-#ifdef NFS_PARANOIA
-printk("nfs_revalidate_inode: %s/%s getattr failed, ino=%ld, error=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_ino, status);
-#endif
+ dfprintk(PAGECACHE, "nfs_revalidate_inode: %s/%s getattr failed, ino=%ld, error=%d\n",
+ dentry->d_parent->d_name.name,
+ dentry->d_name.name, inode->i_ino, status);
if (status != -ESTALE)
goto out;
/*
@@ -683,26 +724,25 @@
* and find out what the filehandle should be.
*/
fh = (u32 *) NFS_FH(dentry);
- printk("NFS: bad fh %08x%08x%08x%08x%08x%08x%08x%08x\n",
+ dfprintk(PAGECACHE, "NFS: bad fh %08x%08x%08x%08x%08x%08x%08x%08x\n",
fh[0],fh[1],fh[2],fh[3],fh[4],fh[5],fh[6],fh[7]);
error = nfs_proc_lookup(server, NFS_FH(dentry->d_parent),
dentry->d_name.name, &fhandle, &fattr);
if (error) {
- printk("NFS: lookup failed, error=%d\n", error);
+ dfprintk(PAGECACHE, "NFS: lookup failed, error=%d\n", error);
goto out;
}
fh = (u32 *) &fhandle;
- printk(" %08x%08x%08x%08x%08x%08x%08x%08x\n",
+ dfprintk(PAGECACHE, " %08x%08x%08x%08x%08x%08x%08x%08x\n",
fh[0],fh[1],fh[2],fh[3],fh[4],fh[5],fh[6],fh[7]);
goto out;
}
status = nfs_refresh_inode(inode, &fattr);
if (status) {
-#ifdef NFS_PARANOIA
-printk("nfs_revalidate_inode: %s/%s refresh failed, ino=%ld, error=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_ino, status);
-#endif
+ dfprintk(PAGECACHE, "nfs_revalidate_inode: %s/%s refresh failed, ino=%ld, error=%d\n",
+ dentry->d_parent->d_name.name,
+ dentry->d_name.name, inode->i_ino, status);
goto out;
}
dfprintk(PAGECACHE, "NFS: %s/%s revalidation complete\n",
@@ -808,29 +848,18 @@
printk("nfs_refresh_inode: inode %ld mode changed, %07o to %07o\n",
inode->i_ino, inode->i_mode, fattr->mode);
#endif
- fattr->mode = inode->i_mode; /* save mode */
- make_bad_inode(inode);
- nfs_inval(inode);
- inode->i_mode = fattr->mode; /* restore mode */
/*
* No need to worry about unhashing the dentry, as the
* lookup validation will know that the inode is bad.
- * (But we fall through to invalidate the caches.)
*/
+ nfs_invalidate_inode(inode);
+ goto out;
out_invalid:
- /*
- * Invalidate the local caches
- */
#ifdef NFS_DEBUG_VERBOSE
printk("nfs_refresh_inode: invalidating %ld pages\n", inode->i_nrpages);
#endif
- if (!S_ISDIR(inode->i_mode))
- invalidate_inode_pages(inode);
- else
- nfs_invalidate_dircache(inode);
- NFS_CACHEINV(inode);
- NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
+ nfs_zap_caches(inode);
goto out;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)