aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeinz Mauelshagen <heinzm@redhat.com>2016-05-19 12:49:27 -0400
committerMike Snitzer <snitzer@redhat.com>2016-06-13 14:40:27 -0400
commitf090279eaff814a550b35bb51aac6b8541bddf97 (patch)
tree63013e80c7294f09668d0d91fa0a714db23a7090
parent702108d194e3649f69afcd2661282a0157c71e54 (diff)
dm raid: check constructor arguments for invalid raid level/argument combinations
Reject invalid flag combinations to avoid potential data corruption or failing raid set construction: - add definitions for constructor flag combinations and invalid flags per level - add bool test functions for the various raid types (also will be used by future reshaping enhancements) - introduce rs_check_for_invalid_flags() and _invalid_flags() to perform the validity checks Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
-rw-r--r--drivers/md/dm-raid.c131
1 files changed, 130 insertions, 1 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index ab7aa7d83364..ebb64eb66def 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -64,6 +64,61 @@ struct raid_dev {
64#define CTR_FLAG_RAID10_COPIES 0x400 /* 2 */ /* Only with raid10 */ 64#define CTR_FLAG_RAID10_COPIES 0x400 /* 2 */ /* Only with raid10 */
65#define CTR_FLAG_RAID10_FORMAT 0x800 /* 2 */ /* Only with raid10 */ 65#define CTR_FLAG_RAID10_FORMAT 0x800 /* 2 */ /* Only with raid10 */
66 66
67/*
68 * Definitions of various constructor flags to
69 * be used in checks of valid / invalid flags
70 * per raid level.
71 */
72/* Define all any sync flags */
73#define CTR_FLAGS_ANY_SYNC (CTR_FLAG_SYNC | CTR_FLAG_NOSYNC)
74
75/* Define flags for options without argument (e.g. 'nosync') */
76#define CTR_FLAG_OPTIONS_NO_ARGS CTR_FLAGS_ANY_SYNC
77
78/* Define flags for options with one argument (e.g. 'delta_disks +2') */
79#define CTR_FLAG_OPTIONS_ONE_ARG (CTR_FLAG_REBUILD | \
80 CTR_FLAG_WRITE_MOSTLY | \
81 CTR_FLAG_DAEMON_SLEEP | \
82 CTR_FLAG_MIN_RECOVERY_RATE | \
83 CTR_FLAG_MAX_RECOVERY_RATE | \
84 CTR_FLAG_MAX_WRITE_BEHIND | \
85 CTR_FLAG_STRIPE_CACHE | \
86 CTR_FLAG_REGION_SIZE | \
87 CTR_FLAG_RAID10_COPIES | \
88 CTR_FLAG_RAID10_FORMAT)
89
90/* All ctr optional arguments */
91#define ALL_CTR_FLAGS (CTR_FLAG_OPTIONS_NO_ARGS | \
92 CTR_FLAG_OPTIONS_ONE_ARG)
93
94/* Invalid options definitions per raid level... */
95
96/* "raid0" does not accept any options */
97#define RAID0_INVALID_FLAGS ALL_CTR_FLAGS
98
99/* "raid1" does not accept stripe cache or any raid10 options */
100#define RAID1_INVALID_FLAGS (CTR_FLAG_STRIPE_CACHE | \
101 CTR_FLAG_RAID10_COPIES | \
102 CTR_FLAG_RAID10_FORMAT)
103
104/* "raid10" does not accept any raid1 or stripe cache options */
105#define RAID10_INVALID_FLAGS (CTR_FLAG_WRITE_MOSTLY | \
106 CTR_FLAG_MAX_WRITE_BEHIND | \
107 CTR_FLAG_STRIPE_CACHE)
108/*
109 * "raid4/5/6" do not accept any raid1 or raid10 specific options
110 *
111 * "raid6" does not accept "nosync", because it is not guaranteed
112 * that both parity and q-syndrome are being written properly with
113 * any writes
114 */
115#define RAID45_INVALID_FLAGS (CTR_FLAG_WRITE_MOSTLY | \
116 CTR_FLAG_MAX_WRITE_BEHIND | \
117 CTR_FLAG_RAID10_FORMAT | \
118 CTR_FLAG_RAID10_COPIES)
119#define RAID6_INVALID_FLAGS (CTR_FLAG_NOSYNC | RAID45_INVALID_FLAGS)
120/* ...invalid options definitions per raid level */
121
67struct raid_set { 122struct raid_set {
68 struct dm_target *ti; 123 struct dm_target *ti;
69 124
@@ -167,6 +222,41 @@ static const char *_argname_by_flag(const uint32_t flag)
167} 222}
168 223
169/* 224/*
225 * bool helpers to test for various raid levels of a raid type
226 */
227
228/* Return true, if raid type in @rt is raid0 */
229static bool rt_is_raid0(struct raid_type *rt)
230{
231 return !rt->level;
232}
233
234/* Return true, if raid type in @rt is raid1 */
235static bool rt_is_raid1(struct raid_type *rt)
236{
237 return rt->level == 1;
238}
239
240/* Return true, if raid type in @rt is raid10 */
241static bool rt_is_raid10(struct raid_type *rt)
242{
243 return rt->level == 10;
244}
245
246/* Return true, if raid type in @rt is raid4/5 */
247static bool rt_is_raid45(struct raid_type *rt)
248{
249 return _in_range(rt->level, 4, 5);
250}
251
252/* Return true, if raid type in @rt is raid6 */
253static bool rt_is_raid6(struct raid_type *rt)
254{
255 return rt->level == 6;
256}
257/* END: raid level bools */
258
259/*
170 * Convenience functions to set ti->error to @errmsg and 260 * Convenience functions to set ti->error to @errmsg and
171 * return @r in order to shorten code in a lot of places 261 * return @r in order to shorten code in a lot of places
172 */ 262 */
@@ -182,6 +272,44 @@ static int ti_error_einval(struct dm_target *ti, const char *errmsg)
182} 272}
183/* END: convenience functions to set ti->error to @errmsg... */ 273/* END: convenience functions to set ti->error to @errmsg... */
184 274
275/* Return invalid ctr flags for the raid level of @rs */
276static uint32_t _invalid_flags(struct raid_set *rs)
277{
278 if (rt_is_raid0(rs->raid_type))
279 return RAID0_INVALID_FLAGS;
280 else if (rt_is_raid1(rs->raid_type))
281 return RAID1_INVALID_FLAGS;
282 else if (rt_is_raid10(rs->raid_type))
283 return RAID10_INVALID_FLAGS;
284 else if (rt_is_raid45(rs->raid_type))
285 return RAID45_INVALID_FLAGS;
286 else if (rt_is_raid6(rs->raid_type))
287 return RAID6_INVALID_FLAGS;
288
289 return ~0;
290}
291
292/*
293 * Check for any invalid flags set on @rs defined by bitset @invalid_flags
294 *
295 * Has to be called after parsing of the ctr flags!
296 */
297static int rs_check_for_invalid_flags(struct raid_set *rs)
298{
299 unsigned int ctr_flags = rs->ctr_flags, flag = 0;
300 const uint32_t invalid_flags = _invalid_flags(rs);
301
302 while ((ctr_flags &= ~flag)) {
303 flag = 1 << __ffs(ctr_flags);
304
305 if (_test_flag(flag, rs->ctr_flags) &&
306 _test_flag(flag, invalid_flags))
307 return ti_error_einval(rs->ti, "Invalid flag combined");
308 }
309
310 return 0;
311}
312
185static char *raid10_md_layout_to_format(int layout) 313static char *raid10_md_layout_to_format(int layout)
186{ 314{
187 /* 315 /*
@@ -806,7 +934,8 @@ static int parse_raid_params(struct raid_set *rs, struct dm_arg_set *as,
806 rs->md.persistent = 0; 934 rs->md.persistent = 0;
807 rs->md.external = 1; 935 rs->md.external = 1;
808 936
809 return 0; 937 /* Check, if any invalid ctr arguments have been passed in for the raid level */
938 return rs_check_for_invalid_flags(rs);
810} 939}
811 940
812static void do_table_event(struct work_struct *ws) 941static void do_table_event(struct work_struct *ws)