Index: linux-2.6.8.1-ck8/fs/bio.c =================================================================== --- linux-2.6.8.1-ck8.orig/fs/bio.c 2004-09-17 00:10:48.655631711 +1000 +++ linux-2.6.8.1-ck8/fs/bio.c 2004-09-17 00:13:51.024704054 +1000 @@ -388,20 +388,17 @@ int bio_uncopy_user(struct bio *bio) struct bio_vec *bvec; int i, ret = 0; - if (bio_data_dir(bio) == READ) { - char *uaddr = bio->bi_private; + char *uaddr = bio->bi_private; - __bio_for_each_segment(bvec, bio, i, 0) { - char *addr = page_address(bvec->bv_page); - - if (!ret && copy_to_user(uaddr, addr, bvec->bv_len)) - ret = -EFAULT; + __bio_for_each_segment(bvec, bio, i, 0) { + char *addr = page_address(bvec->bv_page); + if (bio_data_dir(bio) == READ && !ret && + copy_to_user(uaddr, addr, bvec->bv_len)) + ret = -EFAULT; - __free_page(bvec->bv_page); - uaddr += bvec->bv_len; - } + __free_page(bvec->bv_page); + uaddr += bvec->bv_len; } - bio_put(bio); return ret; } @@ -457,6 +454,7 @@ struct bio *bio_copy_user(request_queue_ */ if (!ret) { if (!write_to_vm) { + unsigned long p = uaddr; bio->bi_rw |= (1 << BIO_RW); /* * for a write, copy in data to kernel pages @@ -465,8 +463,9 @@ struct bio *bio_copy_user(request_queue_ bio_for_each_segment(bvec, bio, i) { char *addr = page_address(bvec->bv_page); - if (copy_from_user(addr, (char *) uaddr, bvec->bv_len)) + if (copy_from_user(addr, (char *) p, bvec->bv_len)) goto cleanup; + p += bvec->bv_len; } }