--- linux/drivers/md/lvm-internal.h.~1~ Sun Nov 11 18:09:32 2001 +++ linux/drivers/md/lvm-internal.h Wed Feb 27 15:38:16 2002 @@ -85,6 +85,9 @@ void lvm_hash_link(lv_block_exception_t *, kdev_t, ulong, lv_t *); int lvm_snapshot_alloc_hash_table(lv_t *); void lvm_drop_snapshot(vg_t *vg, lv_t *, const char *); +int lvm_get_blksize(kdev_t); +int lvm_snapshot_alloc_iobuf_pages(struct kiobuf *, int); +int lvm_do_bulk_copy(kdev_t, kdev_t, uint, uint, uint); /* lvm_fs.c */ --- linux/drivers/md/lvm-snap.c.~1~ Wed Feb 27 15:37:02 2002 +++ linux/drivers/md/lvm-snap.c Thu Feb 28 19:57:21 2002 @@ -222,7 +222,7 @@ return 1; } -inline int lvm_get_blksize(kdev_t dev) +extern int lvm_get_blksize(kdev_t dev) { int correct_size = BLOCK_SIZE, i, major; @@ -259,6 +259,90 @@ #endif +static int lvm_do_bulk_copy_iobuf(struct kiobuf *iobuf, + kdev_t old_dev, kdev_t new_dev, + uint old_start, uint new_start, + uint total_sectors) +{ + int err, ret; + int old_blksize, new_blksize, io_sectors; + int min_blksize, max_blksize; + + old_blksize = get_hardsect_size(old_dev); + new_blksize = get_hardsect_size(new_dev); + + max_blksize = max(old_blksize, new_blksize); + min_blksize = min(old_blksize, new_blksize); + + err = -EINVAL; + if (total_sectors % (max_blksize>>9)) + goto out; + + while (total_sectors) + { + io_sectors = min(total_sectors, (uint) KIO_MAX_SECTORS); + total_sectors -= io_sectors; + + iobuf->length = io_sectors << 9; + + if(!lvm_snapshot_prepare_blocks(iobuf->blocks, old_start, + io_sectors, old_blksize)) + goto out; + + ret = brw_kiovec(READ, 1, &iobuf, old_dev, + iobuf->blocks, old_blksize) ; + if (ret != (io_sectors<<9)) + goto fail_io; + + if(!lvm_snapshot_prepare_blocks(iobuf->blocks, new_start, + io_sectors, new_blksize)) + goto out; + + ret = brw_kiovec(WRITE, 1, &iobuf, new_dev, + iobuf->blocks, new_blksize); + if (ret != (io_sectors<<9)) + goto fail_io; + + old_start += io_sectors; + new_start += io_sectors; + } + err = 0; +out: + return err; + +fail_io: + if (ret < 0) + err = ret; + else + err = -EIO; + goto out; +} + + +extern int lvm_do_bulk_copy(kdev_t old_dev, kdev_t new_dev, + uint old_start, uint new_start, + uint total_sectors) +{ + struct kiobuf *iobuf; + int err; + + err = alloc_kiovec(1, &iobuf); + if (err) + return err; + + err = lvm_snapshot_alloc_iobuf_pages(iobuf, KIO_MAX_SECTORS); + if (err) + goto out; + + err = lvm_do_bulk_copy_iobuf(iobuf, old_dev, new_dev, + old_start, new_start, total_sectors); + unmap_kiobuf(iobuf); +out: + free_kiovec(1, &iobuf); + return err; +} + + int lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap) { uint pvn; @@ -335,7 +419,6 @@ vg_t *vg, lv_t* lv_snap) { const char * reason; - unsigned long phys_start; unsigned long org_start, snap_start, snap_phys_dev, virt_start, pe_off; int idx = lv_snap->lv_remap_ptr, chunk_size = lv_snap->lv_chunk_size; struct kiobuf * iobuf; @@ -370,44 +453,9 @@ iobuf = lv_snap->lv_iobuf; - blksize_org = get_hardsect_size(org_phys_dev); - blksize_snap = get_hardsect_size(snap_phys_dev); - max_blksize = max(blksize_org, blksize_snap); - min_blksize = min(blksize_org, blksize_snap); - max_sectors = KIO_MAX_SECTORS * (min_blksize>>9); - - if (chunk_size % (max_blksize>>9)) - goto fail_blksize; - - /* Don't change org_start, we need it to fill in the exception table */ - phys_start = org_start; - - while (chunk_size) - { - nr_sectors = min(chunk_size, max_sectors); - chunk_size -= nr_sectors; - - iobuf->length = nr_sectors << 9; - - if(!lvm_snapshot_prepare_blocks(iobuf->blocks, phys_start, - nr_sectors, blksize_org)) - goto fail_prepare; - - if (brw_kiovec(READ, 1, &iobuf, org_phys_dev, - iobuf->blocks, blksize_org) != (nr_sectors<<9)) - goto fail_raw_read; - - if(!lvm_snapshot_prepare_blocks(iobuf->blocks, snap_start, - nr_sectors, blksize_snap)) - goto fail_prepare; - - if (brw_kiovec(WRITE, 1, &iobuf, snap_phys_dev, - iobuf->blocks, blksize_snap) != (nr_sectors<<9)) - goto fail_raw_write; - - phys_start += nr_sectors; - snap_start += nr_sectors; - } + if (lvm_do_bulk_copy_iobuf(iobuf, org_phys_dev, snap_phys_dev, + org_start, snap_start, chunk_size)) + goto fail_io; #ifdef DEBUG_SNAPSHOT /* invalidate the logical snapshot buffer cache */ @@ -437,19 +485,8 @@ fail_out_of_space: reason = "out of space"; goto out; - fail_raw_read: - reason = "read error"; - goto out; - fail_raw_write: - reason = "write error"; - goto out; - fail_blksize: - reason = "blocksize error"; - goto out; - - fail_prepare: - reason = "couldn't prepare kiovec blocks " - "(start probably isn't block aligned)"; + fail_io: + reason = "IO error"; goto out; }