diff -urN linux-2.4.21/fs/block_dev.c linux-2.4.21.SuSE/fs/block_dev.c
--- linux-2.4.21/fs/block_dev.c	2003-07-01 15:49:54.000000000 +0200
+++ linux-2.4.21.SuSE/fs/block_dev.c	2003-07-01 15:51:21.000000000 +0200
@@ -719,6 +719,8 @@
 	direct_IO: blkdev_direct_IO,
 };
 
+static int	blkdev_kvec_read(struct file *filp, kvec_cb_t cb, size_t size, loff_t pos);
+static int	blkdev_kvec_write(struct file *filp, kvec_cb_t cb, size_t size, loff_t pos);
 struct file_operations def_blk_fops = {
 	open:		blkdev_open,
 	release:	blkdev_close,
@@ -728,6 +730,10 @@
 	mmap:		generic_file_mmap,
 	fsync:		block_fsync,
 	ioctl:		blkdev_ioctl,
+	aio_read:	generic_file_aio_read,
+	aio_write:	generic_file_aio_write,
+	kvec_read:	blkdev_kvec_read,
+	kvec_write:	blkdev_kvec_write,
 };
 
 const char * bdevname(kdev_t dev)
@@ -741,3 +747,121 @@
 	sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
 	return buffer;
 }
+static int blkdev_kvec_rw(struct file *filp, int rw, kvec_cb_t cb, size_t size, loff_t pos);
+static int blkdev_kvec_read(struct file *file, kvec_cb_t cb, size_t size, loff_t pos)
+{
+	if (file->f_flags & O_DIRECT)
+		return blkdev_kvec_rw(file, READ, cb, size, pos);
+	else
+		return generic_file_kvec_read(file, cb, size, pos);
+}
+
+static int blkdev_kvec_write(struct file *file, kvec_cb_t cb, size_t size, loff_t pos)
+{
+	if (file->f_flags & O_DIRECT)
+		return blkdev_kvec_rw(file, WRITE, cb, size, pos);
+	else
+		return generic_file_kvec_write(file, cb, size, pos);
+}
+
+static int	blkdev_kvec_rw(struct file *filp, int rw, kvec_cb_t cb, size_t size, loff_t pos)
+{
+	int		err;
+	unsigned	minor;
+	kdev_t		dev;
+	unsigned long	limit, blocknr, blocks;
+
+	unsigned	sector_size, sector_bits, sector_mask;
+	unsigned	max_sectors;
+	unsigned	i;
+
+	pr_debug("blkdev_kvec_rw: %p %d %d %p %d %d %Lu\n", filp, rw, nr, kiovec, flags, size, pos);
+	/*
+	 * First, a few checks on device size limits 
+	 */
+
+	dev = filp->f_dentry->d_inode->i_rdev;
+	sector_size = 512;
+	if (is_mounted(dev)) {
+		if (blksize_size[MAJOR(dev)])
+			sector_size = blksize_size[MAJOR(dev)][MINOR(dev)];
+	} else {
+		if (hardsect_size[MAJOR(dev)])
+			sector_size = hardsect_size[MAJOR(dev)][MINOR(dev)];
+	}
+
+	if (sector_size == 512)  /* Fastpath */
+		sector_bits = 9;
+	else {
+		for (sector_bits = 0; sector_size > (1 << sector_bits); sector_bits++);
+		if ((1 << sector_bits) != sector_size) {
+			BUG();
+			return -EINVAL;
+		}
+	}
+
+	sector_mask = sector_size - 1;
+	max_sectors = 25000; /* KIO_MAX_SECTORS >> (sector_bits - 9); */
+	
+	if (blk_size[MAJOR(dev)])
+		limit = (((loff_t) blk_size[MAJOR(dev)][MINOR(dev)]) << BLOCK_SIZE_BITS) >> sector_bits;
+	else
+		limit = INT_MAX;
+	pr_debug("blkdev_kvec_rw: dev %d:%d (+%lu)\n",
+		 MAJOR(dev), MINOR(dev), limit);
+
+	/* EOF at the end */
+	err = 0;
+	if (!size || (pos >> sector_bits) == limit) {
+		pr_debug("blkdev_kvec_rw: %Lu > %lu, %d\n", pos >> sector_bits, limit, sector_bits);
+		cb.fn(cb.data, cb.vec, err);
+		return 0;
+	}
+
+	/* ENXIO for io beyond the end */
+	err = -ENXIO;
+	if ((pos >> sector_bits) >= limit) {
+		pr_debug("blkdev_kvec_rw: %Lu > %lu, %d\n", pos >> sector_bits, limit, sector_bits);
+		goto out;
+	}
+
+	err = -EINVAL;
+	if ((pos < 0) || (pos & sector_mask) || (size & sector_mask)) {
+		pr_debug("pos(%Ld)/size(%lu) wrong(%d)\n", pos, size, sector_mask);
+		goto out;
+	}
+
+	/* Verify that the scatter-gather list is sector aligned. */
+	for (i=0; i<cb.vec->nr; i++)
+		if ((cb.vec->veclet[i].offset & sector_mask) ||
+		    (cb.vec->veclet[i].length & sector_mask)) {
+			pr_debug("veclet offset/length wrong");
+			goto out;
+		}
+
+	/*
+	 * Split the IO into KIO_MAX_SECTORS chunks, mapping and
+	 * unmapping the single kiobuf as we go to perform each chunk of
+	 * IO.  
+	 */
+
+	blocknr = pos >> sector_bits;
+	blocks = size >> sector_bits;
+	if (blocks > max_sectors)
+		blocks = max_sectors;
+	if (blocks > limit - blocknr)
+		blocks = limit - blocknr;
+	err = -ENXIO;
+	if (!blocks) {
+		pr_debug("blkdev: !blocks %d %ld %ld\n", max_sectors, limit, blocknr);
+		goto out;
+	}
+
+	err = brw_kvec_async(rw, cb, dev, blocks, blocknr, sector_bits);
+out:
+	if (err)
+		printk(KERN_DEBUG "blkdev_kvec_rw: ret is %d\n", err);
+	return err;
+}
+
+
diff -urN linux-2.4.21/mm/filemap.c linux-2.4.21.SuSE/mm/filemap.c
--- linux-2.4.21/mm/filemap.c	2003-07-01 15:49:55.000000000 +0200
+++ linux-2.4.21.SuSE/mm/filemap.c	2003-07-01 15:51:21.000000000 +0200
@@ -3913,6 +3913,9 @@
 	unsigned long nr_pages;
 	int ret;
 
+	/* Use the mapping host inode to get block and CODA right */
+	inode = as->host;
+
 	if (io->rw == WRITE) {
 		unsigned long long tmp;
 		loff_t limit;