Messages in this thread Patch in this message | | | From | "DoMiNo" <> | Subject | [PATCH] UUID and label support for root file-system | Date | Thu, 29 Jul 1999 17:42:58 +0200 |
| |
OK , here is a patch which makes it possible to specify the root FS by its UUID or volume label. It works with ext2 only for obvious reasons.
Usage : pass the root= parameter to the kernel
root=UUID:43534543-6565-656-6565564564 for UUIDs or root=L:myLinuxRoot for labels
root=/dev/hda1 and root=305 work too, as before.
When using lilo use the append="root=what-ever" instead of just root=xxx.
The patch is agains kernel 2.2.5 , but applies to 2.2.10 too.
Send (or CC) any comments to me at david.balazic@uni-mb.si ( I'm not subscribed to linux-kernel )
The patch ( also avaliable at http://www.uni-mb.si/~uel003r2a/uuid.patch , this has the tabs mangled) :
diff -u -r linux-2.2.5-22-redhat/Documentation/Configure.help linux/Documentation/Configure.help --- linux-2.2.5-22-redhat/Documentation/Configure.help Wed Jun 2 14:36:15 1999 +++ linux/Documentation/Configure.help Thu Jul 29 17:08:59 1999 @@ -6826,6 +6826,25 @@ compiled as a module, and so this could be dangerous. Most everyone wants to say Y here.
+Select root file-system by UUID or volume label +CONFIG_ROOT_FS_LABEL + If you say Y, you will be able to select the root file-system + by it's UUID or volume label with the root= kernel parameter. + Examples : + root=UUID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + root=L:linux-root + + You can still use the old root=/dev/hda1 and root=307 forms. + + Currently, it works only with the ext2 filesystem. + + If you are using LILO you MUST use the option + append="root=L:xxx" instead of just root=L:xxx + in the lilo.conf file. LILO tries to parse the boot= + option itself, while it just passes the append string + to the kernel. Loadlin and other loader may have similar problems. + If you say Y, you will be able to select the root file-system + ISO 9660 CDROM filesystem support CONFIG_ISO9660_FS This is the standard filesystem used on CDROMs. It was previously diff -u -r linux-2.2.5-22-redhat/fs/Config.in linux/fs/Config.in --- linux-2.2.5-22-redhat/fs/Config.in Mon Mar 8 00:25:23 1999 +++ linux/fs/Config.in Thu Jul 29 15:53:05 1999 @@ -49,6 +49,9 @@ fi tristate 'ROM filesystem support' CONFIG_ROMFS_FS tristate 'Second extended fs support' CONFIG_EXT2_FS +if [ "$CONFIG_EXT2_FS" = "y" ]; then + bool 'Select root file-system by UUID or volume label' CONFIG_ROOT_FS_LABEL +fi tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS tristate 'UFS filesystem support' CONFIG_UFS_FS if [ "$CONFIG_UFS_FS" != "n" ]; then diff -u -r linux-2.2.5-22-redhat/fs/super.c linux/fs/super.c --- linux-2.2.5-22-redhat/fs/super.c Wed Jun 2 14:36:14 1999 +++ linux/fs/super.c Thu Jul 29 16:14:34 1999 @@ -15,6 +15,9 @@ * * Added kerneld support: Jacques Gelinas and Bjorn Ekwall * Added change_root: Werner Almesberger & Hans Lermen, Feb '96 + * + * Added support for selecting the root-fs by UUID or label + * David Balazic <1stein@writeme.com>, Jul 1999 */
#include <linux/config.h> @@ -36,6 +39,11 @@ #include <linux/kmod.h> #endif
+#ifdef CONFIG_ROOT_FS_LABEL +#include <linux/genhd.h> +#include <linux/ext2_fs.h> +#endif + /* * We use a semaphore to synchronize all mount/umount * activity - imagine the mess if we have a race between @@ -1114,6 +1122,52 @@ goto dput_and_out; }
+#ifdef CONFIG_ROOT_FS_LABEL +/* + * check_dev(int major,int minor) + * check if the partition has the right label or UUID. + * Based on code from util-linux-2.9s/mount/mount_by_label.c + * ( matching the label/UUID ) and /usr/src/linux/fs/ext2/super.c + * ( loading the blocks ) + */ +static int __init check_dev(int major, int minor) +{ + extern char root_dev_label[16]; + extern int root_dev_type; + int blocksize; + unsigned long logic_sb_block = 1; + unsigned long offset = 0; + kdev_t dev; + struct buffer_head *bh; + struct ext2_super_block *e2sb; + int result = 0; + + dev = to_kdev_t((major << 8) | (minor & 0xff)); /* or maybe MKDEV(major,minor) ? */ + + if ((blocksize = get_hardblocksize(dev)) == 0) + blocksize = BLOCK_SIZE; + + if (blocksize != BLOCK_SIZE) { + logic_sb_block = (1 * BLOCK_SIZE) / blocksize; + offset = (1 * BLOCK_SIZE) % blocksize; + } + if (!(bh = bread(dev, logic_sb_block, blocksize))) + return 0; + + e2sb = (struct ext2_super_block *) (((char *) bh->b_data) + offset); + + if (le16_to_cpu(e2sb->s_magic) == EXT2_SUPER_MAGIC) { + if (strncmp((root_dev_type == 1) ? (char *) e2sb->s_uuid : e2sb->s_volume_name, + root_dev_label, 16)) + result = 0; + else + result = 1; + } + brelse(bh); + return result; +} +#endif + void __init mount_root(void) { struct file_system_type * fs_type; @@ -1123,6 +1177,29 @@ struct file filp; int retval;
+#ifdef CONFIG_ROOT_FS_LABEL + extern int root_dev_type; + + if (root_dev_type != 0) { + struct gendisk *p; + int n; + + if (root_dev_type == 3) + panic("Badly formatted UUID was supplied as kernel parameter root"); + + for (p = gendisk_head; p; p = p->next) + for (n = 0; n < (p->nr_real << p->minor_shift); n++) + if (p->part[n].nr_sects > 8) /* avoid empty , too small and extended partitions */ + if (check_dev(p->major, n)) { + ROOT_DEV = to_kdev_t((p->major << 8) | (n & 0xff)); + goto root_dev_found; + } +/* panic("VFS: didn't found the root fs based on UUID or label"); */ + printk("VFS: didn't found the root fs based on UUID or label, trying old method\n"); + } + root_dev_found: +#endif + #ifdef CONFIG_ROOT_NFS if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) { ROOT_DEV = 0; diff -u -r linux-2.2.5-22-redhat/init/main.c linux/init/main.c --- linux-2.2.5-22-redhat/init/main.c Wed Jun 2 14:36:14 1999 +++ linux/init/main.c Thu Jul 29 16:20:01 1999 @@ -7,6 +7,9 @@ * Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96 * Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96 * Simplified starting of init: Michael A. Griffith <grif@acm.org> + * + * Added support for selecting the root file system by ext2 label or UUID : + * David Balazic <1stein@writeme.com> Jul 1999 */
#define __KERNEL_SYSCALLS__ @@ -539,8 +542,70 @@ return to_kdev_t(base + simple_strtoul(line,NULL,base?10:16)); }
+#ifdef CONFIG_ROOT_FS_LABEL +char root_dev_label[16]; +int root_dev_type; /* 0 - normal /dev/xxx or 302 , + 1 - UUID, 2 - label , 3 - bad UUID */ + +/* taken from util-linux-2.9s/mount/mount_by_label.c */ +static u_char __init fromhex(char c) +{ + if (isdigit(c)) + return (c - '0'); + else if (islower(c)) + return (c - 'a' + 10); + else + return (c - 'A' + 10); +} + +static void __init parse_uuid(const char *s) +{ + int i; + + if (strlen(s) != 36 || + s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-') + goto bad_uuid; + for (i = 0; i < 16; i++) { + if (*s == '-') + s++; + if (!isxdigit(s[0]) || !isxdigit(s[1])) + goto bad_uuid; + root_dev_label[i] = ((fromhex(s[0]) << 4) | fromhex(s[1])); + s += 2; + } + return; + bad_uuid: + root_dev_type = 3; + +/* panic("Bad UUID was supplied for root-fs\n"); */ + + /* Unfortunately , panic() doesn't work here. + * The machine is stopped , but there is no output, + * except "... Decompressing kernel ..." + * so I delay it until mount_root time + */ +} +#endif + static void __init root_dev_setup(char *line, int *num) { +#ifdef CONFIG_ROOT_FS_LABEL + if (strncmp(line, "L:", 2) == 0) { + line += 2; + strncpy(root_dev_label, line, 16); + root_dev_type = 2; + /* maybe a warning would be appropriate + * if the supplied label is longer than 16 chars, + * now it is silently truncated */ + return; + } else if (strncmp(line, "UUID:", 5) == 0) { + line += 5; + root_dev_type = 1; + parse_uuid(line); + return; + } + root_dev_type = 0; +#endif ROOT_DEV = name_to_kdev_t(line); }
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |