Messages in this thread Patch in this message |  | | | Date | Wed, 20 Aug 1997 09:50:03 -0400 | | From | Bill Hawes <> | | Subject | Re: 2.1.51-1 -- mount borked |
| |
Jason Burrell wrote: > > I might be missing something, but it looks like filesystem > mounts in 2.1.51-pre1 have a potentially major problem. > > I booted and typoed a mount command, mounting /dev/hdb1 on the mount point > /.1 instead of /dev/hdc2 on /.1. I didn't catch this for a while, though, > and the system happily mounted it. > > # df > Filesystem 1024-blocks Used Available Capacity Mounted on > /dev/hdb1 2970455 992404 1824434 35% / > /dev/hdb1 2970455 992404 1824434 35% /.1 > > And, of course, I can't umount it because it's busy.
The problem seems to be that the current fs_may_mount always returns success, and when the system rereads the super_block, it gets a new root dentry and so doesn't realize that the device is already mounted.
I've attached a patch for fs/super that should fix things up. Instead of calling fs_may_mount, it checks whether the super_block and root dentry are already present before reading the sb.
Incidentally, we may as well get rid of fs_xxx_mount, as they're no longer used in the new scheme of things.
Regards, Bill--- fs/super.c.old Tue Aug 19 09:15:12 1997 +++ fs/super.c Wed Aug 20 09:19:03 1997 @@ -753,43 +760,50 @@ struct vfsmount *vfsmnt; int error; + error = -EACCES; if (!(flags & MS_RDONLY) && dev && is_read_only(dev)) - return -EACCES; + goto out; /*flags |= MS_RDONLY;*/ dir_d = namei(dir_name); error = PTR_ERR(dir_d); if (IS_ERR(dir_d)) - return error; + goto out; + + error = -EBUSY; + if (dir_d->d_covers != dir_d) + goto dput_and_out; + + error = -ENOTDIR; + if (!S_ISDIR(dir_d->d_inode->i_mode)) + goto dput_and_out; + + /* + * Check whether to read the super block + */ + error = -EINVAL; + if (!(sb = get_super(dev)) || !sb->s_root) + sb = read_super(dev,type,flags,data,0); + if (!sb || !sb->s_root) + goto dput_and_out; + + error = -EBUSY; + if (sb->s_root->d_covers != sb->s_root) + goto dput_and_out; - if (dir_d->d_covers != dir_d) { - dput(dir_d); - return -EBUSY; - } - if (!S_ISDIR(dir_d->d_inode->i_mode)) { - dput(dir_d); - return -ENOTDIR; - } - if (!fs_may_mount(dev)) { - dput(dir_d); - return -EBUSY; - } - sb = read_super(dev,type,flags,data,0); - if (!sb) { - dput(dir_d); - return -EINVAL; - } - if (sb->s_root->d_covers != sb->s_root) { - dput(dir_d); - return -EBUSY; - } vfsmnt = add_vfsmnt(dev, dev_name, dir_name); if (vfsmnt) { vfsmnt->mnt_sb = sb; vfsmnt->mnt_flags = flags; } + /* N.B. what if add_vfsmnt failed?? */ d_mount(dir_d, sb->s_root); return 0; /* we don't dput(dir) - see umount */ + +dput_and_out: + dput(dir_d); +out: + return error; } |  |