diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-06-13 16:29:25 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-06-13 16:29:25 +0000 |
commit | db7d4daea91e105e3859cf461d7e53b9b77454b2 (patch) | |
tree | 9bb65b95440af09e8aca63abe56970dd3360cc57 /fs/nfs/inode.c | |
parent | 9c1c01ead627bdda9211c9abd5b758d6c687d8ac (diff) |
Merge with Linux 2.2.8.
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 151 |
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; } |