Patch for NCP inode race

Bill Hawes (whawes@star.net)
Tue, 08 Jul 1997 14:28:17 -0400


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

Troels Arvin wrote:
> ... so my appetite for inode-related patches is high.

The attached patch (in conjunction with my clear_inode patch) should fix
your NCP-related inode problems (or at least some of them :-)).

>From studying the code it appears that blocking while closing the file
was allowing the inode to be put back in service, so that the open count
was > 1 when clear_inode was called. The changes I made postpone the
release of the inode's data structures until after the call to
clear_inode. Then if the inode is put back in use, the routine exits
harmlessly.

The patch is against 2.0.30. I haven't tested it (other than to see
that it compiles), so please let me know of any further problems.

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

--- fs/ncpfs/inode.c.old Sat Nov 30 05:21:21 1996
+++ fs/ncpfs/inode.c Tue Jul 8 14:08:45 1997
@@ -125,27 +125,28 @@
}
}

+/*
+ * WSH 07/08/97: Defer release of inode and file structures until inode has
+ * been cleared. This avoids a race condition in case the inode is put back
+ * in use before being cleared.
+ */
static void
ncp_put_inode(struct inode *inode)
{
- struct nw_file_info *finfo = NCP_FINFO(inode);
- struct super_block *sb = inode->i_sb;
+ struct super_block *sb = inode->i_sb;
+ struct ncp_server *server = NCP_SERVER(inode);
+ struct ncp_inode_info *iinfo = NCP_INOP(inode);
+ struct nw_file_info *finfo = NCP_FINFO(inode);

+if (inode->i_count > 1)
+printk("ncp_put_inode: inode %ld still in use\n", inode->i_ino);
+
lock_super(sb);
- if (finfo->opened != 0)
- {
- if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle)!=0)
- {
- /* We can't do anything but complain. */
- printk("ncp_put_inode: could not close\n");
- }
- }
-
DDPRINTK("ncp_put_inode: put %s\n",
- finfo->i.entryName);
-
- ncp_free_inode_info(NCP_INOP(inode));
-
+ finfo->i.entryName);
+ /*
+ * This operation should never block.
+ */
if (S_ISDIR(inode->i_mode))
{
DDPRINTK("ncp_put_inode: put directory %ld\n",
@@ -154,6 +155,24 @@
}

clear_inode(inode);
+
+ /*
+ * Check whether the inode was cleared, and if so go ahead and release
+ * the NCP data structures.
+ */
+ if (inode->i_count == 0) {
+ if (finfo->opened != 0)
+ {
+ if (ncp_close_file(server, finfo->file_handle) != 0)
+ {
+ /* We can't do anything but complain. */
+ printk("ncp_put_inode: could not close %s\n",
+ finfo->i.entryName);
+ }
+ }
+
+ ncp_free_inode_info(iinfo);
+ }
unlock_super(sb);
}

--------------8A2A1943BE6E18D82336876C--