Subject: vfs: leverage bd_super in get_active_super

Using get_active_super will not work properly if the fs (like btrfs) does not
save its s_bdev with the device it is on.  Also it does not provide the entire
picture, since an filesystem can be contained on multiple disks (again like
btrfs).

Fortunately we now have a bd_super field in struct block_device were a pointer
to the superblock sitting on top of the block device can be stored.

Filesystems using the vfs helper mount_bdev (the ext filesystems, xfs, etc) and
gfs2 already do this (for the former it is a freebie), so for these there is
no need to iterate through the list of superblocks; we can get the superblock
directly from ->bd_super which is more efficient and what this patch
implements.

A multi-device filesystem (once again lile btrfs) can use that field to store
a pointer to the superblock for each block device in its storage pool. By
doing so it would get_active_super and, by extension, thaw_bdev initiated
freezes working.

Thanks go to Josef Bacik and Christoph Hellwig for initiating this effort
to fix btrfs and for suggesting the solution implemented here, respectively.

Cc: Josef Bacik <jba...@fusionio.com>
Cc: Christoph Hellwig <h...@infradead.org>
Signed-off-by: Fernando Luis Vazquez Cao <ferna...@oss.ntt.co.jp>
---

diff -urNp linux-3.6-orig/fs/super.c linux-3.6/fs/super.c
--- linux-3.6-orig/fs/super.c   2012-10-10 11:20:58.000122252 +0900
+++ linux-3.6/fs/super.c        2012-10-10 14:56:44.260186674 +0900
@@ -725,18 +725,22 @@ struct super_block *get_active_super(str
 
 restart:
        spin_lock(&sb_lock);
+       if ((sb = bdev->bd_super) != NULL)
+               goto out_grabsuper;
        list_for_each_entry(sb, &super_blocks, s_list) {
                if (hlist_unhashed(&sb->s_instances))
                        continue;
-               if (sb->s_bdev == bdev) {
-                       if (grab_super(sb)) /* drops sb_lock */
-                               return sb;
-                       else
-                               goto restart;
-               }
+               if (sb->s_bdev == bdev)
+                       goto out_grabsuper;
        }
        spin_unlock(&sb_lock);
        return NULL;
+
+out_grabsuper:
+       if (grab_super(sb)) /* drops sb_lock */
+               return sb;
+       else
+               goto restart;
 }
  
 struct super_block *user_get_super(dev_t dev)


--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to