## Automatically generated incremental diff
## From:   linux-2.5.1-pre6
## To:     linux-2.5.1-pre7
## Robot:  $Id: make-incremental-diff,v 1.8 2001/12/04 06:05:04 hpa Exp $

diff -urN linux-2.5.1-pre6/Makefile linux/Makefile
--- linux-2.5.1-pre6/Makefile	Fri Dec  7 17:30:28 2001
+++ linux/Makefile	Fri Dec  7 17:31:16 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 1
-EXTRAVERSION =-pre6
+EXTRAVERSION =-pre7
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -257,8 +257,8 @@
 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) \
@@ -333,6 +333,9 @@
 	$(CC) $(CFLAGS) $(CFLAGS_KERNEL) -DUTS_MACHINE='"$(ARCH)"' -c -o init/version.o init/version.c
 
 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
diff -urN linux-2.5.1-pre6/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c
--- linux-2.5.1-pre6/arch/i386/kernel/pci-pc.c	Fri Dec  7 17:30:28 2001
+++ linux/arch/i386/kernel/pci-pc.c	Fri Dec  7 17:31:16 2001
@@ -1114,17 +1114,26 @@
  * 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);
 	}
 }
 
@@ -1138,6 +1147,9 @@
 	{ 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 }
 };
 
diff -urN linux-2.5.1-pre6/drivers/block/elevator.c linux/drivers/block/elevator.c
--- linux-2.5.1-pre6/drivers/block/elevator.c	Fri Dec  7 17:30:28 2001
+++ linux/drivers/block/elevator.c	Fri Dec  7 17:31:16 2001
@@ -61,6 +61,12 @@
 	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
 	 */
@@ -95,6 +101,9 @@
  */
 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
 	 */
@@ -133,6 +142,8 @@
 			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;
@@ -225,6 +236,9 @@
 
 		if (__rq->flags & (REQ_BARRIER | REQ_STARTED))
 			break;
+
+		if (!(__rq->flags & REQ_CMD))
+			continue;
 
 		if (!elv_rq_merge_ok(__rq, bio))
 			continue;
diff -urN linux-2.5.1-pre6/drivers/block/floppy.c linux/drivers/block/floppy.c
--- linux-2.5.1-pre6/drivers/block/floppy.c	Fri Dec  7 17:30:28 2001
+++ linux/drivers/block/floppy.c	Fri Dec  7 17:31:16 2001
@@ -3914,7 +3914,7 @@
     {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];
diff -urN linux-2.5.1-pre6/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- linux-2.5.1-pre6/drivers/block/ll_rw_blk.c	Fri Dec  7 17:30:28 2001
+++ linux/drivers/block/ll_rw_blk.c	Fri Dec  7 17:31:16 2001
@@ -291,13 +291,13 @@
 	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
 	 */
@@ -305,7 +305,6 @@
 	rq->cmd[3] = (block >> 16) & 0xff;
 	rq->cmd[4] = (block >>  8) & 0xff;
 	rq->cmd[5] = block & 0xff;
-	rq->cmd[6] = 0;
 
 	/*
 	 * and transfer length
@@ -347,7 +346,7 @@
 	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;
@@ -357,9 +356,7 @@
 	/*
 	 * for each bio in rq
 	 */
-	j = 0;
 	rq_for_each_bio(bio, rq) {
-		j++;
 		/*
 		 * for each segment in bio
 		 */
@@ -386,7 +383,6 @@
 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();
 				}
 
@@ -411,7 +407,7 @@
 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;
 	}
@@ -480,9 +476,17 @@
  */
 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);
 }
 
 /**
diff -urN linux-2.5.1-pre6/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c
--- linux-2.5.1-pre6/drivers/char/pc_keyb.c	Fri Dec  7 17:30:28 2001
+++ linux/drivers/char/pc_keyb.c	Fri Dec  7 17:31:16 2001
@@ -1090,6 +1090,7 @@
 		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. */
@@ -1099,7 +1100,6 @@
 	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;
 }
 
diff -urN linux-2.5.1-pre6/fs/bio.c linux/fs/bio.c
--- linux-2.5.1-pre6/fs/bio.c	Fri Dec  7 17:30:28 2001
+++ linux/fs/bio.c	Fri Dec  7 17:31:17 2001
@@ -377,7 +377,7 @@
 		/*
 		 * 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;
 
@@ -392,8 +392,7 @@
 				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);
 			}
@@ -405,7 +404,7 @@
 			} else {
 				kunmap_atomic(vto, KM_BIO_IRQ);
 				kunmap_atomic(vfrom, KM_BIO_IRQ);
-				__restore_flags(flags);
+				local_irq_restore(flags);
 			}
 
 fill_in:
@@ -424,10 +423,8 @@
 	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;
@@ -613,6 +610,11 @@
 	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);
 }
 
diff -urN linux-2.5.1-pre6/fs/namespace.c linux/fs/namespace.c
--- linux-2.5.1-pre6/fs/namespace.c	Fri Dec  7 17:30:28 2001
+++ linux/fs/namespace.c	Fri Dec  7 17:31:17 2001
@@ -15,12 +15,10 @@
 #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);
@@ -31,9 +29,7 @@
 
 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)
 {
@@ -462,8 +458,7 @@
 	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)
@@ -928,6 +923,44 @@
  * 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);
@@ -939,6 +972,9 @@
 };
 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)
 {
@@ -1030,93 +1066,3 @@
 	} 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(&current->fs->lock);
-	old_rootmnt = mntget(current->fs->rootmnt);
-	read_unlock(&current->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
diff -urN linux-2.5.1-pre6/fs/super.c linux/fs/super.c
--- linux-2.5.1-pre6/fs/super.c	Fri Dec  7 17:30:28 2001
+++ linux/fs/super.c	Fri Dec  7 17:31:17 2001
@@ -21,36 +21,21 @@
  */
 
 #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;
 
@@ -429,10 +414,6 @@
 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;
@@ -549,37 +530,6 @@
 	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
@@ -708,17 +658,30 @@
 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,
@@ -743,13 +706,12 @@
 		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);
@@ -898,213 +860,4 @@
 struct vfsmount *kern_mount(struct file_system_type *type)
 {
 	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);
 }
diff -urN linux-2.5.1-pre6/include/linux/bio.h linux/include/linux/bio.h
--- linux-2.5.1-pre6/include/linux/bio.h	Fri Dec  7 17:30:28 2001
+++ linux/include/linux/bio.h	Fri Dec  7 17:31:17 2001
@@ -100,7 +100,6 @@
 #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)))
@@ -136,10 +135,17 @@
 
 #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
diff -urN linux-2.5.1-pre6/include/linux/blk.h linux/include/linux/blk.h
--- linux-2.5.1-pre6/include/linux/blk.h	Fri Dec  7 17:30:28 2001
+++ linux/include/linux/blk.h	Fri Dec  7 17:31:17 2001
@@ -22,6 +22,9 @@
 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
diff -urN linux-2.5.1-pre6/include/linux/device.h linux/include/linux/device.h
--- linux-2.5.1-pre6/include/linux/device.h	Fri Dec  7 17:30:28 2001
+++ linux/include/linux/device.h	Fri Dec  7 17:31:17 2001
@@ -113,10 +113,6 @@
 	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;
diff -urN linux-2.5.1-pre6/include/linux/fs.h linux/include/linux/fs.h
--- linux-2.5.1-pre6/include/linux/fs.h	Fri Dec  7 17:30:28 2001
+++ linux/include/linux/fs.h	Fri Dec  7 17:31:17 2001
@@ -1447,11 +1447,9 @@
 
 
 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 *);
diff -urN linux-2.5.1-pre6/include/linux/pci_ids.h linux/include/linux/pci_ids.h
--- linux-2.5.1-pre6/include/linux/pci_ids.h	Fri Dec  7 17:30:28 2001
+++ linux/include/linux/pci_ids.h	Fri Dec  7 17:31:17 2001
@@ -912,7 +912,7 @@
 #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
@@ -946,9 +946,11 @@
 #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
diff -urN linux-2.5.1-pre6/init/do_mounts.c linux/init/do_mounts.c
--- linux-2.5.1-pre6/init/do_mounts.c	Wed Dec 31 16:00:00 1969
+++ linux/init/do_mounts.c	Fri Dec  7 17:31:17 2001
@@ -0,0 +1,558 @@
+#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(&current->fs->lock);
+	old_rootmnt = mntget(current->fs->pwdmnt);
+	read_unlock(&current->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 ();
+}
diff -urN linux-2.5.1-pre6/init/main.c linux/init/main.c
--- linux-2.5.1-pre6/init/main.c	Fri Dec  7 17:30:28 2001
+++ linux/init/main.c	Fri Dec  7 17:31:17 2001
@@ -120,17 +120,10 @@
 
 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)
 {
@@ -141,175 +134,6 @@
 
 __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;
@@ -376,22 +200,6 @@
 		(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)
@@ -408,8 +216,6 @@
 	return 1;
 }
 
-__setup("ro", readonly);
-__setup("rw", readwrite);
 __setup("debug", debug_kernel);
 __setup("quiet", quiet_kernel);
 
@@ -624,21 +430,6 @@
 	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)
@@ -745,61 +536,7 @@
 #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)
 {
diff -urN linux-2.5.1-pre6/kernel/device.c linux/kernel/device.c
--- linux-2.5.1-pre6/kernel/device.c	Fri Dec  7 17:30:28 2001
+++ linux/kernel/device.c	Fri Dec  7 17:31:17 2001
@@ -50,11 +50,6 @@
 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 *);
@@ -379,12 +374,24 @@
 	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);
 }
@@ -875,76 +882,6 @@
 	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 */
@@ -981,27 +918,13 @@
 		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)
diff -urN linux-2.5.1-pre6/mm/highmem.c linux/mm/highmem.c
--- linux-2.5.1-pre6/mm/highmem.c	Fri Dec  7 17:30:28 2001
+++ linux/mm/highmem.c	Fri Dec  7 17:31:17 2001
@@ -214,7 +214,7 @@
 	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];
 
 		/*
@@ -225,12 +225,11 @@
 
 		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);
 	}
 }
 
@@ -263,28 +262,39 @@
 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;
