[dm-devel] [PATCH 09/10] dm snapshot: Track snapshot-merged writes
Mark McLoughlin
markmc at redhat.com
Tue Apr 1 07:32:56 UTC 2008
Add the ability to track writes to the snapshot-merged target which
have been mapped to the COW device.
Rationale is that we won't want to start merging a chunk until all
writes to that chunk have completed. Reads don't matter because the
contents of the chunk on the COW device is not affected by the merging
process.
Signed-off-by: Mark McLoughlin <markmc at redhat.com>
---
drivers/md/dm-snap.c | 36 +++++++++++++++++++++++++++++++-----
1 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 5236763..bc13f35 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -1380,6 +1380,7 @@ static int merged_map(struct dm_target *ti, struct bio *bio,
struct dm_merged *merged = ti->private;
struct dm_snapshot *s = &merged->snap;
struct dm_snap_exception *e;
+ struct dm_snap_pending_exception *pe;
chunk_t chunk;
int r = DM_MAPIO_REMAPPED;;
@@ -1388,28 +1389,52 @@ static int merged_map(struct dm_target *ti, struct bio *bio,
chunk = sector_to_chunk(s, bio->bi_sector);
- down_read(&s->lock);
+ down_write(&s->lock);
if (!s->valid) {
- up_read(&s->lock);
+ up_write(&s->lock);
return -EIO;
}
e = lookup_exception(&s->complete, chunk);
- if (e)
+ if (e) {
+ if (bio_rw(bio) == WRITE) {
+ pe = __find_pending_exception(s, chunk, 0);
+ if (!pe) {
+ __invalidate_snapshot(s, -ENOMEM);
+ r = -EIO;
+ goto out_unlock;
+ }
+ map_context->ptr = pe;
+ }
+
remap_exception(s, e, bio, chunk);
- else {
+ } else {
bio->bi_bdev = s->origin->bdev;
if (bio_rw(bio) == WRITE)
r = do_origin(s->origin, bio->bi_sector, bio);
}
- up_read(&s->lock);
+out_unlock:
+ up_write(&s->lock);
return r;
}
+static int merged_end_io(struct dm_target *ti, struct bio *bio,
+ int error, union map_info *map_context)
+{
+ struct dm_snap_pending_exception *pe = map_context->ptr;
+
+ if (bio_rw(bio) != WRITE || !pe)
+ return error;
+
+ put_pending_exception(pe);
+
+ return error;
+}
+
static void merged_resume(struct dm_target *ti)
{
struct dm_merged *merged = ti->private;
@@ -1477,6 +1502,7 @@ static struct target_type merged_target = {
.ctr = merged_ctr,
.dtr = merged_dtr,
.map = merged_map,
+ .end_io = merged_end_io,
.resume = merged_resume,
.status = merged_status,
};
--
1.5.4.1
More information about the dm-devel
mailing list