The patch titled dm snapshot: tidy pe ref counting has been added to the -mm tree. Its filename is dm-snapshot-tidy-pe-ref-counting.patch See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find out what to do about this ------------------------------------------------------ Subject: dm snapshot: tidy pe ref counting From: Alasdair G Kergon <agk@xxxxxxxxxx> Rename sibling_count to ref_count and introduce get and put functions. Signed-off-by: Alasdair G Kergon <agk@xxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxx> --- drivers/md/dm-snap.c | 83 +++++++++++++++++++++++------------------ 1 files changed, 48 insertions(+), 35 deletions(-) diff -puN drivers/md/dm-snap.c~dm-snapshot-tidy-pe-ref-counting drivers/md/dm-snap.c --- a/drivers/md/dm-snap.c~dm-snapshot-tidy-pe-ref-counting +++ a/drivers/md/dm-snap.c @@ -59,7 +59,7 @@ struct pending_exception { /* * The primary pending_exception is the one that holds - * the sibling_count and the list of origin_bios for a + * the ref_count and the list of origin_bios for a * group of pending_exceptions. It is always last to get freed. * These fields get set up when writing to the origin. */ @@ -72,7 +72,7 @@ struct pending_exception { * the sibling concerned and not pe->primary_pe->snap->lock unless * they are the same. */ - atomic_t sibling_count; + atomic_t ref_count; /* Pointer back to snapshot context */ struct dm_snapshot *snap; @@ -653,10 +653,46 @@ static void __invalidate_snapshot(struct dm_table_event(s->table); } +static void get_pending_exception(struct pending_exception *pe) +{ + atomic_inc(&pe->ref_count); +} + +static struct bio *put_pending_exception(struct pending_exception *pe) +{ + struct pending_exception *primary_pe; + struct bio *origin_bios = NULL; + + primary_pe = pe->primary_pe; + + /* + * If this pe is involved in a write to the origin and + * it is the last sibling to complete then release + * the bios for the original write to the origin. + */ + if (primary_pe && + atomic_dec_and_test(&primary_pe->ref_count)) + origin_bios = bio_list_get(&primary_pe->origin_bios); + + /* + * Free the pe if it's not linked to an origin write or if + * it's not itself a primary pe. + */ + if (!primary_pe || primary_pe != pe) + free_pending_exception(pe); + + /* + * Free the primary pe if nothing references it. + */ + if (primary_pe && !atomic_read(&primary_pe->ref_count)) + free_pending_exception(primary_pe); + + return origin_bios; +} + static void pending_complete(struct pending_exception *pe, int success) { struct exception *e; - struct pending_exception *primary_pe; struct dm_snapshot *s = pe->snap; struct bio *origin_bios = NULL; struct bio *snapshot_bios = NULL; @@ -695,30 +731,7 @@ static void pending_complete(struct pend out: snapshot_bios = bio_list_get(&pe->snapshot_bios); - - primary_pe = pe->primary_pe; - - /* - * If this pe is involved in a write to the origin and - * it is the last sibling to complete then release - * the bios for the original write to the origin. - */ - if (primary_pe && - atomic_dec_and_test(&primary_pe->sibling_count)) - origin_bios = bio_list_get(&primary_pe->origin_bios); - - /* - * Free the pe if it's not linked to an origin write or if - * it's not itself a primary pe. - */ - if (!primary_pe || primary_pe != pe) - free_pending_exception(pe); - - /* - * Free the primary pe if nothing references it. - */ - if (primary_pe && !atomic_read(&primary_pe->sibling_count)) - free_pending_exception(primary_pe); + origin_bios = put_pending_exception(pe); up_write(&s->lock); @@ -829,7 +842,7 @@ __find_pending_exception(struct dm_snaps bio_list_init(&pe->origin_bios); bio_list_init(&pe->snapshot_bios); pe->primary_pe = NULL; - atomic_set(&pe->sibling_count, 1); + atomic_set(&pe->ref_count, 0); pe->snap = s; pe->started = 0; @@ -838,6 +851,7 @@ __find_pending_exception(struct dm_snaps return NULL; } + get_pending_exception(pe); insert_exception(&s->pending, &pe->e); out: @@ -1012,7 +1026,7 @@ static int __origin_write(struct list_he * is already remapped in this snapshot * and trigger an exception if not. * - * sibling_count is initialised to 1 so pending_complete() + * ref_count is initialised to 1 so pending_complete() * won't destroy the primary_pe while we're inside this loop. */ e = lookup_exception(&snap->complete, chunk); @@ -1043,8 +1057,8 @@ static int __origin_write(struct list_he } if (!pe->primary_pe) { - atomic_inc(&primary_pe->sibling_count); pe->primary_pe = primary_pe; + get_pending_exception(primary_pe); } if (!pe->started) { @@ -1057,20 +1071,20 @@ static int __origin_write(struct list_he } if (!primary_pe) - goto out; + return r; /* * If this is the first time we're processing this chunk and - * sibling_count is now 1 it means all the pending exceptions + * ref_count is now 1 it means all the pending exceptions * got completed while we were in the loop above, so it falls to * us here to remove the primary_pe and submit any origin_bios. */ - if (first && atomic_dec_and_test(&primary_pe->sibling_count)) { + if (first && atomic_dec_and_test(&primary_pe->ref_count)) { flush_bios(bio_list_get(&primary_pe->origin_bios)); free_pending_exception(primary_pe); /* If we got here, pe_queue is necessarily empty. */ - goto out; + return r; } /* @@ -1079,7 +1093,6 @@ static int __origin_write(struct list_he list_for_each_entry_safe(pe, next_pe, &pe_queue, list) start_copy(pe); - out: return r; } _ Patches currently in -mm which might be from agk@xxxxxxxxxx are dm-support-ioctls-on-mapped-devices.patch dm-linear-support-ioctls.patch dm-mpath-support-ioctls.patch dm-export-blkdev_driver_ioctl.patch dm-support-ioctls-on-mapped-devices-fix-with-fake-file.patch dm-fix-alloc_dev-error-path.patch dm-snapshot-fix-invalidation-enomem.patch dm-snapshot-allow-zero-chunk_size.patch dm-snapshot-fix-metadata-error-handling.patch dm-snapshot-make-read-and-write-exception-functions-void.patch dm-snapshot-fix-metadata-writing-when-suspending.patch dm-snapshot-tidy-snapshot_map.patch dm-snapshot-tidy-pending_complete.patch dm-snapshot-add-workqueue.patch dm-snapshot-tidy-pe-ref-counting.patch dm-snapshot-fix-freeing-pending-exception.patch dm-mirror-remove-trailing-space-from-table.patch dm-mpath-tidy-ctr.patch dm-mpath-use-kzalloc.patch dm-add-uevent-change-event-on-resume.patch dm-add-debug-macro.patch dm-table-add-target-preresume.patch dm-crypt-add-key-msg.patch dm-crypt-restructure-for-workqueue-change.patch dm-crypt-restructure-write-processing.patch dm-crypt-move-io-to-workqueue.patch dm-crypt-use-private-biosets.patch dm-use-private-biosets.patch dm-extract-device-limit-setting.patch dm-table-add-target-flush.patch md-dm-reduce-stack-usage-with-stacked-block-devices.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html