Date: Sat, 8 Jul 2006 11:28:01 -0400 From: Craig Rodrigues <rodrigc@crodrigues.org> To: freebsd-current@freebsd.org Cc: freebsd-arch@freebsd.org Subject: [RFC] mount can figure out fstype automatically Message-ID: <20060708152801.GA3671@crodrigues.org>
next in thread | raw e-mail | index | archive | help
Hi, One of the pet peeves I have with FreeBSD is that if I have a device with a local filesystem that I want to mount, I need to explicitly know what type of filesystem is on the device in order to mount it from the command-line. For example, mount -t cd9660 mount -t udf mount -t ext2fs mount -t msdosfs Where this is particularly annoying is if I have multiple USB thumb drives with different filesystems on them. What I usually end up doing is something like: file - < /dev/ad0s4 to figure out the filesystem type, and then mount -t [whatever] to mount it. What I would like to do is: mount /dev/ad0s4 /mnt and if I do not specify a filesystem type with -t, the mount program should "magically" figure out how to mount the disk. This is closer to how the mount program behaves on Linux for example. I've come up with a patch that does this, by interpreting an fstype of "" as: - starting with "ufs", iterate over all the local filesystem types that we know about, and try to mount the device Comments? Index: sys/kern/vfs_mount.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_mount.c,v retrieving revision 1.228 diff -u -u -r1.228 vfs_mount.c --- sys/kern/vfs_mount.c 27 Jun 2006 14:46:31 -0000 1.228 +++ sys/kern/vfs_mount.c 8 Jul 2006 14:01:52 -0000 @@ -567,6 +567,34 @@ } static int +vfs_domount_try(struct thread *td, char *fspath, int fsflags, + void *fsdata) +{ + struct vfsconf *vfsp; + int error; + printf("Mounting: %s first\n", "ufs"); + error = vfs_domount(td, "ufs", fspath, fsflags, fsdata); + if (error == 0) { + printf("successfully mounted: %s\n", "ufs"); + } + if (error != 0) { + TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) { + if ((strcmp("ufs", vfsp->vfc_name) != 0) && + !(vfsp->vfc_flags & VFCF_NETWORK) && + !(vfsp->vfc_flags & VFCF_SYNTHETIC)) { + printf("Mounting: %s\n", vfsp->vfc_name); + error = vfs_domount(td, vfsp->vfc_name, fspath, fsflags, fsdata); + if (error == 0) { + printf("successfully mounted: %s\n", vfsp->vfc_name); + break; + } + } + } + } + return error; +} + +static int vfs_donmount(struct thread *td, int fsflags, struct uio *fsoptions) { struct vfsoptlist *optlist; @@ -596,7 +624,7 @@ */ fstypelen = 0; error = vfs_getopt(optlist, "fstype", (void **)&fstype, &fstypelen); - if (error || fstype[fstypelen - 1] != '\0') { + if (error || (fstypelen > 0 && fstype[fstypelen - 1] != '\0')) { error = EINVAL; if (errmsg != NULL) strncpy(errmsg, "Invalid fstype", errmsg_len); @@ -606,6 +634,7 @@ error = vfs_getopt(optlist, "fspath", (void **)&fspath, &fspathlen); if (error || fspath[fspathlen - 1] != '\0') { error = EINVAL; + printf("%s:%d EINVAL\n", __FILE__, __LINE__); if (errmsg != NULL) strncpy(errmsg, "Invalid fspath", errmsg_len); goto bail; @@ -686,7 +715,14 @@ } mtx_lock(&Giant); - error = vfs_domount(td, fstype, fspath, fsflags, optlist); + if (fstypelen > 1) { + /* fstype was specified, go directly to vfs_domount() */ + error = vfs_domount(td, fstype, fspath, fsflags, optlist); + } + else { + /* we do not know the fstype, try to probe for it */ + error = vfs_domount_try(td, fspath, fsflags, optlist); + } mtx_unlock(&Giant); bail: /* copyout the errmsg */ Index: sbin/mount/mount.c =================================================================== RCS file: /home/ncvs/src/sbin/mount/mount.c,v retrieving revision 1.87 diff -u -u -r1.87 mount.c --- sbin/mount/mount.c 10 Jun 2006 01:44:57 -0000 1.87 +++ sbin/mount/mount.c 8 Jul 2006 14:14:47 -0000 @@ -200,7 +200,7 @@ all = init_flags = 0; vfslist = NULL; - vfstype = "ufs"; + vfstype = ""; while ((ch = getopt(argc, argv, "adF:fo:prwt:uv")) != -1) switch (ch) { case 'a': Index: sbin/mount/mount_fs.c =================================================================== RCS file: /home/ncvs/src/sbin/mount/mount_fs.c,v retrieving revision 1.2 diff -u -u -r1.2 mount_fs.c --- sbin/mount/mount_fs.c 13 Nov 2005 01:27:57 -0000 1.2 +++ sbin/mount/mount_fs.c 8 Jul 2006 14:14:47 -0000 @@ -50,6 +50,7 @@ #include <sys/param.h> #include <sys/mount.h> +#include <sys/uio.h> #include <err.h> #include <getopt.h> @@ -82,8 +83,9 @@ int iovlen; int mntflags = 0; int ch; - char *dev, *dir, mntpath[MAXPATHLEN]; + char *dev, *dir, mntpath[MAXPATHLEN], frompath[MAXPATHLEN]; char fstype[32]; + //char errmsg[1024] = { 0 }; char *p, *val; int ret; @@ -121,15 +123,35 @@ dir = argv[1]; (void)checkpath(dir, mntpath); + if (realpath(dev, frompath) != NULL) { + dev = frompath; + } (void)rmslashes(dev, dev); build_iovec(&iov, &iovlen, "fstype", fstype, (size_t)-1); build_iovec(&iov, &iovlen, "fspath", mntpath, (size_t)-1); build_iovec(&iov, &iovlen, "from", dev, (size_t)-1); - + //build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); + printf("fstype: %s, fspath: %s, from: %s\n", fstype, mntpath, dev); +retry: ret = nmount(iov, iovlen, mntflags); - if (ret < 0) - err(1, "%s", dev); + if (ret < 0 && iov[1].iov_len == 0) { + /* + * If an fstype was not specified, and nmount() failed, + * try again with an fstype of "ufs". This is for backwards + * compatibility with older kernels which do not support + * do_mount_try() with an fstype of "". + */ + iov[1].iov_base = strdup("ufs"); + iov[1].iov_len = 4; + printf("Trying again....\n"); + goto retry; + } + + if (ret < 0) { + //err(1, "%s %s", dev, errmsg); + //err(1, "%s", dev); + } return (ret); } -- Craig Rodrigues rodrigc@crodrigues.org
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20060708152801.GA3671>