diff options
Diffstat (limited to 'drivers/md/dm-snap-persistent.c')
-rw-r--r-- | drivers/md/dm-snap-persistent.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index bf71583296f7..117a05e40090 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c | |||
@@ -7,6 +7,7 @@ | |||
7 | 7 | ||
8 | #include "dm-exception-store.h" | 8 | #include "dm-exception-store.h" |
9 | 9 | ||
10 | #include <linux/ctype.h> | ||
10 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
11 | #include <linux/pagemap.h> | 12 | #include <linux/pagemap.h> |
12 | #include <linux/vmalloc.h> | 13 | #include <linux/vmalloc.h> |
@@ -843,10 +844,10 @@ static void persistent_drop_snapshot(struct dm_exception_store *store) | |||
843 | DMWARN("write header failed"); | 844 | DMWARN("write header failed"); |
844 | } | 845 | } |
845 | 846 | ||
846 | static int persistent_ctr(struct dm_exception_store *store, | 847 | static int persistent_ctr(struct dm_exception_store *store, char *options) |
847 | unsigned argc, char **argv) | ||
848 | { | 848 | { |
849 | struct pstore *ps; | 849 | struct pstore *ps; |
850 | int r; | ||
850 | 851 | ||
851 | /* allocate the pstore */ | 852 | /* allocate the pstore */ |
852 | ps = kzalloc(sizeof(*ps), GFP_KERNEL); | 853 | ps = kzalloc(sizeof(*ps), GFP_KERNEL); |
@@ -868,14 +869,32 @@ static int persistent_ctr(struct dm_exception_store *store, | |||
868 | 869 | ||
869 | ps->metadata_wq = alloc_workqueue("ksnaphd", WQ_MEM_RECLAIM, 0); | 870 | ps->metadata_wq = alloc_workqueue("ksnaphd", WQ_MEM_RECLAIM, 0); |
870 | if (!ps->metadata_wq) { | 871 | if (!ps->metadata_wq) { |
871 | kfree(ps); | ||
872 | DMERR("couldn't start header metadata update thread"); | 872 | DMERR("couldn't start header metadata update thread"); |
873 | return -ENOMEM; | 873 | r = -ENOMEM; |
874 | goto err_workqueue; | ||
875 | } | ||
876 | |||
877 | if (options) { | ||
878 | char overflow = toupper(options[0]); | ||
879 | if (overflow == 'O') | ||
880 | store->userspace_supports_overflow = true; | ||
881 | else { | ||
882 | DMERR("Unsupported persistent store option: %s", options); | ||
883 | r = -EINVAL; | ||
884 | goto err_options; | ||
885 | } | ||
874 | } | 886 | } |
875 | 887 | ||
876 | store->context = ps; | 888 | store->context = ps; |
877 | 889 | ||
878 | return 0; | 890 | return 0; |
891 | |||
892 | err_options: | ||
893 | destroy_workqueue(ps->metadata_wq); | ||
894 | err_workqueue: | ||
895 | kfree(ps); | ||
896 | |||
897 | return r; | ||
879 | } | 898 | } |
880 | 899 | ||
881 | static unsigned persistent_status(struct dm_exception_store *store, | 900 | static unsigned persistent_status(struct dm_exception_store *store, |
@@ -888,7 +907,8 @@ static unsigned persistent_status(struct dm_exception_store *store, | |||
888 | case STATUSTYPE_INFO: | 907 | case STATUSTYPE_INFO: |
889 | break; | 908 | break; |
890 | case STATUSTYPE_TABLE: | 909 | case STATUSTYPE_TABLE: |
891 | DMEMIT(" P %llu", (unsigned long long)store->chunk_size); | 910 | DMEMIT(" %s %llu", store->userspace_supports_overflow ? "PO" : "P", |
911 | (unsigned long long)store->chunk_size); | ||
892 | } | 912 | } |
893 | 913 | ||
894 | return sz; | 914 | return sz; |