Commit 394a567d authored by Kai Germaschewski's avatar Kai Germaschewski

Merge linux-isdn@linux-isdn.bkbits.net:linux-2.5.do_mounts

into tp1.ruhr-uni-bochum.de:/scratch/kai/kernel/v2.5/linux-2.5.do_mounts
parents f2818fdd c5e3ab0e
......@@ -3,6 +3,9 @@
#
obj-y := main.o version.o do_mounts.o initramfs.o
obj-$(CONFIG_DEVFS_FS) += do_mounts_devfs.o
obj-$(CONFIG_BLK_DEV_RAM) += do_mounts_rd.o
obj-$(CONFIG_BLK_DEV_MD) += do_mounts_md.o
# files to be removed upon make clean
clean-files := ../include/linux/compile.h
......
This diff is collapsed.
#define __KERNEL_SYSCALLS__
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/init.h>
#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/mount.h>
#include <linux/blk.h>
#include <linux/root_dev.h>
asmlinkage long sys_unlink(const char *name);
asmlinkage long sys_mknod(const char *name, int mode, dev_t dev);
asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
asmlinkage long sys_ioctl(int fd, int cmd, unsigned long arg);
asmlinkage long sys_mkdir(const char *name, int mode);
asmlinkage long sys_rmdir(const char *name);
asmlinkage long sys_chdir(const char *name);
asmlinkage long sys_fchdir(int fd);
asmlinkage long sys_chroot(const char *name);
asmlinkage long sys_mount(char *dev_name, char *dir_name, char *type,
unsigned long flags, void *data);
asmlinkage long sys_umount(char *name, int flags);
dev_t name_to_dev_t(char *name);
void change_floppy(char *fmt, ...);
void mount_block_root(char *name, int flags);
void mount_root(void);
extern int root_mountflags;
#ifdef CONFIG_DEVFS_FS
void mount_devfs(void);
void umount_devfs(char *path);
int create_dev(char *name, dev_t dev, char *devfs_name);
#else
static inline void mount_devfs(void) {}
static inline void umount_devfs(const char *path) {}
static inline int create_dev(char *name, dev_t dev, char *devfs_name)
{
sys_unlink(name);
return sys_mknod(name, S_IFBLK|0600, dev);
}
#endif
#ifdef CONFIG_BLK_DEV_RAM
int __init rd_load_disk(int n);
int __init rd_load_image(char *from);
#else
static inline int rd_load_disk(int n) { return 0; }
static inline int rd_load_image(char *from) { return 0; }
#endif
#ifdef CONFIG_BLK_DEV_INITRD
int __init initrd_load(void);
#else
static inline int initrd_load(void) { return 0; }
#endif
#ifdef CONFIG_BLK_DEV_MD
void md_run_setup(void);
#else
static inline void md_run_setup(void) {}
#endif
#include <linux/kernel.h>
#include <linux/dirent.h>
#include <linux/string.h>
#include "do_mounts.h"
extern asmlinkage long sys_symlink(const char *old, const char *new);
extern asmlinkage long sys_access(const char * filename, int mode);
extern asmlinkage long sys_getdents64(unsigned int fd, void * dirent,
unsigned int count);
void __init mount_devfs(void)
{
sys_mount("devfs", "/dev", "devfs", 0, NULL);
}
void __init umount_devfs(char *path)
{
sys_umount(path, 0);
}
/*
* If the dir will fit in *buf, return its length. If it won't fit, return
* zero. Return -ve on error.
*/
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; bytes < len; bytes += n) {
n = sys_getdents64(fd, p + bytes, len - bytes);
if (n < 0)
return n;
if (n == 0)
return bytes;
}
return 0;
}
/*
* Try to read all of a directory. Returns the contents at *p, which
* is kmalloced memory. Returns the number of bytes read at *len. Returns
* NULL on error.
*/
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 << MAX_ORDER); 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 == -EINVAL)
continue; /* Try a larger buffer */
if (n < 0)
break;
}
close(fd);
return NULL;
}
/*
* recursively scan <path>, looking for a device node of type <dev>
*/
static int __init find_in_devfs(char *path, dev_t dev)
{
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);
return -1;
}
/*
* create a device node called <name> which points to
* <devfs_name> if possible, otherwise find a device node
* which matches <dev> and make <name> a symlink pointing to it.
*/
int __init create_dev(char *name, dev_t dev, char *devfs_name)
{
char path[64];
sys_unlink(name);
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;
strcpy(path, "/dev");
if (find_in_devfs(path, dev) < 0)
return -1;
return sys_symlink(path + 5, name);
}
#include <linux/raid/md.h>
#include "do_mounts.h"
/*
* 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.
*/
static int __initdata raid_noautodetect;
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 <dcinege@psychosis.com>
* 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) == 0)
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_noautodetect = 1;
pos += wlen+1;
}
return 1;
}
__setup("raid=", raid_setup);
__setup("md=", md_setup);
void __init md_run_setup(void)
{
create_dev("/dev/md0", MKDEV(MD_MAJOR, 0), "md/0");
if (raid_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();
}
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment