patch for 2.1.80 fs/super.c

Bill Hawes (whawes@star.net)
Wed, 21 Jan 1998 10:09:30 -0500


This is a multi-part message in MIME format.
--------------F38ACE77F865BC1354BDB1A0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

The attached patch cleans up the code relating to the add_vfsmnt()
routine. Passing the superblock pointer instead of the device reduces
duplicated code and ensures that all vfsmnt structures are initialized
correctly.

I've pulled the code for finding an empty superblock out of read_super
and created a get_empty_super() call so that it can be used for the NFS
root case as well.

One other minor simplification was made to eliminate a redundant call to
get_super() prior to calling read_super(). (The call to read_super calls
get_super() anyway.) With our current approach to mounting there should
be no need to check for sb->s_root, as it's not allowable to have an
unlocked superblock with a device but no root dentry.

Regards,
Bill
--------------F38ACE77F865BC1354BDB1A0
Content-Type: text/plain; charset=us-ascii; name="super_80-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="super_80-patch"

--- linux-2.1.80/fs/super.c.old Tue Jan 13 10:38:30 1998
+++ linux-2.1.80/fs/super.c Wed Jan 21 10:05:17 1998
@@ -95,28 +95,37 @@
/* NOTREACHED */
}

-struct vfsmount *add_vfsmnt(kdev_t dev, const char *dev_name, const char *dir_name)
+static struct vfsmount *add_vfsmnt(struct super_block *sb,
+ const char *dev_name, const char *dir_name)
{
struct vfsmount *lptr;
- char *tmp;
+ char *tmp, *name;

lptr = (struct vfsmount *)kmalloc(sizeof(struct vfsmount), GFP_KERNEL);
- if (!lptr)
- return NULL;
+ if (!lptr)
+ goto out;
memset(lptr, 0, sizeof(struct vfsmount));

- lptr->mnt_dev = dev;
+ lptr->mnt_sb = sb;
+ lptr->mnt_dev = sb->s_dev;
+ lptr->mnt_flags = sb->s_flags;
sema_init(&lptr->mnt_sem, 1);
+
+ /* N.B. Is it really OK to have a vfsmount without names? */
if (dev_name && !IS_ERR(tmp = getname(dev_name))) {
- if ((lptr->mnt_devname =
- (char *) kmalloc(strlen(tmp)+1, GFP_KERNEL)) != (char *)NULL)
- strcpy(lptr->mnt_devname, tmp);
+ name = (char *) kmalloc(strlen(tmp)+1, GFP_KERNEL);
+ if (name) {
+ strcpy(name, tmp);
+ lptr->mnt_devname = name;
+ }
putname(tmp);
}
if (dir_name && !IS_ERR(tmp = getname(dir_name))) {
- if ((lptr->mnt_dirname =
- (char *) kmalloc(strlen(tmp)+1, GFP_KERNEL)) != (char *)NULL)
- strcpy(lptr->mnt_dirname, tmp);
+ name = (char *) kmalloc(strlen(tmp)+1, GFP_KERNEL);
+ if (name) {
+ strcpy(name, tmp);
+ lptr->mnt_dirname = name;
+ }
putname(tmp);
}

@@ -126,10 +135,11 @@
vfsmnttail->mnt_next = lptr;
vfsmnttail = lptr;
}
- return (lptr);
+out:
+ return lptr;
}

-void remove_vfsmnt(kdev_t dev)
+static void remove_vfsmnt(kdev_t dev)
{
struct vfsmount *lptr, *tofree;

@@ -496,6 +506,23 @@
return err;
}

+/*
+ * Find a super_block with no device assigned.
+ */
+static struct super_block *get_empty_super(void)
+{
+ struct super_block *s = 0+super_blocks;
+
+ for (; s < NR_SUPER+super_blocks; s++) {
+ if (s->s_dev)
+ continue;
+ if (!s->s_lock)
+ return s;
+ printk("VFS: empty superblock %p locked!\n", s);
+ }
+ return NULL;
+}
+
static struct super_block * read_super(kdev_t dev,const char *name,int flags,
void *data, int silent)
{
@@ -503,44 +530,39 @@
struct file_system_type *type;

if (!dev)
- goto out_fail;
+ goto out_null;
check_disk_change(dev);
s = get_super(dev);
if (s)
- return s;
+ goto out;
+
type = get_fs_type(name);
if (!type) {
printk("VFS: on device %s: get_fs_type(%s) failed\n",
kdevname(dev), name);
- goto out_fail;
- }
- for (s = 0+super_blocks ;; s++) {
- if (s >= NR_SUPER+super_blocks)
- goto out_fail;
- if (s->s_dev)
- continue;
- if (s->s_lock) {
- printk("VFS: empty superblock %p locked!\n", s);
- continue;
- }
- break;
+ goto out;
}
+ s = get_empty_super();
+ if (!s)
+ goto out;
s->s_dev = dev;
s->s_flags = flags;
s->s_dirt = 0;
/* N.B. Should lock superblock now ... */
- if (!type->read_super(s,data, silent))
- goto fail;
+ if (!type->read_super(s, data, silent))
+ goto out_fail;
s->s_dev = dev; /* N.B. why do this again?? */
s->s_rd_only = 0;
s->s_type = type;
+out:
return s;

/* N.B. s_dev should be cleared in type->read_super */
-fail:
- s->s_dev = 0;
out_fail:
- return NULL;
+ s->s_dev = 0;
+out_null:
+ s = NULL;
+ goto out;
}

/*
@@ -603,17 +629,16 @@
dentry->d_covers = covered;
}

-static int do_umount(kdev_t dev,int unmount_root)
+static int do_umount(kdev_t dev, int unmount_root)
{
struct super_block * sb;
int retval;

+ retval = -ENOENT;
sb = get_super(dev);
- if (!sb)
- return -ENOENT;
+ if (!sb || !sb->s_root)
+ goto out;

- if (!sb->s_root)
- return -ENOENT;
/*
* Before checking whether the filesystem is still busy,
* make sure the kernel doesn't hold any quotafiles open
@@ -659,7 +685,6 @@
sb->s_op->put_super(sb);
}
remove_vfsmnt(dev);
- retval = 0;
out:
return retval;
}
@@ -781,7 +806,7 @@

int do_mount(kdev_t dev, const char * dev_name, const char * dir_name, const char * type, int flags, void * data)
{
- struct dentry * dir_d = NULL;
+ struct dentry * dir_d;
struct super_block * sb;
struct vfsmount *vfsmnt;
int error;
@@ -806,15 +831,13 @@
goto dput_and_out;

/*
- * Check whether to read the super block
+ * Note: If the superblock already exists,
+ * read_super just does a get_super().
*/
- sb = get_super(dev);
- if (!sb || !sb->s_root) {
- error = -EINVAL;
- sb = read_super(dev,type,flags,data,0);
- if (!sb)
- goto dput_and_out;
- }
+ error = -EINVAL;
+ sb = read_super(dev, type, flags, data, 0);
+ if (!sb)
+ goto dput_and_out;

/*
* We may have slept while reading the super block,
@@ -825,20 +848,19 @@
goto dput_and_out;

error = -ENOMEM;
- vfsmnt = add_vfsmnt(dev, dev_name, dir_name);
- if (vfsmnt) {
- vfsmnt->mnt_sb = sb;
- vfsmnt->mnt_flags = flags;
- d_mount(dir_d, sb->s_root);
- error = 0;
- goto out; /* we don't dput(dir) - see umount */
- }
+ vfsmnt = add_vfsmnt(sb, dev_name, dir_name);
+ if (!vfsmnt)
+ goto dput_and_out;
+ d_mount(dir_d, sb->s_root);
+ error = 0; /* we don't dput(dir_d) - see umount */

-dput_and_out:
- dput(dir_d);
out:
up(&mount_sem);
return error;
+
+dput_and_out:
+ dput(dir_d);
+ goto out;
}


@@ -1063,14 +1085,11 @@
if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
ROOT_DEV = 0;
if ((fs_type = get_fs_type("nfs"))) {
- if ((vfsmnt = add_vfsmnt(ROOT_DEV, "/dev/root", "/"))) {
-
- sb = &super_blocks[0];
- while (sb->s_dev) sb++;
- vfsmnt->mnt_sb = sb;
-
- sb->s_dev = get_unnamed_dev();
- sb->s_flags = root_mountflags & ~MS_RDONLY;
+ sb = get_empty_super(); /* "can't fail" */
+ sb->s_dev = get_unnamed_dev();
+ sb->s_flags = root_mountflags & ~MS_RDONLY;
+ vfsmnt = add_vfsmnt(sb, "/dev/root", "/");
+ if (vfsmnt) {
if (nfs_root_mount(sb) >= 0) {
sb->s_rd_only = 0;
sb->s_dirt = 0;
@@ -1081,9 +1100,10 @@
printk (KERN_NOTICE "VFS: Mounted root (nfs filesystem).\n");
return;
}
- sb->s_dev = 0;
- put_unnamed_dev(sb->s_dev);
+ remove_vfsmnt(sb->s_dev);
}
+ put_unnamed_dev(sb->s_dev);
+ sb->s_dev = 0;
}
if (!ROOT_DEV) {
printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");
@@ -1136,12 +1156,10 @@
printk ("VFS: Mounted root (%s filesystem)%s.\n",
fs_type->name,
(sb->s_flags & MS_RDONLY) ? " readonly" : "");
- vfsmnt = add_vfsmnt(ROOT_DEV, "/dev/root", "/");
- if (!vfsmnt)
- panic("VFS: add_vfsmnt failed for root fs");
- vfsmnt->mnt_sb = sb;
- vfsmnt->mnt_flags = root_mountflags;
- return;
+ vfsmnt = add_vfsmnt(sb, "/dev/root", "/");
+ if (vfsmnt)
+ return;
+ panic("VFS: add_vfsmnt failed for root fs");
}
}
panic("VFS: Unable to mount root fs on %s",
@@ -1225,10 +1243,8 @@
return error;
}
remove_vfsmnt(old_root_dev);
- vfsmnt = add_vfsmnt(old_root_dev,"/dev/root.old",put_old);
+ vfsmnt = add_vfsmnt(old_root->d_sb, "/dev/root.old", put_old);
if (vfsmnt) {
- vfsmnt->mnt_sb = old_root->d_inode->i_sb;
- vfsmnt->mnt_flags = vfsmnt->mnt_sb->s_flags;
d_mount(dir_d,old_root);
return 0;
}

--------------F38ACE77F865BC1354BDB1A0--