From owner-freebsd-arch@FreeBSD.ORG Sat Oct 8 02:46:20 2005 Return-Path: X-Original-To: freebsd-arch@freebsd.org Delivered-To: freebsd-arch@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 57DB416A41F for ; Sat, 8 Oct 2005 02:46:20 +0000 (GMT) (envelope-from rodrigc@crodrigues.org) Received: from sccrmhc11.comcast.net (sccrmhc11.comcast.net [63.240.76.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id BDC2F43D46 for ; Sat, 8 Oct 2005 02:46:19 +0000 (GMT) (envelope-from rodrigc@crodrigues.org) Received: from c-66-30-112-178.hsd1.ma.comcast.net ([66.30.112.178]) by comcast.net (sccrmhc11) with ESMTP id <20051008024618011009d731e>; Sat, 8 Oct 2005 02:46:18 +0000 Received: from c-66-30-112-178.hsd1.ma.comcast.net (localhost.127.in-addr.arpa [127.0.0.1]) by c-66-30-112-178.hsd1.ma.comcast.net (8.13.4/8.13.1) with ESMTP id j982kKLW029944 for ; Fri, 7 Oct 2005 22:46:20 -0400 (EDT) (envelope-from rodrigc@c-66-30-112-178.hsd1.ma.comcast.net) Received: (from rodrigc@localhost) by c-66-30-112-178.hsd1.ma.comcast.net (8.13.4/8.13.1/Submit) id j982kKPX029943 for freebsd-arch@freebsd.org; Fri, 7 Oct 2005 22:46:20 -0400 (EDT) (envelope-from rodrigc) Date: Fri, 7 Oct 2005 22:46:20 -0400 From: Craig Rodrigues To: freebsd-arch@freebsd.org Message-ID: <20051008024620.GA29824@crodrigues.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="EeQfGwPcQSOJBaQU" Content-Disposition: inline User-Agent: Mutt/1.4.2.1i Subject: [RFC] Teaching mount(8) to use nmount() X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 08 Oct 2005 02:46:20 -0000 --EeQfGwPcQSOJBaQU Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi, The mount(8) command-line program that is used in FreeBSD behaves more or less as follows: The mount program will process the command-line arguments, and then fork() and do one of the following: -> The filesystem to mount is UFS, either by specifying "-t ufs" or omitting the -t flag entirely. An internal function mount_ufs() which in turn calls the "old-style" mount() syscall to actually mount the filesystem -> If you specify some other filesystem, "-t myfoofs", then the mount program will exec() a copy of "mount_myfoofs", passing the command-line parameters that are necessary to mount the FS. If someone comes along with a new filesystem, they then need to create a new mount_mynewfs binary, in order to mount the filesystem with mount -t mynewfs. This is OK, but leads to a plethora of mount_* binaries which are probably unnecessary. I think that the mount program should eventually do the following: -> for most filesystems (including UFS), the mount program should parse command-line arguments, and invoke the new nmount() syscall -> for very exceptional cases (not to be encouraged), like NFS, SMBFS, etc., instead of calling nmount() directly, we can fork() a new mount_nfs, mount_smbfs, etc. binary and do the mount Since I don't know how all the existing mount programs work, and I don't know the dependencies on how UFS mounting works, I propose an interim behavior for mount: if (filesystem_to_mount == "ufs" ) { call special mount_ufs() function } else if (filesystem_to_mount == something that needs an external binary) { fork() and exec("mount_somefoofs"); } else { call nmount() } When things get cleaned up, we can eliminate the special mount_ufs() function, and just have everything call nmount(), except for the special cases which need their own mount program. In the list of filesystems which need an external binary, I put all the mount_* binaries I could find on my FreeBSD box except the ones for mount_std, mount_devfs, mount_fdescfs, mount_linprocfs, mount_procfs because: -> all these binaries are copies of mount_std, mount_std checks argv[0] to see how it was invoked. if argv[0] == "mount_std" it is an error else { strip out the mount_ part of argv[0], and nmount() that filesystem } -> so mount_std and friends are basically thin wrappers around nmount I would appreciate any comments on the attached patch. -- Craig Rodrigues rodrigc@crodrigues.org --EeQfGwPcQSOJBaQU Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="mount.txt" ? ktrace.out ? mount ? mount.8.gz Index: Makefile =================================================================== RCS file: /home/ncvs/src/sbin/mount/Makefile,v retrieving revision 1.16 diff -u -u -r1.16 Makefile --- Makefile 7 Oct 2005 02:22:48 -0000 1.16 +++ Makefile 8 Oct 2005 02:23:29 -0000 @@ -2,7 +2,7 @@ # $FreeBSD: src/sbin/mount/Makefile,v 1.16 2005/10/07 02:22:48 rodrigc Exp $ PROG= mount -SRCS= mount.c mount_ufs.c getmntopts.c vfslist.c +SRCS= mount.c mount_fs.c mount_ufs.c getmntopts.c vfslist.c WARNS?= 3 MAN= mount.8 # We do NOT install the getmntopts.3 man page. Index: extern.h =================================================================== RCS file: /home/ncvs/src/sbin/mount/extern.h,v retrieving revision 1.5 diff -u -u -r1.5 extern.h --- extern.h 7 Oct 2005 02:18:20 -0000 1.5 +++ extern.h 8 Oct 2005 02:23:29 -0000 @@ -32,3 +32,4 @@ /* mount_ufs.c */ int mount_ufs(int, char * const []); +int mount_fs(const char *, int, char * const []); Index: mount.c =================================================================== RCS file: /home/ncvs/src/sbin/mount/mount.c,v retrieving revision 1.71 diff -u -u -r1.71 mount.c --- mount.c 7 Oct 2005 02:22:04 -0000 1.71 +++ mount.c 8 Oct 2005 02:23:29 -0000 @@ -120,6 +120,67 @@ 0 }; +static int +use_mountprog(const char *vfstype) +{ + /* XXX: We need to get away from implementing external mount + * programs for every filesystem, and move towards having + * each filesystem properly implement the nmount() system call. + */ + unsigned int i; + const char *fs[] = { + "cd9660", "ext2fs", "mfs", "msdosfs", "nfs", "nfs4", "ntfs", + "nwfs", "nullfs", "portalfs", "reiserfs", "smbfs", "udf", "umapfs", + "unionfs", + NULL + }; + + for (i=0; fs[i] != NULL; ++i) { + if (strcmp(vfstype, fs[i]) == 0) + return 1; + } + + return 0; +} + +static int +exec_mountprog(const char *vfstype, const char *name, const char *execname, + char *const argv[]) +{ + pid_t pid; + int status; + + switch (pid = fork()) { + case -1: /* Error. */ + warn("fork"); + exit (1); + case 0: /* Child. */ + /* Go find an executable. */ + execvP(execname, _PATH_SYSPATH, argv); + if (errno == ENOENT) { + warn("exec %s not found in %s", execname, + _PATH_SYSPATH); + } + exit(1); + default: /* Parent. */ + if (waitpid(pid, &status, 0) < 0) { + warn("waitpid"); + return (1); + } + + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) != 0) + return (WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + warnx("%s: %s", name, sys_siglist[WTERMSIG(status)]); + return (1); + } + break; + } + + return (0); +} + int main(int argc, char *argv[]) { @@ -385,8 +446,7 @@ { const char *argv[100]; struct statfs sf; - pid_t pid; - int argc, i, status; + int argc, i, ret; char *optbuf, execname[PATH_MAX], mntpath[PATH_MAX]; #if __GNUC__ @@ -447,50 +507,26 @@ return (0); } - switch (pid = fork()) { - case -1: /* Error. */ - warn("fork"); - free(optbuf); - return (1); - case 0: /* Child. */ - if (strcmp(vfstype, "ufs") == 0) - exit(mount_ufs(argc, (char * const *) argv)); - - /* Go find an executable. */ - execvP(execname, _PATH_SYSPATH, (char * const *)argv); - if (errno == ENOENT) { - warn("exec mount_%s not found in %s", vfstype, - _PATH_SYSPATH); - } - exit(1); - /* NOTREACHED */ - default: /* Parent. */ - free(optbuf); + if (strcmp(vfstype, "ufs")==0) { + ret = mount_ufs(argc, (char * const *) argv); + } else if (use_mountprog(vfstype)) { + ret = exec_mountprog(vfstype, name, execname, + (char * const *)argv); + } else { + ret = mount_fs(vfstype, argc,(char * const *)argv); + } - if (waitpid(pid, &status, 0) < 0) { - warn("waitpid"); - return (1); - } + free(optbuf); - if (WIFEXITED(status)) { - if (WEXITSTATUS(status) != 0) - return (WEXITSTATUS(status)); - } else if (WIFSIGNALED(status)) { - warnx("%s: %s", name, sys_siglist[WTERMSIG(status)]); + if (verbose) { + if (statfs(name, &sf) < 0) { + warn("statfs %s", name); return (1); } - - if (verbose) { - if (statfs(name, &sf) < 0) { - warn("statfs %s", name); - return (1); - } - if (fstab_style) - putfsent(&sf); - else - prmount(&sf); - } - break; + if (fstab_style) + putfsent(&sf); + else + prmount(&sf); } return (0); Index: mount_fs.c =================================================================== RCS file: mount_fs.c diff -N mount_fs.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ mount_fs.c 8 Oct 2005 02:23:29 -0000 @@ -0,0 +1,139 @@ +/* + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software donated to Berkeley by + * Jan-Simon Pendry. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. 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. + */ + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1992, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)mount_fs.c 8.6 (Berkeley) 4/26/95"; +#endif +static const char rcsid[] = + "$Id$"; +#endif /* not lint */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "extern.h" +#include "mntopts.h" + +struct mntopt mopts[] = { + MOPT_STDOPTS, + MOPT_END +}; + +extern int getmnt_silent; + +static void +usage(void) +{ + (void)fprintf(stderr, + "usage: mount_xfs [-t fstype] [-o options] target_fs mount_point\n"); + exit(1); +} + +int +mount_fs(const char *vfstype, int argc, char * const argv[]) +{ + struct iovec *iov; + int iovlen; + int mntflags = 0; + int ch; + char *dev, *dir, mntpath[MAXPATHLEN]; + char fstype[32]; + char *p, *val; + int ret; + int i; + printf("argc is: %d\n", argc); for (i=0; i < argc; ++i) { printf("%d: %s\n", argc, argv[i]); } + strncpy(fstype, vfstype, sizeof(fstype)); + + getmnt_silent = 1; + iov = NULL; + iovlen = 0; + + optind = optreset = 1; /* Reset for parse of new argv. */ + while ((ch = getopt(argc, argv, "o:")) != -1) { + switch(ch) { + case 'o': + getmntopts(optarg, mopts, &mntflags, 0); + p = strchr(optarg, '='); + val = ""; + if (p != NULL) { + *p = '\0'; + val = p + 1; + } + build_iovec(&iov, &iovlen, optarg, val, -1); + break; + case '?': + default: + usage(); + } + } + + argc -= optind; + argv += optind; + printf("argc is: %d\n", argc); + if (argc != 2) + usage(); + + dev = argv[0]; + dir = argv[1]; + + (void)checkpath(dir, mntpath); + (void)rmslashes(dev, dev); + + build_iovec(&iov, &iovlen, "fstype", fstype, -1); + build_iovec(&iov, &iovlen, "fspath", mntpath, -1); + build_iovec(&iov, &iovlen, "from", dev, -1); + + ret = nmount(iov, iovlen, mntflags); + if (ret < 0) + err(1, "%s", dev); + + return (ret); +} --EeQfGwPcQSOJBaQU--