VERSION = 2
PATCHLEVEL = 5
SUBLEVEL = 1
-EXTRAVERSION =-pre6
+EXTRAVERSION =-pre7
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
boot: vmlinux
@$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C arch/$(ARCH)/boot
-vmlinux: include/linux/version.h $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
- $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \
+vmlinux: include/linux/version.h $(CONFIGURATION) init/main.o init/version.o init/do_mounts.o linuxsubdirs
+ $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o init/do_mounts.o \
--start-group \
$(CORE_FILES) \
$(DRIVERS) \
init/main.o: init/main.c include/config/MARKER
$(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -c -o $*.o $<
+init/do_mounts.o: init/do_mounts.c include/config/MARKER
+ $(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -c -o $*.o $<
+
fs lib mm ipc kernel drivers net: dummy
$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" $(subst $@, _dir_$@, $@)
* But it does seem to fix some unspecified problem
* with 'movntq' copies on Athlons.
*
- * VIA 8363 chipset:
- * - bit 7 at offset 0x55: Debug (RW)
+ * VIA 8363,8622,8361 Northbridges:
+ * - bits 5, 6, 7 at offset 0x55 need to be turned off
+ * VIA 8367 (KT266x) Northbridges:
+ * - bits 5, 6, 7 at offset 0x95 need to be turned off
*/
static void __init pci_fixup_via_athlon_bug(struct pci_dev *d)
{
u8 v;
- pci_read_config_byte(d, 0x55, &v);
- if (v & 0x80) {
+ int where = 0x55;
+
+ if (d->device == PCI_DEVICE_ID_VIA_8367_0) {
+ where = 0x95; /* the memory write queue timer register is
+ different for the kt266x's: 0x95 not 0x55 */
+ }
+
+ pci_read_config_byte(d, where, &v);
+ if (v & 0xe0) {
printk("Trying to stomp on Athlon bug...\n");
- v &= 0x7f; /* clear bit 55.7 */
- pci_write_config_byte(d, 0x55, v);
+ v &= 0x1f; /* clear bits 5, 6, 7 */
+ pci_write_config_byte(d, where, v);
}
}
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci_fixup_piix4_acpi },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_athlon_bug },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_athlon_bug },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_athlon_bug },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_athlon_bug },
{ 0 }
};
BUG_ON(next_rq->flags & REQ_STARTED);
+ /*
+ * not a sector based request
+ */
+ if (!(next_rq->flags & REQ_CMD))
+ return 0;
+
/*
* if the device is different (not a normal case) just check if
* bio is after rq
*/
inline int elv_rq_merge_ok(struct request *rq, struct bio *bio)
{
+ if (!(rq->flags & REQ_CMD))
+ return 0;
+
/*
* different data direction or already started, don't merge
*/
break;
if (__rq->flags & (REQ_BARRIER | REQ_STARTED))
break;
+ if (!(__rq->flags & REQ_CMD))
+ continue;
if (!*req && bio_rq_in_between(bio, __rq, &q->queue_head))
*req = __rq;
if (__rq->flags & (REQ_BARRIER | REQ_STARTED))
break;
+ if (!(__rq->flags & REQ_CMD))
+ continue;
+
if (!elv_rq_merge_ok(__rq, bio))
continue;
{NULL, t360, t1200, t3in+5+8, t3in+5, t3in, t3in};
base_minor = (drive < 4) ? drive : (124 + drive);
- if (UDP->cmos <= NUMBER(default_drive_params)) {
+ if (UDP->cmos < NUMBER(default_drive_params)) {
i = 0;
do {
char name[16];
if (!(rq->flags & REQ_CMD))
return 0;
+ memset(rq->cmd, 0, sizeof(rq->cmd));
+
if (rq_data_dir(rq) == READ)
rq->cmd[0] = READ_10;
else
rq->cmd[0] = WRITE_10;
- rq->cmd[1] = 0;
-
/*
* fill in lba
*/
rq->cmd[3] = (block >> 16) & 0xff;
rq->cmd[4] = (block >> 8) & 0xff;
rq->cmd[5] = block & 0xff;
- rq->cmd[6] = 0;
/*
* and transfer length
unsigned long long lastend;
struct bio_vec *bvec;
struct bio *bio;
- int nsegs, i, cluster, j;
+ int nsegs, i, cluster;
nsegs = 0;
bio = rq->bio;
/*
* for each bio in rq
*/
- j = 0;
rq_for_each_bio(bio, rq) {
- j++;
/*
* for each segment in bio
*/
new_segment:
if (nsegs > q->max_segments) {
printk("map: %d >= %d\n", nsegs, q->max_segments);
- printk("map %d, %d, bio_sectors %d, vcnt %d\n", i, j, bio_sectors(bio), bio->bi_vcnt);
BUG();
}
static inline int ll_new_segment(request_queue_t *q, struct request *req,
struct bio *bio)
{
- if (req->nr_segments + bio->bi_vcnt < q->max_segments) {
+ if (req->nr_segments + bio->bi_vcnt <= q->max_segments) {
req->nr_segments += bio->bi_vcnt;
return 1;
}
*/
static inline void __generic_unplug_device(request_queue_t *q)
{
- if (test_and_clear_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags))
- if (!elv_queue_empty(q))
- q->request_fn(q);
+ /*
+ * not plugged
+ */
+ if (!test_and_clear_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags))
+ return;
+
+ /*
+ * was plugged, fire request_fn if queue has stuff to do
+ */
+ if (!elv_queue_empty(q))
+ q->request_fn(q);
}
/**
spin_unlock_irqrestore(&aux_count_lock, flags);
return -EBUSY;
}
+ spin_unlock_irqrestore(&aux_count_lock, flags);
kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable the
auxiliary port on
controller. */
mdelay(2); /* Ensure we follow the kbc access delay rules.. */
send_data(KBD_CMD_ENABLE); /* try to workaround toshiba4030cdt problem */
- spin_unlock_irqrestore(&aux_count_lock, flags);
return 0;
}
/*
* iterate iovec list and alloc pages + copy data
*/
- bio_for_each_segment(bv, bio, i) {
+ __bio_for_each_segment(bv, bio, i, 0) {
struct bio_vec *bbv = &b->bi_io_vec[i];
char *vfrom, *vto;
vfrom = kmap(bv->bv_page);
vto = kmap(bbv->bv_page);
} else {
- __save_flags(flags);
- __cli();
+ local_irq_save(flags);
vfrom = kmap_atomic(bv->bv_page, KM_BIO_IRQ);
vto = kmap_atomic(bbv->bv_page, KM_BIO_IRQ);
}
} else {
kunmap_atomic(vto, KM_BIO_IRQ);
kunmap_atomic(vfrom, KM_BIO_IRQ);
- __restore_flags(flags);
+ local_irq_restore(flags);
}
fill_in:
return b;
oom:
- while (i >= 0) {
+ while (--i >= 0)
__free_page(b->bi_io_vec[i].bv_page);
- i--;
- }
bio_pool_put(b);
return NULL;
if (err)
kio->errno = err;
+ /*
+ * final atomic_dec of io_count to match our initial setting of 1.
+ * I/O may or may not have completed at this point, final completion
+ * handler is only run on last decrement.
+ */
end_kio_request(kio, !err);
}
#include <linux/quotaops.h>
#include <linux/acct.h>
#include <linux/module.h>
-#include <linux/devfs_fs_kernel.h>
+#include <linux/seq_file.h>
#include <asm/uaccess.h>
-#include <linux/seq_file.h>
-
struct vfsmount *do_kern_mount(char *type, int flags, char *name, void *data);
int do_remount_sb(struct super_block *sb, int flags, void * data);
void kill_super(struct super_block *sb);
static LIST_HEAD(vfsmntlist);
static DECLARE_MUTEX(mount_sem);
-
-/* Will be static */
-struct vfsmount *root_vfsmnt;
+static struct vfsmount *root_vfsmnt;
static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
{
return NULL;
}
-/* Will become static */
-int graft_tree(struct vfsmount *mnt, struct nameidata *nd)
+static int graft_tree(struct vfsmount *mnt, struct nameidata *nd)
{
int err;
if (mnt->mnt_sb->s_flags & MS_NOUSER)
* In 2.5 we'll use ramfs or tmpfs, but for now it's all we need - just
* something to go with root vfsmount.
*/
+static struct inode_operations rootfs_dir_inode_operations;
+static struct file_operations rootfs_dir_operations;
+static int rootfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+ struct inode * inode = new_inode(dir->i_sb);
+ int error = -ENOSPC;
+ if (inode) {
+ inode->i_mode = S_IFDIR|mode;
+ inode->i_uid = current->fsuid;
+ inode->i_gid = current->fsgid;
+ inode->i_op = &rootfs_dir_inode_operations;
+ inode->i_fop = &rootfs_dir_operations;
+ d_instantiate(dentry, inode);
+ dget(dentry);
+ error = 0;
+ }
+ return error;
+}
+static int rootfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
+{
+ struct inode * inode = new_inode(dir->i_sb);
+ int error = -ENOSPC;
+ if (inode) {
+ inode->i_uid = current->fsuid;
+ inode->i_gid = current->fsgid;
+ init_special_inode(inode, mode, dev);
+ d_instantiate(dentry, inode);
+ dget(dentry);
+ error = 0;
+ }
+ return error;
+}
+static int rootfs_unlink(struct inode * dir, struct dentry *dentry)
+{
+ dentry->d_inode->i_nlink--;
+ dput(dentry);
+ return 0;
+}
static struct dentry *rootfs_lookup(struct inode *dir, struct dentry *dentry)
{
d_add(dentry, NULL);
};
static struct inode_operations rootfs_dir_inode_operations = {
lookup: rootfs_lookup,
+ mkdir: rootfs_mkdir,
+ mknod: rootfs_mknod,
+ unlink: rootfs_unlink,
};
static struct super_block *rootfs_read_super(struct super_block * sb, void * data, int silent)
{
} while (i);
init_mount_tree();
}
-
-#ifdef CONFIG_BLK_DEV_INITRD
-
-int __init change_root(kdev_t new_root_dev,const char *put_old)
-{
- struct vfsmount *old_rootmnt;
- struct nameidata devfs_nd, nd;
- struct nameidata parent_nd;
- char *new_devname = kmalloc(strlen("/dev/root.old")+1, GFP_KERNEL);
- int error = 0;
-
- if (new_devname)
- strcpy(new_devname, "/dev/root.old");
-
- read_lock(¤t->fs->lock);
- old_rootmnt = mntget(current->fs->rootmnt);
- read_unlock(¤t->fs->lock);
- /* First unmount devfs if mounted */
- if (path_init("/dev", LOOKUP_FOLLOW|LOOKUP_POSITIVE, &devfs_nd))
- error = path_walk("/dev", &devfs_nd);
- if (!error) {
- if (devfs_nd.mnt->mnt_sb->s_magic == DEVFS_SUPER_MAGIC &&
- devfs_nd.dentry == devfs_nd.mnt->mnt_root) {
- do_umount(devfs_nd.mnt, 0);
- }
- path_release(&devfs_nd);
- }
- set_fs_pwd(current->fs, root_vfsmnt, root_vfsmnt->mnt_root);
- set_fs_root(current->fs, root_vfsmnt, root_vfsmnt->mnt_root);
- spin_lock(&dcache_lock);
- detach_mnt(old_rootmnt, &parent_nd);
- spin_unlock(&dcache_lock);
- ROOT_DEV = new_root_dev;
- mount_root();
-#if 1
- shrink_dcache();
- printk("change_root: old root has d_count=%d\n",
- atomic_read(&old_rootmnt->mnt_root->d_count));
-#endif
- mount_devfs_fs ();
- /*
- * Get the new mount directory
- */
- error = 0;
- if (path_init(put_old, LOOKUP_FOLLOW|LOOKUP_POSITIVE|LOOKUP_DIRECTORY, &nd))
- error = path_walk(put_old, &nd);
- if (error) {
- int blivet;
- struct block_device *ramdisk = old_rootmnt->mnt_sb->s_bdev;
-
- atomic_inc(&ramdisk->bd_count);
- blivet = blkdev_get(ramdisk, FMODE_READ, 0, BDEV_FS);
- printk(KERN_NOTICE "Trying to unmount old root ... ");
- if (!blivet) {
- spin_lock(&dcache_lock);
- list_del_init(&old_rootmnt->mnt_list);
- spin_unlock(&dcache_lock);
- mntput(old_rootmnt);
- mntput(old_rootmnt);
- blivet = ioctl_by_bdev(ramdisk, BLKFLSBUF, 0);
- path_release(&parent_nd);
- blkdev_put(ramdisk, BDEV_FS);
- }
- if (blivet) {
- printk(KERN_ERR "error %d\n", blivet);
- } else {
- printk("okay\n");
- error = 0;
- }
- kfree(new_devname);
- return error;
- }
-
- spin_lock(&dcache_lock);
- attach_mnt(old_rootmnt, &nd);
- if (new_devname) {
- if (old_rootmnt->mnt_devname)
- kfree(old_rootmnt->mnt_devname);
- old_rootmnt->mnt_devname = new_devname;
- }
- spin_unlock(&dcache_lock);
-
- /* put the old stuff */
- path_release(&parent_nd);
- mntput(old_rootmnt);
- path_release(&nd);
- return 0;
-}
-
-#endif
*/
#include <linux/config.h>
-#include <linux/string.h>
#include <linux/slab.h>
#include <linux/locks.h>
#include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h>
-#include <linux/fd.h>
-#include <linux/init.h>
#include <linux/major.h>
-#include <linux/quotaops.h>
#include <linux/acct.h>
#include <asm/uaccess.h>
-#include <linux/nfs_fs.h>
-#include <linux/nfs_fs_sb.h>
-#include <linux/nfs_mount.h>
-
#include <linux/kmod.h>
#define __NO_VERSION__
#include <linux/module.h>
-extern void wait_for_keypress(void);
-
-extern int root_mountflags;
-
int do_remount_sb(struct super_block *sb, int flags, void * data);
-/* this is initialized in init/main.c */
-kdev_t ROOT_DEV;
-
LIST_HEAD(super_blocks);
spinlock_t sb_lock = SPIN_LOCK_UNLOCKED;
void free_vfsmnt(struct vfsmount *mnt);
void set_devname(struct vfsmount *mnt, const char *name);
-/* Will go away */
-extern struct vfsmount *root_vfsmnt;
-extern int graft_tree(struct vfsmount *mnt, struct nameidata *nd);
-
static inline struct super_block * find_super(kdev_t dev)
{
struct list_head *p;
return err;
}
-static struct super_block * read_super(kdev_t dev, struct block_device *bdev,
- struct file_system_type *type, int flags,
- void *data)
-{
- struct super_block * s;
- s = alloc_super();
- if (!s)
- goto out;
- s->s_dev = dev;
- s->s_bdev = bdev;
- s->s_flags = flags;
- spin_lock(&sb_lock);
- insert_super(s, type);
- lock_super(s);
- if (!type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
- goto out_fail;
- s->s_flags |= MS_ACTIVE;
- unlock_super(s);
- /* tell bdcache that we are going to keep this one */
- if (bdev)
- atomic_inc(&bdev->bd_count);
-out:
- return s;
-
-out_fail:
- unlock_super(s);
- deactivate_super(s);
- remove_super(s);
- return NULL;
-}
-
/*
* Unnamed block devices are dummy devices used by virtual
* filesystems which don't use real block-devices. -- jrs
static struct super_block *get_sb_nodev(struct file_system_type *fs_type,
int flags, void * data)
{
- kdev_t dev;
- int error = -EMFILE;
- dev = get_unnamed_dev();
- if (dev) {
- struct super_block * sb;
- error = -EINVAL;
- sb = read_super(dev, NULL, fs_type, flags, data);
- if (sb)
- return sb;
+ struct super_block *s = alloc_super();
+
+ if (!s)
+ return ERR_PTR(-ENOMEM);
+ s->s_dev = get_unnamed_dev();
+ if (!s->s_dev) {
+ destroy_super(s);
+ return ERR_PTR(-EMFILE);
}
- return ERR_PTR(error);
+ s->s_flags = flags;
+ spin_lock(&sb_lock);
+ insert_super(s, fs_type);
+ lock_super(s);
+ if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
+ goto out_fail;
+ s->s_flags |= MS_ACTIVE;
+ unlock_super(s);
+ return s;
+
+out_fail:
+ unlock_super(s);
+ deactivate_super(s);
+ remove_super(s);
+ return ERR_PTR(-EINVAL);
}
static struct super_block *get_sb_single(struct file_system_type *fs_type,
do_remount_sb(old, flags, data);
return old;
} else {
- kdev_t dev = get_unnamed_dev();
- if (!dev) {
+ s->s_dev = get_unnamed_dev();
+ if (!s->s_dev) {
spin_unlock(&sb_lock);
destroy_super(s);
return ERR_PTR(-EMFILE);
}
- s->s_dev = dev;
s->s_flags = flags;
insert_super(s, fs_type);
lock_super(s);
{
return do_kern_mount((char *)type->name, 0, (char *)type->name, NULL);
}
-
-static char * __initdata root_mount_data;
-static int __init root_data_setup(char *str)
-{
- root_mount_data = str;
- return 1;
-}
-
-static char * __initdata root_fs_names;
-static int __init fs_names_setup(char *str)
-{
- root_fs_names = str;
- return 1;
-}
-
-__setup("rootflags=", root_data_setup);
-__setup("rootfstype=", fs_names_setup);
-
-static void __init get_fs_names(char *page)
-{
- char *s = page;
-
- if (root_fs_names) {
- strcpy(page, root_fs_names);
- while (*s++) {
- if (s[-1] == ',')
- s[-1] = '\0';
- }
- } else {
- int len = get_filesystem_list(page);
- char *p, *next;
-
- page[len] = '\0';
- for (p = page-1; p; p = next) {
- next = strchr(++p, '\n');
- if (*p++ != '\t')
- continue;
- while ((*s++ = *p++) != '\n')
- ;
- s[-1] = '\0';
- }
- }
- *s = '\0';
-}
-
-void __init mount_root(void)
-{
- struct nameidata root_nd;
- struct super_block * sb;
- struct vfsmount *vfsmnt;
- struct block_device *bdev = NULL;
- mode_t mode;
- int retval;
- void *handle;
- char path[64];
- char *name = "/dev/root";
- char *fs_names, *p;
-#ifdef CONFIG_ROOT_NFS
- void *data;
-#endif
- root_mountflags |= MS_VERBOSE;
-
-#ifdef CONFIG_ROOT_NFS
- if (MAJOR(ROOT_DEV) != UNNAMED_MAJOR)
- goto skip_nfs;
- data = nfs_root_data();
- if (!data)
- goto no_nfs;
- vfsmnt = do_kern_mount("nfs", root_mountflags, "/dev/root", data);
- if (!IS_ERR(vfsmnt)) {
- printk ("VFS: Mounted root (%s filesystem).\n", "nfs");
- ROOT_DEV = vfsmnt->mnt_sb->s_dev;
- goto attach_it;
- }
-no_nfs:
- printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");
- ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0);
-skip_nfs:
-#endif
-
-#ifdef CONFIG_BLK_DEV_FD
- if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
-#ifdef CONFIG_BLK_DEV_RAM
- extern int rd_doload;
- extern void rd_load_secondary(void);
-#endif
- floppy_eject();
-#ifndef CONFIG_BLK_DEV_RAM
- printk(KERN_NOTICE "(Warning, this kernel has no ramdisk support)\n");
-#else
- /* rd_doload is 2 for a dual initrd/ramload setup */
- if(rd_doload==2)
- rd_load_secondary();
- else
-#endif
- {
- printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
- wait_for_keypress();
- }
- }
-#endif
-
- fs_names = __getname();
- get_fs_names(fs_names);
-
- devfs_make_root (root_device_name);
- handle = devfs_find_handle (NULL, ROOT_DEVICE_NAME,
- MAJOR (ROOT_DEV), MINOR (ROOT_DEV),
- DEVFS_SPECIAL_BLK, 1);
- if (handle) {
- int n;
- unsigned major, minor;
-
- devfs_get_maj_min (handle, &major, &minor);
- ROOT_DEV = MKDEV (major, minor);
- if (!ROOT_DEV)
- panic("I have no root and I want to scream");
- n = devfs_generate_path (handle, path + 5, sizeof (path) - 5);
- if (n >= 0) {
- name = path + n;
- devfs_mk_symlink (NULL, "root", DEVFS_FL_DEFAULT,
- name + 5, NULL, NULL);
- memcpy (name, "/dev/", 5);
- }
- }
-
-retry:
- bdev = bdget(kdev_t_to_nr(ROOT_DEV));
- if (!bdev)
- panic(__FUNCTION__ ": unable to allocate root device");
- bdev->bd_op = devfs_get_ops (handle);
- mode = FMODE_READ;
- if (!(root_mountflags & MS_RDONLY))
- mode |= FMODE_WRITE;
- retval = blkdev_get(bdev, mode, 0, BDEV_FS);
- if (retval == -EROFS) {
- root_mountflags |= MS_RDONLY;
- goto retry;
- }
- if (retval) {
- /*
- * Allow the user to distinguish between failed open
- * and bad superblock on root device.
- */
-Eio:
- printk ("VFS: Cannot open root device \"%s\" or %s\n",
- root_device_name, kdevname (ROOT_DEV));
- printk ("Please append a correct \"root=\" boot option\n");
- panic("VFS: Unable to mount root fs on %s",
- kdevname(ROOT_DEV));
- }
-
- check_disk_change(ROOT_DEV);
- sb = get_super(ROOT_DEV);
- if (sb) {
- /* FIXME */
- p = (char *)sb->s_type->name;
- atomic_inc(&sb->s_active);
- up_read(&sb->s_umount);
- down_write(&sb->s_umount);
- goto mount_it;
- }
-
- for (p = fs_names; *p; p += strlen(p)+1) {
- struct file_system_type * fs_type = get_fs_type(p);
- if (!fs_type)
- continue;
- atomic_inc(&bdev->bd_count);
- retval = blkdev_get(bdev, mode, 0, BDEV_FS);
- if (retval)
- goto Eio;
- sb = read_super(ROOT_DEV, bdev, fs_type,
- root_mountflags, root_mount_data);
- put_filesystem(fs_type);
- if (sb) {
- blkdev_put(bdev, BDEV_FS);
- goto mount_it;
- }
- }
- panic("VFS: Unable to mount root fs on %s", kdevname(ROOT_DEV));
-
-mount_it:
- /* FIXME */
- up_write(&sb->s_umount);
- printk ("VFS: Mounted root (%s filesystem)%s.\n", p,
- (sb->s_flags & MS_RDONLY) ? " readonly" : "");
- putname(fs_names);
- vfsmnt = alloc_vfsmnt();
- if (!vfsmnt)
- panic("VFS: alloc_vfsmnt failed for root fs");
-
- set_devname(vfsmnt, name);
- vfsmnt->mnt_sb = sb;
- vfsmnt->mnt_root = dget(sb->s_root);
- bdput(bdev); /* sb holds a reference */
-
-
-#ifdef CONFIG_ROOT_NFS
-attach_it:
-#endif
- root_nd.mnt = root_vfsmnt;
- root_nd.dentry = root_vfsmnt->mnt_sb->s_root;
- graft_tree(vfsmnt, &root_nd);
-
- set_fs_root(current->fs, vfsmnt, vfsmnt->mnt_root);
- set_fs_pwd(current->fs, vfsmnt, vfsmnt->mnt_root);
-
- mntput(vfsmnt);
-}
#define bio_iovec_idx(bio, idx) (&((bio)->bi_io_vec[(idx)]))
#define bio_iovec(bio) bio_iovec_idx((bio), (bio)->bi_idx)
#define bio_page(bio) bio_iovec((bio))->bv_page
-#define __bio_offset(bio, idx) bio_iovec_idx((bio), (idx))->bv_offset
#define bio_offset(bio) bio_iovec((bio))->bv_offset
#define bio_sectors(bio) ((bio)->bi_size >> 9)
#define bio_data(bio) (page_address(bio_page((bio))) + bio_offset((bio)))
#define bio_io_error(bio) bio_endio((bio), 0, bio_sectors((bio)))
-#define bio_for_each_segment(bvl, bio, i) \
- for (bvl = bio_iovec((bio)), i = (bio)->bi_idx; \
+/*
+ * drivers should not use the __ version unless they _really_ want to
+ * run through the entire bio and not just pending pieces
+ */
+#define __bio_for_each_segment(bvl, bio, i, start_idx) \
+ for (bvl = bio_iovec_idx((bio), (start_idx)), i = (start_idx); \
i < (bio)->bi_vcnt; \
bvl++, i++)
+#define bio_for_each_segment(bvl, bio, i) \
+ __bio_for_each_segment(bvl, bio, i, (bio)->bi_idx)
+
/*
* get a reference to a bio, so it won't disappear. the intended use is
* something like:
extern unsigned long initrd_start,initrd_end;
extern int mount_initrd; /* zero if initrd should not be mounted */
extern int initrd_below_start_ok; /* 1 if it is not an error if initrd_start < memory_start */
+extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start; /* starting block # of image */
void initrd_init(void);
#endif
int (*add_device) (struct iobus*, char*);
};
-extern int iobus_register_driver(struct iobus_driver * driver);
-extern void iobus_unregister_driver(struct iobus_driver * driver);
-extern struct iobus_driver * iobus_find_driver(char *name);
-
struct iobus {
spinlock_t lock; /* lock for bus */
atomic_t refcount;
extern void show_buffers(void);
-extern void mount_root(void);
#ifdef CONFIG_BLK_DEV_INITRD
extern unsigned int real_root_dev;
-extern int change_root(kdev_t, const char *);
#endif
extern ssize_t char_read(struct file *, char *, size_t, loff_t *);
#define PCI_DEVICE_ID_TTI_HPT366 0x0004
#define PCI_VENDOR_ID_VIA 0x1106
-#define PCI_DEVICE_ID_VIA_8363_0 0x0305
+#define PCI_DEVICE_ID_VIA_8363_0 0x0305
#define PCI_DEVICE_ID_VIA_8371_0 0x0391
#define PCI_DEVICE_ID_VIA_8501_0 0x0501
#define PCI_DEVICE_ID_VIA_82C505 0x0505
#define PCI_DEVICE_ID_VIA_8233_7 0x3065
#define PCI_DEVICE_ID_VIA_82C686_6 0x3068
#define PCI_DEVICE_ID_VIA_8233_0 0x3074
+#define PCI_DEVICE_ID_VIA_8622 0x3102
#define PCI_DEVICE_ID_VIA_8233C_0 0x3109
+#define PCI_DEVICE_ID_VIA_8361 0x3112
#define PCI_DEVICE_ID_VIA_8633_0 0x3091
-#define PCI_DEVICE_ID_VIA_8367_0 0x3099
+#define PCI_DEVICE_ID_VIA_8367_0 0x3099
#define PCI_DEVICE_ID_VIA_86C100A 0x6100
#define PCI_DEVICE_ID_VIA_8231 0x8231
#define PCI_DEVICE_ID_VIA_8231_4 0x8235
--- /dev/null
+#define __KERNEL_SYSCALLS__
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/unistd.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/smp_lock.h>
+#include <linux/blk.h>
+#include <linux/tty.h>
+
+#include <linux/nfs_fs.h>
+#include <linux/nfs_fs_sb.h>
+#include <linux/nfs_mount.h>
+
+#include <asm/uaccess.h>
+
+/* syscalls missing from unistd.h */
+
+static inline _syscall2(int,mkdir,char *,name,int,mode);
+static inline _syscall1(int,chdir,char *,name);
+static inline _syscall1(int,chroot,char *,name);
+static inline _syscall1(int,unlink,char *,name);
+static inline _syscall3(int,mknod,char *,name,int,mode,dev_t,dev);
+static inline _syscall5(int,mount,char *,dev,char *,dir,char *,type,
+ unsigned long,flags,void *,data);
+static inline _syscall2(int,umount,char *,name,int,flags);
+
+extern void rd_load(void);
+extern void initrd_load(void);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */
+#endif
+int root_mountflags = MS_RDONLY;
+char root_device_name[64];
+
+/* this is initialized in init/main.c */
+kdev_t ROOT_DEV;
+
+static int __init readonly(char *str)
+{
+ if (*str)
+ return 0;
+ root_mountflags |= MS_RDONLY;
+ return 1;
+}
+
+static int __init readwrite(char *str)
+{
+ if (*str)
+ return 0;
+ root_mountflags &= ~MS_RDONLY;
+ return 1;
+}
+
+__setup("ro", readonly);
+__setup("rw", readwrite);
+
+static struct dev_name_struct {
+ const char *name;
+ const int num;
+} root_dev_names[] __initdata = {
+ { "nfs", 0x00ff },
+ { "hda", 0x0300 },
+ { "hdb", 0x0340 },
+ { "loop", 0x0700 },
+ { "hdc", 0x1600 },
+ { "hdd", 0x1640 },
+ { "hde", 0x2100 },
+ { "hdf", 0x2140 },
+ { "hdg", 0x2200 },
+ { "hdh", 0x2240 },
+ { "hdi", 0x3800 },
+ { "hdj", 0x3840 },
+ { "hdk", 0x3900 },
+ { "hdl", 0x3940 },
+ { "hdm", 0x5800 },
+ { "hdn", 0x5840 },
+ { "hdo", 0x5900 },
+ { "hdp", 0x5940 },
+ { "hdq", 0x5A00 },
+ { "hdr", 0x5A40 },
+ { "hds", 0x5B00 },
+ { "hdt", 0x5B40 },
+ { "sda", 0x0800 },
+ { "sdb", 0x0810 },
+ { "sdc", 0x0820 },
+ { "sdd", 0x0830 },
+ { "sde", 0x0840 },
+ { "sdf", 0x0850 },
+ { "sdg", 0x0860 },
+ { "sdh", 0x0870 },
+ { "sdi", 0x0880 },
+ { "sdj", 0x0890 },
+ { "sdk", 0x08a0 },
+ { "sdl", 0x08b0 },
+ { "sdm", 0x08c0 },
+ { "sdn", 0x08d0 },
+ { "sdo", 0x08e0 },
+ { "sdp", 0x08f0 },
+ { "ada", 0x1c00 },
+ { "adb", 0x1c10 },
+ { "adc", 0x1c20 },
+ { "add", 0x1c30 },
+ { "ade", 0x1c40 },
+ { "fd", 0x0200 },
+ { "md", 0x0900 },
+ { "xda", 0x0d00 },
+ { "xdb", 0x0d40 },
+ { "ram", 0x0100 },
+ { "scd", 0x0b00 },
+ { "mcd", 0x1700 },
+ { "cdu535", 0x1800 },
+ { "sonycd", 0x1800 },
+ { "aztcd", 0x1d00 },
+ { "cm206cd", 0x2000 },
+ { "gscd", 0x1000 },
+ { "sbpcd", 0x1900 },
+ { "eda", 0x2400 },
+ { "edb", 0x2440 },
+ { "pda", 0x2d00 },
+ { "pdb", 0x2d10 },
+ { "pdc", 0x2d20 },
+ { "pdd", 0x2d30 },
+ { "pcd", 0x2e00 },
+ { "pf", 0x2f00 },
+ { "apblock", APBLOCK_MAJOR << 8},
+ { "ddv", DDV_MAJOR << 8},
+ { "jsfd", JSFD_MAJOR << 8},
+#if defined(CONFIG_ARCH_S390)
+ { "dasda", (DASD_MAJOR << MINORBITS) },
+ { "dasdb", (DASD_MAJOR << MINORBITS) + (1 << 2) },
+ { "dasdc", (DASD_MAJOR << MINORBITS) + (2 << 2) },
+ { "dasdd", (DASD_MAJOR << MINORBITS) + (3 << 2) },
+ { "dasde", (DASD_MAJOR << MINORBITS) + (4 << 2) },
+ { "dasdf", (DASD_MAJOR << MINORBITS) + (5 << 2) },
+ { "dasdg", (DASD_MAJOR << MINORBITS) + (6 << 2) },
+ { "dasdh", (DASD_MAJOR << MINORBITS) + (7 << 2) },
+#endif
+#if defined(CONFIG_BLK_CPQ_DA) || defined(CONFIG_BLK_CPQ_DA_MODULE)
+ { "ida/c0d0p",0x4800 },
+ { "ida/c0d1p",0x4810 },
+ { "ida/c0d2p",0x4820 },
+ { "ida/c0d3p",0x4830 },
+ { "ida/c0d4p",0x4840 },
+ { "ida/c0d5p",0x4850 },
+ { "ida/c0d6p",0x4860 },
+ { "ida/c0d7p",0x4870 },
+ { "ida/c0d8p",0x4880 },
+ { "ida/c0d9p",0x4890 },
+ { "ida/c0d10p",0x48A0 },
+ { "ida/c0d11p",0x48B0 },
+ { "ida/c0d12p",0x48C0 },
+ { "ida/c0d13p",0x48D0 },
+ { "ida/c0d14p",0x48E0 },
+ { "ida/c0d15p",0x48F0 },
+#endif
+#if defined(CONFIG_BLK_CPQ_CISS_DA) || defined(CONFIG_BLK_CPQ_CISS_DA_MODULE)
+ { "cciss/c0d0p",0x6800 },
+ { "cciss/c0d1p",0x6810 },
+ { "cciss/c0d2p",0x6820 },
+ { "cciss/c0d3p",0x6830 },
+ { "cciss/c0d4p",0x6840 },
+ { "cciss/c0d5p",0x6850 },
+ { "cciss/c0d6p",0x6860 },
+ { "cciss/c0d7p",0x6870 },
+ { "cciss/c0d8p",0x6880 },
+ { "cciss/c0d9p",0x6890 },
+ { "cciss/c0d10p",0x68A0 },
+ { "cciss/c0d11p",0x68B0 },
+ { "cciss/c0d12p",0x68C0 },
+ { "cciss/c0d13p",0x68D0 },
+ { "cciss/c0d14p",0x68E0 },
+ { "cciss/c0d15p",0x68F0 },
+#endif
+ { "nftla", 0x5d00 },
+ { "nftlb", 0x5d10 },
+ { "nftlc", 0x5d20 },
+ { "nftld", 0x5d30 },
+ { "ftla", 0x2c00 },
+ { "ftlb", 0x2c08 },
+ { "ftlc", 0x2c10 },
+ { "ftld", 0x2c18 },
+ { "mtdblock", 0x1f00 },
+ { NULL, 0 }
+};
+
+kdev_t __init name_to_kdev_t(char *line)
+{
+ int base = 0;
+
+ if (strncmp(line,"/dev/",5) == 0) {
+ struct dev_name_struct *dev = root_dev_names;
+ line += 5;
+ do {
+ int len = strlen(dev->name);
+ if (strncmp(line,dev->name,len) == 0) {
+ line += len;
+ base = dev->num;
+ break;
+ }
+ dev++;
+ } while (dev->name);
+ }
+ return to_kdev_t(base + simple_strtoul(line,NULL,base?10:16));
+}
+
+static int __init root_dev_setup(char *line)
+{
+ int i;
+ char ch;
+
+ ROOT_DEV = name_to_kdev_t(line);
+ memset (root_device_name, 0, sizeof root_device_name);
+ if (strncmp (line, "/dev/", 5) == 0) line += 5;
+ for (i = 0; i < sizeof root_device_name - 1; ++i)
+ {
+ ch = line[i];
+ if ( isspace (ch) || (ch == ',') || (ch == '\0') ) break;
+ root_device_name[i] = ch;
+ }
+ return 1;
+}
+
+__setup("root=", root_dev_setup);
+
+static char * __initdata root_mount_data;
+static int __init root_data_setup(char *str)
+{
+ root_mount_data = str;
+ return 1;
+}
+
+static char * __initdata root_fs_names;
+static int __init fs_names_setup(char *str)
+{
+ root_fs_names = str;
+ return 1;
+}
+
+__setup("rootflags=", root_data_setup);
+__setup("rootfstype=", fs_names_setup);
+
+static void __init get_fs_names(char *page)
+{
+ char *s = page;
+
+ if (root_fs_names) {
+ strcpy(page, root_fs_names);
+ while (*s++) {
+ if (s[-1] == ',')
+ s[-1] = '\0';
+ }
+ } else {
+ int len = get_filesystem_list(page);
+ char *p, *next;
+
+ page[len] = '\0';
+ for (p = page-1; p; p = next) {
+ next = strchr(++p, '\n');
+ if (*p++ != '\t')
+ continue;
+ while ((*s++ = *p++) != '\n')
+ ;
+ s[-1] = '\0';
+ }
+ }
+ *s = '\0';
+}
+
+static void __init mount_root(void)
+{
+ void *handle;
+ char path[64];
+ char *name = "/dev/root";
+ char *fs_names, *p;
+ int err;
+ int do_devfs = 0;
+#ifdef CONFIG_ROOT_NFS
+ void *data;
+#endif
+ root_mountflags |= MS_VERBOSE;
+
+ fs_names = __getname();
+ get_fs_names(fs_names);
+
+#ifdef CONFIG_ROOT_NFS
+ if (MAJOR(ROOT_DEV) != UNNAMED_MAJOR)
+ goto skip_nfs;
+ data = nfs_root_data();
+ if (!data)
+ goto no_nfs;
+ err = mount("/dev/root", "/root", "nfs", root_mountflags, data);
+ if (!err)
+ goto done;
+no_nfs:
+ printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");
+ ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0);
+skip_nfs:
+#endif
+
+#ifdef CONFIG_BLK_DEV_FD
+ if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
+#ifdef CONFIG_BLK_DEV_RAM
+ extern int rd_doload;
+ extern void rd_load_secondary(void);
+#endif
+ floppy_eject();
+#ifndef CONFIG_BLK_DEV_RAM
+ printk(KERN_NOTICE "(Warning, this kernel has no ramdisk support)\n");
+#else
+ /* rd_doload is 2 for a dual initrd/ramload setup */
+ if(rd_doload==2)
+ rd_load_secondary();
+ else
+#endif
+ {
+ printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
+ wait_for_keypress();
+ }
+ }
+#endif
+
+ devfs_make_root (root_device_name);
+ handle = devfs_find_handle (NULL, ROOT_DEVICE_NAME,
+ MAJOR (ROOT_DEV), MINOR (ROOT_DEV),
+ DEVFS_SPECIAL_BLK, 1);
+ if (handle) {
+ int n;
+ unsigned major, minor;
+
+ devfs_get_maj_min (handle, &major, &minor);
+ ROOT_DEV = MKDEV (major, minor);
+ if (!ROOT_DEV)
+ panic("I have no root and I want to scream");
+ n = devfs_generate_path (handle, path + 5, sizeof (path) - 5);
+ if (n >= 0) {
+ name = path + n;
+ devfs_mk_symlink (NULL, "root", DEVFS_FL_DEFAULT,
+ name + 5, NULL, NULL);
+ memcpy (name, "/dev/", 5);
+ do_devfs = 1;
+ }
+ }
+ chdir("/dev");
+ unlink("root");
+ mknod("root", S_IFBLK|0600, kdev_t_to_nr(ROOT_DEV));
+ if (do_devfs)
+ mount("devfs", ".", "devfs", 0, NULL);
+retry:
+ for (p = fs_names; *p; p += strlen(p)+1) {
+ err = mount(name,"/root",p,root_mountflags,root_mount_data);
+ switch (err) {
+ case 0:
+ goto done;
+ case -EACCES:
+ root_mountflags |= MS_RDONLY;
+ goto retry;
+ case -EINVAL:
+ continue;
+ }
+ /*
+ * Allow the user to distinguish between failed open
+ * and bad superblock on root device.
+ */
+ printk ("VFS: Cannot open root device \"%s\" or %s\n",
+ root_device_name, kdevname (ROOT_DEV));
+ printk ("Please append a correct \"root=\" boot option\n");
+ panic("VFS: Unable to mount root fs on %s",
+ kdevname(ROOT_DEV));
+ }
+ panic("VFS: Unable to mount root fs on %s", kdevname(ROOT_DEV));
+
+done:
+ putname(fs_names);
+ if (do_devfs)
+ umount(".", 0);
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+
+static int __init change_root(kdev_t new_root_dev,const char *put_old)
+{
+ struct vfsmount *old_rootmnt;
+ struct nameidata devfs_nd;
+ char *new_devname = kmalloc(strlen("/dev/root.old")+1, GFP_KERNEL);
+ int error = 0;
+
+ if (new_devname)
+ strcpy(new_devname, "/dev/root.old");
+
+ /* .. here is directory mounted over root */
+ mount("..", ".", NULL, MS_MOVE, NULL);
+ chdir("/old");
+
+ read_lock(¤t->fs->lock);
+ old_rootmnt = mntget(current->fs->pwdmnt);
+ read_unlock(¤t->fs->lock);
+
+ /* First unmount devfs if mounted */
+ if (path_init("/old/dev", LOOKUP_FOLLOW|LOOKUP_POSITIVE, &devfs_nd))
+ error = path_walk("/old/dev", &devfs_nd);
+ if (!error) {
+ if (devfs_nd.mnt->mnt_sb->s_magic == DEVFS_SUPER_MAGIC &&
+ devfs_nd.dentry == devfs_nd.mnt->mnt_root)
+ umount("/old/dev", 0);
+ path_release(&devfs_nd);
+ }
+
+ ROOT_DEV = new_root_dev;
+ mount_root();
+
+ chdir("/root");
+ ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev;
+ printk("VFS: Mounted root (%s filesystem)%s.\n",
+ current->fs->pwdmnt->mnt_sb->s_type->name,
+ (current->fs->pwdmnt->mnt_sb->s_flags & MS_RDONLY) ? " readonly" : "");
+
+#if 1
+ shrink_dcache();
+ printk("change_root: old root has d_count=%d\n",
+ atomic_read(&old_rootmnt->mnt_root->d_count));
+#endif
+
+ error = mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
+ if (error) {
+ int blivet;
+ struct block_device *ramdisk = old_rootmnt->mnt_sb->s_bdev;
+
+ atomic_inc(&ramdisk->bd_count);
+ blivet = blkdev_get(ramdisk, FMODE_READ, 0, BDEV_FS);
+ printk(KERN_NOTICE "Trying to unmount old root ... ");
+ umount("/old", MNT_DETACH);
+ if (!blivet) {
+ blivet = ioctl_by_bdev(ramdisk, BLKFLSBUF, 0);
+ blkdev_put(ramdisk, BDEV_FS);
+ }
+ if (blivet) {
+ printk(KERN_ERR "error %d\n", blivet);
+ } else {
+ printk("okay\n");
+ error = 0;
+ }
+ } else {
+ spin_lock(&dcache_lock);
+ if (new_devname) {
+ void *p = old_rootmnt->mnt_devname;
+ old_rootmnt->mnt_devname = new_devname;
+ new_devname = p;
+ }
+ spin_unlock(&dcache_lock);
+ }
+
+ /* put the old stuff */
+ mntput(old_rootmnt);
+ kfree(new_devname);
+ return error;
+}
+
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+static int do_linuxrc(void * shell)
+{
+ static char *argv[] = { "linuxrc", NULL, };
+ extern char * envp_init[];
+
+ chdir("/root");
+ mount(".", "/", NULL, MS_MOVE, NULL);
+ chroot(".");
+
+ mount_devfs_fs ();
+
+ close(0);close(1);close(2);
+ setsid();
+ (void) open("/dev/console",O_RDWR,0);
+ (void) dup(0);
+ (void) dup(0);
+ return execve(shell, argv, envp_init);
+}
+
+#endif
+
+/*
+ * Prepare the namespace - decide what/where to mount, load ramdisks, etc.
+ */
+void prepare_namespace(void)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+ int real_root_mountflags = root_mountflags;
+ if (!initrd_start)
+ mount_initrd = 0;
+ if (mount_initrd)
+ root_mountflags &= ~MS_RDONLY;
+ real_root_dev = ROOT_DEV;
+#endif
+ mkdir("/dev", 0700);
+ mkdir("/root", 0700);
+
+#ifdef CONFIG_BLK_DEV_RAM
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (mount_initrd)
+ initrd_load();
+ else
+#endif
+ rd_load();
+#endif
+
+ /* Mount the root filesystem.. */
+ mount_root();
+ chdir("/root");
+ ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev;
+ printk("VFS: Mounted root (%s filesystem)%s.\n",
+ current->fs->pwdmnt->mnt_sb->s_type->name,
+ (current->fs->pwdmnt->mnt_sb->s_flags & MS_RDONLY) ? " readonly" : "");
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ root_mountflags = real_root_mountflags;
+ if (mount_initrd && ROOT_DEV != real_root_dev
+ && MAJOR(ROOT_DEV) == RAMDISK_MAJOR && MINOR(ROOT_DEV) == 0) {
+ int error;
+ int i, pid;
+ mkdir("/old", 0700);
+ chdir("/old");
+
+ pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
+ if (pid > 0) {
+ while (pid != wait(&i)) {
+ current->policy |= SCHED_YIELD;
+ schedule();
+ }
+ }
+ if (MAJOR(real_root_dev) != RAMDISK_MAJOR
+ || MINOR(real_root_dev) != 0) {
+ error = change_root(real_root_dev,"/initrd");
+ if (error)
+ printk(KERN_ERR "Change root to /initrd: "
+ "error %d\n",error);
+
+ chdir("/root");
+ mount(".", "/", NULL, MS_MOVE, NULL);
+ chroot(".");
+
+ mount_devfs_fs ();
+ return;
+ }
+ chroot("..");
+ chdir("/");
+ return;
+ }
+#endif
+ mount(".", "/", NULL, MS_MOVE, NULL);
+ chroot(".");
+
+ mount_devfs_fs ();
+}
int rows, cols;
-#ifdef CONFIG_BLK_DEV_INITRD
-unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */
-#endif
-
-int root_mountflags = MS_RDONLY;
char *execute_command;
-char root_device_name[64];
-
static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
-static char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
+char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
static int __init profile_setup(char *str)
{
__setup("profile=", profile_setup);
-
-static struct dev_name_struct {
- const char *name;
- const int num;
-} root_dev_names[] __initdata = {
- { "nfs", 0x00ff },
- { "hda", 0x0300 },
- { "hdb", 0x0340 },
- { "loop", 0x0700 },
- { "hdc", 0x1600 },
- { "hdd", 0x1640 },
- { "hde", 0x2100 },
- { "hdf", 0x2140 },
- { "hdg", 0x2200 },
- { "hdh", 0x2240 },
- { "hdi", 0x3800 },
- { "hdj", 0x3840 },
- { "hdk", 0x3900 },
- { "hdl", 0x3940 },
- { "hdm", 0x5800 },
- { "hdn", 0x5840 },
- { "hdo", 0x5900 },
- { "hdp", 0x5940 },
- { "hdq", 0x5A00 },
- { "hdr", 0x5A40 },
- { "hds", 0x5B00 },
- { "hdt", 0x5B40 },
- { "sda", 0x0800 },
- { "sdb", 0x0810 },
- { "sdc", 0x0820 },
- { "sdd", 0x0830 },
- { "sde", 0x0840 },
- { "sdf", 0x0850 },
- { "sdg", 0x0860 },
- { "sdh", 0x0870 },
- { "sdi", 0x0880 },
- { "sdj", 0x0890 },
- { "sdk", 0x08a0 },
- { "sdl", 0x08b0 },
- { "sdm", 0x08c0 },
- { "sdn", 0x08d0 },
- { "sdo", 0x08e0 },
- { "sdp", 0x08f0 },
- { "ada", 0x1c00 },
- { "adb", 0x1c10 },
- { "adc", 0x1c20 },
- { "add", 0x1c30 },
- { "ade", 0x1c40 },
- { "fd", 0x0200 },
- { "md", 0x0900 },
- { "xda", 0x0d00 },
- { "xdb", 0x0d40 },
- { "ram", 0x0100 },
- { "scd", 0x0b00 },
- { "mcd", 0x1700 },
- { "cdu535", 0x1800 },
- { "sonycd", 0x1800 },
- { "aztcd", 0x1d00 },
- { "cm206cd", 0x2000 },
- { "gscd", 0x1000 },
- { "sbpcd", 0x1900 },
- { "eda", 0x2400 },
- { "edb", 0x2440 },
- { "pda", 0x2d00 },
- { "pdb", 0x2d10 },
- { "pdc", 0x2d20 },
- { "pdd", 0x2d30 },
- { "pcd", 0x2e00 },
- { "pf", 0x2f00 },
- { "apblock", APBLOCK_MAJOR << 8},
- { "ddv", DDV_MAJOR << 8},
- { "jsfd", JSFD_MAJOR << 8},
-#if defined(CONFIG_ARCH_S390)
- { "dasda", (DASD_MAJOR << MINORBITS) },
- { "dasdb", (DASD_MAJOR << MINORBITS) + (1 << 2) },
- { "dasdc", (DASD_MAJOR << MINORBITS) + (2 << 2) },
- { "dasdd", (DASD_MAJOR << MINORBITS) + (3 << 2) },
- { "dasde", (DASD_MAJOR << MINORBITS) + (4 << 2) },
- { "dasdf", (DASD_MAJOR << MINORBITS) + (5 << 2) },
- { "dasdg", (DASD_MAJOR << MINORBITS) + (6 << 2) },
- { "dasdh", (DASD_MAJOR << MINORBITS) + (7 << 2) },
-#endif
-#if defined(CONFIG_BLK_CPQ_DA) || defined(CONFIG_BLK_CPQ_DA_MODULE)
- { "ida/c0d0p",0x4800 },
- { "ida/c0d1p",0x4810 },
- { "ida/c0d2p",0x4820 },
- { "ida/c0d3p",0x4830 },
- { "ida/c0d4p",0x4840 },
- { "ida/c0d5p",0x4850 },
- { "ida/c0d6p",0x4860 },
- { "ida/c0d7p",0x4870 },
- { "ida/c0d8p",0x4880 },
- { "ida/c0d9p",0x4890 },
- { "ida/c0d10p",0x48A0 },
- { "ida/c0d11p",0x48B0 },
- { "ida/c0d12p",0x48C0 },
- { "ida/c0d13p",0x48D0 },
- { "ida/c0d14p",0x48E0 },
- { "ida/c0d15p",0x48F0 },
-#endif
-#if defined(CONFIG_BLK_CPQ_CISS_DA) || defined(CONFIG_BLK_CPQ_CISS_DA_MODULE)
- { "cciss/c0d0p",0x6800 },
- { "cciss/c0d1p",0x6810 },
- { "cciss/c0d2p",0x6820 },
- { "cciss/c0d3p",0x6830 },
- { "cciss/c0d4p",0x6840 },
- { "cciss/c0d5p",0x6850 },
- { "cciss/c0d6p",0x6860 },
- { "cciss/c0d7p",0x6870 },
- { "cciss/c0d8p",0x6880 },
- { "cciss/c0d9p",0x6890 },
- { "cciss/c0d10p",0x68A0 },
- { "cciss/c0d11p",0x68B0 },
- { "cciss/c0d12p",0x68C0 },
- { "cciss/c0d13p",0x68D0 },
- { "cciss/c0d14p",0x68E0 },
- { "cciss/c0d15p",0x68F0 },
-#endif
- { "nftla", 0x5d00 },
- { "nftlb", 0x5d10 },
- { "nftlc", 0x5d20 },
- { "nftld", 0x5d30 },
- { "ftla", 0x2c00 },
- { "ftlb", 0x2c08 },
- { "ftlc", 0x2c10 },
- { "ftld", 0x2c18 },
- { "mtdblock", 0x1f00 },
- { NULL, 0 }
-};
-
-kdev_t __init name_to_kdev_t(char *line)
-{
- int base = 0;
-
- if (strncmp(line,"/dev/",5) == 0) {
- struct dev_name_struct *dev = root_dev_names;
- line += 5;
- do {
- int len = strlen(dev->name);
- if (strncmp(line,dev->name,len) == 0) {
- line += len;
- base = dev->num;
- break;
- }
- dev++;
- } while (dev->name);
- }
- return to_kdev_t(base + simple_strtoul(line,NULL,base?10:16));
-}
-
-static int __init root_dev_setup(char *line)
-{
- int i;
- char ch;
-
- ROOT_DEV = name_to_kdev_t(line);
- memset (root_device_name, 0, sizeof root_device_name);
- if (strncmp (line, "/dev/", 5) == 0) line += 5;
- for (i = 0; i < sizeof root_device_name - 1; ++i)
- {
- ch = line[i];
- if ( isspace (ch) || (ch == ',') || (ch == '\0') ) break;
- root_device_name[i] = ch;
- }
- return 1;
-}
-
-__setup("root=", root_dev_setup);
-
static int __init checksetup(char *line)
{
struct kernel_param *p;
(loops_per_jiffy/(5000/HZ)) % 100);
}
-static int __init readonly(char *str)
-{
- if (*str)
- return 0;
- root_mountflags |= MS_RDONLY;
- return 1;
-}
-
-static int __init readwrite(char *str)
-{
- if (*str)
- return 0;
- root_mountflags &= ~MS_RDONLY;
- return 1;
-}
-
static int __init debug_kernel(char *str)
{
if (*str)
return 1;
}
-__setup("ro", readonly);
-__setup("rw", readwrite);
__setup("debug", debug_kernel);
__setup("quiet", quiet_kernel);
rest_init();
}
-#ifdef CONFIG_BLK_DEV_INITRD
-static int do_linuxrc(void * shell)
-{
- static char *argv[] = { "linuxrc", NULL, };
-
- close(0);close(1);close(2);
- setsid();
- (void) open("/dev/console",O_RDWR,0);
- (void) dup(0);
- (void) dup(0);
- return execve(shell, argv, envp_init);
-}
-
-#endif
-
struct task_struct *child_reaper = &init_task;
static void __init do_initcalls(void)
#endif
}
-extern void rd_load(void);
-extern void initrd_load(void);
-
-/*
- * Prepare the namespace - decide what/where to mount, load ramdisks, etc.
- */
-static void prepare_namespace(void)
-{
-#ifdef CONFIG_BLK_DEV_INITRD
- int real_root_mountflags = root_mountflags;
- if (!initrd_start)
- mount_initrd = 0;
- if (mount_initrd)
- root_mountflags &= ~MS_RDONLY;
- real_root_dev = ROOT_DEV;
-#endif
-
-#ifdef CONFIG_BLK_DEV_RAM
-#ifdef CONFIG_BLK_DEV_INITRD
- if (mount_initrd)
- initrd_load();
- else
-#endif
- rd_load();
-#endif
-
- /* Mount the root filesystem.. */
- mount_root();
-
- mount_devfs_fs ();
-
-#ifdef CONFIG_BLK_DEV_INITRD
- root_mountflags = real_root_mountflags;
- if (mount_initrd && ROOT_DEV != real_root_dev
- && MAJOR(ROOT_DEV) == RAMDISK_MAJOR && MINOR(ROOT_DEV) == 0) {
- int error;
- int i, pid;
-
- pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
- if (pid > 0) {
- while (pid != wait(&i)) {
- current->policy |= SCHED_YIELD;
- schedule();
- }
- }
- if (MAJOR(real_root_dev) != RAMDISK_MAJOR
- || MINOR(real_root_dev) != 0) {
- error = change_root(real_root_dev,"/initrd");
- if (error)
- printk(KERN_ERR "Change root to /initrd: "
- "error %d\n",error);
- }
- }
-#endif
-}
+extern void prepare_namespace(void);
static int init(void * unused)
{
int (*platform_notify_remove)(struct device * dev) = NULL;
static spinlock_t device_lock;
-static LIST_HEAD(device_gc_list);
-
-static int kdeviced_pid = 0;
-static DECLARE_WAIT_QUEUE_HEAD(kdeviced_wait);
-static DECLARE_COMPLETION(kdeviced_exited);
static ssize_t device_read_status(char *, size_t, loff_t, void *);
static ssize_t device_write_status(const char *, size_t, loff_t, void *);
list_del_init(&dev->node);
unlock_iobus(parent);
- /* queue the device to be removed by the reaper. */
- spin_lock(&device_lock);
- list_add_tail(&dev->node,&device_gc_list);
- spin_unlock(&device_lock);
+ /* remove the driverfs directory */
+ device_remove_dir(dev);
+
+ if (dev->subordinate)
+ iobus_remove_dir(dev->subordinate);
- wake_up(&kdeviced_wait);
+ /* Notify the platform of the removal, in case they
+ * need to do anything...
+ */
+ if (platform_notify_remove)
+ platform_notify_remove(dev);
+
+ /* Tell the driver to clean up after itself.
+ * Note that we likely didn't allocate the device,
+ * so this is the driver's chance to free that up...
+ */
+ if (dev->driver && dev->driver->remove)
+ dev->driver->remove(dev,REMOVE_FREE_RESOURCES);
put_iobus(parent);
}
return error < 0 ? error : count;
}
-/* Device Garbage Collection
- * When a device's reference count reaches 0, it is removed from it's
- * parent's list and added to a list of devices waiting to be removed.
- *
- * We don't directly remove it ourselves, because someone could have an
- * open file.
- *
- * We don't allocate an event for keventd, becuase we may be here from
- * an interrupt; and how do those things get freed, anyway?
- *
- * Instead, when a device's reference count reaches 0, it is removed
- * from its parent's list of children and added to the list of devices
- * to be reaped.
- *
- * When we spawn a thread that gets woken up every time a device is added
- * to the unused list.
- */
-static inline void __reap_device(struct device * dev)
-{
- /* FIXME: What do we do for a bridge? */
-
- /* remove the driverfs directory */
- device_remove_dir(dev);
-
- if (dev->subordinate)
- iobus_remove_dir(dev->subordinate);
-
- /* Notify the platform of the removal, in case they
- * need to do anything...
- */
- if (platform_notify_remove)
- platform_notify_remove(dev);
-
- /* Tell the driver to clean up after itself.
- * Note that we likely didn't allocate the device,
- * so this is the driver's chance to free that up...
- */
- if (dev->driver && dev->driver->remove)
- dev->driver->remove(dev,REMOVE_FREE_RESOURCES);
-}
-
-static int device_cleanup_thread(void * data)
-{
- daemonize();
-
- strcpy(current->comm,"kdeviced");
-
- do {
- struct list_head * node;
-
- spin_lock(&device_lock);
- node = device_gc_list.next;
- while(node != &device_gc_list) {
- list_del_init(node);
- spin_unlock(&device_lock);
- __reap_device(list_to_dev(node));
-
- spin_lock(&device_lock);
- node = device_gc_list.next;
- }
- spin_unlock(&device_lock);
-
- interruptible_sleep_on(&kdeviced_wait);
- } while(!signal_pending(current));
-
- DBG("kdeviced exiting\n");
- complete_and_exit(&kdeviced_exited,0);
- return 0;
-}
-
static int __init device_init_root(void)
{
/* initialize parent bus lists */
return error;
}
- /* initialise the garbage collection */
- pid = kernel_thread(device_cleanup_thread,NULL,
- (CLONE_FS | CLONE_FILES | CLONE_SIGHAND));
- if (pid > 0)
- kdeviced_pid = pid;
- else {
- DBG("DEV: Could not start cleanup thread\n");
- return pid;
- }
-
DBG("DEV: Done Initialising\n");
return error;
}
void __exit device_driver_exit(void)
{
- if (kdeviced_pid) {
- kill_proc(kdeviced_pid,SIGTERM,1);
- kdeviced_pid = 0;
- wait_for_completion(&kdeviced_exited);
- }
+
}
static int __init device_setup(char *str)
struct bio_vec *tovec, *fromvec;
int i;
- bio_for_each_segment(tovec, to, i) {
+ __bio_for_each_segment(tovec, to, i, 0) {
fromvec = &from->bi_io_vec[i];
/*
vfrom = page_address(fromvec->bv_page) + fromvec->bv_offset;
- __save_flags(flags);
- __cli();
+ local_irq_save(flags);
vto = kmap_atomic(tovec->bv_page, KM_BOUNCE_READ);
- memcpy(vto + tovec->bv_offset, vfrom, to->bi_size);
+ memcpy(vto + tovec->bv_offset, vfrom, tovec->bv_len);
kunmap_atomic(vto, KM_BOUNCE_READ);
- __restore_flags(flags);
+ local_irq_restore(flags);
}
}
static inline int bounce_end_io (struct bio *bio, int nr_sectors)
{
struct bio *bio_orig = bio->bi_private;
- struct page *page = bio_page(bio);
+ struct bio_vec *bvec, *org_vec;
unsigned long flags;
- int ret;
+ int ret, i;
- if (test_bit(BIO_UPTODATE, &bio->bi_flags))
- set_bit(BIO_UPTODATE, &bio_orig->bi_flags);
+ if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
+ goto out_eio;
- ret = bio_orig->bi_end_io(bio_orig, nr_sectors);
+ set_bit(BIO_UPTODATE, &bio_orig->bi_flags);
+ /*
+ * free up bounce indirect pages used
+ */
spin_lock_irqsave(&emergency_lock, flags);
- if (nr_emergency_pages >= POOL_SIZE) {
- spin_unlock_irqrestore(&emergency_lock, flags);
- __free_page(page);
- } else {
- /*
- * We are abusing page->list to manage
- * the highmem emergency pool:
- */
- list_add(&page->list, &emergency_pages);
- nr_emergency_pages++;
- spin_unlock_irqrestore(&emergency_lock, flags);
+ __bio_for_each_segment(bvec, bio, i, 0) {
+ org_vec = &bio_orig->bi_io_vec[i];
+ if (bvec->bv_page == org_vec->bv_page)
+ continue;
+
+ if (nr_emergency_pages >= POOL_SIZE)
+ __free_page(bvec->bv_page);
+ else {
+ /*
+ * We are abusing page->list to manage
+ * the highmem emergency pool:
+ */
+ list_add(&bvec->bv_page->list, &emergency_pages);
+ nr_emergency_pages++;
+ }
}
+ spin_unlock_irqrestore(&emergency_lock, flags);
+
+out_eio:
+ ret = bio_orig->bi_end_io(bio_orig, nr_sectors);
bio_put(bio);
return ret;