Re: [PATCH] fs/super.c fixes - second series (3/11)

From: Alexander Viro (viro@math.psu.edu)
Date: Sun Aug 12 2001 - 20:26:52 EST


Part 3/11

And now the second part - we expand the call of read_super() in get_sb_bdev()
and move superblock allocation in the beginning of the function. That
gets the search in super_blocks for existing superblocks from our device
together with insertion of new superblock into the list (if search fails, that
is). We hold sb_lock over that area, which makes the whole "add if we hadn't
one" thing atomic.

diff -urN S9-pre1-get_sb_bdev/fs/super.c S9-pre1-get_sb_bdev2/fs/super.c
--- S9-pre1-get_sb_bdev/fs/super.c Sun Aug 12 20:45:49 2001
+++ S9-pre1-get_sb_bdev2/fs/super.c Sun Aug 12 20:45:49 2001
@@ -898,7 +898,7 @@
         struct inode *inode;
         struct block_device *bdev;
         struct block_device_operations *bdops;
- struct super_block * sb;
+ struct super_block * s;
         struct nameidata nd;
         struct list_head *p;
         kdev_t dev;
@@ -935,6 +935,12 @@
         if (!(flags & MS_RDONLY) && is_read_only(dev))
                 goto out1;
 
+ error = -ENOMEM;
+ s = alloc_super();
+ if (!s)
+ goto out1;
+ down_write(&s->s_umount);
+
         error = -EBUSY;
 restart:
         spin_lock(&sb_lock);
@@ -946,22 +952,47 @@
                 if (old->s_type != fs_type ||
                     ((flags ^ old->s_flags) & MS_RDONLY)) {
                         spin_unlock(&sb_lock);
+ atomic_dec(&s->s_active);
+ put_super(s);
                         goto out1;
                 }
                 if (!grab_super(old))
                         goto restart;
+ atomic_dec(&s->s_active);
+ put_super(s);
                 blkdev_put(bdev, BDEV_FS);
                 path_release(&nd);
                 return old;
         }
+ s->s_dev = dev;
+ s->s_bdev = bdev;
+ s->s_flags = flags;
+ s->s_type = fs_type;
+ list_add (&s->s_list, super_blocks.prev);
+
         spin_unlock(&sb_lock);
+
         error = -EINVAL;
- sb = read_super(dev, bdev, fs_type, flags, data, 0);
- if (sb) {
- get_filesystem(fs_type);
- path_release(&nd);
- return sb;
- }
+ lock_super(s);
+ if (!fs_type->read_super(s, data, 0))
+ goto out_fail;
+ unlock_super(s);
+ /* tell bdcache that we are going to keep this one */
+ atomic_inc(&bdev->bd_count);
+ get_filesystem(fs_type);
+ path_release(&nd);
+ return s;
+
+out_fail:
+ s->s_dev = 0;
+ s->s_bdev = 0;
+ s->s_type = NULL;
+ unlock_super(s);
+ atomic_dec(&s->s_active);
+ spin_lock(&sb_lock);
+ list_del(&s->s_list);
+ spin_unlock(&sb_lock);
+ put_super(s);
 out1:
         blkdev_put(bdev, BDEV_FS);
 out:

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Wed Aug 15 2001 - 21:00:43 EST