summaryrefslogtreecommitdiffstats
path: root/fs/nfs/inode.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-06-13 16:29:25 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-06-13 16:29:25 +0000
commitdb7d4daea91e105e3859cf461d7e53b9b77454b2 (patch)
tree9bb65b95440af09e8aca63abe56970dd3360cc57 /fs/nfs/inode.c
parent9c1c01ead627bdda9211c9abd5b758d6c687d8ac (diff)
Merge with Linux 2.2.8.
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r--fs/nfs/inode.c151
1 files changed, 100 insertions, 51 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 72130244a..c46eeb57b 100644
--- a/fs/nfs/inode.c
+++ b/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 *);
@@ -224,6 +226,8 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
lock_super(sb);
+ sb->s_flags |= MS_ODD_RENAME; /* This should go away */
+
sb->s_magic = NFS_SUPER_MAGIC;
sb->s_op = &nfs_sops;
sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
@@ -232,6 +236,11 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
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;
@@ -386,25 +395,61 @@ nfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
* 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);
}
/*
@@ -506,7 +551,7 @@ static struct inode *
__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);
@@ -525,27 +570,30 @@ retry:
* 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;
@@ -597,10 +645,8 @@ printk("nfs_notify_change: revalidate failed, error=%d\n", error);
sattr.gid = attr->ia_gid;
sattr.size = (u32) -1;
- if ((attr->ia_valid & ATTR_SIZE) && S_ISREG(inode->i_mode)) {
+ if ((attr->ia_valid & ATTR_SIZE) && S_ISREG(inode->i_mode))
sattr.size = attr->ia_size;
- nfs_flush_trunc(inode, sattr.size);
- }
sattr.mtime.seconds = sattr.mtime.useconds = (u32) -1;
if (attr->ia_valid & ATTR_MTIME) {
@@ -614,6 +660,10 @@ printk("nfs_notify_change: revalidate failed, error=%d\n", error);
sattr.atime.useconds = 0;
}
+ error = nfs_wb_all(inode);
+ if (error)
+ goto out;
+
error = nfs_proc_setattr(NFS_DSERVER(dentry), NFS_FH(dentry),
&sattr, &fattr);
if (error)
@@ -646,6 +696,22 @@ nfs_revalidate(struct dentry *dentry)
}
/*
+ * These are probably going to contain hooks for
+ * allocating and releasing RPC credentials for
+ * the file. I'll have to think about Tronds patch
+ * a bit more..
+ */
+int nfs_open(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+int nfs_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+/*
* This function is called whenever some part of NFS notices that
* the cached attributes have to be refreshed.
*/
@@ -656,10 +722,6 @@ _nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
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);
@@ -668,10 +730,9 @@ _nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
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;
/*
@@ -679,26 +740,25 @@ dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_ino, status);
* 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",
@@ -804,29 +864,18 @@ out_changed:
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;
}