updated patch for 2.1.57 nfs client

Bill Hawes (whawes@star.net)
Sun, 05 Oct 1997 13:21:16 -0400


This is a multi-part message in MIME format.
--------------78EF18CBBFE087D9772967DE
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

I've made some further improvements to the nfs client and have attached
the latest patch.

The most important change involved updating dentry timestamps (the
d_time field) after every successful nfs lookup. Previously the code
only set d_time when a dentry was created, which would lead to many
attempts to invalidate it after the timestamp had expired. The
reasoning here is that if an nfs operation was successful, the path used
for the operation must be OK, so we can renew the dentry timestamps.

Regards,
Bill
--------------78EF18CBBFE087D9772967DE
Content-Type: text/plain; charset=us-ascii; name="nfs_57-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="nfs_57-patch"

--- linux-2.1.57/fs/nfs/inode.c.old Sat Sep 6 16:03:33 1997
+++ linux-2.1.57/fs/nfs/inode.c Sun Oct 5 12:55:09 1997
@@ -67,6 +67,7 @@
{
inode->i_blksize = inode->i_sb->s_blocksize;
inode->i_mode = 0;
+ inode->i_rdev = 0;
inode->i_op = NULL;
NFS_CACHEINV(inode);
}
@@ -75,6 +76,11 @@
nfs_put_inode(struct inode * inode)
{
dprintk("NFS: put_inode(%x/%ld)\n", inode->i_dev, inode->i_ino);
+ /*
+ * We want to get rid of unused inodes ...
+ */
+ if (inode->i_count == 1)
+ inode->i_nlink = 0;
}

static void
@@ -90,13 +96,16 @@
struct nfs_server *server = &sb->u.nfs_sb.s_server;
struct rpc_clnt *rpc;

+ /*
+ * Lock the super block while we bring down the daemons.
+ */
+ lock_super(sb);
if ((rpc = server->client) != NULL)
rpc_shutdown_client(rpc);

if (!(server->flags & NFS_MOUNT_NONLM))
lockd_down(); /* release rpc.lockd */
rpciod_down(); /* release rpciod */
- lock_super(sb);
sb->s_dev = 0;
unlock_super(sb);
MOD_DEC_USE_COUNT;
@@ -147,14 +156,12 @@
unsigned int authflavor;
int tcp;
kdev_t dev = sb->s_dev;
+ struct inode *root_inode;

MOD_INC_USE_COUNT;
- if (!data) {
- printk("nfs_read_super: missing data argument\n");
- sb->s_dev = 0;
- MOD_DEC_USE_COUNT;
- return NULL;
- }
+ if (!data)
+ goto out_miss_args;
+
if (data->version != NFS_MOUNT_VERSION) {
printk("nfs warning: mount version %s than kernel\n",
data->version < NFS_MOUNT_VERSION ? "older" : "newer");
@@ -164,13 +171,19 @@
data->bsize = 0;
}

+ /* We now require that the mount process passes the remote address */
+ memcpy(&srvaddr, &data->addr, sizeof(srvaddr));
+ if (srvaddr.sin_addr.s_addr == INADDR_ANY)
+ goto out_no_remote;
+
lock_super(sb);

- server = &sb->u.nfs_sb.s_server;
sb->s_magic = NFS_SUPER_MAGIC;
sb->s_dev = dev;
sb->s_op = &nfs_sops;
sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
+ sb->u.nfs_sb.s_root = data->root;
+ server = &sb->u.nfs_sb.s_server;
server->rsize = nfs_block_size(data->rsize, NULL);
server->wsize = nfs_block_size(data->wsize, NULL);
server->flags = data->flags;
@@ -179,15 +192,6 @@
server->acdirmin = data->acdirmin*HZ;
server->acdirmax = data->acdirmax*HZ;
strcpy(server->hostname, data->hostname);
- sb->u.nfs_sb.s_root = data->root;
-
- /* We now require that the mount process passes the remote address */
- memcpy(&srvaddr, &data->addr, sizeof(srvaddr));
- if (srvaddr.sin_addr.s_addr == INADDR_ANY) {
- printk("NFS: mount program didn't pass remote address!\n");
- MOD_DEC_USE_COUNT;
- return NULL;
- }

/* Which protocol do we use? */
tcp = (data->flags & NFS_MOUNT_TCP);
@@ -210,18 +214,13 @@
/* Now create transport and client */
xprt = xprt_create_proto(tcp? IPPROTO_TCP : IPPROTO_UDP,
&srvaddr, &timeparms);
- if (xprt == NULL) {
- printk("NFS: cannot create RPC transport.\n");
- goto failure;
- }
+ if (xprt == NULL)
+ goto out_no_xprt;

clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
NFS_VERSION, authflavor);
- if (clnt == NULL) {
- printk("NFS: cannot create RPC client.\n");
- xprt_destroy(xprt);
- goto failure;
- }
+ if (clnt == NULL)
+ goto out_no_client;

clnt->cl_intr = (data->flags & NFS_MOUNT_INTR)? 1 : 0;
clnt->cl_softrtry = (data->flags & NFS_MOUNT_SOFT)? 1 : 0;
@@ -229,29 +228,67 @@
server->client = clnt;

/* Fire up rpciod if not yet running */
+#ifdef RPCIOD_RESULT
+ if (rpciod_up())
+ goto out_no_iod;
+#else
rpciod_up();
+#endif

- /* Unlock super block and try to get root fh attributes */
+ /*
+ * Keep the super block locked while we try to get
+ * the root fh attributes.
+ */
+ root_inode = nfs_fhget(sb, &data->root, NULL);
+ if (!root_inode)
+ goto out_no_root;
+ sb->s_root = d_alloc_root(root_inode, NULL);
+ if (!sb->s_root)
+ goto out_no_root;
+ /* We're airborne */
unlock_super(sb);

- sb->s_root = d_alloc_root(nfs_fhget(sb, &data->root, NULL), NULL);
- if (sb->s_root != NULL) {
- /* We're airborne */
- if (!(server->flags & NFS_MOUNT_NONLM))
- lockd_up();
- return sb;
- }
+ /* Check whether to start the lockd process */
+ if (!(server->flags & NFS_MOUNT_NONLM))
+ lockd_up();
+ return sb;

/* Yargs. It didn't work out. */
+out_no_root:
printk("nfs_read_super: get root inode failed\n");
- rpc_shutdown_client(server->client);
+ iput(root_inode);
rpciod_down();
+#ifdef RPCIOD_RESULT
+ goto out_shutdown;

-failure:
- MOD_DEC_USE_COUNT;
- if (sb->s_lock)
- unlock_super(sb);
+out_no_iod:
+ printk("nfs_read_super: couldn't start rpciod!\n");
+out_shutdown:
+#endif
+ rpc_shutdown_client(server->client);
+ goto out_unlock;
+
+out_no_client:
+ printk("NFS: cannot create RPC client.\n");
+ xprt_destroy(xprt);
+ goto out_unlock;
+
+out_no_xprt:
+ printk("NFS: cannot create RPC transport.\n");
+out_unlock:
+ unlock_super(sb);
+ goto out_fail;
+
+out_no_remote:
+ printk("NFS: mount program didn't pass remote address!\n");
+ goto out_fail;
+
+out_miss_args:
+ printk("nfs_read_super: missing data argument\n");
+
+out_fail:
sb->s_dev = 0;
+ MOD_DEC_USE_COUNT;
return NULL;
}

--- linux-2.1.57/fs/nfs/dir.c.old Fri Sep 26 08:10:51 1997
+++ linux-2.1.57/fs/nfs/dir.c Sun Oct 5 12:48:44 1997
@@ -350,20 +350,46 @@
unsigned long time = jiffies - dentry->d_time;
unsigned long max = 5*HZ;

- if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
- max = 10*HZ;
+ if (dentry->d_inode) {
+ if (is_bad_inode(dentry->d_inode)) {
+#if 1
+printk("nfs_lookup_validate: %s/%s has dud inode\n",
+dentry->d_parent->d_name.name, dentry->d_name.name);
+#endif
+ goto bad;
+ }
+ if (S_ISDIR(dentry->d_inode->i_mode))
+ max = 10*HZ;
+ }
+
return time < max;
+bad:
+ return 0;
}

static void nfs_silly_delete(struct dentry *);

static struct dentry_operations nfs_dentry_operations = {
- nfs_lookup_revalidate,
+ nfs_lookup_revalidate, /* d_validate(struct dentry *) */
0, /* d_hash */
0, /* d_compare */
- nfs_silly_delete,
+ nfs_silly_delete, /* d_delete(struct dentry *) */
};

+/*
+ * Whenever a lookup succeeds, we know the parent directories
+ * are all valid, so we want to update the dentry timestamps.
+ */
+void nfs_renew_times(struct dentry * dentry)
+{
+ for (;;) {
+ dentry->d_time = jiffies;
+ if (dentry == dentry->d_parent)
+ break;
+ dentry = dentry->d_parent;
+ }
+}
+
static int nfs_lookup(struct inode *dir, struct dentry * dentry)
{
struct inode *inode;
@@ -383,20 +409,42 @@
if (len > NFS_MAXNAMLEN)
return -ENAMETOOLONG;

- error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dir), dentry->d_name.name, &fhandle, &fattr);
-
+ error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dir),
+ dentry->d_name.name, &fhandle, &fattr);
inode = NULL;
+ if (error == -ENOENT)
+ goto no_entry;
if (!error) {
+ error = -EACCES;
inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
- if (!inode)
- return -EACCES;
- } else if (error != -ENOENT)
- return error;
-
- dentry->d_time = jiffies;
- dentry->d_op = &nfs_dentry_operations;
- d_add(dentry, inode);
- return 0;
+ if (inode) {
+ no_entry:
+ dentry->d_op = &nfs_dentry_operations;
+ d_add(dentry, inode);
+ nfs_renew_times(dentry);
+ error = 0;
+ }
+ }
+ return error;
+}
+
+/*
+ * Code common to create, mkdir, and mknod.
+ */
+static int nfs_instantiate(struct inode *dir, struct dentry *dentry,
+ struct nfs_fattr *fattr, struct nfs_fh *fhandle)
+{
+ struct inode *inode;
+ int error = -EACCES;
+
+ inode = nfs_fhget(dir->i_sb, fhandle, fattr);
+ if (inode) {
+ nfs_invalidate_dircache(dir);
+ d_instantiate(dentry, inode);
+ nfs_renew_times(dentry);
+ error = 0;
+ }
+ return error;
}

static int nfs_create(struct inode *dir, struct dentry * dentry, int mode)
@@ -404,7 +452,6 @@
struct nfs_sattr sattr;
struct nfs_fattr fattr;
struct nfs_fh fhandle;
- struct inode *inode;
int error;

dfprintk(VFS, "NFS: create(%x/%ld, %s\n",
@@ -422,18 +469,10 @@
sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
- dentry->d_name.name, &sattr, &fhandle, &fattr);
-
- if (error)
- return error;
-
- inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
- if (!inode)
- return -EACCES;
-
- nfs_invalidate_dircache(dir);
- d_instantiate(dentry, inode);
- return 0;
+ dentry->d_name.name, &sattr, &fhandle, &fattr);
+ if (!error)
+ error = nfs_instantiate(dir, dentry, &fattr, &fhandle);
+ return error;
}

static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
@@ -441,7 +480,6 @@
struct nfs_sattr sattr;
struct nfs_fattr fattr;
struct nfs_fh fhandle;
- struct inode *inode;
int error;

dfprintk(VFS, "NFS: mknod(%x/%ld, %s\n",
@@ -462,18 +500,10 @@

sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
- dentry->d_name.name, &sattr, &fhandle, &fattr);
-
- if (error)
- return error;
-
- inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
- if (!inode)
- return -EACCES;
-
- nfs_invalidate_dircache(dir);
- d_instantiate(dentry, inode);
- return 0;
+ dentry->d_name.name, &sattr, &fhandle, &fattr);
+ if (!error)
+ error = nfs_instantiate(dir, dentry, &fattr, &fhandle);
+ return error;
}

static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
@@ -481,7 +511,6 @@
struct nfs_sattr sattr;
struct nfs_fattr fattr;
struct nfs_fh fhandle;
- struct inode * inode;
int error;

dfprintk(VFS, "NFS: mkdir(%x/%ld, %s\n",
@@ -500,20 +529,16 @@
sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;

error = nfs_proc_mkdir(NFS_SERVER(dir), NFS_FH(dir),
- dentry->d_name.name, &sattr, &fhandle, &fattr);
-
- if (error)
- return error;
-
- inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
- if (!inode)
- return -EACCES;
-
- nfs_invalidate_dircache(dir);
- d_instantiate(dentry, inode);
- return 0;
+ dentry->d_name.name, &sattr, &fhandle, &fattr);
+ if (!error)
+ error = nfs_instantiate(dir, dentry, &fattr, &fhandle);
+ return error;
}

+/*
+ * Update inode->i_nlink immediately after a successful operation.
+ * (See comments for nfs_unlink.)
+ */
static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
{
int error;
@@ -530,12 +555,14 @@
return -ENAMETOOLONG;

error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dir), dentry->d_name.name);
- if (error)
- return error;
-
- nfs_invalidate_dircache(dir);
- d_delete(dentry);
- return 0;
+ if (!error) {
+ if (dentry->d_inode->i_nlink)
+ dentry->d_inode->i_nlink --;
+ nfs_invalidate_dircache(dir);
+ nfs_renew_times(dentry);
+ d_delete(dentry);
+ }
+ return error;
}


@@ -642,16 +669,15 @@
error = nfs_proc_rename(NFS_SERVER(dir),
NFS_FH(dir), dentry->d_name.name,
NFS_FH(dir), silly);
- if (error) {
- dput(sdentry);
- return error;
+ if (!error) {
+ nfs_invalidate_dircache(dir);
+ d_move(dentry, sdentry);
+ dentry->d_flags |= DCACHE_NFSFS_RENAMED;
+ /* If we return 0 we don't unlink */
+ nfs_renew_times(dentry);
}
- nfs_invalidate_dircache(dir);
- d_move(dentry, sdentry);
dput(sdentry);
- dentry->d_flags |= DCACHE_NFSFS_RENAMED;
-
- return 0; /* don't unlink */
+ return error;
}

static void nfs_silly_delete(struct dentry *dentry)
@@ -670,8 +696,18 @@
if (error < 0)
printk("NFS " __FUNCTION__ " failed (err = %d)\n",
-error);
- dentry->d_inode->i_nlink --;
+ if (dentry->d_inode) {
+ if (dentry->d_inode->i_nlink)
+ dentry->d_inode->i_nlink --;
+ } else
+ printk("nfs_silly_delete: negative dentry %s/%s\n",
+ dentry->d_parent->d_name.name,
+ dentry->d_name.name);
nfs_invalidate_dircache(dir);
+ /*
+ * The dentry is unhashed, but we want to make it negative.
+ */
+ d_delete(dentry);
}
}

@@ -680,8 +716,11 @@
*
* If sillyrename() returns 0, we do nothing, otherwise we unlink.
*
- * inode->i_nlink is updated here rather than waiting for the next
- * nfs_refresh_inode() for cosmetic reasons only.
+ * Updating inode->i_nlink here rather than waiting for the next
+ * nfs_refresh_inode() is not merely cosmetic; once an object has
+ * been deleted, we want to get rid of the inode locally. The NFS
+ * server may reuse the fileid for a new inode, and we don't want
+ * that to be confused with this inode.
*/
static int nfs_unlink(struct inode *dir, struct dentry *dentry)
{
@@ -700,20 +739,19 @@

error = nfs_sillyrename(dir, dentry);

- if (error == -EBUSY) {
- return -EBUSY;
- } else if (error < 0) {
+ if (error && error != -EBUSY) {
error = nfs_proc_remove(NFS_SERVER(dir),
NFS_FH(dir), dentry->d_name.name);
- if (error < 0)
- return error;
-
- dentry->d_inode->i_nlink --;
- nfs_invalidate_dircache(dir);
- d_delete(dentry);
+ if (!error) {
+ if (dentry->d_inode->i_nlink)
+ dentry->d_inode->i_nlink --;
+ nfs_invalidate_dircache(dir);
+ d_delete(dentry);
+ nfs_renew_times(dentry);
+ }
}

- return 0;
+ return error;
}

static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
@@ -740,22 +778,21 @@
sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;

error = nfs_proc_symlink(NFS_SERVER(dir), NFS_FH(dir),
- dentry->d_name.name, symname, &sattr);
-
- if (error)
- return error;
-
- nfs_invalidate_dircache(dir);
- /* this looks _funny_ doesn't it? But: nfs_proc_symlink()
- * only fills in sattr, not fattr. Thus nfs_fhget() cannot be
- * called, it would be pointless, without a valid fattr
- * argument. Other possibility: call nfs_proc_lookup()
- * HERE. But why? If somebody wants to reference this
- * symlink, the cached_lookup() will fail, and
- * nfs_proc_symlink() will be called anyway.
- */
- d_drop(dentry);
- return 0;
+ dentry->d_name.name, symname, &sattr);
+ if (!error) {
+ nfs_invalidate_dircache(dir);
+ nfs_renew_times(dentry->d_parent);
+ /* this looks _funny_ doesn't it? But: nfs_proc_symlink()
+ * only fills in sattr, not fattr. Thus nfs_fhget() cannot be
+ * called, it would be pointless, without a valid fattr
+ * argument. Other possibility: call nfs_proc_lookup()
+ * HERE. But why? If somebody wants to reference this
+ * symlink, the cached_lookup() will fail, and
+ * nfs_proc_symlink() will be called anyway.
+ */
+ d_drop(dentry);
+ }
+ return error;
}

static int nfs_link(struct inode *inode, struct inode *dir, struct dentry *dentry)
@@ -774,17 +811,16 @@
if (dentry->d_name.len > NFS_MAXNAMLEN)
return -ENAMETOOLONG;

- error = nfs_proc_link(NFS_SERVER(inode), NFS_FH(inode),
- NFS_FH(dir), dentry->d_name.name);
-
- if (error)
- return error;
-
- nfs_invalidate_dircache(dir);
- inode->i_count ++;
- inode->i_nlink ++; /* no need to wait for nfs_refresh_inode() */
- d_instantiate(dentry, inode);
- return 0;
+ error = nfs_proc_link(NFS_SERVER(inode), NFS_FH(inode), NFS_FH(dir),
+ dentry->d_name.name);
+ if (!error) {
+ nfs_invalidate_dircache(dir);
+ inode->i_count ++;
+ inode->i_nlink ++; /* no need to wait for nfs_refresh_inode() */
+ d_instantiate(dentry, inode);
+ error = 0;
+ }
+ return error;
}

/*
@@ -843,15 +879,19 @@
error = nfs_proc_rename(NFS_SERVER(old_dir),
NFS_FH(old_dir), old_dentry->d_name.name,
NFS_FH(new_dir), new_dentry->d_name.name);
- if (error)
- return error;
-
- nfs_invalidate_dircache(old_dir);
- nfs_invalidate_dircache(new_dir);
+ if (!error) {
+ nfs_invalidate_dircache(old_dir);
+ nfs_invalidate_dircache(new_dir);
+ /*
+ * We know these paths are still valid ...
+ */
+ nfs_renew_times(old_dentry);
+ nfs_renew_times(new_dentry->d_parent);

- /* Update the dcache */
- d_move(old_dentry, new_dentry);
- return 0;
+ /* Update the dcache */
+ d_move(old_dentry, new_dentry);
+ }
+ return error;
}

/*
@@ -860,23 +900,68 @@
* of the server's inode.
*/

-void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
+int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
{
- int was_empty;
+ int error = -EIO;

dfprintk(VFS, "NFS: refresh_inode(%x/%ld ct=%d)\n",
inode->i_dev, inode->i_ino, inode->i_count);

if (!inode || !fattr) {
printk("nfs_refresh_inode: inode or fattr is NULL\n");
- return;
+ goto out;
}
if (inode->i_ino != fattr->fileid) {
printk("nfs_refresh_inode: inode number mismatch\n");
- return;
+ goto out;
}
- was_empty = (inode->i_mode == 0);
- inode->i_mode = fattr->mode;
+ /*
+ * Check whether the mode has been set, as we only want to
+ * do this once. (We don't allow inodes to change types.)
+ */
+ if (inode->i_mode == 0) {
+ inode->i_mode = fattr->mode;
+ if (S_ISREG(inode->i_mode))
+ inode->i_op = &nfs_file_inode_operations;
+ else if (S_ISDIR(inode->i_mode))
+ inode->i_op = &nfs_dir_inode_operations;
+ else if (S_ISLNK(inode->i_mode))
+ inode->i_op = &nfs_symlink_inode_operations;
+ else if (S_ISCHR(inode->i_mode)) {
+ inode->i_op = &chrdev_inode_operations;
+ inode->i_rdev = to_kdev_t(fattr->rdev);
+ } else if (S_ISBLK(inode->i_mode)) {
+ inode->i_op = &blkdev_inode_operations;
+ inode->i_rdev = to_kdev_t(fattr->rdev);
+ } else if (S_ISFIFO(inode->i_mode))
+ init_fifo(inode);
+ else
+ inode->i_op = NULL;
+ } else if ((inode->i_mode & S_IFMT) == (fattr->mode & S_IFMT)) {
+ inode->i_mode = fattr->mode;
+ } else {
+ mode_t old_mode;
+ /*
+ * Big trouble! The inode has become a different object.
+ */
+#if 1
+printk("nfs_refresh_inode: mode changed, %07o to %07o\n",
+inode->i_mode, fattr->mode);
+#endif
+ old_mode = inode->i_mode; /* save mode */
+ make_bad_inode(inode);
+ inode->i_mode = old_mode; /* restore mode */
+ inode->i_nlink = 0;
+ /*
+ * No need to worry about unhashing the dentry, as the
+ * lookup validation will know that the inode is bad.
+ * (But we do want to invalidate the caches.)
+ */
+ invalidate_inode_pages(inode);
+ nfs_invalidate_dircache(inode);
+ goto out;
+ }
+
inode->i_nlink = fattr->nlink;
inode->i_uid = fattr->uid;
inode->i_gid = fattr->gid;
@@ -893,29 +978,13 @@
NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
}
inode->i_size = fattr->size;
- if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- inode->i_rdev = to_kdev_t(fattr->rdev);
- else
- inode->i_rdev = 0;
inode->i_blocks = fattr->blocks;
inode->i_atime = fattr->atime.seconds;
inode->i_mtime = fattr->mtime.seconds;
inode->i_ctime = fattr->ctime.seconds;
- if (S_ISREG(inode->i_mode))
- inode->i_op = &nfs_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
- inode->i_op = &nfs_dir_inode_operations;
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &nfs_symlink_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode)) {
- if (was_empty)
- init_fifo(inode);
- } else
- inode->i_op = NULL;
+ error = 0;
+out:
+ return error;
}

/*
--- linux-2.1.57/include/linux/nfs_fs.h.old Sat Sep 20 08:16:16 1997
+++ linux-2.1.57/include/linux/nfs_fs.h Sat Oct 4 16:03:03 1997
@@ -138,7 +138,7 @@
extern int init_nfs_fs(void);
extern struct inode *nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle,
struct nfs_fattr *fattr);
-extern void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr);
+extern int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr);
extern int nfs_revalidate(struct inode *);
extern int _nfs_revalidate_inode(struct nfs_server *, struct inode *);

--------------78EF18CBBFE087D9772967DE--