diff -ur -b linux/fs/buffer.c linux_brw/fs/buffer.c
--- linux/fs/buffer.c	Mon Feb 19 17:36:43 2001
+++ linux_brw/fs/buffer.c	Mon Feb 19 17:29:30 2001
@@ -1293,7 +1293,6 @@
 			iosize = 0;
 		}
 		
-		put_unused_buffer_head(tmp);
 		iosize += size;
 	}
 	wake_up(&buffer_wait);
@@ -1316,8 +1315,9 @@
  * It is up to the caller to make sure that there are enough blocks
  * passed in to completely map the iobufs to disk.  */
 
-int brw_kiovec(int rw, int nr, struct kiobuf *iovec[], 
-	       kdev_t dev, unsigned long b[], int size, int bmap)
+int brw_kiovec_bh(int rw, int nr, struct kiobuf *iovec[],
+		  kdev_t dev, unsigned long b[], int size, int bmap,
+		  struct buffer_head *bh[], int nbh)
 {
 	int		err;
 	int		length;
@@ -1331,11 +1331,20 @@
 	struct kiobuf *	iobuf = NULL;
 	unsigned long	page;
 	struct page *	map;
-	struct buffer_head *tmp, *bh[KIO_MAX_SECTORS];
+	struct buffer_head *tmp;
 
 	/* 
 	 * First, do some alignment and validity checks 
 	 */
+	if(!bh)
+		panic("brw_kiovec_bh: bh == NULL\n");
+
+	for (i = 0; i < nbh; i++) {
+		if(!bh[i])
+			panic("brw_kiovec_bh: bh[%d] == NULL\n", i);
+		memset(bh[i], 0, sizeof(**bh));
+	}
+
 	for (i = 0; i < nr; i++) {
 		iobuf = iovec[i];
 		if ((iobuf->offset & (size-1)) ||
@@ -1367,7 +1376,7 @@
 
 			while (length > 0) {
 				blocknr = b[bufind++];
-				tmp = get_unused_buffer_head(0);
+				tmp = bh[bhind];
 				if (!tmp) {
 					err = -ENOMEM;
 					goto error;
@@ -1387,7 +1396,7 @@
 
 				dprintk ("buffer %d (%d) at %p\n", 
 					 bhind, tmp->b_blocknr, tmp->b_data);
-				bh[bhind++] = tmp;
+				bhind++;
 				length -= size;
 				offset += size;
 
@@ -1395,7 +1404,7 @@
 				 * Start the IO if we have got too much or if
 				 * this is the end of the last iobuf 
 				 */
-				if (bhind >= KIO_MAX_SECTORS) {
+				if (bhind >= nbh) {
 					err = do_kio(rw, bhind, bh, size);
 					if (err >= 0)
 						transferred += err;
@@ -1430,11 +1439,29 @@
  error:
 	/* We got an error allocation the bh'es.  Just free the current
            buffer_heads and exit. */
-	for (i = 0; i < bhind; i++)
-		put_unused_buffer_head(bh[i]);
 	wake_up(&buffer_wait);
 	goto finished;
 }
+
+int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
+		kdev_t dev, unsigned long b[], int size, int bmap) {
+	int i, ret, nbh;
+	struct buffer_head *bh[KIO_MAX_SECTORS];
+
+	nbh = (nr > KIO_MAX_SECTORS) ? KIO_MAX_SECTORS : nr;
+	for(i = 0; i < nbh; i++)
+		if(!(bh[i] = get_unused_buffer_head(0))) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+	ret = brw_kiovec_bh(rw, nr, iovec, dev, b, size, bmap, bh, nbh);
+
+ out:
+	while(i) put_unused_buffer_head(bh[--i]);
+	return ret;
+}
+
 
 /*
  * Start I/O on a page.
diff -ur -b linux/include/linux/iobuf.h linux_brw/include/linux/iobuf.h
--- linux/include/linux/iobuf.h	Mon Feb 19 17:36:43 2001
+++ linux_brw/include/linux/iobuf.h	Mon Feb 19 17:31:17 2001
@@ -64,6 +64,10 @@
 
 /* fs/buffer.c */
 
+int	brw_kiovec_bh(int rw, int nr, struct kiobuf *iovec[], 
+		      kdev_t dev, unsigned long b[], int size, int bmap,
+		      struct buffer_head *bh[], int nbh);
+
 int	brw_kiovec(int rw, int nr, struct kiobuf *iovec[], 
 		   kdev_t dev, unsigned long b[], int size, int bmap);
 
diff -ur -b linux/kernel/ksyms.c linux_brw/kernel/ksyms.c
--- linux/kernel/ksyms.c	Mon Feb 19 17:36:43 2001
+++ linux_brw/kernel/ksyms.c	Mon Feb 19 17:24:49 2001
@@ -260,6 +260,7 @@
 EXPORT_SYMBOL(alloc_kiovec);
 EXPORT_SYMBOL(free_kiovec);
 EXPORT_SYMBOL(expand_kiobuf);
+EXPORT_SYMBOL(brw_kiovec_bh);
 EXPORT_SYMBOL(brw_kiovec);
 
 /* tty routines */
