[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Patch: Fix locking in diskfs_S_dir_rename

From: olafBuddenhagen
Subject: Patch: Fix locking in diskfs_S_dir_rename
Date: Wed, 7 Nov 2007 00:39:04 +0100
User-agent: Mutt/1.5.16 (2007-06-11)


This fix dedicated to Linus Torvalds -- it was the git test suite that
originally uncovered the problem ;-)

In diskfs_S_dir_rename(), the second call to diskfs_lookup() returns a
reference (with lock) in tfp. In some cases, this reference isn't
dropped before return: When there is already a node of the given target
name, which is a directory (that's the case the git testsuite triggers);
or when trying to rename a file when the maximum link count for this
file is reached.

The stray lock causes the next sync run to hang, resulting in further
propagation of the locking issues, ultimately making the whole FS hang
-- seems to be the same kind of problem that causes most of the hangs
nowadays. (However, as the situation handled here is rather obscure, the
more frequent hangs are probably caused by other, similar bugs in other

The patch below ensures the references are correctly released. I
confirmed that it fixes both of the cases mentioned above.

With the fix applied, git-core in Debian now builds fine out of the box.
(git-cvs is uninstallable though, because of a dependency on
libdbd-sqlite3-perl which is missing, probably necessary for
git-cvsserver that is one part of the git-cvs package.)

Note: Although I did the initial part of the analysis, and came up with
a first half-working fix, the actual correct patch was created by Samuel
Thibault. (Who else? ;-) )


Index: libdiskfs/dir-rename.c
RCS file: /cvsroot/hurd/hurd/libdiskfs/dir-rename.c,v
retrieving revision 1.19
diff -u -p -r1.19 dir-rename.c
--- libdiskfs/dir-rename.c      14 Feb 1997 01:19:23 -0000      1.19
+++ libdiskfs/dir-rename.c      4 Nov 2007 23:36:44 -0000
@@ -138,6 +138,7 @@ diskfs_S_dir_rename (struct protid *from
       diskfs_drop_dirstat (tdp, ds);
       diskfs_nrele (fnp);
+      diskfs_nput (tnp);
       mutex_unlock (&tdp->lock);
       return EISDIR;
@@ -149,6 +150,8 @@ diskfs_S_dir_rename (struct protid *from
       diskfs_drop_dirstat (tdp, ds);
       diskfs_nput (fnp);
+      if (tnp)
+        diskfs_nput (tnp);
       mutex_unlock (&tdp->lock);
       return EMLINK;

reply via email to

[Prev in Thread] Current Thread [Next in Thread]