Move active filesystems

Matthew Wilcox (willy@odie.barnet.ac.uk)
Tue, 9 Jun 1998 00:46:51 +0100 (BST)


Here is my patch against 2.0.33 which allows you to move a mount from
one mount point to another. I haven't looked at anything in userland -
mount(8) may need todging. As I previously explained this is useful as
it allows people to use a file which is laid out as an ext2 partition
on their native partition as their root, then _move_ their partition to
the new root filesystem and unmount the initrd. I will update this for
2.0.34 / 2.1.x tomorrow.

Note to linux-arm people: this is the first step; I'll work on a new
root floppy tomorrow.

-- 
Set Alias$Case Set Alias$[ |||| |MSet Alias$Otherwise Set Alias$[ \ Matthew
"" |MSet Alias$When If %0=%%0 Then Set Alias$[ "" ||MIf %0=%%0    \ Wilcox
Then Set Alias$Otherwise Set Alias$[ |||||||||||||||| ||MIf       \
%0=%%0 Then Set Alias$When Set Alias$[ ||||||||||||||||

--- fs/super.c.orig Mon Aug 18 21:01:15 1997 +++ fs/super.c Mon Jun 8 22:28:38 1998 @@ -771,21 +771,48 @@ return 0; } -static int do_remount(const char *dir,int flags,char *data) +static int do_remount(const char *dev, const char *dir,int flags,char *data) { struct inode *dir_i; int retval; - retval = namei(dir, &dir_i); - if (retval) + if ((retval = namei(dir, &dir_i))) + return retval; + if ((retval = do_remount_sb(dir_i->i_sb, flags, data))) return retval; if (dir_i != dir_i->i_sb->s_mounted) { + struct inode *dev_i; + struct vfsmount *vfsmnt; + if ((retval = namei(dev, &dev_i))) + return retval; + vfsmnt = lookup_vfsmnt(dev_i->i_rdev); + if (!vfsmnt) return 0; /* I dunno... but it's consistent */ + if (dir_i->i_count != 1 || dir_i->i_mount + || dir_i->i_sb->s_dev == dev_i->i_rdev) { + iput(dir_i); + return -EBUSY; + } + if (!S_ISDIR(dir_i->i_mode)) { + iput(dir_i); + return -ENOTDIR; + } + /* Note that the tests here are not complete. Nothing + stops the incompetent sysadmin remounting /a on /a/b/a + if b is a different filesystem. This would be tricky + to implement and probably pointless. mount(8) would + be a better place to put sanity checks, I believe */ + iput(vfsmnt->mnt_sb->s_covered); + vfsmnt->mnt_sb->s_covered->i_mount = NULL; + vfsmnt->mnt_sb->s_covered = dir_i; + dir_i->i_mount = vfsmnt->mnt_sb->s_mounted; + kfree(vfsmnt->mnt_dirname); + if ((vfsmnt->mnt_dirname = + (char *) kmalloc(strlen(dir)+1, GFP_KERNEL)) != (char *)NULL) + strcpy(vfsmnt->mnt_dirname, dir); + } else { iput(dir_i); - return -EINVAL; } - retval = do_remount_sb(dir_i->i_sb, flags, data); - iput(dir_i); - return retval; + return 0; } static int copy_mount_options (const void * data, unsigned long *where) @@ -847,7 +874,7 @@ retval = copy_mount_options (data, &page); if (retval < 0) return retval; - retval = do_remount(dir_name, + retval = do_remount(dev_name, dir_name, new_flags & ~MS_MGC_MSK & ~MS_REMOUNT, (char *) page); free_page(page);

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu