patch for race in do_unlink

Bill Hawes (whawes@star.net)
Mon, 04 Aug 1997 12:30:51 -0400


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

Hi Linus,

I've attached a patch for 2.1.47 to fix a race involving unlinking.
It's possible for one process to have unlinked an inode (yielding a
negative dentry) while another one is proceeding to unlink the same
object. The second one results in a call to ext2_unlink with a NULL
inode, leading to unhappiness of the oops variety.

I think the correct fix is to regard unlinking a negative dentry as a
no-op, as in the patch, but maybe it's an error condition?

This was triggered by some further changes I've made in refill_freelist,
which I think will be very helpful under low memory. The new code now
waits on a locked buffer before attempting to allocate from the reserved
pages; the problem with the existing code is that even after doing a
wakeup_bdflush, the previously dirty buffers are still locked. Thus all
the tasks wanting buffers were depleting the reserved pages, when all
they really needed to do was wait for some buffers to unlock after being
written out.

With the new buffer code I've been able to do make -j4 in a 6M machine
without ever touching the pages below min_free_pages+5. It still needs
some testing, though, and based on the above experience may take some
time to chase down newly exposed races.

Also, I'm reviewing my 2.0.30 patches and will be forwarding a minimal
fs/buffer.c patch shortly. Do you have a time frame in mind for 2.0.31
yet? If possible I'd like to resolve some problems in kernel/dup_mmap
in time for the release.

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

--- fs/namei.c.old Thu Jul 24 17:36:07 1997
+++ fs/namei.c Mon Aug 4 11:53:40 1997
@@ -827,6 +830,12 @@
dentry = lookup_dentry(name, NULL, 0);
error = PTR_ERR(dentry);
if (IS_ERR(dentry))
+ goto exit;
+ /*
+ * Check for a negative dentry ... no need to do anything.
+ */
+ error = 0;
+ if (!dentry->d_inode)
goto exit;

dir = lock_parent(dentry);

--------------1AD3A1F5DE67FFC8A2B90B1A--