>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"