Index: linux-2.6/drivers/md/dm-snap.c =================================================================== --- linux-2.6.orig/drivers/md/dm-snap.c +++ linux-2.6/drivers/md/dm-snap.c @@ -92,6 +92,17 @@ struct dm_snapshot { struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE]; }; +struct dm_snapshare { + struct dm_snapshot *snap; + + struct list_head shared_list; + + atomic_t pending_exceptions_count; + + /* The on disk metadata handler */ + struct dm_exception_store *store; +}; + static struct workqueue_struct *ksnapd; static void flush_queued_bios(struct work_struct *work); @@ -530,6 +541,7 @@ static int snapshot_ctr(struct dm_target { sector_t hash_size, cow_dev_size, origin_dev_size, max_buckets; struct dm_dev *origin; + struct dm_snapshare *ss; struct dm_snapshot *s; int i; int r = -EINVAL; @@ -546,11 +558,20 @@ static int snapshot_ctr(struct dm_target argv++; argc--; + ss = kzalloc(sizeof(*ss), GFP_KERNEL); + if (!ss) { + ti->error = "Failed to allocate snapshot memory"; + return -ENOMEM; + } + INIT_LIST_HEAD(&ss->shared_list); + atomic_set(&ss->pending_exceptions_count, 0); + r = create_exception_store(ti, argc, argv, &args_used, &store); if (r) { ti->error = "Failed to create snapshot exception store"; - return r; + goto bad_exception_store; } + ss->store = store; argv += args_used; argc -= args_used; @@ -586,9 +607,9 @@ static int snapshot_ctr(struct dm_target ti->error = "Failed to create snapshot structure"; goto bad_alloc_snapshot; } - + ss->snap = s; s->origin = origin; - s->store = store; + s->store = ss->store; /* Add snapshot to the list of snapshots for this origin */ /* Exceptions aren't triggered till snapshot_resume() is called */ @@ -598,8 +619,8 @@ static int snapshot_ctr(struct dm_target goto bad_load_and_register; } - ti->private = s; - ti->split_io = s->store->chunk_size; + ti->private = ss; + ti->split_io = store->chunk_size; return 0; @@ -612,6 +633,9 @@ bad_alloc_snapshot: bad_origin: dm_exception_store_destroy(store); +bad_exception_store: + kfree(ss); + return r; } @@ -620,7 +644,8 @@ static void snapshot_dtr(struct dm_targe #ifdef CONFIG_DM_DEBUG int i; #endif - struct dm_snapshot *s = ti->private; + struct dm_snapshare *ss = ti->private; + struct dm_snapshot *s = ss->snap; flush_workqueue(ksnapd); @@ -643,9 +668,11 @@ static void snapshot_dtr(struct dm_targe dm_put_device(ti, s->origin); - dm_exception_store_destroy(s->store); - dealloc_snapshot(s); + + dm_exception_store_destroy(ss->store); + + kfree(ss); } /* @@ -843,7 +870,8 @@ static void start_copy(struct dm_snap_pe * this. */ static struct dm_snap_pending_exception * -__find_pending_exception(struct dm_snapshot *s, struct bio *bio, int group) +__find_pending_exception(struct dm_snapshot *s, struct bio *bio, + struct dm_snapshare *ss) { struct dm_exception *e, *tmp_e; struct dm_snap_pending_exception *pe; @@ -887,7 +915,7 @@ __find_pending_exception(struct dm_snaps atomic_set(&pe->ref_count, 0); pe->started = 0; - if (s->store->type->prepare_exception(s->store, &pe->e, group)) { + if (s->store->type->prepare_exception(s->store, &pe->e, ss ? 0 : 1)) { dm_free_exception(s->pending, &pe->e); return NULL; } @@ -909,12 +937,13 @@ static void remap_exception(struct dm_sn static int snapshot_map(struct dm_target *ti, struct bio *bio, union map_info *map_context) { - struct dm_snapshot *s = ti->private; + struct dm_snapshare *ss = ti->private; + struct dm_snapshot *s = ss->snap; int rtn, r = DM_MAPIO_REMAPPED; chunk_t chunk, new_chunk; struct dm_snap_pending_exception *pe = NULL; - chunk = sector_to_chunk(s->store, bio->bi_sector); + chunk = sector_to_chunk(ss->store, bio->bi_sector); /* Full snapshots are not usable */ /* To get here the table must be live so s->active is always set. */ @@ -931,7 +960,7 @@ static int snapshot_map(struct dm_target } /* If the block is already remapped - use that, else remap it */ - rtn = s->store->type->lookup_exception(s->store, chunk, &new_chunk, 0); + rtn = ss->store->type->lookup_exception(ss->store, chunk, &new_chunk, 0); if (!rtn) { remap_exception(s, bio, new_chunk); goto out_unlock; @@ -950,7 +979,7 @@ static int snapshot_map(struct dm_target * writeable. */ if (bio_rw(bio) == WRITE) { - pe = __find_pending_exception(s, bio, 0); + pe = __find_pending_exception(s, bio, ss); if (!pe) { __invalidate_snapshot(s, -ENOMEM); r = -EIO; @@ -983,7 +1012,8 @@ out: static int snapshot_end_io(struct dm_target *ti, struct bio *bio, int error, union map_info *map_context) { - struct dm_snapshot *s = ti->private; + struct dm_snapshare *ss = ti->private; + struct dm_snapshot *s = ss->snap; struct dm_snap_tracked_chunk *c = map_context->ptr; if (c) @@ -995,7 +1025,8 @@ static int snapshot_end_io(struct dm_tar static void snapshot_resume(struct dm_target *ti) { int r; - struct dm_snapshot *s = ti->private; + struct dm_snapshare *ss = ti->private; + struct dm_snapshot *s = ss->snap; /* * Target resumes cannot fail, which leaves us in a tight spot. @@ -1004,47 +1035,48 @@ static void snapshot_resume(struct dm_ta * If invalid, mark the snapshot as such. However, if other, * what can we do? Mark 'not active'? */ - r = s->store->type->resume(s->store); - if (r == -EINVAL) - r = s->valid = 0; - + r = ss->store->type->resume(ss->store); down_write(&s->lock); - s->active = (r) ? 0 : 1; + if (r == -EINVAL) + s->valid = 0; + else + s->active = (r) ? 0 : 1; up_write(&s->lock); } static void snapshot_presuspend(struct dm_target *ti) { - struct dm_snapshot *s = ti->private; + struct dm_snapshare *ss = ti->private; - if(s->store->type->presuspend) - s->store->type->presuspend(s->store); + if(ss->store->type->presuspend) + ss->store->type->presuspend(ss->store); } static void snapshot_postsuspend(struct dm_target *ti) { - struct dm_snapshot *s = ti->private; + struct dm_snapshare *ss = ti->private; - if (s->store->type->postsuspend) - s->store->type->postsuspend(s->store); + if (ss->store->type->postsuspend) + ss->store->type->postsuspend(ss->store); } static int snapshot_status(struct dm_target *ti, status_type_t type, char *result, unsigned int maxlen) { unsigned int sz = 0; - struct dm_snapshot *snap = ti->private; + struct dm_snapshare *ss = ti->private; + struct dm_snapshot *s = ss->snap; switch (type) { case STATUSTYPE_INFO: - if (!snap->valid) + if (!s->valid) DMEMIT("Invalid"); else { - if (snap->store->type->fraction_full) { + if (ss->store->type->fraction_full) { sector_t numerator, denominator; - snap->store->type->fraction_full(snap->store, - &numerator, - &denominator); + ss->store->type->fraction_full(ss->store, + &numerator, + &denominator); DMEMIT("%llu/%llu", (unsigned long long)numerator, (unsigned long long)denominator); @@ -1060,9 +1092,9 @@ static int snapshot_status(struct dm_tar * to make private copies if the output is to * make sense. */ - DMEMIT("%s ", snap->origin->name); - snap->store->type->status(snap->store, type, - result+sz, maxlen-sz); + DMEMIT("%s ", s->origin->name); + ss->store->type->status(ss->store, type, + result+sz, maxlen-sz); break; } @@ -1072,10 +1104,10 @@ static int snapshot_status(struct dm_tar static int snapshot_message(struct dm_target *ti, unsigned argc, char **argv) { int r = 0; - struct dm_snapshot *s = ti->private; + struct dm_snapshare *ss = ti->private; - if (s->store->type->message) - r = s->store->type->message(s->store, argc, argv); + if (ss->store->type->message) + r = ss->store->type->message(ss->store, argc, argv); return r; } @@ -1130,7 +1162,7 @@ static int __origin_write(struct list_he */ BUG_ON(rtn != -ENOENT); - pe = __find_pending_exception(snap, bio, 1); + pe = __find_pending_exception(snap, bio, NULL); if (!pe) { __invalidate_snapshot(snap, -ENOMEM); goto next_snapshot; -- dm-devel mailing list dm-devel@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/dm-devel