Date: Mon, 6 Feb 2023 23:17:56 GMT From: Kirk McKusick <mckusick@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: 668dfa016698 - stable/13 - Document the mntopts(3) functions. Message-ID: <202302062317.316NHuFa037599@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by mckusick: URL: https://cgit.FreeBSD.org/src/commit/?id=668dfa01669858c2468a96d7d0a8b5c808aea5e2 commit 668dfa01669858c2468a96d7d0a8b5c808aea5e2 Author: Kirk McKusick <mckusick@FreeBSD.org> AuthorDate: 2023-01-15 18:20:48 +0000 Commit: Kirk McKusick <mckusick@FreeBSD.org> CommitDate: 2023-02-06 23:17:39 +0000 Document the mntopts(3) functions. Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D37907 (cherry picked from commit 906c312bbf7493ccbcce883936d67e5c66a9c3c2) --- sbin/fsck/Makefile | 4 + sbin/fsck/fsck.c | 5 +- sbin/fsck/fsutil.c | 44 ------ sbin/fsck/fsutil.h | 1 - sbin/fsck_ffs/main.c | 96 +----------- sbin/growfs/growfs.c | 110 ++------------ sbin/mount/Makefile | 11 +- sbin/mount/getmntopts.3 | 181 ----------------------- sbin/mount/getmntopts.c | 95 +++++++++++- sbin/mount/mntopts.3 | 381 ++++++++++++++++++++++++++++++++++++++++++++++++ sbin/mount/mntopts.h | 2 + sbin/mount/mount.c | 18 +-- sbin/tunefs/tunefs.c | 33 +---- 13 files changed, 513 insertions(+), 468 deletions(-) diff --git a/sbin/fsck/Makefile b/sbin/fsck/Makefile index 8d3dd214857e..d8106d082230 100644 --- a/sbin/fsck/Makefile +++ b/sbin/fsck/Makefile @@ -4,6 +4,10 @@ PACKAGE=runtime PROG= fsck SRCS= fsck.c fsutil.c preen.c +SRCS+= getmntopts.c MAN= fsck.8 +MOUNT= ${SRCTOP}/sbin/mount +CFLAGS+= -I${MOUNT} +.PATH: ${MOUNT} .include <bsd.prog.mk> diff --git a/sbin/fsck/fsck.c b/sbin/fsck/fsck.c index bb053fe56253..b6ad92ebf49b 100644 --- a/sbin/fsck/fsck.c +++ b/sbin/fsck/fsck.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include <err.h> #include <fstab.h> #include <fcntl.h> +#include <mntopts.h> #include <paths.h> #include <signal.h> #include <stdio.h> @@ -206,7 +207,7 @@ main(int argc, char *argv[]) _PATH_DEV, spec); spec = device; } - mntp = getmntpt(spec); + mntp = getmntpoint(spec); if (mntp != NULL) { spec = mntp->f_mntfromname; mntpt = mntp->f_mntonname; @@ -269,7 +270,7 @@ isok(struct fstab *fs) if (flags & DO_BACKGRD) { if (!strcmp(fs->fs_type, FSTAB_RO)) return (0); - if (getmntpt(fs->fs_spec) == NULL) + if (getmntpoint(fs->fs_spec) == NULL) return (0); if (checkfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, "-F", 0)) return (0); diff --git a/sbin/fsck/fsutil.c b/sbin/fsck/fsutil.c index 9644697e2530..a3888eeea25a 100644 --- a/sbin/fsck/fsutil.c +++ b/sbin/fsck/fsutil.c @@ -188,50 +188,6 @@ devcheck(const char *origname) return (origname); } -/* - * Get the mount point information for name. - */ -struct statfs * -getmntpt(const char *name) -{ - struct stat devstat, mntdevstat; - char device[sizeof(_PATH_DEV) - 1 + MNAMELEN]; - char *dev_name; - struct statfs *mntbuf, *statfsp; - int i, mntsize, isdev; - - if (stat(name, &devstat) != 0) - return (NULL); - if (S_ISCHR(devstat.st_mode) || S_ISBLK(devstat.st_mode)) - isdev = 1; - else - isdev = 0; - mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); - for (i = 0; i < mntsize; i++) { - statfsp = &mntbuf[i]; - dev_name = statfsp->f_mntfromname; - if (*dev_name != '/') { - if (strlen(_PATH_DEV) + strlen(dev_name) + 1 > - sizeof(statfsp->f_mntfromname)) - continue; - strcpy(device, _PATH_DEV); - strcat(device, dev_name); - strcpy(statfsp->f_mntfromname, device); - } - if (isdev == 0) { - if (strcmp(name, statfsp->f_mntonname)) - continue; - return (statfsp); - } - if (stat(dev_name, &mntdevstat) == 0 && - mntdevstat.st_rdev == devstat.st_rdev) - return (statfsp); - } - statfsp = NULL; - return (statfsp); -} - - void * emalloc(size_t s) { diff --git a/sbin/fsck/fsutil.h b/sbin/fsck/fsutil.h index e65f5ddecb01..bd0954d44ba1 100644 --- a/sbin/fsck/fsutil.h +++ b/sbin/fsck/fsutil.h @@ -39,7 +39,6 @@ void panic(const char *, ...) __dead2 __printflike(1, 2); const char *devcheck(const char *); const char *cdevname(void); void setcdevname(const char *, int); -struct statfs *getmntpt(const char *); void *emalloc(size_t); void *erealloc(void *, size_t); char *estrdup(const char *); diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c index 3a492c289bfe..c5dc10f1c3b0 100644 --- a/sbin/fsck_ffs/main.c +++ b/sbin/fsck_ffs/main.c @@ -76,8 +76,6 @@ static void usage(void) __dead2; static intmax_t argtoimax(int flag, const char *req, const char *str, int base); static int checkfilesys(char *filesys); static int setup_bkgrdchk(struct statfs *mntp, int sbrdfailed, char **filesys); -static int chkdoreload(struct statfs *mntp); -static struct statfs *getmntpt(const char *); int main(int argc, char *argv[]) @@ -258,7 +256,7 @@ checkfilesys(char *filesys) * if it is listed among the mounted file systems. Failing that * check to see if it is listed in /etc/fstab. */ - mntp = getmntpt(filesys); + mntp = getmntpoint(filesys); if (mntp != NULL) filesys = mntp->f_mntfromname; else @@ -311,7 +309,7 @@ checkfilesys(char *filesys) (FS_UNCLEAN | FS_NEEDSFSCK)) == 0) { bufinit(); gjournal_check(filesys); - if (chkdoreload(mntp) == 0) + if (chkdoreload(mntp, pwarn) == 0) exit(0); exit(4); } else { @@ -357,7 +355,7 @@ checkfilesys(char *filesys) sujrecovery = 1; if (suj_check(filesys) == 0) { printf("\n***** FILE SYSTEM MARKED CLEAN *****\n"); - if (chkdoreload(mntp) == 0) + if (chkdoreload(mntp, pwarn) == 0) exit(0); exit(4); } @@ -561,7 +559,7 @@ checkfilesys(char *filesys) return (ERESTART); printf("\n***** PLEASE RERUN FSCK *****\n"); } - if (chkdoreload(mntp) != 0) { + if (chkdoreload(mntp, pwarn) != 0) { if (!fsmodified) return (0); if (!preen) @@ -715,92 +713,6 @@ setup_bkgrdchk(struct statfs *mntp, int sbreadfailed, char **filesys) return (1); } -static int -chkdoreload(struct statfs *mntp) -{ - struct iovec *iov; - int iovlen; - char errmsg[255]; - - if (mntp == NULL) - return (0); - - iov = NULL; - iovlen = 0; - errmsg[0] = '\0'; - /* - * We modified a mounted file system. Do a mount update on - * it unless it is read-write, so we can continue using it - * as safely as possible. - */ - if (mntp->f_flags & MNT_RDONLY) { - build_iovec(&iov, &iovlen, "fstype", "ffs", 4); - build_iovec(&iov, &iovlen, "from", mntp->f_mntfromname, - (size_t)-1); - build_iovec(&iov, &iovlen, "fspath", mntp->f_mntonname, - (size_t)-1); - build_iovec(&iov, &iovlen, "errmsg", errmsg, - sizeof(errmsg)); - build_iovec(&iov, &iovlen, "update", NULL, 0); - build_iovec(&iov, &iovlen, "reload", NULL, 0); - /* - * XX: We need the following line until we clean up - * nmount parsing of root mounts and NFS root mounts. - */ - build_iovec(&iov, &iovlen, "ro", NULL, 0); - if (nmount(iov, iovlen, mntp->f_flags) == 0) { - return (0); - } - pwarn("mount reload of '%s' failed: %s %s\n\n", - mntp->f_mntonname, strerror(errno), errmsg); - return (1); - } - return (0); -} - -/* - * Get the mount point information for name. - */ -static struct statfs * -getmntpt(const char *name) -{ - struct stat devstat, mntdevstat; - char device[sizeof(_PATH_DEV) - 1 + MNAMELEN]; - char *ddevname; - struct statfs *mntbuf, *statfsp; - int i, mntsize, isdev; - - if (stat(name, &devstat) != 0) - return (NULL); - if (S_ISCHR(devstat.st_mode) || S_ISBLK(devstat.st_mode)) - isdev = 1; - else - isdev = 0; - mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); - for (i = 0; i < mntsize; i++) { - statfsp = &mntbuf[i]; - ddevname = statfsp->f_mntfromname; - if (*ddevname != '/') { - if (strlen(_PATH_DEV) + strlen(ddevname) + 1 > - sizeof(statfsp->f_mntfromname)) - continue; - strcpy(device, _PATH_DEV); - strcat(device, ddevname); - strcpy(statfsp->f_mntfromname, device); - } - if (isdev == 0) { - if (strcmp(name, statfsp->f_mntonname)) - continue; - return (statfsp); - } - if (stat(ddevname, &mntdevstat) == 0 && - mntdevstat.st_rdev == devstat.st_rdev) - return (statfsp); - } - statfsp = NULL; - return (statfsp); -} - static void usage(void) { diff --git a/sbin/growfs/growfs.c b/sbin/growfs/growfs.c index 69e6f04dd4c2..c7ef0ced4ed6 100644 --- a/sbin/growfs/growfs.c +++ b/sbin/growfs/growfs.c @@ -118,7 +118,6 @@ static void updjcg(int, time_t, int, int, unsigned int); static void updcsloc(time_t, int, int, unsigned int); static void frag_adjust(ufs2_daddr_t, int); static void updclst(int); -static void mount_reload(const struct statfs *stfs); static void cgckhash(struct cg *); /* @@ -1263,76 +1262,11 @@ is_dev(const char *name) return (1); } -/* - * Return mountpoint on which the device is currently mounted. - */ -static const struct statfs * -dev_to_statfs(const char *dev) -{ - struct stat devstat, mntdevstat; - struct statfs *mntbuf, *statfsp; - char device[MAXPATHLEN]; - char *mntdevname; - int i, mntsize; - - /* - * First check the mounted filesystems. - */ - if (stat(dev, &devstat) != 0) - return (NULL); - if (!S_ISCHR(devstat.st_mode) && !S_ISBLK(devstat.st_mode)) - return (NULL); - - mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); - for (i = 0; i < mntsize; i++) { - statfsp = &mntbuf[i]; - mntdevname = statfsp->f_mntfromname; - if (*mntdevname != '/') { - strcpy(device, _PATH_DEV); - strcat(device, mntdevname); - mntdevname = device; - } - if (stat(mntdevname, &mntdevstat) == 0 && - mntdevstat.st_rdev == devstat.st_rdev) - return (statfsp); - } - - return (NULL); -} - static const char * -mountpoint_to_dev(const char *mountpoint) -{ - struct statfs *mntbuf, *statfsp; - struct fstab *fs; - int i, mntsize; - - /* - * First check the mounted filesystems. - */ - mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); - for (i = 0; i < mntsize; i++) { - statfsp = &mntbuf[i]; - - if (strcmp(statfsp->f_mntonname, mountpoint) == 0) - return (statfsp->f_mntfromname); - } - - /* - * Check the fstab. - */ - fs = getfsfile(mountpoint); - if (fs != NULL) - return (fs->fs_spec); - - return (NULL); -} - -static const char * -getdev(const char *name) +getdev(const char *name, struct statfs *statfsp) { static char device[MAXPATHLEN]; - const char *cp, *dev; + const char *cp; if (is_dev(name)) return (name); @@ -1344,9 +1278,8 @@ getdev(const char *name) return (device); } - dev = mountpoint_to_dev(name); - if (dev != NULL && is_dev(dev)) - return (dev); + if (statfsp != NULL) + return (statfsp->f_mntfromname); return (NULL); } @@ -1378,7 +1311,7 @@ main(int argc, char **argv) DBG_FUNC("main") struct fs *fs; const char *device; - const struct statfs *statfsp; + struct statfs *statfsp; uint64_t size = 0; off_t mediasize; int error, j, fsi, fso, ch, ret, Nflag = 0, yflag = 0; @@ -1430,12 +1363,11 @@ main(int argc, char **argv) /* * Now try to guess the device name. */ - device = getdev(*argv); + statfsp = getmntpoint(*argv); + device = getdev(*argv, statfsp); if (device == NULL) errx(1, "cannot find special device for %s", *argv); - statfsp = dev_to_statfs(device); - fsi = open(device, O_RDONLY); if (fsi < 0) err(1, "%s", device); @@ -1666,8 +1598,9 @@ main(int argc, char **argv) error = close(fso); if (error != 0) err(1, "close"); - if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) != 0) - mount_reload(statfsp); + if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) != 0 && + chkdoreload(statfsp, warn) != 0) + exit(9); } DBG_CLOSE; @@ -1734,29 +1667,6 @@ updclst(int block) return; } -static void -mount_reload(const struct statfs *stfs) -{ - char errmsg[255]; - struct iovec *iov; - int iovlen; - - iov = NULL; - iovlen = 0; - *errmsg = '\0'; - build_iovec(&iov, &iovlen, "fstype", __DECONST(char *, "ffs"), 4); - build_iovec(&iov, &iovlen, "fspath", __DECONST(char *, stfs->f_mntonname), (size_t)-1); - build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); - build_iovec(&iov, &iovlen, "update", NULL, 0); - build_iovec(&iov, &iovlen, "reload", NULL, 0); - - if (nmount(iov, iovlen, stfs->f_flags) < 0) { - errmsg[sizeof(errmsg) - 1] = '\0'; - err(9, "%s: cannot reload filesystem%s%s", stfs->f_mntonname, - *errmsg != '\0' ? ": " : "", errmsg); - } -} - /* * Calculate the check-hash of the cylinder group. */ diff --git a/sbin/mount/Makefile b/sbin/mount/Makefile index 34ba498a2a3f..1bc84039b121 100644 --- a/sbin/mount/Makefile +++ b/sbin/mount/Makefile @@ -4,8 +4,15 @@ PACKAGE=runtime PROG= mount SRCS= mount.c mount_fs.c getmntopts.c vfslist.c -MAN= mount.8 -# We do NOT install the getmntopts.3 man page. +MAN= mntopts.3 mount.8 +MLINKS+= mntopts.3 getmntopts.3 +MLINKS+= mntopts.3 getmntpoint.3 +MLINKS+= mntopts.3 chkdoreload.3 +MLINKS+= mntopts.3 build_iovec.3 +MLINKS+= mntopts.3 build_iovec_argf.3 +MLINKS+= mntopts.3 free_iovec.3 +MLINKS+= mntopts.3 checkpath.3 +MLINKS+= mntopts.3 rmslashes.3 LIBADD= util xo diff --git a/sbin/mount/getmntopts.3 b/sbin/mount/getmntopts.3 deleted file mode 100644 index b87956d051b7..000000000000 --- a/sbin/mount/getmntopts.3 +++ /dev/null @@ -1,181 +0,0 @@ -.\" Copyright (c) 1994 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)getmntopts.3 8.3 (Berkeley) 3/30/95 -.\" $FreeBSD$ -.\" -.Dd February 17, 2008 -.Dt GETMNTOPTS 3 -.Os -.Sh NAME -.Nm getmntopts -.Nd scan mount options -.Sh SYNOPSIS -.Fd #include \&"mntopts.h" -.Ft void -.Fo getmntopts -.Fa "const char *options" "const struct mntopt *mopts" -.Fa "int *flagp" "int *altflagp" -.Fc -.Sh DESCRIPTION -The -.Fn getmntopts -function takes a comma separated option list and a list -of valid option names, and computes the bitmask -corresponding to the requested set of options. -.Pp -The string -.Fa options -is broken down into a sequence of comma separated tokens. -Each token is looked up in the table described by -.Fa mopts -and the bits in -the word referenced by either -.Fa flagp -or -.Fa altflagp -(depending on the -.Va m_altloc -field of the option's table entry) -are updated. -The flag words are not initialized by -.Fn getmntopts . -The table, -.Fa mopts , -has the following format: -.Bd -literal -struct mntopt { - char *m_option; /* option name */ - int m_inverse; /* is this a negative option, e.g., "dev" */ - int m_flag; /* bit to set, e.g., MNT_RDONLY */ - int m_altloc; /* non-zero to use altflagp rather than flagp */ -}; -.Ed -.Pp -The members of this structure are: -.Bl -tag -width m_inverse -.It Va m_option -the option name, -for example -.Dq Li suid . -.It Va m_inverse -tells -.Fn getmntopts -that the name has the inverse meaning of the -bit. -For example, -.Dq Li suid -is the string, whereas the -mount flag is -.Dv MNT_NOSUID . -In this case, the sense of the string and the flag -are inverted, so the -.Va m_inverse -flag should be set. -.It Va m_flag -the value of the bit to be set or cleared in -the flag word when the option is recognized. -The bit is set when the option is discovered, -but cleared if the option name was preceded -by the letters -.Dq Li no . -The -.Va m_inverse -flag causes these two operations to be reversed. -.It Va m_altloc -the bit should be set or cleared in -.Fa altflagp -rather than -.Fa flagp . -.El -.Pp -Each of the user visible -.Dv MNT_ -flags has a corresponding -.Dv MOPT_ -macro which defines an appropriate -.Vt "struct mntopt" -entry. -To simplify the program interface and ensure consistency across all -programs, a general purpose macro, -.Dv MOPT_STDOPTS , -is defined which -contains an entry for all the generic VFS options. -In addition, the macros -.Dv MOPT_FORCE -and -.Dv MOPT_UPDATE -exist to enable the -.Dv MNT_FORCE -and -.Dv MNT_UPDATE -flags to be set. -Finally, the table must be terminated by an entry with a -.Dv NULL -first element. -.Sh EXAMPLES -Most commands will use the standard option set. -Local file systems which support the -.Dv MNT_UPDATE -flag, would also have an -.Dv MOPT_UPDATE -entry. -This can be declared and used as follows: -.Bd -literal -#include "mntopts.h" - -struct mntopt mopts[] = { - MOPT_STDOPTS, - MOPT_UPDATE, - { NULL } -}; - - ... - mntflags = mntaltflags = 0; - ... - getmntopts(options, mopts, &mntflags, &mntaltflags); - ... -.Ed -.Sh DIAGNOSTICS -If the external integer variable -.Va getmnt_silent -is zero, then the -.Fn getmntopts -function displays an error message and exits if an -unrecognized option is encountered. -Otherwise unrecognized options are silently ignored. -By default -.Va getmnt_silent -is zero. -.Sh SEE ALSO -.Xr err 3 , -.Xr mount 8 -.Sh HISTORY -The -.Fn getmntopts -function appeared in -.Bx 4.4 . diff --git a/sbin/mount/getmntopts.c b/sbin/mount/getmntopts.c index 0ee6d99ed8b9..e6607c385341 100644 --- a/sbin/mount/getmntopts.c +++ b/sbin/mount/getmntopts.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include <err.h> #include <errno.h> +#include <paths.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -153,6 +154,98 @@ checkpath_allow_file(const char *path, char *resolved) return (0); } +/* + * Get the mount point information for name. Name may be mount point name + * or device name (with or without /dev/ preprended). + */ +struct statfs * +getmntpoint(const char *name) +{ + struct stat devstat, mntdevstat; + char device[sizeof(_PATH_DEV) - 1 + MNAMELEN]; + char *ddevname; + struct statfs *mntbuf, *statfsp; + int i, mntsize, isdev; + + if (stat(name, &devstat) != 0) + return (NULL); + if (S_ISCHR(devstat.st_mode) || S_ISBLK(devstat.st_mode)) + isdev = 1; + else + isdev = 0; + mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); + for (i = 0; i < mntsize; i++) { + statfsp = &mntbuf[i]; + ddevname = statfsp->f_mntfromname; + if (*ddevname != '/') { + if (strlen(_PATH_DEV) + strlen(ddevname) + 1 > + sizeof(statfsp->f_mntfromname)) + continue; + strcpy(device, _PATH_DEV); + strcat(device, ddevname); + strcpy(statfsp->f_mntfromname, device); + } + if (isdev == 0) { + if (strcmp(name, statfsp->f_mntonname)) + continue; + return (statfsp); + } + if (stat(ddevname, &mntdevstat) == 0 && + mntdevstat.st_rdev == devstat.st_rdev) + return (statfsp); + } + return (NULL); +} + +/* + * If possible reload a mounted filesystem. + * When prtmsg != NULL print a warning if a reload is attempted, but fails. + * Return 0 on success, 1 on failure. + */ +int +chkdoreload(struct statfs *mntp, + void (*prtmsg)(const char *, ...) __printflike(1,2)) +{ + struct iovec *iov; + int iovlen, error; + char errmsg[255]; + + /* + * If the filesystem is not mounted it does not need to be reloaded. + * If it is mounted for writing, then it could not have been opened + * for writing by a utility, so does not need to be reloaded. + */ + if (mntp == NULL || (mntp->f_flags & MNT_RDONLY) == 0) + return (0); + + /* + * We modified a mounted file system. Do a mount update on + * it so we can continue using it as safely as possible. + */ + iov = NULL; + iovlen = 0; + errmsg[0] = '\0'; + build_iovec(&iov, &iovlen, "fstype", __DECONST(void *, "ffs"), 4); + build_iovec(&iov, &iovlen, "from", mntp->f_mntfromname, (size_t)-1); + build_iovec(&iov, &iovlen, "fspath", mntp->f_mntonname, (size_t)-1); + build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); + build_iovec(&iov, &iovlen, "update", NULL, 0); + build_iovec(&iov, &iovlen, "reload", NULL, 0); + /* + * XX: We need the following line until we clean up + * nmount parsing of root mounts and NFS root mounts. + */ + build_iovec(&iov, &iovlen, "ro", NULL, 0); + error = nmount(iov, iovlen, mntp->f_flags); + free_iovec(&iov, &iovlen); + if (error == 0) + return (0); + if (prtmsg != NULL) + prtmsg("mount reload of '%s' failed: %s %s\n\n", + mntp->f_mntonname, strerror(errno), errmsg); + return (1); +} + void build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val, size_t len) @@ -207,7 +300,7 @@ free_iovec(struct iovec **iov, int *iovlen) { int i; - for (i = 0; i < *iovlen; i++) + for (i = 0; i < *iovlen; i += 2) free((*iov)[i].iov_base); free(*iov); } diff --git a/sbin/mount/mntopts.3 b/sbin/mount/mntopts.3 new file mode 100644 index 000000000000..782acabef1a0 --- /dev/null +++ b/sbin/mount/mntopts.3 @@ -0,0 +1,381 @@ +.\" Copyright (c) 2023 Marshall Kirk McKusick +.\" Copyright (c) 1994 The Regents of the University of California. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)getmntopts.3 8.3 (Berkeley) 3/30/95 +.\" +.Dd January 19, 2023 +.Dt MNTOPTS 3 +.Os +.Sh NAME +.Nm getmntopts , +.Nm getmntpoint , +.Nm chkdoreload , +.Nm build_iovec , +.Nm build_iovec_argf , +.Nm free_iovec , +.Nm checkpath , +.Nm rmslashes +.Nd "mount point operations" +.Sh SYNOPSIS +.In mntopts.h +.Ft void +.Fo getmntopts +.Fa "const char *options" "const struct mntopt *mopts" +.Fa "int *flagp" "int *altflagp" +.Fc +.Ft struct statfs * +.Fn getmntpoint "const char *name" +.Ft int +.Fo chkdoreload +.Fa "struct statfs *mntp" +.Fa "void (*prtmsg)(const char *fmt, ...)" +.Fc +.Ft void +.Fo build_iovec +.Fa "struct iovec **iov" "int *iovlen" "const char *name" "void *val" +.Fa "size_t len" +.Fc +.Ft void +.Fo build_iovec_argf +.Fa "struct iovec **iov" "int *iovlen" "const char *name" +.Fa "const char *fmt" "..." +.Fc +.Ft void +.Fn free_iovec "struct iovec **iov" "int *iovlen" +.Ft int +.Fn checkpath "const char *path" "char *resolved" +.Ft void +.Fn rmslashes "char *rrpin" "char *rrpout" +.Sh DESCRIPTION +The +.Nm mntopts +functions support operations associated with a mount point. +For historic reasons are in a file in the sources for the +.Xr mount 8 +program. +Thus, to access them the following lines need to be added to the +.Nm Makefile +of the program wanting to use them: +.Bd -literal +SRCS+= getmntopts.c +MOUNT= ${SRCTOP}/sbin/mount +CFLAGS+= -I${MOUNT} +\&.PATH: ${MOUNT} +.Ed +.Pp +The +.Fn getmntopts +function takes a comma separated option list and a list +of valid option names, and computes the bitmask +corresponding to the requested set of options. +.Pp +The string +.Fa options +is broken down into a sequence of comma separated tokens. +Each token is looked up in the table described by +.Fa mopts +and the bits in +the word referenced by either +.Fa flagp +or +.Fa altflagp +(depending on the +.Va m_altloc +field of the option's table entry) +are updated. +The flag words are not initialized by +.Fn getmntopts . +The table, +.Fa mopts , +has the following format: +.Bd -literal +struct mntopt { + char *m_option; /* option name */ + int m_inverse; /* is this a negative option, e.g., "dev" */ + int m_flag; /* bit to set, e.g., MNT_RDONLY */ + int m_altloc; /* non-zero to use altflagp rather than flagp */ +}; +.Ed +.Pp +The members of this structure are: +.Bl -tag -width m_inverse +.It Va m_option +the option name, +for example +.Dq Li suid . +.It Va m_inverse +tells +.Fn getmntopts +that the name has the inverse meaning of the +bit. +For example, +.Dq Li suid +is the string, whereas the +mount flag is +.Dv MNT_NOSUID . +In this case, the sense of the string and the flag +are inverted, so the +.Va m_inverse +flag should be set. +.It Va m_flag +the value of the bit to be set or cleared in +the flag word when the option is recognized. +The bit is set when the option is discovered, +but cleared if the option name was preceded +by the letters +.Dq Li no . +The +.Va m_inverse +flag causes these two operations to be reversed. +.It Va m_altloc +the bit should be set or cleared in +.Fa altflagp +rather than +.Fa flagp . +.El +.Pp +Each of the user visible +.Dv MNT_ +flags has a corresponding +.Dv MOPT_ +macro which defines an appropriate +.Vt "struct mntopt" +entry. +To simplify the program interface and ensure consistency across all +programs, a general purpose macro, +.Dv MOPT_STDOPTS , +is defined which +contains an entry for all the generic VFS options. +In addition, the macros +.Dv MOPT_FORCE +and +.Dv MOPT_UPDATE +exist to enable the +.Dv MNT_FORCE +and +.Dv MNT_UPDATE +flags to be set. +Finally, the table must be terminated by an entry with a +.Dv NULL +first element. +.Pp +The +.Fn getmntpoint +function takes the pathname of a possible mount point +or of a device (with or without +.Pa /dev/ +prepended to it). +If the pathname is a directory or a file, +.Fn getmntpoint +checks to see if the mount point currently has a filesystem +mounted on it. +If the pathname is a device, +.Fn getmntpoint +checks to see if it is currently mounted. +If there is an associated mount, a pointer to a +.Vt "struct statfs" *** 319 LINES SKIPPED ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202302062317.316NHuFa037599>