patch-2.4.0-test12 linux/fs/nfs/inode.c
Next file: linux/fs/nfs/nfs3proc.c
Previous file: linux/fs/nfs/file.c
Back to the patch index
Back to the overall index
- Lines: 444
- Date:
Mon Dec 11 17:46:04 2000
- Orig file:
v2.4.0-test11/linux/fs/nfs/inode.c
- Orig date:
Sun Nov 19 18:44:19 2000
diff -u --recursive --new-file v2.4.0-test11/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
@@ -39,7 +39,7 @@
#define NFSDBG_FACILITY NFSDBG_VFS
#define NFS_PARANOIA 1
-static struct inode * __nfs_fhget(struct super_block *, struct nfs_fattr *);
+static struct inode * __nfs_fhget(struct super_block *, struct nfs_fh *, struct nfs_fattr *);
void nfs_zap_caches(struct inode *);
static void nfs_invalidate_inode(struct inode *);
@@ -222,13 +222,10 @@
return NULL;
}
- inode = __nfs_fhget(sb, &fattr);
+ inode = __nfs_fhget(sb, rootfh, &fattr);
return inode;
}
-extern struct nfs_fh *nfs_fh_alloc(void);
-extern void nfs_fh_free(struct nfs_fh *p);
-
/*
* The way this works is that the mount process passes a structure
* in the data argument which contains the server's IP address
@@ -242,7 +239,7 @@
struct nfs_server *server;
struct rpc_xprt *xprt = NULL;
struct rpc_clnt *clnt = NULL;
- struct nfs_fh *root = &data->root, *root_fh, fh;
+ struct nfs_fh *root = &data->root, fh;
struct inode *root_inode = NULL;
unsigned int authflavor;
struct sockaddr_in srvaddr;
@@ -365,16 +362,10 @@
* Keep the super block locked while we try to get
* the root fh attributes.
*/
- root_fh = nfs_fh_alloc();
- if (!root_fh)
- goto out_no_fh;
- memcpy((u8*)root_fh, (u8*)root, sizeof(*root));
-
/* Did getting the root inode fail? */
if (!(root_inode = nfs_get_root(sb, root))
&& (data->flags & NFS_MOUNT_VER3)) {
data->flags &= ~NFS_MOUNT_VER3;
- nfs_fh_free(root_fh);
rpciod_down();
rpc_shutdown_client(server->client);
goto nfsv3_try_again;
@@ -387,7 +378,6 @@
goto out_no_root;
sb->s_root->d_op = &nfs_dentry_operations;
- sb->s_root->d_fsdata = root_fh;
/* Get some general file system info */
if (server->rpc_ops->statfs(server, root, &fsinfo) >= 0) {
@@ -462,8 +452,6 @@
out_no_root:
printk("nfs_read_super: get root inode failed\n");
iput(root_inode);
- nfs_fh_free(root_fh);
-out_no_fh:
rpciod_down();
goto out_shutdown;
@@ -507,7 +495,7 @@
struct nfs_fsinfo res;
int error;
- error = server->rpc_ops->statfs(server, NFS_FH(sb->s_root), &res);
+ error = server->rpc_ops->statfs(server, NFS_FH(sb->s_root->d_inode), &res);
buf->f_type = NFS_SUPER_MAGIC;
if (error < 0)
goto out_err;
@@ -532,43 +520,6 @@
}
/*
- * Free all unused dentries in an inode's alias list.
- *
- * Subtle note: we have to be very careful not to cause
- * any IO operations with the stale dentries, as this
- * 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
- */
-static int
-nfs_free_dentries(struct inode *inode)
-{
- struct list_head *tmp, *head;
- int unhashed;
-
- if (S_ISDIR(inode->i_mode)) {
- struct dentry *dentry = d_find_alias(inode);
- if (dentry) {
- shrink_dcache_parent(dentry);
- dput(dentry);
- }
- }
- d_prune_aliases(inode);
- spin_lock(&dcache_lock);
- head = &inode->i_dentry;
- tmp = head;
- unhashed = 0;
- while ((tmp = tmp->next) != head) {
- struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
- if (list_empty(&dentry->d_hash))
- unhashed++;
- }
- spin_unlock(&dcache_lock);
- return unhashed;
-}
-
-/*
* Invalidate the local caches
*/
void
@@ -600,7 +551,7 @@
* Fill in inode information from the fattr.
*/
static void
-nfs_fill_inode(struct inode *inode, struct nfs_fattr *fattr)
+nfs_fill_inode(struct inode *inode, struct nfs_fh *fh, struct nfs_fattr *fattr)
{
/*
* Check whether the mode has been set, as we only want to
@@ -638,10 +589,16 @@
NFS_CACHE_ISIZE(inode) = fattr->size;
NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
NFS_ATTRTIMEO_UPDATE(inode) = jiffies;
+ memcpy(&inode->u.nfs_i.fh, fh, sizeof(inode->u.nfs_i.fh));
}
nfs_refresh_inode(inode, fattr);
}
+struct nfs_find_desc {
+ struct nfs_fh *fh;
+ struct nfs_fattr *fattr;
+};
+
/*
* In NFSv3 we can have 64bit inode numbers. In order to support
* this, and re-exported directories (also seen in NFSv2)
@@ -651,43 +608,38 @@
static int
nfs_find_actor(struct inode *inode, unsigned long ino, void *opaque)
{
- struct nfs_fattr *fattr = (struct nfs_fattr *)opaque;
+ struct nfs_find_desc *desc = (struct nfs_find_desc *)opaque;
+ struct nfs_fh *fh = desc->fh;
+ struct nfs_fattr *fattr = desc->fattr;
+
if (NFS_FSID(inode) != fattr->fsid)
return 0;
if (NFS_FILEID(inode) != fattr->fileid)
return 0;
+ if (memcmp(&inode->u.nfs_i.fh, fh, sizeof(inode->u.nfs_i.fh)) != 0)
+ return 0;
return 1;
}
-static int
-nfs_inode_is_stale(struct inode *inode, struct nfs_fattr *fattr)
+int
+nfs_inode_is_stale(struct inode *inode, struct nfs_fh *fh, struct nfs_fattr *fattr)
{
- int unhashed;
- int is_stale = 0;
+ /* Empty inodes are not stale */
+ if (!inode->i_mode)
+ return 0;
- if (inode->i_mode &&
- (fattr->mode & S_IFMT) != (inode->i_mode & S_IFMT))
- is_stale = 1;
+ if ((fattr->mode & S_IFMT) != (inode->i_mode & S_IFMT))
+ return 1;
if (is_bad_inode(inode))
- is_stale = 1;
-
- /*
- * If the inode seems stale, free up cached dentries.
- */
- unhashed = nfs_free_dentries(inode);
+ return 1;
- /* Assume we're holding an i_count
- *
- * NB: sockets sometimes have volatile file handles
- * don't invalidate their inodes even if all dentries are
- * unhashed.
- */
- if (unhashed && atomic_read(&inode->i_count) == unhashed + 1
- && !S_ISSOCK(inode->i_mode) && !S_ISFIFO(inode->i_mode))
- is_stale = 1;
+ /* Has the filehandle changed? If so is the old one stale? */
+ if (memcmp(&inode->u.nfs_i.fh, fh, sizeof(inode->u.nfs_i.fh)) != 0 &&
+ __nfs_revalidate_inode(NFS_SERVER(inode),inode) == -ESTALE)
+ return 1;
- return is_stale;
+ return 0;
}
/*
@@ -696,8 +648,6 @@
* the vfs read_inode function because there is no way to pass the
* file handle or current attributes into the read_inode function.
*
- * We provide a special check for NetApp .snapshot directories to avoid
- * inode aliasing problems. All snapshot inodes are anonymous (unhashed).
*/
struct inode *
nfs_fhget(struct dentry *dentry, struct nfs_fh *fhandle,
@@ -708,44 +658,16 @@
dprintk("NFS: nfs_fhget(%s/%s fileid=%Ld)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
(long long)fattr->fileid);
-
- /* Install the file handle in the dentry */
- memcpy(dentry->d_fsdata, fhandle, sizeof(struct nfs_fh));
-
-#ifdef CONFIG_NFS_SNAPSHOT
- /*
- * Check for NetApp snapshot dentries, and get an
- * unhashed inode to avoid aliasing problems.
- */
- if ((dentry->d_parent->d_inode->u.nfs_i.flags & NFS_IS_SNAPSHOT) ||
- (dentry->d_name.len == 9 &&
- memcmp(dentry->d_name.name, ".snapshot", 9) == 0)) {
- struct inode *inode = new_inode(sb);
- if (!inode)
- goto out;
- inode->i_ino = nfs_fattr_to_ino_t(fattr);
- nfs_read_inode(inode);
- nfs_fill_inode(inode, fattr);
- inode->u.nfs_i.flags |= NFS_IS_SNAPSHOT;
- dprintk("NFS: nfs_fhget(snapshot ino=%ld)\n", inode->i_ino);
- out:
- return inode;
- }
-#endif
- return __nfs_fhget(sb, fattr);
+ return __nfs_fhget(sb, fhandle, fattr);
}
/*
* Look up the inode by super block and fattr->fileid.
- *
- * Note carefully the special handling of busy inodes (i_count > 1).
- * With the kernel 2.1.xx dcache all inodes except hard links must
- * have i_count == 1 after iget(). Otherwise, it indicates that the
- * server has reused a fileid (i_ino) and we have a stale inode.
*/
static struct inode *
-__nfs_fhget(struct super_block *sb, struct nfs_fattr *fattr)
+__nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
{
+ struct nfs_find_desc desc = { fh, fattr };
struct inode *inode = NULL;
unsigned long ino;
@@ -759,33 +681,13 @@
ino = nfs_fattr_to_ino_t(fattr);
- while((inode = iget4(sb, ino, nfs_find_actor, fattr)) != NULL) {
-
- /*
- * Check for busy inodes, and attempt to get rid of any
- * unused local references. If successful, we release the
- * inode and try again.
- *
- * Note that the busy test uses the values in the fattr,
- * as the inode may have become a different object.
- * (We can probably handle modes changes here, too.)
- */
- if (!nfs_inode_is_stale(inode,fattr))
- break;
-
- dprintk("__nfs_fhget: inode %ld still busy, i_count=%d\n",
- inode->i_ino, atomic_read(&inode->i_count));
- nfs_zap_caches(inode);
- remove_inode_hash(inode);
- iput(inode);
- }
-
- if (!inode)
+ if (!(inode = iget4(sb, ino, nfs_find_actor, &desc)))
goto out_no_inode;
- nfs_fill_inode(inode, fattr);
- dprintk("NFS: __nfs_fhget(%x/%ld ct=%d)\n",
- inode->i_dev, inode->i_ino, atomic_read(&inode->i_count));
+ nfs_fill_inode(inode, fh, fattr);
+ dprintk("NFS: __nfs_fhget(%x/%Ld ct=%d)\n",
+ inode->i_dev, (long long)NFS_FILEID(inode),
+ atomic_read(&inode->i_count));
out:
return inode;
@@ -820,7 +722,7 @@
if (error)
goto out;
- error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr);
+ error = NFS_PROTO(inode)->setattr(inode, &fattr, attr);
if (error)
goto out;
/*
@@ -872,7 +774,8 @@
int
nfs_revalidate(struct dentry *dentry)
{
- return nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+ struct inode *inode = dentry->d_inode;
+ return nfs_revalidate_inode(NFS_SERVER(inode), inode);
}
/*
@@ -913,18 +816,16 @@
* the cached attributes have to be refreshed.
*/
int
-__nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
+__nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
{
- struct inode *inode = dentry->d_inode;
int status = 0;
struct nfs_fattr fattr;
- dfprintk(PAGECACHE, "NFS: revalidating %s/%s, ino=%ld\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- inode->i_ino);
+ dfprintk(PAGECACHE, "NFS: revalidating (%x/%Ld)\n",
+ inode->i_dev, (long long)NFS_FILEID(inode));
lock_kernel();
- if (!inode || is_bad_inode(inode)) {
+ if (!inode || is_bad_inode(inode) || NFS_STALE(inode)) {
unlock_kernel();
return -ESTALE;
}
@@ -936,55 +837,35 @@
return status;
}
if (time_before(jiffies,NFS_READTIME(inode)+NFS_ATTRTIMEO(inode))) {
- unlock_kernel();
- return 0;
+ status = NFS_STALE(inode) ? -ESTALE : 0;
+ goto out_nowait;
}
}
NFS_FLAGS(inode) |= NFS_INO_REVALIDATING;
- status = NFS_PROTO(inode)->getattr(dentry, &fattr);
+ status = NFS_PROTO(inode)->getattr(inode, &fattr);
if (status) {
- struct dentry *dir = dentry->d_parent;
- struct inode *dir_i = dir->d_inode;
- int error;
- u32 *fh;
- struct nfs_fh fhandle;
- dfprintk(PAGECACHE, "nfs_revalidate_inode: %s/%s getattr failed, ino=%ld, error=%d\n",
- dir->d_name.name, dentry->d_name.name,
- inode->i_ino, status);
- if (status != -ESTALE)
- goto out;
- /*
- * A "stale filehandle" error ... show the current fh
- * and find out what the filehandle should be.
- */
- fh = (u32 *) NFS_FH(dentry)->data;
- 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_PROTO(dir_i)->lookup(dir, &dentry->d_name,
- &fhandle, &fattr);
- if (error) {
- dfprintk(PAGECACHE, "NFS: lookup failed, error=%d\n", error);
- goto out;
+ dfprintk(PAGECACHE, "nfs_revalidate_inode: (%x/%Ld) getattr failed, error=%d\n",
+ inode->i_dev, (long long)NFS_FILEID(inode), status);
+ if (status == -ESTALE) {
+ NFS_FLAGS(inode) |= NFS_INO_STALE;
+ remove_inode_hash(inode);
}
- fh = (u32 *) fhandle.data;
- 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) {
- 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);
+ dfprintk(PAGECACHE, "nfs_revalidate_inode: (%x/%Ld) refresh failed, error=%d\n",
+ inode->i_dev, (long long)NFS_FILEID(inode), status);
goto out;
}
- dfprintk(PAGECACHE, "NFS: %s/%s revalidation complete\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ dfprintk(PAGECACHE, "NFS: (%x/%Ld) revalidation complete\n",
+ inode->i_dev, (long long)NFS_FILEID(inode));
out:
NFS_FLAGS(inode) &= ~NFS_INO_REVALIDATING;
wake_up(&inode->i_wait);
+ out_nowait:
unlock_kernel();
return status;
}
@@ -1165,8 +1046,6 @@
*/
static DECLARE_FSTYPE(nfs_fs_type, "nfs", nfs_read_super, FS_ODD_RENAME);
-extern int nfs_init_fhcache(void);
-extern void nfs_destroy_fhcache(void);
extern int nfs_init_nfspagecache(void);
extern void nfs_destroy_nfspagecache(void);
extern int nfs_init_readpagecache(void);
@@ -1180,10 +1059,6 @@
{
int err;
- err = nfs_init_fhcache();
- if (err)
- return err;
-
err = nfs_init_nfspagecache();
if (err)
return err;
@@ -1218,7 +1093,6 @@
{
nfs_destroy_readpagecache();
nfs_destroy_nfspagecache();
- nfs_destroy_fhcache();
#ifdef CONFIG_PROC_FS
rpc_proc_unregister("nfs");
#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)