>Number:         149803
>Category:       kern
>Synopsis:       [patch] loader: set vfs.mount.rootfrom using label
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Aug 19 11:40:00 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Thomas Quinot
>Release:        FreeBSD 8.0-STABLE amd64
>Organization:
>Environment:
System: FreeBSD melamine.cuivre.fr.eu.org 8.0-STABLE FreeBSD 8.0-STABLE #0: Sun 
Mar 28 14:46:11 CEST 2010 
tho...@melamine.cuivre.fr.eu.org:/usr/obj/usr/src/sys/GENERIC amd64


        
>Description:
        The loader code that sets vfs.root.mountfrom currently requires 
/etc/fstab
        on the root filesystem to contain an appropriate device name. This 
proposed
        change provides an alternative way of passing the root device from
        loader to kernel, namely by relying on a volume label (in the geom_label
        sense) found on the candidate root device. This allows the root 
filesystem
        to be mounted even in the absence of a /etc/fstab entry for it if it
        has a supported label (UFS label, UFS unique id, ext2fs label, ISO 9660
        volume name...) It could conceivably be extended to also include support
        for GPT partition labels.

        A typical use case for this feature is a nanoBSD setup with two possible
        boot slices. With this change, you do not need to have a different 
/etc/fstab
        on the two slices, you can select one slice at boot and the kernel will
        know to mount it using its UFS id.

        The new code is activated when either there's no entry for / in 
/etc/fstab,
        or when there's one mentioning the special name "/dev/rootdev". I have 
also
        included a trivial rc.d patch that creates /dev/rootdev as a symlink at 
boot,
        for consistency.

>How-To-Repeat:
        
>Fix:

Index: etc/rc.d/root
===================================================================
--- etc/rc.d/root       (révision 200035)
+++ etc/rc.d/root       (copie de travail)
@@ -36,6 +36,16 @@
        if [ -x /sbin/nextboot ]; then
                /sbin/nextboot -D > /dev/null 2>&1
        fi
+
+       # Create rootdev link
+       rootmnt=`kenv vfs.root.mountfrom`
+       rootdev=${rootmnt#*:}
+       (
+       cd /dev
+       if [ -e "${rootdev}" ]; then
+               ln -s ${rootdev} rootdev
+       fi
+       )
 }
 
 load_rc_config $name
Index: lib/libstand/ioctl.c
===================================================================
--- lib/libstand/ioctl.c        (révision 200035)
+++ lib/libstand/ioctl.c        (copie de travail)
@@ -64,6 +64,7 @@
 __FBSDID("$FreeBSD$");
 
 #include "stand.h"
+#include "saioctl.h"
 
 int
 ioctl(fd, cmd, arg)
@@ -77,12 +78,31 @@
                errno = EBADF;
                return (-1);
        }
-       if (f->f_flags & F_RAW) {
-               errno = (f->f_dev->dv_ioctl)(f, cmd, arg);
-               if (errno)
-                       return (-1);
-               return (0);
+       switch (SAIO_LAYER(cmd)) {
+               case SAIO_DEV:
+                       if (f->f_flags & F_RAW)
+                               errno = (f->f_dev->dv_ioctl)(f, cmd, arg);
+                       else
+                               errno = EIO;
+                       break;
+               case SAIO_FS:
+                       switch (cmd) {
+                               case SAIOGFSTYPE:
+                                       *(const char **)arg = f->f_ops->fs_name;
+                                       errno = 0;
+                                       break;
+                               case SAIOGFSLABEL:
+                                       *(const char **)arg = f->f_labeldev;
+                                       errno = 0;
+                                       break;
+                               default:
+                                       errno = EINVAL;
+                       }
+                       break;
+               default:
+                       errno = EINVAL;
        }
-       errno = EIO;
-       return (-1);
+       if (errno)
+               return (-1);
+       return (0);
 }
Index: lib/libstand/ext2fs.c
===================================================================
--- lib/libstand/ext2fs.c       (révision 200035)
+++ lib/libstand/ext2fs.c       (copie de travail)
@@ -386,6 +386,11 @@
        fs->fs_ipb = fs->fs_bsize / fs->fs_isize;
        fs->fs_fsbtodb = (fs->fs_bsize / DEV_BSIZE) - 1;
 
+       if (fs->fs_fd.fd_volname[0] != '\0') {
+               sprintf(namebuf, "/dev/ext2fs/%s", fs->fs_fd.fd_volname);
+               f->f_labeldev = strdup(namebuf);
+       }
+
        /*
         * we have to load in the "group descriptors" here
         */
@@ -794,6 +799,10 @@
        struct file *fp = (struct file *)f->f_fsdata;
        int level;
 
+       if (f->f_labeldev != NULL) {
+               free(f->f_labeldev);
+               f->f_labeldev = NULL;
+       }
        f->f_fsdata = (void *)0;
        if (fp == (struct file *)0)
                return (0);
Index: lib/libstand/Makefile
===================================================================
--- lib/libstand/Makefile       (révision 200035)
+++ lib/libstand/Makefile       (copie de travail)
@@ -12,7 +12,7 @@
 LIB=           stand
 NO_PROFILE=
 NO_PIC=
-INCS=          stand.h
+INCS=          stand.h saioctl.h
 MAN=           libstand.3
 
 CFLAGS+= -ffreestanding -Wformat
Index: lib/libstand/ufs.c
===================================================================
--- lib/libstand/ufs.c  (révision 200035)
+++ lib/libstand/ufs.c  (copie de travail)
@@ -538,6 +538,15 @@
                goto out;
        }
        /*
+        * Find a unique device name.
+        */
+       if (fs->fs_volname[0] != '\0') {
+               sprintf (namebuf, "/dev/ufs/%s", fs->fs_volname);
+       } else {
+               sprintf (namebuf, "/dev/ufsid/%08x%08x", fs->fs_id[0], 
fs->fs_id[1]);
+       }
+       f->f_labeldev = strdup(namebuf);
+       /*
         * Calculate indirect block levels.
         */
        {
@@ -711,6 +720,8 @@
        if (fp->f_buf)
                free(fp->f_buf);
        free(fp->f_fs);
+       free(f->f_labeldev);
+       f->f_labeldev = NULL;
        free(fp);
        return (0);
 }
Index: lib/libstand/open.c
===================================================================
--- lib/libstand/open.c (révision 200035)
+++ lib/libstand/open.c (copie de travail)
@@ -123,7 +123,6 @@
 
        error = ((*file_system[i]).fo_open)(file, f);
        if (error == 0) {
-           
            f->f_ops = file_system[i];
            o_rainit(f);
            return (fd);
Index: lib/libstand/saioctl.h
===================================================================
--- lib/libstand/saioctl.h      (révision 200035)
+++ lib/libstand/saioctl.h      (copie de travail)
@@ -33,18 +33,30 @@
  * $FreeBSD$
  */
 
-/* ioctl's -- for disks just now */
-#define        SAIOHDR         (('d'<<8)|1)    /* next i/o includes header */
-#define        SAIOCHECK       (('d'<<8)|2)    /* next i/o checks data */
-#define        SAIOHCHECK      (('d'<<8)|3)    /* next i/o checks header & 
data */
-#define        SAIONOBAD       (('d'<<8)|4)    /* inhibit bad sector 
forwarding */
-#define        SAIODOBAD       (('d'<<8)|5)    /* enable bad sector forwarding 
*/
-#define        SAIOECCLIM      (('d'<<8)|6)    /* set limit to ecc correction, 
bits */
-#define        SAIOECCUNL      (('d'<<8)|7)    /* use standard ecc procedures 
*/
-#define        SAIORETRIES     (('d'<<8)|8)    /* set retry count for unit */
-#define        SAIODEVDATA     (('d'<<8)|9)    /* get pointer to pack label */
-#define        SAIOSSI         (('d'<<8)|10)   /* set skip sector inhibit */
-#define        SAIONOSSI       (('d'<<8)|11)   /* inhibit skip sector handling 
*/
-#define        SAIOSSDEV       (('d'<<8)|12)   /* is device skip sector type? 
*/
-#define        SAIODEBUG       (('d'<<8)|13)   /* enable/disable debugging */
-#define        SAIOGBADINFO    (('d'<<8)|14)   /* get bad-sector table */
+/* ioctl's */
+
+#define SAIO_LAYER(cmd) (cmd & 0xf0000000)
+#define SAIO_DEV (0 << 28)
+#define SAIO_FS  (1 << 28)
+
+/* DEV layer */
+
+#define        SAIOHDR         (SAIO_DEV|('d'<<8)|1)   /* next i/o includes 
header */
+#define        SAIOCHECK       (SAIO_DEV|('d'<<8)|2)   /* next i/o checks data 
*/
+#define        SAIOHCHECK      (SAIO_DEV|('d'<<8)|3)   /* next i/o checks 
header & data */
+#define        SAIONOBAD       (SAIO_DEV|('d'<<8)|4)   /* inhibit bad sector 
forwarding */
+#define        SAIODOBAD       (SAIO_DEV|('d'<<8)|5)   /* enable bad sector 
forwarding */
+#define        SAIOECCLIM      (SAIO_DEV|('d'<<8)|6)   /* set limit to ecc 
correction, bits */
+#define        SAIOECCUNL      (SAIO_DEV|('d'<<8)|7)   /* use standard ecc 
procedures */
+#define        SAIORETRIES     (SAIO_DEV|('d'<<8)|8)   /* set retry count for 
unit */
+#define        SAIODEVDATA     (SAIO_DEV|('d'<<8)|9)   /* get pointer to pack 
label */
+#define        SAIOSSI         (SAIO_DEV|('d'<<8)|10)  /* set skip sector 
inhibit */
+#define        SAIONOSSI       (SAIO_DEV|('d'<<8)|11)  /* inhibit skip sector 
handling */
+#define        SAIOSSDEV       (SAIO_DEV|('d'<<8)|12)  /* is device skip 
sector type? */
+#define        SAIODEBUG       (SAIO_DEV|('d'<<8)|13)  /* enable/disable 
debugging */
+#define        SAIOGBADINFO    (SAIO_DEV|('d'<<8)|14)  /* get bad-sector table 
*/
+
+/* FS layer */
+
+#define SAIOGFSTYPE    (SAIO_FS|('f'<<8)|1)    /* get file system type */
+#define SAIOGFSLABEL   (SAIO_FS|('f'<<8)|2)    /* get unique device name */
Index: lib/libstand/cd9660.c
===================================================================
--- lib/libstand/cd9660.c       (révision 200035)
+++ lib/libstand/cd9660.c       (copie de travail)
@@ -276,6 +276,7 @@
        struct iso_directory_record rec;
        struct iso_directory_record *dp = 0;
        int rc, first, use_rrip, lenskip;
+       char labelbuf[64];
 
        /* First find the volume descriptor */
        buf = malloc(buf_size = ISO_DEFAULT_BLOCK_SIZE);
@@ -301,6 +302,9 @@
        if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE)
                goto out;
 
+       sprintf(labelbuf, "/dev/iso9660/%s", vd->volume_id);
+       f->f_labeldev = strdup(labelbuf);
+
        rec = *(struct iso_directory_record *) vd->root_directory_record;
        if (*path == '/') path++; /* eat leading '/' */
 
@@ -410,6 +414,8 @@
 {
        struct file *fp = (struct file *)f->f_fsdata;
 
+       free(f->f_labeldev);
+       f->f_labeldev = NULL;
        f->f_fsdata = 0;
        free(fp);
 
Index: lib/libstand/stand.h
===================================================================
--- lib/libstand/stand.h        (révision 200035)
+++ lib/libstand/stand.h        (copie de travail)
@@ -164,6 +164,7 @@
     char               *f_rabuf;       /* readahead buffer pointer */
     size_t             f_ralen;        /* valid data in readahead buffer */
     off_t              f_raoffset;     /* consumer offset in readahead buffer 
*/
+    char               *f_labeldev;    /* unique device name for this file 
system */
 #define SOPEN_RASIZE   512
 };
 
Index: sys/boot/common/boot.c
===================================================================
--- sys/boot/common/boot.c      (révision 200035)
+++ sys/boot/common/boot.c      (copie de travail)
@@ -32,6 +32,8 @@
  */
 
 #include <stand.h>
+#include <sys/ioctl.h>
+#include <saioctl.h>
 #include <string.h>
 
 #include "bootstrap.h"
@@ -361,11 +363,18 @@
                cp++;
        *cp = 0;
        options = strdup(ep);
-       /* Build the <fstype>:<device> and save it in vfs.root.mountfrom */
-       sprintf(lbuf, "%s:%s", fstyp, dev);
+
+       /* Build the <fstype>:<device> and save it in vfs.root.mountfrom,
+        * except if dev is special value "/dev/rootdev", in which case
+        * we rely to the value determined below to provide the proper
+        * device name.
+        */
+       if (strcmp (dev, "/dev/rootdev")) {
+               sprintf(lbuf, "%s:%s", fstyp, dev);
+               setenv("vfs.root.mountfrom", lbuf, 0);
+       }
        free(dev);
        free(fstyp);
-       setenv("vfs.root.mountfrom", lbuf, 0);
 
        /* Don't override vfs.root.mountfrom.options if it is already set */
        if (getenv("vfs.root.mountfrom.options") == NULL) {
@@ -376,6 +385,18 @@
        error = 0;
        break;
     }
+
+    if (getenv("vfs.root.mountfrom") == NULL) {
+       /* Try to get device name from on-disk label */
+       if (ioctl(fd, SAIOGFSTYPE, &fstyp) == 0 &&
+           ioctl(fd, SAIOGFSLABEL, &dev)  == 0)
+       {
+               sprintf(lbuf, "%s:%s", fstyp, dev);
+               setenv("vfs.root.mountfrom", lbuf, 0);
+               error = 0;
+       }
+    }
+
     close(fd);
     return(error);
 }
        


>Release-Note:
>Audit-Trail:
>Unformatted:
_______________________________________________
freebsd-bugs@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"

Reply via email to