From: Kenn H. <ke...@us...> - 2003-06-19 23:31:52
|
Update of /cvsroot/linux-vax/kernel-2.5/init In directory sc8-pr-cvs1:/tmp/cvs-serv16009/init Modified Files: do_mounts.c Log Message: Merge with 2.5.48 Index: do_mounts.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.5/init/do_mounts.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- do_mounts.c 18 May 2003 18:25:23 -0000 1.2 +++ do_mounts.c 19 Jun 2003 23:31:47 -0000 1.3 @@ -12,6 +12,7 @@ #include <linux/init.h> #include <linux/suspend.h> #include <linux/root_dev.h> +#include <linux/mount.h> #include <linux/nfs_fs.h> #include <linux/nfs_fs_sb.h> @@ -20,6 +21,8 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> +#include <linux/raid/md.h> + #define BUILD_CRAMDISK extern int get_filesystem_list(char * buf); @@ -36,6 +39,10 @@ extern asmlinkage long sys_mknod(const char *name, int mode, dev_t dev); extern asmlinkage long sys_umount(char *name, int flags); extern asmlinkage long sys_ioctl(int fd, int cmd, unsigned long arg); +extern asmlinkage long sys_access(const char * filename, int mode); +extern asmlinkage long sys_newstat(char * filename, struct stat * statbuf); +extern asmlinkage long sys_getdents64(unsigned int fd, void * dirent, + unsigned int count); #ifdef CONFIG_BLK_DEV_INITRD unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */ @@ -315,25 +322,125 @@ } #endif +#ifdef CONFIG_DEVFS_FS +static int __init do_read_dir(int fd, void *buf, int len) +{ + long bytes, n; + char *p = buf; + lseek(fd, 0, 0); + + for (bytes = 0, p = buf; bytes < len; bytes += n, p+=n) { + n = sys_getdents64(fd, p, len - bytes); + if (n < 0) + return -1; + if (n == 0) + return bytes; + } + return 0; +} + +static void * __init read_dir(char *path, int *len) +{ + int size; + int fd = open(path, 0, 0); + + *len = 0; + if (fd < 0) + return NULL; + + for (size = 1<<9; size < (1<<18); size <<= 1) { + void *p = kmalloc(size, GFP_KERNEL); + int n; + if (!p) + break; + n = do_read_dir(fd, p, size); + if (n > 0) { + close(fd); + *len = n; + return p; + } + kfree(p); + if (n < 0) + break; + } + close(fd); + return NULL; +} +#endif + +struct linux_dirent64 { + u64 d_ino; + s64 d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[0]; +}; + +static int __init find_in_devfs(char *path, dev_t dev) +{ +#ifdef CONFIG_DEVFS_FS + struct stat buf; + char *end = path + strlen(path); + int rest = path + 64 - end; + int size; + char *p = read_dir(path, &size); + char *s; + + if (!p) + return -1; + for (s = p; s < p + size; s += ((struct linux_dirent64 *)s)->d_reclen) { + struct linux_dirent64 *d = (struct linux_dirent64 *)s; + if (strlen(d->d_name) + 2 > rest) + continue; + switch (d->d_type) { + case DT_BLK: + sprintf(end, "/%s", d->d_name); + if (sys_newstat(path, &buf) < 0) + break; + if (!S_ISBLK(buf.st_mode)) + break; + if (buf.st_rdev != dev) + break; + kfree(p); + return 0; + case DT_DIR: + if (strcmp(d->d_name, ".") == 0) + break; + if (strcmp(d->d_name, "..") == 0) + break; + sprintf(end, "/%s", d->d_name); + if (find_in_devfs(path, dev) < 0) + break; + kfree(p); + return 0; + } + } + kfree(p); +#endif + return -1; +} + static int __init create_dev(char *name, dev_t dev, char *devfs_name) { - void *handle; char path[64]; - int n; sys_unlink(name); if (!do_devfs) return sys_mknod(name, S_IFBLK|0600, dev); - handle = devfs_get_handle(NULL, !dev ? devfs_name : NULL, - MAJOR(dev), MINOR(dev), DEVFS_SPECIAL_BLK, 1); - if (!handle) + if (devfs_name && devfs_name[0]) { + if (strncmp(devfs_name, "/dev/", 5) == 0) + devfs_name += 5; + sprintf(path, "/dev/%s", devfs_name); + if (sys_access(path, 0) == 0) + return sys_symlink(devfs_name, name); + } + if (!dev) return -1; - n = devfs_generate_path(handle, path + 5, sizeof (path) - 5); - devfs_put(handle); - if (n < 0) + strcpy(path, "/dev"); + if (find_in_devfs(path, dev) < 0) return -1; - return sys_symlink(path + n + 5, name); + return sys_symlink(path + 5, name); } #if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD) @@ -730,12 +837,22 @@ return rd_load_image("/dev/initrd"); } +static void __init md_run_setup(void); + /* * Prepare the namespace - decide what/where to mount, load ramdisks, etc. */ void prepare_namespace(void) { - int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; + int is_floppy; + +#ifdef CONFIG_DEVFS_FS + sys_mount("devfs", "/dev", "devfs", 0, NULL); + do_devfs = 1; +#endif + + md_run_setup(); + if (saved_root_name[0]) { char *p = saved_root_name; ROOT_DEV = name_to_dev_t(p); @@ -743,24 +860,15 @@ p += 5; strcpy(root_device_name, p); } + + is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; + #ifdef CONFIG_BLK_DEV_INITRD if (!initrd_start) mount_initrd = 0; real_root_dev = ROOT_DEV; #endif -/* These were removed in 2.5.46 but I've temporarily re-instated them - until initramfs creation is fixed up in 2.5.47 - KPH */ - sys_mkdir("/dev", 0700); - sys_mkdir("/root", 0700); - sys_mknod("/dev/console", S_IFCHR|0600, MKDEV(TTYAUX_MAJOR, 1)); -/* End */ - -#ifdef CONFIG_DEVFS_FS - sys_mount("devfs", "/dev", "devfs", 0, NULL); - do_devfs = 1; -#endif - create_dev("/dev/root", ROOT_DEV, NULL); /* This has to be before mounting root, because even readonly mount of reiserfs would replay @@ -929,3 +1037,260 @@ } #endif /* BUILD_CRAMDISK && CONFIG_BLK_DEV_RAM */ + +#ifdef CONFIG_BLK_DEV_MD + +/* + * When md (and any require personalities) are compiled into the kernel + * (not a module), arrays can be assembles are boot time using with AUTODETECT + * where specially marked partitions are registered with md_autodetect_dev(), + * and with MD_BOOT where devices to be collected are given on the boot line + * with md=..... + * The code for that is here. + */ + +struct { + int set; + int noautodetect; +} raid_setup_args __initdata; + +static struct { + char device_set [MAX_MD_DEVS]; + int pers[MAX_MD_DEVS]; + int chunk[MAX_MD_DEVS]; + char *device_names[MAX_MD_DEVS]; +} md_setup_args __initdata; + +/* + * Parse the command-line parameters given our kernel, but do not + * actually try to invoke the MD device now; that is handled by + * md_setup_drive after the low-level disk drivers have initialised. + * + * 27/11/1999: Fixed to work correctly with the 2.3 kernel (which + * assigns the task of parsing integer arguments to the + * invoked program now). Added ability to initialise all + * the MD devices (by specifying multiple "md=" lines) + * instead of just one. -- KTK + * 18May2000: Added support for persistent-superblock arrays: + * md=n,0,factor,fault,device-list uses RAID0 for device n + * md=n,-1,factor,fault,device-list uses LINEAR for device n + * md=n,device-list reads a RAID superblock from the devices + * elements in device-list are read by name_to_kdev_t so can be + * a hex number or something like /dev/hda1 /dev/sdb + * 2001-06-03: Dave Cinege <dc...@ps...> + * Shifted name_to_kdev_t() and related operations to md_set_drive() + * for later execution. Rewrote section to make devfs compatible. + */ +static int __init md_setup(char *str) +{ + int minor, level, factor, fault, pers; + char *pername = ""; + char *str1 = str; + + if (get_option(&str, &minor) != 2) { /* MD Number */ + printk(KERN_WARNING "md: Too few arguments supplied to md=.\n"); + return 0; + } + if (minor >= MAX_MD_DEVS) { + printk(KERN_WARNING "md: md=%d, Minor device number too high.\n", minor); + return 0; + } else if (md_setup_args.device_names[minor]) { + printk(KERN_WARNING "md: md=%d, Specified more than once. " + "Replacing previous definition.\n", minor); + } + switch (get_option(&str, &level)) { /* RAID Personality */ + case 2: /* could be 0 or -1.. */ + if (level == 0 || level == LEVEL_LINEAR) { + if (get_option(&str, &factor) != 2 || /* Chunk Size */ + get_option(&str, &fault) != 2) { + printk(KERN_WARNING "md: Too few arguments supplied to md=.\n"); + return 0; + } + md_setup_args.pers[minor] = level; + md_setup_args.chunk[minor] = 1 << (factor+12); + switch(level) { + case LEVEL_LINEAR: + pers = LINEAR; + pername = "linear"; + break; + case 0: + pers = RAID0; + pername = "raid0"; + break; + default: + printk(KERN_WARNING + "md: The kernel has not been configured for raid%d support!\n", + level); + return 0; + } + md_setup_args.pers[minor] = pers; + break; + } + /* FALL THROUGH */ + case 1: /* the first device is numeric */ + str = str1; + /* FALL THROUGH */ + case 0: + md_setup_args.pers[minor] = 0; + pername="super-block"; + } + + printk(KERN_INFO "md: Will configure md%d (%s) from %s, below.\n", + minor, pername, str); + md_setup_args.device_names[minor] = str; + + return 1; +} +static void __init md_setup_drive(void) +{ + int minor, i; + dev_t dev; + dev_t devices[MD_SB_DISKS+1]; + + for (minor = 0; minor < MAX_MD_DEVS; minor++) { + int fd; + int err = 0; + char *devname; + mdu_disk_info_t dinfo; + char name[16], devfs_name[16]; + + if (!(devname = md_setup_args.device_names[minor])) + continue; + + sprintf(name, "/dev/md%d", minor); + sprintf(devfs_name, "/dev/md/%d", minor); + create_dev(name, MKDEV(MD_MAJOR, minor), devfs_name); + for (i = 0; i < MD_SB_DISKS && devname != 0; i++) { + char *p; + char comp_name[64]; + struct stat buf; + + p = strchr(devname, ','); + if (p) + *p++ = 0; + + dev = name_to_dev_t(devname); + if (strncmp(devname, "/dev/", 5)) + devname += 5; + snprintf(comp_name, 63, "/dev/%s", devname); + if (sys_newstat(comp_name, &buf) == 0 && + S_ISBLK(buf.st_mode)) + dev = buf.st_rdev; + if (!dev) { + printk(KERN_WARNING "md: Unknown device name: %s\n", devname); + break; + } + + devices[i] = dev; + md_setup_args.device_set[minor] = 1; + + devname = p; + } + devices[i] = 0; + + if (!md_setup_args.device_set[minor]) + continue; + + printk(KERN_INFO "md: Loading md%d: %s\n", minor, md_setup_args.device_names[minor]); + + fd = open(name, 0, 0); + if (fd < 0) { + printk(KERN_ERR "md: open failed - cannot start array %d\n", minor); + continue; + } + if (sys_ioctl(fd, SET_ARRAY_INFO, 0) == -EBUSY) { + printk(KERN_WARNING + "md: Ignoring md=%d, already autodetected. (Use raid=noautodetect)\n", + minor); + close(fd); + continue; + } + + if (md_setup_args.pers[minor]) { + /* non-persistent */ + mdu_array_info_t ainfo; + ainfo.level = pers_to_level(md_setup_args.pers[minor]); + ainfo.size = 0; + ainfo.nr_disks =0; + ainfo.raid_disks =0; + while (devices[ainfo.raid_disks]) + ainfo.raid_disks++; + ainfo.md_minor =minor; + ainfo.not_persistent = 1; + + ainfo.state = (1 << MD_SB_CLEAN); + ainfo.layout = 0; + ainfo.chunk_size = md_setup_args.chunk[minor]; + err = sys_ioctl(fd, SET_ARRAY_INFO, (long)&ainfo); + for (i = 0; !err && i <= MD_SB_DISKS; i++) { + dev = devices[i]; + if (!dev) + break; + dinfo.number = i; + dinfo.raid_disk = i; + dinfo.state = (1<<MD_DISK_ACTIVE)|(1<<MD_DISK_SYNC); + dinfo.major = MAJOR(dev); + dinfo.minor = MINOR(dev); + err = sys_ioctl(fd, ADD_NEW_DISK, (long)&dinfo); + } + } else { + /* persistent */ + for (i = 0; i <= MD_SB_DISKS; i++) { + dev = devices[i]; + if (!dev) + break; + dinfo.major = MAJOR(dev); + dinfo.minor = MINOR(dev); + sys_ioctl(fd, ADD_NEW_DISK, (long)&dinfo); + } + } + if (!err) + err = sys_ioctl(fd, RUN_ARRAY, 0); + if (err) + printk(KERN_WARNING "md: starting md%d failed\n", minor); + close(fd); + } +} + +static int __init raid_setup(char *str) +{ + int len, pos; + + len = strlen(str) + 1; + pos = 0; + + while (pos < len) { + char *comma = strchr(str+pos, ','); + int wlen; + if (comma) + wlen = (comma-str)-pos; + else wlen = (len-1)-pos; + + if (!strncmp(str, "noautodetect", wlen)) + raid_setup_args.noautodetect = 1; + pos += wlen+1; + } + raid_setup_args.set = 1; + return 1; +} + +__setup("raid=", raid_setup); +__setup("md=", md_setup); +#endif + +static void __init md_run_setup(void) +{ +#ifdef CONFIG_BLK_DEV_MD + create_dev("/dev/md0", MKDEV(MD_MAJOR, 0), "md/0"); + if (raid_setup_args.noautodetect) + printk(KERN_INFO "md: Skipping autodetection of RAID arrays. (raid=noautodetect)\n"); + else { + int fd = open("/dev/md0", 0, 0); + if (fd >= 0) { + sys_ioctl(fd, RAID_AUTORUN, 0); + close(fd); + } + } + md_setup_drive(); +#endif +} |