diff options
Diffstat (limited to 'init')
-rw-r--r-- | init/Kconfig | 108 | ||||
-rw-r--r-- | init/Makefile | 1 | ||||
-rw-r--r-- | init/do_mounts.c | 13 | ||||
-rw-r--r-- | init/do_mounts.h | 16 | ||||
-rw-r--r-- | init/do_mounts_devfs.c | 137 | ||||
-rw-r--r-- | init/do_mounts_initrd.c | 6 | ||||
-rw-r--r-- | init/do_mounts_md.c | 7 | ||||
-rw-r--r-- | init/do_mounts_rd.c | 4 | ||||
-rw-r--r-- | init/initramfs.c | 36 | ||||
-rw-r--r-- | init/main.c | 79 | ||||
-rw-r--r-- | init/version.c | 1 |
11 files changed, 190 insertions, 218 deletions
diff --git a/init/Kconfig b/init/Kconfig index df864a358221..4381006dd666 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1,3 +1,11 @@ +config DEFCONFIG_LIST + string + option defconfig_list + default "/lib/modules/$UNAME_RELEASE/.config" + default "/etc/kernel-config" + default "/boot/config-$UNAME_RELEASE" + default "arch/$ARCH/defconfig" + menu "Code maturity level options" config EXPERIMENTAL @@ -46,8 +54,8 @@ config LOCK_KERNEL config INIT_ENV_ARG_LIMIT int - default 32 if !USERMODE - default 128 if USERMODE + default 32 if !UML + default 128 if UML help Maximum of each of the number of arguments and environment variables passed to init from the kernel command line. @@ -150,21 +158,29 @@ config BSD_PROCESS_ACCT_V3 for processing it. A preliminary version of these tools is available at <http://www.physik3.uni-rostock.de/tim/kernel/utils/acct/>. -config SYSCTL - bool "Sysctl support" - ---help--- - The sysctl interface provides a means of dynamically changing - certain kernel parameters and variables on the fly without requiring - a recompile of the kernel or reboot of the system. The primary - interface consists of a system call, but if you say Y to "/proc - file system support", a tree of modifiable sysctl entries will be - generated beneath the /proc/sys directory. They are explained in the - files in <file:Documentation/sysctl/>. Note that enabling this - option will enlarge the kernel by at least 8 KB. - - As it is generally a good thing, you should say Y here unless - building a kernel for install/rescue disks or your system is very - limited in memory. +config TASKSTATS + bool "Export task/process statistics through netlink (EXPERIMENTAL)" + depends on NET + default n + help + Export selected statistics for tasks/processes through the + generic netlink interface. Unlike BSD process accounting, the + statistics are available during the lifetime of tasks/processes as + responses to commands. Like BSD accounting, they are sent to user + space on task exit. + + Say N if unsure. + +config TASK_DELAY_ACCT + bool "Enable per-task delay accounting (EXPERIMENTAL)" + depends on TASKSTATS + help + Collect information on time spent by a task waiting for system + resources like cpu, synchronous block I/O completion and swapping + in pages. Such statistics can help in setting a task's priorities + relative to other tasks for cpu, io, rss limits etc. + + Say N if unsure. config AUDIT bool "Auditing support" @@ -228,23 +244,6 @@ config RELAY source "usr/Kconfig" -config UID16 - bool "Enable 16-bit UID system calls" if EMBEDDED - depends on ARM || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && SPARC32_COMPAT) || UML || (X86_64 && IA32_EMULATION) - default y - help - This enables the legacy 16-bit UID syscall wrappers. - -config VM86 - depends X86 - default y - bool "Enable VM86 support" if EMBEDDED - help - This option is required by programs like DOSEMU to run 16-bit legacy - code on X86 processors. It also may be needed by software like - XFree86 to initialize some video cards via BIOS. Disabling this - option saves about 6k. - config CC_OPTIMIZE_FOR_SIZE bool "Optimize for size (Look out for broken compilers!)" default y @@ -266,6 +265,33 @@ menuconfig EMBEDDED environments which can tolerate a "non-standard" kernel. Only use this if you really know what you are doing. +config UID16 + bool "Enable 16-bit UID system calls" if EMBEDDED + depends on ARM || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && SPARC32_COMPAT) || UML || (X86_64 && IA32_EMULATION) + default y + help + This enables the legacy 16-bit UID syscall wrappers. + +config SYSCTL + bool + +config SYSCTL_SYSCALL + bool "Sysctl syscall support" + default n + select SYSCTL + ---help--- + Enable the deprecated sysctl system call. sys_sysctl uses + binary paths that have been found to be a major pain to maintain + and use. The interface in /proc/sys is now the primary and what + everyone uses. + + Nothing has been using the binary sysctl interface for some time + time now so nothing should break if you disable sysctl syscall + support, and you kernel will get marginally smaller. + + Unless you have an application that uses the sys_syscall interface + you should probably say N here. + config KALLSYMS bool "Load all symbols for debugging/kksymoops" if EMBEDDED default y @@ -343,6 +369,7 @@ config BASE_FULL config FUTEX bool "Enable futex support" if EMBEDDED default y + select RT_MUTEXES help Disabling this option will cause the kernel to be built without support for "fast userspace mutexes". The resulting kernel may not @@ -375,8 +402,21 @@ config SLAB SLOB is more space efficient but does not scale well and is more susceptible to fragmentation. +config VM_EVENT_COUNTERS + default y + bool "Enable VM event counters for /proc/vmstat" if EMBEDDED + help + VM event counters are only needed to for event counts to be + shown. They have no function for the kernel itself. This + option allows the disabling of the VM event counters. + /proc/vmstat will only show page counts. + endmenu # General setup +config RT_MUTEXES + boolean + select PLIST + config TINY_SHMEM default !SHMEM bool diff --git a/init/Makefile b/init/Makefile index a2300078f2b7..633a268d270d 100644 --- a/init/Makefile +++ b/init/Makefile @@ -6,7 +6,6 @@ obj-y := main.o version.o mounts.o initramfs.o obj-$(CONFIG_GENERIC_CALIBRATE_DELAY) += calibrate.o mounts-y := do_mounts.o -mounts-$(CONFIG_DEVFS_FS) += do_mounts_devfs.o mounts-$(CONFIG_BLK_DEV_RAM) += do_mounts_rd.o mounts-$(CONFIG_BLK_DEV_INITRD) += do_mounts_initrd.o mounts-$(CONFIG_BLK_DEV_MD) += do_mounts_md.o diff --git a/init/do_mounts.c b/init/do_mounts.c index 21b3b8f33a72..b290aadb1d3f 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -8,6 +8,7 @@ #include <linux/security.h> #include <linux/delay.h> #include <linux/mount.h> +#include <linux/device.h> #include <linux/nfs_fs.h> #include <linux/nfs_fs_sb.h> @@ -325,7 +326,7 @@ static int __init mount_nfs_root(void) { void *data = nfs_root_data(); - create_dev("/dev/root", ROOT_DEV, NULL); + create_dev("/dev/root", ROOT_DEV); if (data && do_mount_root("/dev/root", "nfs", root_mountflags, data) == 0) return 1; @@ -386,7 +387,7 @@ void __init mount_root(void) change_floppy("root floppy"); } #endif - create_dev("/dev/root", ROOT_DEV, root_device_name); + create_dev("/dev/root", ROOT_DEV); mount_block_root("/dev/root", root_mountflags); } @@ -397,14 +398,16 @@ void __init prepare_namespace(void) { int is_floppy; - mount_devfs(); - if (root_delay) { printk(KERN_INFO "Waiting %dsec before mounting root device...\n", root_delay); ssleep(root_delay); } + /* wait for the known devices to complete their probing */ + while (driver_probe_done() != 0) + msleep(100); + md_run_setup(); if (saved_root_name[0]) { @@ -428,10 +431,8 @@ void __init prepare_namespace(void) mount_root(); out: - umount_devfs("/dev"); sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot("."); security_sb_post_mountroot(); - mount_devfs_fs (); } diff --git a/init/do_mounts.h b/init/do_mounts.h index e0a7ac9649e1..e7f2e7fa066e 100644 --- a/init/do_mounts.h +++ b/init/do_mounts.h @@ -1,6 +1,5 @@ #include <linux/config.h> #include <linux/kernel.h> -#include <linux/devfs_fs_kernel.h> #include <linux/init.h> #include <linux/syscalls.h> #include <linux/unistd.h> @@ -15,25 +14,12 @@ void mount_root(void); extern int root_mountflags; extern char *root_device_name; -#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) +static inline int create_dev(char *name, dev_t dev) { sys_unlink(name); return sys_mknod(name, S_IFBLK|0600, new_encode_dev(dev)); } -#endif - #if BITS_PER_LONG == 32 static inline u32 bstat(char *name) { diff --git a/init/do_mounts_devfs.c b/init/do_mounts_devfs.c deleted file mode 100644 index cc526474690a..000000000000 --- a/init/do_mounts_devfs.c +++ /dev/null @@ -1,137 +0,0 @@ - -#include <linux/kernel.h> -#include <linux/dirent.h> -#include <linux/string.h> - -#include "do_mounts.h" - -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; - sys_lseek(fd, 0, 0); - - for (bytes = 0; bytes < len; bytes += n) { - n = sys_getdents64(fd, (struct linux_dirent64 *)(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 = sys_open(path, 0, 0); - - *len = 0; - if (fd < 0) - return NULL; - - for (size = 1 << 9; size <= (PAGE_SIZE << 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) { - sys_close(fd); - *len = n; - return p; - } - kfree(p); - if (n == -EINVAL) - continue; /* Try a larger buffer */ - if (n < 0) - break; - } - sys_close(fd); - return NULL; -} - -/* - * recursively scan <path>, looking for a device node of type <dev> - */ -static int __init find_in_devfs(char *path, unsigned dev) -{ - 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 (bstat(path) != 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, new_encode_dev(dev)) < 0) - return -1; - return sys_symlink(path + 5, name); -} diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c index 405f9031af87..a06f037fa000 100644 --- a/init/do_mounts_initrd.c +++ b/init/do_mounts_initrd.c @@ -44,7 +44,7 @@ static void __init handle_initrd(void) int pid; real_root_dev = new_encode_dev(ROOT_DEV); - create_dev("/dev/root.old", Root_RAM0, NULL); + create_dev("/dev/root.old", Root_RAM0); /* mount initrd on rootfs' /root */ mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); sys_mkdir("/old", 0700); @@ -54,7 +54,6 @@ static void __init handle_initrd(void) sys_chdir("/root"); sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot("."); - mount_devfs_fs (); current->flags |= PF_NOFREEZE; pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); @@ -71,7 +70,6 @@ static void __init handle_initrd(void) sys_chroot("."); sys_close(old_fd); sys_close(root_fd); - umount_devfs("/old/dev"); if (new_decode_dev(real_root_dev) == Root_RAM0) { sys_chdir("/old"); @@ -107,7 +105,7 @@ static void __init handle_initrd(void) int __init initrd_load(void) { if (mount_initrd) { - create_dev("/dev/ram", Root_RAM0, NULL); + create_dev("/dev/ram", Root_RAM0); /* * Load the initrd data into /dev/ram0. Execute it as initrd * unless /dev/ram0 is supposed to be our actual root device, diff --git a/init/do_mounts_md.c b/init/do_mounts_md.c index f6f36806f84a..2429e1bf8c60 100644 --- a/init/do_mounts_md.c +++ b/init/do_mounts_md.c @@ -125,19 +125,18 @@ static void __init md_setup_drive(void) int err = 0; char *devname; mdu_disk_info_t dinfo; - char name[16], devfs_name[16]; + char name[16]; minor = md_setup_args[ent].minor; partitioned = md_setup_args[ent].partitioned; devname = md_setup_args[ent].device_names; sprintf(name, "/dev/md%s%d", partitioned?"_d":"", minor); - sprintf(devfs_name, "/dev/md/%s%d", partitioned?"d":"", minor); if (partitioned) dev = MKDEV(mdp_major, minor << MdpMinorShift); else dev = MKDEV(MD_MAJOR, minor); - create_dev(name, dev, devfs_name); + create_dev(name, dev); for (i = 0; i < MD_SB_DISKS && devname != 0; i++) { char *p; char comp_name[64]; @@ -272,7 +271,7 @@ __setup("md=", md_setup); void __init md_run_setup(void) { - create_dev("/dev/md0", MKDEV(MD_MAJOR, 0), "md/0"); + create_dev("/dev/md0", MKDEV(MD_MAJOR, 0)); if (raid_noautodetect) printk(KERN_INFO "md: Skipping autodetection of RAID arrays. (raid=noautodetect)\n"); else { diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index c2683fcd792d..ed652f40f075 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c @@ -262,8 +262,8 @@ int __init rd_load_disk(int n) { if (rd_prompt) change_floppy("root floppy disk to be loaded into RAM disk"); - create_dev("/dev/root", ROOT_DEV, root_device_name); - create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n), NULL); + create_dev("/dev/root", ROOT_DEV); + create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n)); return rd_load_image("/dev/root"); } diff --git a/init/initramfs.c b/init/initramfs.c index f81cfa40a719..d28c1094d7e5 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -30,6 +30,7 @@ static void __init free(void *where) static __initdata struct hash { int ino, minor, major; + mode_t mode; struct hash *next; char name[N_ALIGN(PATH_MAX)]; } *head[32]; @@ -41,7 +42,8 @@ static inline int hash(int major, int minor, int ino) return tmp & 31; } -static char __init *find_link(int major, int minor, int ino, char *name) +static char __init *find_link(int major, int minor, int ino, + mode_t mode, char *name) { struct hash **p, *q; for (p = head + hash(major, minor, ino); *p; p = &(*p)->next) { @@ -51,14 +53,17 @@ static char __init *find_link(int major, int minor, int ino, char *name) continue; if ((*p)->major != major) continue; + if (((*p)->mode ^ mode) & S_IFMT) + continue; return (*p)->name; } q = (struct hash *)malloc(sizeof(struct hash)); if (!q) panic("can't allocate link hash entry"); - q->ino = ino; - q->minor = minor; q->major = major; + q->minor = minor; + q->ino = ino; + q->mode = mode; strcpy(q->name, name); q->next = NULL; *p = q; @@ -229,13 +234,25 @@ static int __init do_reset(void) static int __init maybe_link(void) { if (nlink >= 2) { - char *old = find_link(major, minor, ino, collected); + char *old = find_link(major, minor, ino, mode, collected); if (old) return (sys_link(old, collected) < 0) ? -1 : 1; } return 0; } +static void __init clean_path(char *path, mode_t mode) +{ + struct stat st; + + if (!sys_newlstat(path, &st) && (st.st_mode^mode) & S_IFMT) { + if (S_ISDIR(st.st_mode)) + sys_rmdir(path); + else + sys_unlink(path); + } +} + static __initdata int wfd; static int __init do_name(void) @@ -248,9 +265,15 @@ static int __init do_name(void) } if (dry_run) return 0; + clean_path(collected, mode); if (S_ISREG(mode)) { - if (maybe_link() >= 0) { - wfd = sys_open(collected, O_WRONLY|O_CREAT, mode); + int ml = maybe_link(); + if (ml >= 0) { + int openflags = O_WRONLY|O_CREAT; + if (ml != 1) + openflags |= O_TRUNC; + wfd = sys_open(collected, openflags, mode); + if (wfd >= 0) { sys_fchown(wfd, uid, gid); sys_fchmod(wfd, mode); @@ -291,6 +314,7 @@ static int __init do_copy(void) static int __init do_symlink(void) { collected[N_ALIGN(name_len) + body_len] = '\0'; + clean_path(collected, 0); sys_symlink(collected + N_ALIGN(name_len), collected); sys_lchown(collected, uid, gid); state = SkipIt; diff --git a/init/main.c b/init/main.c index f715b9b89753..0766e69712b2 100644 --- a/init/main.c +++ b/init/main.c @@ -11,11 +11,9 @@ #define __KERNEL_SYSCALLS__ -#include <linux/config.h> #include <linux/types.h> #include <linux/module.h> #include <linux/proc_fs.h> -#include <linux/devfs_fs_kernel.h> #include <linux/kernel.h> #include <linux/syscalls.h> #include <linux/string.h> @@ -43,10 +41,16 @@ #include <linux/cpu.h> #include <linux/cpuset.h> #include <linux/efi.h> +#include <linux/taskstats_kern.h> +#include <linux/delayacct.h> #include <linux/unistd.h> #include <linux/rmap.h> #include <linux/mempolicy.h> #include <linux/key.h> +#include <linux/unwind.h> +#include <linux/buffer_head.h> +#include <linux/debug_locks.h> +#include <linux/lockdep.h> #include <asm/io.h> #include <asm/bugs.h> @@ -79,7 +83,6 @@ extern void mca_init(void); extern void sbus_init(void); extern void sysctl_init(void); extern void signals_init(void); -extern void buffer_init(void); extern void pidhash_init(void); extern void pidmap_init(void); extern void prio_tree_init(void); @@ -125,6 +128,18 @@ static char *ramdisk_execute_command; static unsigned int max_cpus = NR_CPUS; /* + * If set, this is an indication to the drivers that reset the underlying + * device before going ahead with the initialization otherwise driver might + * rely on the BIOS and skip the reset operation. + * + * This is useful if kernel is booting in an unreliable environment. + * For ex. kdump situaiton where previous kernel has crashed, BIOS has been + * skipped and devices will be in unknown state. + */ +unsigned int reset_devices; +EXPORT_SYMBOL(reset_devices); + +/* * Setup routine for controlling SMP activation * * Command-line option of "nosmp" or "maxcpus=0" will disable SMP @@ -150,6 +165,14 @@ static int __init maxcpus(char *str) __setup("maxcpus=", maxcpus); +static int __init set_reset_devices(char *str) +{ + reset_devices = 1; + return 1; +} + +__setup("reset_devices", set_reset_devices); + static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, }; char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, }; static const char *panic_later, *panic_param; @@ -159,16 +182,19 @@ extern struct obs_kernel_param __setup_start[], __setup_end[]; static int __init obsolete_checksetup(char *line) { struct obs_kernel_param *p; + int had_early_param = 0; p = __setup_start; do { int n = strlen(p->str); if (!strncmp(line, p->str, n)) { if (p->early) { - /* Already done in parse_early_param? (Needs - * exact match on param part) */ + /* Already done in parse_early_param? + * (Needs exact match on param part). + * Keep iterating, as we can have early + * params and __setups of same names 8( */ if (line[n] == '\0' || line[n] == '=') - return 1; + had_early_param = 1; } else if (!p->setup_func) { printk(KERN_WARNING "Parameter %s is obsolete," " ignored\n", p->str); @@ -178,7 +204,8 @@ static int __init obsolete_checksetup(char *line) } p++; } while (p < __setup_end); - return 0; + + return had_early_param; } /* @@ -446,10 +473,28 @@ static void __init boot_cpu_init(void) cpu_set(cpu, cpu_possible_map); } +void __init __attribute__((weak)) smp_setup_processor_id(void) +{ +} + asmlinkage void __init start_kernel(void) { char * command_line; extern struct kernel_param __start___param[], __stop___param[]; + + smp_setup_processor_id(); + + /* + * Need to run as early as possible, to initialize the + * lockdep hash: + */ + unwind_init(); + lockdep_init(); + + local_irq_disable(); + early_boot_irqs_off(); + early_init_irq_lock_class(); + /* * Interrupts are still disabled. Do necessary setups, then * enable them @@ -489,7 +534,13 @@ asmlinkage void __init start_kernel(void) init_timers(); hrtimers_init(); softirq_init(); + timekeeping_init(); time_init(); + profile_init(); + if (!irqs_disabled()) + printk("start_kernel(): bug: interrupts were enabled early\n"); + early_boot_irqs_on(); + local_irq_enable(); /* * HACK ALERT! This is early. We're enabling the console before @@ -499,8 +550,16 @@ asmlinkage void __init start_kernel(void) console_init(); if (panic_later) panic(panic_later, panic_param); - profile_init(); - local_irq_enable(); + + lockdep_info(); + + /* + * Need to run this when irqs are enabled, because it wants + * to self-test [hard/soft]-irqs on/off lock inversion bugs + * too: + */ + locking_selftest(); + #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start && !initrd_below_start_ok && initrd_start < min_low_pfn << PAGE_SHIFT) { @@ -541,6 +600,8 @@ asmlinkage void __init start_kernel(void) proc_root_init(); #endif cpuset_init(); + taskstats_init_early(); + delayacct_init(); check_bugs(); diff --git a/init/version.c b/init/version.c index 3ddc3ceec2fe..e290802c6bd2 100644 --- a/init/version.c +++ b/init/version.c @@ -10,6 +10,7 @@ #include <linux/module.h> #include <linux/uts.h> #include <linux/utsname.h> +#include <linux/utsrelease.h> #include <linux/version.h> #define version(a) Version_ ## a |