]> git.neil.brown.name Git - LaFS.git/commitdiff
Discard per-device superblocks
authorNeil Brown <neilb@nbeee.brown>
Mon, 19 Jul 2010 05:22:40 +0000 (15:22 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 9 Aug 2010 01:58:11 +0000 (11:58 +1000)
There is no real value in the per-device superblocks.
Just open the device for exclusive access.

This loses the debatable possibility of just using mount
to add devices to an array - that should be remount anyway.

Signed-off-by: NeilBrown <neilb@suse.de>
io.c
roll.c
state.h
super.c

diff --git a/io.c b/io.c
index 0003a06e2b0e0c42215c42c6562ef94664423818..c7734aab71125261522dfd784c798d2a17ce02d2 100644 (file)
--- a/io.c
+++ b/io.c
@@ -85,7 +85,7 @@ lafs_load_page(struct fs *fs, struct page *p, u64 vaddr, int blocks)
                return -EIO;
        }
 
-       bdev = fs->devs[dev].sb->s_bdev;
+       bdev = fs->devs[dev].bdev;
        return lafs_sync_page_io(bdev, sect, 0,
                                 blocks << fs->blocksize_bits,
                                 p, 0) ? 0 : -EIO;
@@ -141,7 +141,7 @@ lafs_load_page_async(struct fs *fs, struct page *p, u64 vaddr,
        if (ac->state == 4)
                return -EIO;
 
-       bdev = fs->devs[dev].sb->s_bdev;
+       bdev = fs->devs[dev].bdev;
        ac->state = 2; /* loading */
        ac->fs = fs;
        async_page_io(bdev, sect, 0,
@@ -167,7 +167,7 @@ lafs_super_write(struct fs *fs, int dev, u64 addr, char *buf, int size)
        struct bio *bio = bio_alloc(GFP_NOIO, 1);
        int rw = WRITE | (1 << BIO_RW_UNPLUG);
 
-       bio->bi_bdev = fs->devs[dev].sb->s_bdev;
+       bio->bi_bdev = fs->devs[dev].bdev;
        bio->bi_sector = addr;
        bio_add_page(bio, virt_to_page(buf), size, offset_in_page(buf));
        bio->bi_private = fs;
@@ -515,7 +515,7 @@ lafs_load_block(struct block *b, struct bio *bio)
                return -EIO;
        }
 
-       bdev = fs->devs[dev].sb->s_bdev;
+       bdev = fs->devs[dev].bdev;
 
        if (!bio) {
                bio = bio_alloc(GFP_NOIO, 1);
@@ -606,7 +606,7 @@ static void write_block(struct fs *fs, struct page *p, int offset,
 
        bio = wc->bio;
        if (bio && virt == wc->bio_virt &&
-           bio->bi_bdev == fs->devs[dev].sb->s_bdev &&
+           bio->bi_bdev == fs->devs[dev].bdev &&
            which == wc->bio_which &&
            bio_add_page(bio, p, fs->blocksize, offset) > 0) {
                /* Added the current bio - too easy */
@@ -650,7 +650,7 @@ static void write_block(struct fs *fs, struct page *p, int offset,
        wc->bio_virt = virt + 1;
        wc->bio_head = head;
        wc->bio_which = which;
-       bio->bi_bdev = fs->devs[dev].sb->s_bdev;
+       bio->bi_bdev = fs->devs[dev].bdev;
        bio->bi_sector = sect;
        bio_add_page(bio, p, fs->blocksize, offset);
 
diff --git a/roll.c b/roll.c
index ceee0c34fbdc911e16c35706855218a9963f24a6..ecb54e4c14944c2fd3612440d14be7a5044b7298 100644 (file)
--- a/roll.c
+++ b/roll.c
@@ -556,9 +556,10 @@ lafs_mount(struct fs *fs)
        fs->rolled = 0;
        fs->ss[0].root = root = iget_locked(fs->prime_sb, 0);
 
+       err = -ENOMEM;
        b = lafs_get_block(root, 0, NULL, GFP_KERNEL, MKREF(mount));
        if (!b)
-               return -ENOMEM;
+               goto err;
        set_bit(B_Root, &b->b.flags);
        b->b.physaddr = fs->ss[0].root_addr;
        set_bit(B_PhysValid, &b->b.flags);
@@ -573,6 +574,7 @@ lafs_mount(struct fs *fs)
        if (err)
                goto err;
        putdref(b, MKREF(mount));
+       b = NULL;
        dprintk("name is %s\n", LAFSI(root)->md.fs.name);
 
        unlock_new_inode(root);
@@ -581,11 +583,11 @@ lafs_mount(struct fs *fs)
        rootdir = lafs_iget(fs->prime_sb, 2, SYNC);
        err = PTR_ERR(rootdir);
        if (IS_ERR(rootdir))
-               goto err2;
+               goto err;
        de = d_alloc_root(rootdir);
        err = PTR_ERR(de);
        if (IS_ERR(de))
-               goto err2;
+               goto err;
        fs->prime_sb->s_root = de;
 
        fs->orphans = lafs_iget(fs->prime_sb, 8, SYNC);
@@ -606,6 +608,5 @@ lafs_mount(struct fs *fs)
 
 err:
        putdref(b, MKREF(mount));
-err2:
        return err;
 }
diff --git a/state.h b/state.h
index 159172937f233db31bd6769e7562852eced68160..f0099aa4cf5366432885a21658460645c781262a 100644 (file)
--- a/state.h
+++ b/state.h
@@ -222,7 +222,7 @@ struct fs {
        struct list_head qhash[QHASHSIZE];
 
        struct fs_dev {
-               struct super_block *sb;
+               struct block_device *bdev;
                struct lafs_dev *devblk;
 
                u64     start, size;
diff --git a/super.c b/super.c
index 59a2c08e00a4dd713929ae553c694f1a8de46c9c..4b0ddbe3f4b6ccd9ceb9c3c00d38fbf429505b09 100644 (file)
--- a/super.c
+++ b/super.c
@@ -208,8 +208,6 @@ compare_state(struct lafs_state *orig, struct lafs_state *new)
  *    dev=  - add another device
  *    new=  - the device is being added.
  *
- * We have a separate 'struct super_block' for each device, but they
- * share the s_fs_info, which lists them all.
  */
 
 struct options {
@@ -220,7 +218,7 @@ struct options {
                const char *dev;
                int is_new;
                int is_name;
-               struct super_block *sb;
+               struct block_device *bdev;
                struct lafs_dev *devblock;
                struct lafs_state *stateblock;
                int devchoice, statechoice;
@@ -285,7 +283,7 @@ parse_opts(struct options *op, const char *name, char *data)
 }
 
 static int
-lafs_fill_super(struct super_block *sb, void *opv, int silent)
+lafs_load_super(struct block_device *bdev, void *opv, int silent)
 {
        /* Find the devblock and the stateblock for this device
 
@@ -305,7 +303,7 @@ lafs_fill_super(struct super_block *sb, void *opv, int silent)
        BUG_ON(dv->devblock);
        BUG_ON(dv->stateblock);
 
-       n = queue_logical_block_size(sb->s_bdev->bd_disk->queue);
+       n = queue_logical_block_size(bdev->bd_disk->queue);
        if (n < LAFS_DEVBLK_SIZE)
                n = LAFS_DEVBLK_SIZE;
        BUG_ON(n > PAGE_SIZE);
@@ -323,7 +321,7 @@ lafs_fill_super(struct super_block *sb, void *opv, int silent)
        sect = 0;
        for (i = 0; i < 4; i++) {
                /* try to read block at 'sect' */
-               int ok = lafs_sync_page_io(sb->s_bdev, sect, 0, n, pg, READ);
+               int ok = lafs_sync_page_io(bdev, sect, 0, n, pg, READ);
 
                if (ok && valid_devblock(page_address(pg), sect)) {
                        if (!have_dev) {
@@ -348,7 +346,7 @@ lafs_fill_super(struct super_block *sb, void *opv, int silent)
                if (i != 1)
                        sect += (n>>9);
                else {
-                       sect = sb->s_bdev->bd_inode->i_size & ~(sector_t)(n-1);
+                       sect = bdev->bd_inode->i_size & ~(sector_t)(n-1);
                        sect >>= 9;
                        sect -= (n>>9)*2;
                }
@@ -367,7 +365,7 @@ lafs_fill_super(struct super_block *sb, void *opv, int silent)
         */
        n = le32_to_cpu(1<<dv->devblock->statebits);
        if ((n & (n-1)) ||
-           n < queue_logical_block_size(sb->s_bdev->bd_disk->queue) ||
+           n < queue_logical_block_size(bdev->bd_disk->queue) ||
            n > 128*1024) {
                printk(KERN_ERR "LaFS: statesize of %u not acceptable.\n", n);
                err = -EINVAL;
@@ -380,7 +378,7 @@ lafs_fill_super(struct super_block *sb, void *opv, int silent)
        for (i = 0; i < 4; i++) {
                int ok;
                sect = le64_to_cpu(dv->devblock->stateaddr[i])>>9;
-               ok = lafs_sync_page_io(sb->s_bdev, sect, 0, n, pg, READ);
+               ok = lafs_sync_page_io(bdev, sect, 0, n, pg, READ);
                if (ok && valid_stateblock(page_address(pg), dv->devblock)) {
                        if (!have_state) {
                                have_state = 1;
@@ -394,9 +392,6 @@ lafs_fill_super(struct super_block *sb, void *opv, int silent)
                }
        }
 
-       /* We allow 29 bits for nanosecs, so they must be even. */
-       sb->s_time_gran = 2;
-
        if (have_state) {
                err = 0;
                dv->devchoice = dev_addr;
@@ -469,22 +464,18 @@ check_devs(struct options *op)
        return newstate;
 }
 
-static struct fs *
-lafs_load(struct options *op, int newest)
+static int
+lafs_load(struct fs *fs, struct options *op, int newest)
 {
        /* We seem to have a full set of devices for the filesystem.
         * Time to create our fs_info structure and fill it out.
         * This only includes information from the dev and state blocks.
         * Finding the root-inode comes a bit later.
         */
-       struct fs *fs;
        struct lafs_state *st;
        int i;
        int err;
 
-       fs = kzalloc(sizeof(*fs), GFP_KERNEL);
-       if (!fs)
-               return fs;
        st = fs->state = op->devlist[newest].stateblock;
        op->devlist[newest].stateblock = NULL;
 #ifdef DUMP
@@ -571,16 +562,15 @@ lafs_load(struct options *op, int newest)
        fs->prime_sb->s_export_op = &lafs_export_ops;
        fs->prime_sb->s_root = NULL;
 
+       /* We allow 29 bits for nanosecs, so they must be even. */
+       fs->prime_sb->s_time_gran = 2;
+
        for (i = 0; i < fs->devices; i++) {
                struct fs_dev *dv = &fs->devs[i];
                struct devent *de = &op->devlist[i];
                int j;
-               dv->sb = de->sb;
-               de->sb = NULL;
-               dv->sb->s_fs_info = fs;
-               dv->sb->s_blocksize = 1 << op->blockbits;
-               dv->sb->s_blocksize_bits = op->blockbits;
-               up_write(&dv->sb->s_umount);
+               dv->bdev = de->bdev;
+               de->bdev = NULL;
 
                dv->devblk = de->devblock;
                de->devblock = NULL;
@@ -622,12 +612,8 @@ lafs_load(struct options *op, int newest)
                        dv->devaddr[j] = le64_to_cpu(dv->devblk->devaddr[j]);
                for (j = 0; j < 4; j++)
                        dv->stateaddr[j] = le64_to_cpu(dv->devblk->stateaddr[j]);
-
-               dv->sb->s_op = &lafs_sops;
-               dv->sb->s_export_op = &lafs_export_ops;
-               dv->sb->s_root = NULL;
        }
-       return fs;
+       return 0;
 
 abort:
        kfree(fs->scan.free_usages);
@@ -635,7 +621,7 @@ abort:
        kfree(fs->devs);
        kfree(fs->ss);
        kfree(fs);
-       return NULL;
+       return -ENOMEM;
 }
 
 static int show_orphans(struct fs *fs)
@@ -685,11 +671,7 @@ static void lafs_kill_sb(struct super_block *sb)
        for (i = 0; i < fs->devices; i++) {
                struct fs_dev *dv = &fs->devs[i];
                kfree(dv->devblk);
-               if (dv->sb)
-                       kill_block_super(dv->sb);
-               /* FIXME should I kfree dv->sb or something here?
-                * maybe used put_super(dv->sb)*/
-               dv->sb = NULL;
+               close_bdev_exclusive(dv->bdev, FMODE_READ|FMODE_WRITE);
        }
 
        /* Final checkpoint will have cleared out the leafs lists,
@@ -775,28 +757,24 @@ lafs_put_super(struct super_block *sb)
 }
 
 static int
-get_lafs_sb_dev(struct options *op, int flags)
+lafs_get_devs(struct fs *fs, struct options *op, int flags)
 {
        int err;
        int i;
-       struct vfsmount mnt;
 
        for (i = 0; i < op->devcnt; i++) {
+               struct block_device *bdev;
                op->curr_dev = i;
-               err = get_sb_bdev(&lafs_fs_type, flags,
-                                 op->devlist[i].dev, op,
-                                 lafs_fill_super, &mnt);
-               if (err < 0)
+               
+               bdev = open_bdev_exclusive(op->devlist[i].dev,
+                                          FMODE_READ|FMODE_WRITE, fs);
+               err = PTR_ERR(bdev);
+               if (IS_ERR(bdev))
                        goto out;
-               dput(mnt.mnt_root);
-               if (i &&
-                   op->devlist[i-1].sb->s_fs_info !=
-                   mnt.mnt_sb->s_fs_info) {
-                       deactivate_super(mnt.mnt_sb);
-                       err = -EBUSY;
+               err = lafs_load_super(bdev, op, flags & MS_SILENT ? 1 : 0);
+               if (err < 0)
                        goto out;
-               }
-               op->devlist[i].sb = mnt.mnt_sb;
+               op->devlist[i].bdev = bdev;
        }
        return 0;
 
@@ -816,7 +794,7 @@ lafs_get_sb(struct file_system_type *fs_type,
         * If the later, we return the primary.
         * If the former, we init the filesystem copying static data
         * to all supers.
-        * First we 'open_bdev_excl' each device, exclusive to lafs
+        * First we 'open_bdev_exclusive' each device, exclusive to lafs
         * Then we 'sget' a superblock that knows any/all the devices.
         * This may be pre-existing, or may be new
         * If new, it will be created knowing all devices.
@@ -825,30 +803,24 @@ lafs_get_sb(struct file_system_type *fs_type,
        struct options op;
        int err;
        int newest;
-       struct fs *fs = NULL;
+       struct fs *fs = kzalloc(sizeof(*fs), GFP_KERNEL);
        char *cdata = data;
        if (cdata == NULL)
                cdata = "";
 
+       err = -ENOMEM;
+       if (!fs)
+               goto out;
        err = parse_opts(&op, dev_name, cdata);
        if (err)
                goto out;
 
-       /* We now have as list of device names.  We call get_sb_bdev
-        * on each to collect some superblocks.  These must all have
-        * the same s_fs_info.  If non-null, we simply return the
-        * primary super
+       /* We now have as list of device names.  We call open_bdev_exclusive
+        * on each to collect some superblocks.
         */
-       err = get_lafs_sb_dev(&op, flags);
+       err = lafs_get_devs(fs, &op, flags);
        if (err)
                goto out;
-       fs = op.devlist[0].sb->s_fs_info;
-       if (fs) {
-               /* Maybe check read-only status FIXME */
-               op.devlist[0].sb = NULL;
-               /* FIXME do I protect any others? */
-               goto out;
-       }
 
        /* Each device has a valid dev and state block.  Hopefully they
         * are all for the same filesystem.  If they don't have the
@@ -865,9 +837,8 @@ lafs_get_sb(struct file_system_type *fs_type,
        /* So they seem to be the same - better create our
         * s_fs_info structure and fill it in
         */
-       err = -ENOMEM;
-       fs = lafs_load(&op, newest);
-       if (!fs)
+       err = lafs_load(fs, &op, newest);
+       if (err)
                goto out;
 
        /* Well, all the devices check out.  Now we need to find the
@@ -894,10 +865,9 @@ out:
                for (i = 0; i < op.devcnt; i++) {
                        kfree(op.devlist[i].devblock);
                        kfree(op.devlist[i].stateblock);
-                       if (op.devlist[i].sb) {
-                               up_write(&op.devlist[i].sb->s_umount);
-                               kill_block_super(op.devlist[i].sb);
-                       }
+                       if (op.devlist[i].bdev)
+                               close_bdev_exclusive(op.devlist[i].bdev,
+                                                    FMODE_READ|FMODE_WRITE);
                }
                kfree(op.devlist);
        }