Subject: "mount -o update" doesn't do anything (#316) Index: sys/ufs_mount.c,etc/mount/ 2.11BSD Description: Mount options (noexec, nosuid, ...) can not be changed without unmounting and remounting a filesystem because the "-u" (also known as "-o update") switch is ignored by the kernel. Repeat-By: mount -u -o nodev /usr mount Note that 'nodev' does not appear in the line for /usr. Also if it is desired to turn off an option it can't be done except by unmounting the filesystem and remounting it. Fix: mount(8) itself changes very little, it was already parsing the '-u' and '-o update' options and passing them to the kernel. The changes to mount(8) add the 'async' option and update the man page. ufs_mount.c is where all the interesting changes take place. Attention is paid to the MNT_UPDATE flag now. The previous hack to update only the root filesystem goes away in favor of a more general method which works for all filesystems. Oh - in case anyone's counting, despite the size of the changes to ufs_mount.c the growth in the kernel's text is only 84 bytes. NOTE: it is possible to update a ReadOnly filesystem to ReadWrite now but NOT the reverse. All other options can be toggled on/off as desired. Kernel support for the 'async' and 'sync' options is in the planning stage now. Turning those options on/off will show up in the output of mount(8) but will have no effect. Toggling the other options (nodev, etc) will do the expected thing. To install the update cut where indicated, saving to a file (/tmp/316) and then: patch -p0 < /tmp/316 cd /usr/src/etc/mount make make install make clean next a new kernel needs to be compiled and installed: cd /sys/YOUR_KERNEL_NAME make if no errors were encountered (overlays too big, etc): make install reboot As always this and previous updates are available via anonymous FTP to either FTP.IIPO.GTEGSC.COM or MOE.2BSD.COM in the directory /pub/2.11BSD. ==========================cut here============================ *** /usr/src/sys/sys/ufs_mount.c.old Fri Mar 1 21:03:35 1996 --- /usr/src/sys/sys/ufs_mount.c Sat Apr 20 21:56:21 1996 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_mount.c 1.7 (2.11BSD GTE) 1996/3/1 */ #include "param.h" --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_mount.c 1.8 (2.11BSD GTE) 1996/4/20 */ #include "param.h" *************** *** 35,89 **** dev_t dev; register struct inode *ip; register struct fs *fs; ! register struct nameidata *ndp = &u.u_nd; u_int lenon, lenfrom; char mnton[MNAMELEN], mntfrom[MNAMELEN]; ! u.u_error = getmdev(&dev, uap->fspec); ! if (u.u_error) return; ndp->ni_nameiop = LOOKUP | FOLLOW; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = (caddr_t)uap->freg; ! ip = namei(ndp); ! if (ip == NULL) return; /* - * This is a hack to update the 'from' field for the root filesystem. When - * the kernel boots the string 'root_device' placed there as a place holder - * until the "mount -a" is done from /etc/rc - at that time the name of the - * root device is known and passed thru to here. If '/' is the directory - * then only the 'from' and 'on' fields are updated. - * * The following two copyinstr calls will not fault because getmdev() or * namei() would have returned an error for invalid parameters. */ copyinstr(uap->freg, mnton, sizeof (mnton) - 1, &lenon); copyinstr(uap->fspec, mntfrom, sizeof (mntfrom) - 1, &lenfrom); ! if (mnton[0] == '/' && mnton[1] == '\0') { iput(ip); ! if (dev != mount[0].m_dev) ! return(u.u_error = EINVAL); ! fs = &mount[0].m_filsys; ! goto updname; } ! if (ip->i_count != 1 || (ip->i_number == ROOTINO)) { ! iput(ip); ! u.u_error = EBUSY; ! return; ! } ! if ((ip->i_mode&IFMT) != IFDIR) { ! iput(ip); ! u.u_error = ENOTDIR; ! return; ! } ! ! fs = mountfs(dev, uap->flags, ip); ! if (fs == 0) ! return; updname: mount_updname(fs, mnton, mntfrom, lenon, lenfrom); } mount_updname(fs, on, from, lenon, lenfrom) --- 35,139 ---- dev_t dev; register struct inode *ip; register struct fs *fs; ! struct nameidata *ndp = &u.u_nd; ! struct mount *mp; u_int lenon, lenfrom; + int error = 0; char mnton[MNAMELEN], mntfrom[MNAMELEN]; ! if (u.u_error = getmdev(&dev, uap->fspec)) return; ndp->ni_nameiop = LOOKUP | FOLLOW; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = (caddr_t)uap->freg; ! if ((ip = namei(ndp)) == NULL) return; + if ((ip->i_mode&IFMT) != IFDIR) { + error = ENOTDIR; + goto cmnout; + } /* * The following two copyinstr calls will not fault because getmdev() or * namei() would have returned an error for invalid parameters. */ copyinstr(uap->freg, mnton, sizeof (mnton) - 1, &lenon); copyinstr(uap->fspec, mntfrom, sizeof (mntfrom) - 1, &lenfrom); ! ! if (uap->flags & MNT_UPDATE) { + fs = ip->i_fs; + mp = (struct mount *) + ((int)fs - offsetof(struct mount, m_filsys)); + if (ip->i_number != ROOTINO) + { + error = EINVAL; /* Not a mount point */ + goto cmnout; + } + /* + * Check that the device passed in is the same one that is in the mount + * table entry for this mount point. + */ + if (dev != mp->m_dev) + { + error = EINVAL; /* not right mount point */ + goto cmnout; + } + /* + * This is where the RW to RO transformation would be done. It is, for now, + * too much work to port pages of code to do (besides which most + * programs get very upset at having access yanked out from under them). + */ + if (fs->fs_ronly == 0 && (uap->flags & MNT_RDONLY)) + { + error = EPERM; /* ! RW to RO updates */ + goto cmnout; + } + /* + * However, going from RO to RW is easy. Then merge in the new + * flags (async, sync, nodev, etc) passed in from the program. + */ + if (fs->fs_ronly && ((uap->flags & MNT_RDONLY) == 0)) + { + fs->fs_ronly = 0; + mp->m_flags &= ~MNT_RDONLY; + } + #define _MF (MNT_NOSUID | MNT_NODEV | MNT_NOEXEC | MNT_ASYNC | MNT_SYNCHRONOUS) + mp->m_flags &= ~_MF; + mp->m_flags |= (uap->flags & _MF); + #undef _MF iput(ip); ! u.u_error = 0; ! goto updname; } ! else ! { ! /* ! * This is where a new mount (not an update of an existing mount point) is ! * done. ! * ! * The directory being mounted on can have no other references AND can not ! * currently be a mount point. Mount points have an inode number of (you ! * guessed it) ROOTINO which is 2. ! */ ! if (ip->i_count != 1 || (ip->i_number == ROOTINO)) ! { ! error = EBUSY; ! goto cmnout; ! } ! fs = mountfs(dev, uap->flags, ip); ! if (fs == 0) ! return; ! } ! /* ! * Lastly, both for new mounts and updates of existing mounts, update the ! * mounted-on and mounted-from fields. ! */ updname: mount_updname(fs, mnton, mntfrom, lenon, lenfrom); + return; + cmnout: + iput(ip); + return(u.u_error = error); } mount_updname(fs, on, from, lenon, lenfrom) *** /usr/src/sys/h/mount.h.old Fri Dec 29 22:00:50 1995 --- /usr/src/sys/h/mount.h Thu Apr 18 21:26:40 1996 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)mount.h 7.2.3 (2.11BSD GTE) 1995/12/29 */ /* --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)mount.h 7.2.4 (2.11BSD GTE) 1996/4/18 */ /* *************** *** 76,86 **** #define MNT_NOEXEC 0x0004 /* can't exec from filesystem */ #define MNT_NOSUID 0x0008 /* don't honor setuid bits on fs */ #define MNT_NODEV 0x0010 /* don't interpret special files */ - - /* - * Flags set by internal operations. - */ #define MNT_QUOTA 0x0020 /* quotas are enabled on filesystem */ /* * Mask of flags that are visible to statfs(). --- 76,83 ---- #define MNT_NOEXEC 0x0004 /* can't exec from filesystem */ #define MNT_NOSUID 0x0008 /* don't honor setuid bits on fs */ #define MNT_NODEV 0x0010 /* don't interpret special files */ #define MNT_QUOTA 0x0020 /* quotas are enabled on filesystem */ + #define MNT_ASYNC 0x0040 /* file system written asynchronously */ /* * Mask of flags that are visible to statfs(). *** /usr/src/etc/mount/mount.c.old Thu Jan 25 21:10:55 1996 --- /usr/src/etc/mount/mount.c Sat Apr 20 21:51:26 1996 *************** *** 36,42 **** "@(#) Copyright (c) 1980, 1989, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; ! static char sccsid[] = "@(#)mount.c 8.19.1 (2.11BSD) 1996/1/16"; #endif /* not lint */ #include --- 36,42 ---- "@(#) Copyright (c) 1980, 1989, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; ! static char sccsid[] = "@(#)mount.c 8.19.2 (2.11BSD) 1996/4/18"; #endif /* not lint */ #include *************** *** 73,81 **** int o_opt; char *o_name; } optnames[] = { - #ifdef notnow { MNT_ASYNC, "asynchronous" }, - #endif { MNT_NODEV, "nodev" }, { MNT_NOEXEC, "noexec" }, { MNT_NOSUID, "nosuid" }, --- 73,79 ---- *** /usr/src/etc/mount/mount_ufs.c.old Thu Jan 25 21:13:18 1996 --- /usr/src/etc/mount/mount_ufs.c Thu Apr 18 21:42:33 1996 *************** *** 36,42 **** "@(#) Copyright (c) 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; ! static char sccsid[] = "@(#)mount_ufs.c 8.2.1 (2.11BSD) 1996/1/16"; #endif /* not lint */ #include --- 36,42 ---- "@(#) Copyright (c) 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; ! static char sccsid[] = "@(#)mount_ufs.c 8.2.2 (2.11BSD) 1996/4/18"; #endif /* not lint */ #include *************** *** 54,62 **** static struct mntopt mopts[] = { MOPT_STDOPTS, - #ifdef notnow MOPT_ASYNC, - #endif MOPT_SYNC, MOPT_UPDATE, { NULL } --- 54,60 ---- *** /usr/src/etc/mount/mount.8.old Tue Jan 16 22:59:36 1996 --- /usr/src/etc/mount/mount.8 Thu Apr 18 21:48:08 1996 *************** *** 29,35 **** .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" ! .\" @(#)mount.8 8.7.1 (2.11BSD) 1996/1/16 .\" .TH MOUNT 8 "January 16, 1996" .UC 7 --- 29,35 ---- .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" ! .\" @(#)mount.8 8.7.2 (2.11BSD) 1996/4/18 .\" .TH MOUNT 8 "January 16, 1996" .UC 7 *************** *** 104,118 **** .B dangerous flag to set, and should not be used unless you are prepared to recreate the file ! system should your system crash. This option is not currently implemented ! in 2.11BSD but is planned for the future. .TP 10 force The same as \fB\-f\fP; forces the revocation of write access when trying to downgrade ! a filesystem mount status from read-write to read-only. Currently a NOP ! in 2.11BSD. .TP 10 nodev Do not interpret character or block special devices on the file system. --- 104,117 ---- .B dangerous flag to set, and should not be used unless you are prepared to recreate the file ! system should your system crash. .TP 10 force The same as \fB\-f\fP; forces the revocation of write access when trying to downgrade ! a filesystem mount status from read-write to read-only. This is not ! (and likely never will be) supported in 2.11BSD. .TP 10 nodev Do not interpret character or block special devices on the file system. *************** *** 134,147 **** .TP 10 sync All I/O ! to the file system should be done synchronously. Not implemented yet in ! 2.11BSD but is planned for the future. .TP 10 update The same as \fB\-u\fP; indicate that the status of an already mounted file system should be changed. - Not currently implemented in 2.11BSD. .PP Any additional options specific to a filesystem type that is not one of the internally known types (see the --- 133,144 ---- .TP 10 sync All I/O ! to the file system should be done synchronously. .TP 10 update The same as \fB\-u\fP; indicate that the status of an already mounted file system should be changed. .PP Any additional options specific to a filesystem type that is not one of the internally known types (see the *************** *** 226,233 **** files on the filesystem are currently open for writing unless the \fB\-f\fP flag is also specified. ! This is currently not implemented in 2.11BSD but it is planned that ! the ability to change the flags (nodev, nosuid, etc) will be implemented. The set of options is determined by first extracting the options for the file system from the .I fstab --- 223,230 ---- files on the filesystem are currently open for writing unless the \fB\-f\fP flag is also specified. ! This is currently not implemented in 2.11BSD. ! The ability to change the flags (nodev, nosuid, etc) is however supported. The set of options is determined by first extracting the options for the file system from the .I fstab *************** *** 261,267 **** and this manpage were ported from 4.4BSD-Lite to 2.11BSD to gain the ability to set the various flags such as \fBnodev\fP, \fBnosuid\fP and so on. Multiple filesystem types are not supported and several of the ! options and flags are not yet implemented. .SH HISTORY A .B mount --- 258,264 ---- and this manpage were ported from 4.4BSD-Lite to 2.11BSD to gain the ability to set the various flags such as \fBnodev\fP, \fBnosuid\fP and so on. Multiple filesystem types are not supported and several of the ! options and flags are not implemented. .SH HISTORY A .B mount *** /VERSION.old Fri Apr 12 22:29:42 1996 --- /VERSION Sat Apr 20 20:38:57 1996 *************** *** 1,4 **** ! Current Patch Level: 315 2.11 BSD ============ --- 1,4 ---- ! Current Patch Level: 316 2.11 BSD ============