[PATCH] fs/super.c fixes - second series (6/11)

Alexander Viro (viro@math.psu.edu)
Sun, 12 Aug 2001 21:28:12 -0400 (EDT)


Part 6/11

* get_sb_single() doesn't rely on kern_mount() being already done.
It simply checks list_empty(&type->fs_supers) and if we already have a
superblocks - grabs and returns it. If we don't have one it does the
right thing - inserts preallocated superblock into the ->fs_supers (and
super_blocks, indeed) and does ->read_super() on it, etc.

It means that get_sb_single() works regardless of the kern_mount() -
if the latter had been done the thing will pick the superblock as it used
to do, if not - no problems.

diff -urN S9-pre1-fs_supers/fs/super.c S9-pre1-get_sb_single/fs/super.c
--- S9-pre1-fs_supers/fs/super.c Sun Aug 12 20:45:50 2001
+++ S9-pre1-get_sb_single/fs/super.c Sun Aug 12 20:45:50 2001
@@ -1031,19 +1031,62 @@
static struct super_block *get_sb_single(struct file_system_type *fs_type,
int flags, void *data)
{
- struct super_block * sb;
+ struct super_block * s = alloc_super();
+ if (!s)
+ return ERR_PTR(-ENOMEM);
+ down_write(&s->s_umount);
/*
* Get the superblock of kernel-wide instance, but
* keep the reference to fs_type.
*/
down(&mount_sem);
- sb = fs_type->kern_mnt->mnt_sb;
- if (!sb)
- BUG();
- atomic_inc(&sb->s_active);
- down_write(&sb->s_umount);
- do_remount_sb(sb, flags, data);
- return sb;
+retry:
+ spin_lock(&sb_lock);
+ if (!list_empty(&fs_type->fs_supers)) {
+ struct super_block *old;
+ old = list_entry(fs_type->fs_supers.next, struct super_block,
+ s_instances);
+ if (!grab_super(old))
+ goto retry;
+ atomic_dec(&s->s_active);
+ put_super(s);
+ do_remount_sb(old, flags, data);
+ return old;
+ } else {
+ kdev_t dev = get_unnamed_dev();
+ if (!dev) {
+ atomic_dec(&s->s_active);
+ put_super(s);
+ up(&mount_sem);
+ return ERR_PTR(-EMFILE);
+ }
+ s->s_dev = dev;
+ s->s_flags = flags;
+ s->s_type = fs_type;
+ list_add (&s->s_list, super_blocks.prev);
+ list_add (&s->s_instances, &fs_type->fs_supers);
+ spin_unlock(&sb_lock);
+ lock_super(s);
+ if (!fs_type->read_super(s, data, 0))
+ goto out_fail;
+ unlock_super(s);
+ 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);
+ list_del(&s->s_instances);
+ spin_unlock(&sb_lock);
+ put_super(s);
+ put_unnamed_dev(dev);
+ up(&mount_sem);
+ return ERR_PTR(-EINVAL);
+ }
}

static void kill_super(struct super_block *sb)

-
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/