]> git.neil.brown.name Git - LaFS.git/commitdiff
Fixed to run_orphans.
authorNeilBrown <neilb@suse.de>
Thu, 3 Sep 2009 05:28:21 +0000 (15:28 +1000)
committerNeilBrown <neilb@suse.de>
Thu, 3 Sep 2009 05:28:21 +0000 (15:28 +1000)
We need to hold a reference to the db, as orphan_release
can drop it.
And an unclaimed inode block with no mx is always free to
be orphan_released.

orphan.c

index 0f3cf62184ef612ae428fdfe4dea3b855437e576..b892da2fee15062a23f2acf78e1918c8b7e7aec0 100644 (file)
--- a/orphan.c
+++ b/orphan.c
@@ -478,27 +478,28 @@ long lafs_run_orphans(struct fs *fs)
                                orphans);
                list_move(&db->orphans, &done);
                mx = orphan_mutex(db);
-               if (!mx || !mutex_trylock(mx))
+               if (!mx && !test_bit(B_Claimed, &db->b.flags))
+                       /* OK not to have a mutex */;
+               else if (!mx || !mutex_trylock(mx))
                        continue;
+               getdref(db, MKREF(run_orphans));
                spin_unlock(&fs->lock);
 
-               /* The 'orphan_list' reference cannot be dropped
-                * while we own the mutex, so our reference to db is safe
-                */
-
-               switch(LAFSI(db->b.inode)->type) {
-               case TypeInodeFile:
-                       lafs_inode_handle_orphan(db);
-                       break;
-               case TypeDir:
-                       lafs_dir_handle_orphan(db);
-                       break;
+               if (!mx)
+                       lafs_orphan_release(fs, db);
+               else {
+                       switch(LAFSI(db->b.inode)->type) {
+                       case TypeInodeFile:
+                               lafs_inode_handle_orphan(db);
+                               break;
+                       case TypeDir:
+                               lafs_dir_handle_orphan(db);
+                               break;
+                       }
+                       mutex_unlock(mx);
                }
-               mutex_unlock(mx);
 
-               /* The block has either been put, or is still on
-                * 'done'.
-                */
+               putdref(db, MKREF(run_orphans));
                spin_lock(&fs->lock);
        }
        list_splice(&done, &fs->pending_orphans);