aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-snap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-snap.c')
-rw-r--r--drivers/md/dm-snap.c239
1 files changed, 233 insertions, 6 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 7ddee7c0c518..dc2412e6c5cf 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -106,8 +106,20 @@ struct dm_snapshot {
106 mempool_t *tracked_chunk_pool; 106 mempool_t *tracked_chunk_pool;
107 spinlock_t tracked_chunk_lock; 107 spinlock_t tracked_chunk_lock;
108 struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE]; 108 struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE];
109
110 /* Wait for events based on state_bits */
111 unsigned long state_bits;
109}; 112};
110 113
114/*
115 * state_bits:
116 * RUNNING_MERGE - Merge operation is in progress.
117 * SHUTDOWN_MERGE - Set to signal that merge needs to be stopped;
118 * cleared afterwards.
119 */
120#define RUNNING_MERGE 0
121#define SHUTDOWN_MERGE 1
122
111struct dm_dev *dm_snap_cow(struct dm_snapshot *s) 123struct dm_dev *dm_snap_cow(struct dm_snapshot *s)
112{ 124{
113 return s->cow; 125 return s->cow;
@@ -386,6 +398,13 @@ static int __validate_exception_handover(struct dm_snapshot *snap)
386 return -EINVAL; 398 return -EINVAL;
387 } 399 }
388 400
401 if (!snap_src->store->type->prepare_merge ||
402 !snap_src->store->type->commit_merge) {
403 snap->ti->error = "Snapshot exception store does not "
404 "support snapshot-merge.";
405 return -EINVAL;
406 }
407
389 return 1; 408 return 1;
390} 409}
391 410
@@ -721,6 +740,178 @@ static int init_hash_tables(struct dm_snapshot *s)
721 return 0; 740 return 0;
722} 741}
723 742
743static void merge_shutdown(struct dm_snapshot *s)
744{
745 clear_bit_unlock(RUNNING_MERGE, &s->state_bits);
746 smp_mb__after_clear_bit();
747 wake_up_bit(&s->state_bits, RUNNING_MERGE);
748}
749
750/*
751 * Remove one chunk from the index of completed exceptions.
752 */
753static int __remove_single_exception_chunk(struct dm_snapshot *s,
754 chunk_t old_chunk)
755{
756 struct dm_exception *e;
757
758 /* FIXME: interlock writes to this chunk */
759
760 e = dm_lookup_exception(&s->complete, old_chunk);
761 if (!e) {
762 DMERR("Corruption detected: exception for block %llu is "
763 "on disk but not in memory",
764 (unsigned long long)old_chunk);
765 return -EINVAL;
766 }
767
768 /*
769 * If this is the only chunk using this exception, remove exception.
770 */
771 if (!dm_consecutive_chunk_count(e)) {
772 dm_remove_exception(e);
773 free_completed_exception(e);
774 return 0;
775 }
776
777 /*
778 * The chunk may be either at the beginning or the end of a
779 * group of consecutive chunks - never in the middle. We are
780 * removing chunks in the opposite order to that in which they
781 * were added, so this should always be true.
782 * Decrement the consecutive chunk counter and adjust the
783 * starting point if necessary.
784 */
785 if (old_chunk == e->old_chunk) {
786 e->old_chunk++;
787 e->new_chunk++;
788 } else if (old_chunk != e->old_chunk +
789 dm_consecutive_chunk_count(e)) {
790 DMERR("Attempt to merge block %llu from the "
791 "middle of a chunk range [%llu - %llu]",
792 (unsigned long long)old_chunk,
793 (unsigned long long)e->old_chunk,
794 (unsigned long long)
795 e->old_chunk + dm_consecutive_chunk_count(e));
796 return -EINVAL;
797 }
798
799 dm_consecutive_chunk_count_dec(e);
800
801 return 0;
802}
803
804static int remove_single_exception_chunk(struct dm_snapshot *s,
805 chunk_t old_chunk)
806{
807 int r = 0;
808
809 down_write(&s->lock);
810 r = __remove_single_exception_chunk(s, old_chunk);
811 up_write(&s->lock);
812
813 return r;
814}
815
816static void merge_callback(int read_err, unsigned long write_err,
817 void *context);
818
819static void snapshot_merge_next_chunks(struct dm_snapshot *s)
820{
821 int r;
822 chunk_t old_chunk, new_chunk;
823 struct dm_io_region src, dest;
824
825 BUG_ON(!test_bit(RUNNING_MERGE, &s->state_bits));
826 if (unlikely(test_bit(SHUTDOWN_MERGE, &s->state_bits)))
827 goto shut;
828
829 /*
830 * valid flag never changes during merge, so no lock required.
831 */
832 if (!s->valid) {
833 DMERR("Snapshot is invalid: can't merge");
834 goto shut;
835 }
836
837 r = s->store->type->prepare_merge(s->store, &old_chunk, &new_chunk);
838 if (r <= 0) {
839 if (r < 0)
840 DMERR("Read error in exception store: "
841 "shutting down merge");
842 goto shut;
843 }
844
845 /* TODO: use larger I/O size once we verify that kcopyd handles it */
846
847 if (remove_single_exception_chunk(s, old_chunk) < 0)
848 goto shut;
849
850 dest.bdev = s->origin->bdev;
851 dest.sector = chunk_to_sector(s->store, old_chunk);
852 dest.count = min((sector_t)s->store->chunk_size,
853 get_dev_size(dest.bdev) - dest.sector);
854
855 src.bdev = s->cow->bdev;
856 src.sector = chunk_to_sector(s->store, new_chunk);
857 src.count = dest.count;
858
859 dm_kcopyd_copy(s->kcopyd_client, &src, 1, &dest, 0, merge_callback, s);
860 return;
861
862shut:
863 merge_shutdown(s);
864}
865
866static void merge_callback(int read_err, unsigned long write_err, void *context)
867{
868 struct dm_snapshot *s = context;
869
870 if (read_err || write_err) {
871 if (read_err)
872 DMERR("Read error: shutting down merge.");
873 else
874 DMERR("Write error: shutting down merge.");
875 goto shut;
876 }
877
878 if (s->store->type->commit_merge(s->store, 1) < 0) {
879 DMERR("Write error in exception store: shutting down merge");
880 goto shut;
881 }
882
883 snapshot_merge_next_chunks(s);
884
885 return;
886
887shut:
888 merge_shutdown(s);
889}
890
891static void start_merge(struct dm_snapshot *s)
892{
893 if (!test_and_set_bit(RUNNING_MERGE, &s->state_bits))
894 snapshot_merge_next_chunks(s);
895}
896
897static int wait_schedule(void *ptr)
898{
899 schedule();
900
901 return 0;
902}
903
904/*
905 * Stop the merging process and wait until it finishes.
906 */
907static void stop_merge(struct dm_snapshot *s)
908{
909 set_bit(SHUTDOWN_MERGE, &s->state_bits);
910 wait_on_bit(&s->state_bits, RUNNING_MERGE, wait_schedule,
911 TASK_UNINTERRUPTIBLE);
912 clear_bit(SHUTDOWN_MERGE, &s->state_bits);
913}
914
724/* 915/*
725 * Construct a snapshot mapping: <origin_dev> <COW-dev> <p/n> <chunk-size> 916 * Construct a snapshot mapping: <origin_dev> <COW-dev> <p/n> <chunk-size>
726 */ 917 */
@@ -791,6 +982,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
791 init_rwsem(&s->lock); 982 init_rwsem(&s->lock);
792 INIT_LIST_HEAD(&s->list); 983 INIT_LIST_HEAD(&s->list);
793 spin_lock_init(&s->pe_lock); 984 spin_lock_init(&s->pe_lock);
985 s->state_bits = 0;
794 986
795 /* Allocate hash table for COW data */ 987 /* Allocate hash table for COW data */
796 if (init_hash_tables(s)) { 988 if (init_hash_tables(s)) {
@@ -963,6 +1155,9 @@ static void snapshot_dtr(struct dm_target *ti)
963 } 1155 }
964 up_read(&_origins_lock); 1156 up_read(&_origins_lock);
965 1157
1158 if (dm_target_is_snapshot_merge(ti))
1159 stop_merge(s);
1160
966 /* Prevent further origin writes from using this snapshot. */ 1161 /* Prevent further origin writes from using this snapshot. */
967 /* After this returns there can be no new kcopyd jobs. */ 1162 /* After this returns there can be no new kcopyd jobs. */
968 unregister_snapshot(s); 1163 unregister_snapshot(s);
@@ -1404,6 +1599,13 @@ static int snapshot_end_io(struct dm_target *ti, struct bio *bio,
1404 return 0; 1599 return 0;
1405} 1600}
1406 1601
1602static void snapshot_merge_presuspend(struct dm_target *ti)
1603{
1604 struct dm_snapshot *s = ti->private;
1605
1606 stop_merge(s);
1607}
1608
1407static void snapshot_postsuspend(struct dm_target *ti) 1609static void snapshot_postsuspend(struct dm_target *ti)
1408{ 1610{
1409 struct dm_snapshot *s = ti->private; 1611 struct dm_snapshot *s = ti->private;
@@ -1464,6 +1666,34 @@ static void snapshot_resume(struct dm_target *ti)
1464 up_write(&s->lock); 1666 up_write(&s->lock);
1465} 1667}
1466 1668
1669static sector_t get_origin_minimum_chunksize(struct block_device *bdev)
1670{
1671 sector_t min_chunksize;
1672
1673 down_read(&_origins_lock);
1674 min_chunksize = __minimum_chunk_size(__lookup_origin(bdev));
1675 up_read(&_origins_lock);
1676
1677 return min_chunksize;
1678}
1679
1680static void snapshot_merge_resume(struct dm_target *ti)
1681{
1682 struct dm_snapshot *s = ti->private;
1683
1684 /*
1685 * Handover exceptions from existing snapshot.
1686 */
1687 snapshot_resume(ti);
1688
1689 /*
1690 * snapshot-merge acts as an origin, so set ti->split_io
1691 */
1692 ti->split_io = get_origin_minimum_chunksize(s->origin->bdev);
1693
1694 start_merge(s);
1695}
1696
1467static int snapshot_status(struct dm_target *ti, status_type_t type, 1697static int snapshot_status(struct dm_target *ti, status_type_t type,
1468 char *result, unsigned int maxlen) 1698 char *result, unsigned int maxlen)
1469{ 1699{
@@ -1722,11 +1952,7 @@ static void origin_resume(struct dm_target *ti)
1722{ 1952{
1723 struct dm_dev *dev = ti->private; 1953 struct dm_dev *dev = ti->private;
1724 1954
1725 down_read(&_origins_lock); 1955 ti->split_io = get_origin_minimum_chunksize(dev->bdev);
1726
1727 ti->split_io = __minimum_chunk_size(__lookup_origin(dev->bdev));
1728
1729 up_read(&_origins_lock);
1730} 1956}
1731 1957
1732static int origin_status(struct dm_target *ti, status_type_t type, char *result, 1958static int origin_status(struct dm_target *ti, status_type_t type, char *result,
@@ -1790,9 +2016,10 @@ static struct target_type merge_target = {
1790 .dtr = snapshot_dtr, 2016 .dtr = snapshot_dtr,
1791 .map = snapshot_merge_map, 2017 .map = snapshot_merge_map,
1792 .end_io = snapshot_end_io, 2018 .end_io = snapshot_end_io,
2019 .presuspend = snapshot_merge_presuspend,
1793 .postsuspend = snapshot_postsuspend, 2020 .postsuspend = snapshot_postsuspend,
1794 .preresume = snapshot_preresume, 2021 .preresume = snapshot_preresume,
1795 .resume = snapshot_resume, 2022 .resume = snapshot_merge_resume,
1796 .status = snapshot_status, 2023 .status = snapshot_status,
1797 .iterate_devices = snapshot_iterate_devices, 2024 .iterate_devices = snapshot_iterate_devices,
1798}; 2025};