DEVTAB - Add mountroot & fstab support for serial numbers, and devtab.
authorMatthew Dillon <dillon@apollo.backplane.com>
Thu, 6 Aug 2009 02:37:53 +0000 (19:37 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Thu, 6 Aug 2009 02:37:53 +0000 (19:37 -0700)
* The vfs.root.mountfrom /boot/loader.conf variable may now specify
  devfs aliases, allowing it to specify root mounts by serial number.
  Here is an example:

    vfs.root.mountfrom="hammer:serno/L41JYE0G.s1d"

  Note that vfs.root.mountfrom may NOT currently specify /etc/devtab labels.

* /etc/fstab may now specify devfs relative paths (such as serial numbers)
  as well as /etc/devtab labels.  A ".suffix" may be used to extend the
  translation so /etc/devtab only needs to specify the base label.

  Example /etc/fstab:

    # Device                Mountpoint FStype  Options  Dump    Pass
    #
    driveA.s1d              /          hammer  rw       1       1
    driveA.s1b              none       swap    sw       0       0
    driveA.s1a              /boot      ufs     rw       1       1
    serno/L41JYE0G.s1d      /fubar     hammer  rw       1       1

   /etc/devtab:

    driveA          serno   L41JYE0G

13 files changed:
include/fstab.h
lib/libc/gen/Makefile.inc
lib/libc/gen/fstab.c
lib/libc/gen/getdevpath.3 [moved from lib/libutil/getdevpath.3 with 99% similarity]
lib/libc/gen/getdevpath.c [moved from lib/libutil/getdevpath.c with 79% similarity]
lib/libutil/Makefile
lib/libutil/libutil.h
sbin/getdevpath/Makefile
sbin/getdevpath/getdevpath.c
share/man/man5/fstab.5
sys/boot/common/loader.8
sys/kern/vfs_conf.c
sys/vfs/devfs/devfs_core.c

index 258078d..9b45019 100644 (file)
@@ -68,6 +68,10 @@ struct fstab {
        int     fs_passno;              /* pass number on parallel fsck */
 };
 
+/* getdevpath(3) */
+#define _HAVE_GETDEVPATH       1       /* allow code conditionalization */
+#define GETDEVPATH_RAWDEV      0x0001
+
 #include <sys/cdefs.h>
 
 __BEGIN_DECLS
@@ -78,6 +82,7 @@ struct fstab  *getfsspec(const char *);
 const char     *getfstab(void);
 int             setfsent(void);
 void            setfstab(const char *);
+char           *getdevpath(const char *devname, int flags);
 __END_DECLS
 
 #endif /* !_FSTAB_H_ */
index c0483a5..3c1c162 100644 (file)
@@ -12,7 +12,8 @@ SRCS+=  _pthread_stubs.c _rand48.c _spinlock_stub.c _thread_init.c \
        dlfcn.c dlfunc.c drand48.c erand48.c err.c errlst.c exec.c \
        fdevname.c fmtcheck.c fmtmsg.c fnmatch.c fpclassifyd.c fpclassifyf.c \
        frexp.c fstab.c ftok.c fts.c ftw.c getbootfile.c getbsize.c \
-       getcap.c getcwd.c getdomainname.c getgrent.c getgrouplist.c \
+       getcap.c getcwd.c getdevpath.c getdomainname.c \
+       getgrent.c getgrouplist.c \
        gethostname.c getloadavg.c getlogin.c getmntinfo.c getmntvinfo.c \
        getnetgrent.c getobjformat.c getosreldate.c getpagesize.c \
        getpeereid.c getprogname.c getpwent.c getttyent.c \
@@ -53,6 +54,7 @@ MAN+= alarm.3 arc4random.3 clock.3 \
        err.3 exec.3 fdevname.3 \
        fmtcheck.3 fmtmsg.3 fnmatch.3 fpclassify.3 frexp.3 ftok.3 fts.3 ftw.3 \
        getbootfile.3 getbsize.3 getcap.3 getcontext.3 getcwd.3 \
+       getdevpath.3 \
        getdiskbyname.3 getdisktabbyname.3 getdomainname.3 getfsent.3 \
        getgrent.3 getgrouplist.3 gethostname.3 getloadavg.3 \
        getmntinfo.3 getnetgrent.3 getobjformat.3 getosreldate.3 \
index 9d7bea1..e057b8e 100644 (file)
@@ -46,6 +46,7 @@
 #include "un-namespace.h"
 
 static FILE *_fs_fp;
+static char *_fs_spec;         /* allocated via getdevpath() */
 static struct fstab _fs_fstab;
 static int LineNo = 0;
 static char *path_fstab;
@@ -55,6 +56,7 @@ static int fsp_set = 0;
 static void error(int);
 static void fixfsfile(void);
 static int fstabscan(void);
+static char *gdplookup(char *spec);
 
 void
 setfstab(const char *file)
@@ -120,7 +122,7 @@ fstabscan(void)
                if (*line == '#' || *line == '\n')
                        continue;
                if (!strpbrk(p, " \t")) {
-                       _fs_fstab.fs_spec = strsep(&p, ":\n");
+                       _fs_fstab.fs_spec = gdplookup(strsep(&p, ":\n"));
                        _fs_fstab.fs_file = strsep(&p, ":\n");
                        fixfsfile();
                        _fs_fstab.fs_type = strsep(&p, ":\n");
@@ -147,6 +149,7 @@ fstabscan(void)
                _fs_fstab.fs_spec = cp;
                if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#')
                        continue;
+               _fs_fstab.fs_spec = gdplookup(_fs_fstab.fs_spec);
                while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
                        ;
                _fs_fstab.fs_file = cp;
@@ -270,6 +273,17 @@ endfsent(void)
        fsp_set = 0;
 }
 
+static char *
+gdplookup(char *spec)
+{
+       if (_fs_spec)
+               free(_fs_spec);
+       _fs_spec = getdevpath(spec, 0);
+       if (strcmp(_fs_spec, spec) != 0)
+               spec = _fs_spec;
+       return(spec);
+}
+
 static void
 error(int err)
 {
similarity index 99%
rename from lib/libutil/getdevpath.3
rename to lib/libc/gen/getdevpath.3
index fa74620..11d2468 100644 (file)
 .Nm getdevpath
 .Nd retrieve device path given name or label
 .Sh LIBRARY
-.Lb libutil
+.Lb libc
 .Sh SYNOPSIS
 .In sys/types.h
-.In libutil.h
+.In fstab.h
 .Ft char *
 .Fn getdevpath "const char *devname" "int flags"
 .Sh DESCRIPTION
similarity index 79%
rename from lib/libutil/getdevpath.c
rename to lib/libc/gen/getdevpath.c
index b2f7c52..62f0def 100644 (file)
@@ -63,16 +63,14 @@ getdevpath(const char *devname, int flags)
 
        if (devname[0] == '/' || devname[0] == '.') {
                asprintf(&path, "%s", devname);
-       } else if ((ptr = strchr(devname, ':')) != NULL) {
-               asprintf(&path, "/dev/%*.*s/%s",
-                       ptr - devname, ptr - devname, devname,
-                       ptr + 1);
        } else {
                asprintf(&path, "/dev/%s", devname);
                if (lstat(path, &st) < 0) {
                        free(path);
                        path = NULL;
                        finddevlabel(&path, devname);
+                       if (path == NULL)
+                               asprintf(&path, "%s", devname);
                } else {
                        stgood = 1;
                }
@@ -104,25 +102,65 @@ finddevlabel(char **pathp, const char *devname)
 {
        const char *prefix = _PATH_DEVTAB_PATHS;
        const char *ptr1;
-       const char *ptr2;
+       const char *trailer;
+       char *label;
+       char *ptr2;
        char *ptr3;
        char *dtpath;
        char *bufp;
        char buf[256];
        FILE *fp;
-       size_t len;
+       size_t len;     /* directory prefix length */
+       size_t dlen;    /* devname length */
+       size_t tlen;    /* devname length without trailer */
+
+       dlen = strlen(devname);
+       if ((trailer = strrchr(devname, '.')) != NULL)
+               tlen = trailer - devname;
+       else
+               tlen = 0;
 
        while (*prefix && *pathp == NULL) {
+               /*
+                * Directory search path
+                */
                ptr1 = strchr(prefix, ':');
                len = (ptr1) ? (size_t)(ptr1 - prefix) : strlen(prefix);
                asprintf(&dtpath, "%*.*s/devtab", len, len, prefix);
+
+               /*
+                * Each devtab file
+                */
                if ((fp = fopen(dtpath, "r")) != NULL) {
                        while (fgets(buf, sizeof(buf), fp) != NULL) {
-                               ptr1 = strtok_r(buf, " \t\r\n", &bufp);
-                               if (ptr1 == NULL || *ptr1 == 0 || *ptr1 == '#')
+                               /*
+                                * Extract label field, check degenerate
+                                * cases.
+                                */
+                               label = strtok_r(buf, " \t\r\n", &bufp);
+                               if (label == NULL || *label == 0 ||
+                                   *label == '#') {
                                        continue;
-                               if (strcmp(devname, ptr1) != 0)
+                               }
+
+                               /*
+                                * Match label, with or without the
+                                * trailer (aka ".s1a").  The trailer
+                                * is tacked on if the match is without
+                                * the trailer.
+                                */
+                               if (strcmp(devname, label) == 0) {
+                                       trailer = "";
+                               } else if (tlen && strlen(label) == tlen &&
+                                          strncmp(devname, label, tlen) == 0) {
+                                       trailer = devname + tlen;
+                               } else {
                                        continue;
+                               }
+
+                               /*
+                                * Match, extract and process remaining fields.
+                                */
                                ptr2 = strtok_r(NULL, " \t\r\n", &bufp);
                                ptr3 = strtok_r(NULL, " \t\r\n", &bufp);
                                if (ptr2 == NULL || ptr3 == NULL)
@@ -131,10 +169,10 @@ finddevlabel(char **pathp, const char *devname)
                                        continue;
                                ptr3 = dodequote(ptr3);
                                if (strcmp(ptr2, "path") == 0) {
-                                       asprintf(pathp, "%s", ptr3);
+                                       asprintf(pathp, "%s%s", ptr3, trailer);
                                } else {
-                                       asprintf(pathp, "/dev/%s/%s",
-                                                ptr2, ptr3);
+                                       asprintf(pathp, "/dev/%s/%s%s",
+                                                ptr2, ptr3, trailer);
                                }
                                break;
                        }
index 9d033c5..9f8db8e 100644 (file)
@@ -10,8 +10,7 @@ SRCS= flopen.c login.c login_tty.c logout.c logwtmp.c pty.c \
        login_cap.c login_class.c login_auth.c login_times.c login_ok.c \
        login_crypt.c _secure_path.c uucplock.c property.c auth.c \
        realhostname.c fparseln.c stub.c pidfile.c trimdomain.c \
-       dehumanize_number.c humanize_number.c pw_util.c \
-       getdevpath.c
+       dehumanize_number.c humanize_number.c pw_util.c
 INCS=  libutil.h login_cap.h
 WARNS?=        3
 
@@ -21,8 +20,7 @@ MAN+= flopen.3 login.3 login_auth.3 login_tty.3 logout.3 logwtmp.3 pty.3 \
        login_cap.3 login_class.3 login_times.3 login_ok.3 \
        _secure_path.3 uucplock.3 property.3 auth.3 realhostname.3 \
        realhostname_sa.3 trimdomain.3 fparseln.3 pidfile.3 \
-       humanize_number.3 \
-       getdevpath.3
+       humanize_number.3
 MAN+=  login.conf.5 auth.conf.5
 MLINKS+= property.3 properties_read.3  property.3 properties_free.3
 MLINKS+= property.3 property_find.3
index b90d7d2..e00676c 100644 (file)
@@ -103,7 +103,6 @@ struct passwd *pw_scan(const char *_line, int _flags);
 const char *pw_tempname(void);
 int    pw_tmp(int _mfd);
 #endif
-char   *getdevpath(const char *devname, int flags);
 __END_DECLS
 
 #define UU_LOCK_INUSE (1)
@@ -141,8 +140,4 @@ __END_DECLS
 #define HN_GETSCALE            0x10 
 #define HN_AUTOSCALE           0x20 
 
-/* getdevpath(3) */
-#define _HAVE_GETDEVPATH       1       /* allow code conditionalization */
-#define GETDEVPATH_RAWDEV      0x0001
-
 #endif /* !_LIBUTIL_H_ */
index 82922e5..e19b152 100644 (file)
@@ -1,7 +1,6 @@
 # Makefile for getdevpath
 #
 PROG=  getdevpath
-LDADD= -lutil
 MAN=   getdevpath.8
 
 .include <bsd.prog.mk>
index 126b7b7..359c258 100644 (file)
@@ -36,7 +36,7 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <libutil.h>
+#include <fstab.h>
 
 static void usage(void);
 
index b3ddd0c..d419442 100644 (file)
@@ -66,7 +66,12 @@ doing their thing.
 The first field,
 .Pq Fa fs_spec ,
 describes the special file or
-remote file system to be mounted.
+remote file system to be mounted.  This may be a /dev/<path>, a label
+from a devtab (typically /etc/devtab), or a host:path for NFS.
+Note that devtab labels maybe augmented with a ".suffix" trailer.  For
+example "mydisk.s1a".
+Also note /dev based paths can mount serial numbers similar to devtab
+labels by using the path "/dev/serno/SERIALNO[.suffix]".
 .Pp
 The second field,
 .Pq Fa fs_file ,
index 82be916..b74adce 100644 (file)
@@ -545,6 +545,9 @@ for kernel root file system.
 Used with boot-only partition, which is typically mounted on root file system as
 .Pa /boot .
 Example: "hammer:da8s1a"
+.Pp
+You may not specify devtab labels here but you can specify paths available
+to devfs such as "hammer:serno/L41JYE0G.s1d".
 .El
 .Ss BUILTIN PARSER
 When a builtin command is executed, the rest of the line is taken
index f03ccca..4a6d818 100644 (file)
@@ -547,8 +547,6 @@ cdev_t
 kgetdiskbyname(const char *name) 
 {
        char *cp;
-       int nlen;
-       int unit, slice, part;
        cdev_t rdev;
 
        /*
@@ -557,58 +555,11 @@ kgetdiskbyname(const char *name)
        if (strncmp(name, __SYS_PATH_DEV, sizeof(__SYS_PATH_DEV) - 1) == 0)
                name += sizeof(__SYS_PATH_DEV) - 1;
        cp = __DECONST(char *, name);
-       while (*cp == '/')
-               ++cp;
-       while (*cp >= 'a' && *cp <= 'z')
-               ++cp;
-       if (cp == name) {
-               kprintf("missing device name\n");
-               return (NULL);
-       }
-       nlen = cp - name;
-
-       /*
-        * Get the unit.
-        */
-       unit = strtol(cp, &cp, 10);
-       if (name + nlen == (const char *)cp || unit < 0 || unit >= DKMAXUNITS) {
-               kprintf("bad unit: %d\n", unit);
-               return (NULL);
-       }
-
-       /*
-        * Get the slice.  Note that if no partition or partition 'a' is
-        * specified, and no slice is specified, we will try both 'ad0a'
-        * (which is what you get when slice is 0), and also 'ad0' (the
-        * whole-disk partition, slice == 1).
-        */
-       if (*cp == 's') {
-               slice = cp[1] - '0';
-               if (slice >= 1)
-                       ++slice;
-               cp += 2;
-       } else {
-               slice = 0;
-       }
-
-       /*
-        * Get the partition.
-        */
-       if (*cp >= 'a' && *cp <= 'p') {
-               part = *cp - 'a';
-               ++cp;
-       } else {
-               part = 0;
-       }
-
-       if (*cp != '\0') {
-               kprintf("junk after name: %s\n", cp);
-               return (NULL);
-       }
 
        /*
         * Locate the device
         */
+       kprintf("tryroot %s\n", name);
        rdev = devfs_find_device_by_name(name);
        if (rdev == NULL) {
                kprintf("no disk named '%s'\n", name);
index c87ef05..324cd37 100644 (file)
@@ -1401,15 +1401,24 @@ devfs_chandler_del_worker(char *name)
 static int
 devfs_find_device_by_name_worker(devfs_msg_t devfs_msg)
 {
-       cdev_t dev, dev1;
+       struct devfs_alias *alias;
+       cdev_t dev;
        cdev_t found = NULL;
 
-       TAILQ_FOREACH_MUTABLE(dev, &devfs_dev_list, link, dev1) {
-               if (!strcmp(devfs_msg->mdv_name, dev->si_name)) {
+       TAILQ_FOREACH(dev, &devfs_dev_list, link) {
+               if (strcmp(devfs_msg->mdv_name, dev->si_name) == 0) {
                        found = dev;
                        break;
                }
        }
+       if (found == NULL) {
+               TAILQ_FOREACH(alias, &devfs_alias_list, link) {
+                       if (strcmp(devfs_msg->mdv_name, alias->name) == 0) {
+                               found = alias->dev_target;
+                               break;
+                       }
+               }
+       }
        devfs_msg->mdv_cdev = found;
 
        return 0;
@@ -1450,7 +1459,7 @@ devfs_make_alias_worker(struct devfs_alias *alias)
        int found = 0;
 
        TAILQ_FOREACH(alias2, &devfs_alias_list, link) {
-               if (!memcmp(alias->name, alias2->name, len)) {
+               if (!memcmp(alias->name, alias2->name, len)) { /* XXX */
                        found = 1;
                        break;
                }