author: Dave Chinner <dchinner@redhat.com> 2011-07-08 14:14:41 +1000
committer: Al Viro <viro@zeniv.linux.org.uk> 2011-07-20 01:44:38 -0400
commit: 12ad3ab66103e6582ca69c0c9de18b13487eaaef
parent: 09cc9fc7a7c3d872065426d7fb0f0ad6d3eb90fc
Commit Summary:
Diffstat:
1 file changed, 30 insertions, 0 deletions
diff --git a/fs/super.c b/fs/super.c
index 73ab9f9b3571..e63c754447ce 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -242,6 +242,39 @@ static int grab_super(struct super_block *s) __releases(sb_lock)
return 0;
}
+/*
+ * grab_super_passive - acquire a passive reference
+ * @s: reference we are trying to grab
+ *
+ * Tries to acquire a passive reference. This is used in places where we
+ * cannot take an active reference but we need to ensure that the
+ * superblock does not go away while we are working on it. It returns
+ * false if a reference was not gained, and returns true with the s_umount
+ * lock held in read mode if a reference is gained. On successful return,
+ * the caller must drop the s_umount lock and the passive reference when
+ * done.
+ */
+bool grab_super_passive(struct super_block *sb)
+{
+ spin_lock(&sb_lock);
+ if (list_empty(&sb->s_instances)) {
+ spin_unlock(&sb_lock);
+ return false;
+ }
+
+ sb->s_count++;
+ spin_unlock(&sb_lock);
+
+ if (down_read_trylock(&sb->s_umount)) {
+ if (sb->s_root)
+ return true;
+ up_read(&sb->s_umount);
+ }
+
+ put_super(sb);
+ return false;
+}
+
/*
* Superblock locking. We really ought to get rid of these two.
*/