aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-10-05 18:17:40 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-10-05 18:17:40 -0400
commit076264ada9a307300be7a4581165f9c9deed5d1b (patch)
treedca4d0067d40018d1daa9e069f0a1119e47bd049
parent0f380715e51f5ff418cfccb4cd0d4fe4c48c3241 (diff)
parent41dcf197ad5373a7dd0a4b6572aec2e3ec6a0e49 (diff)
Merge tag 'for-4.14/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper fixes from Mike Snitzer: - a stable fix for the alignment of the event number reported at the end of the 'DM_LIST_DEVICES' ioctl. - a couple stable fixes for the DM crypt target. - a DM raid health status reporting fix. * tag 'for-4.14/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm: dm raid: fix incorrect status output at the end of a "recover" process dm crypt: reject sector_size feature if device length is not aligned to it dm crypt: fix memory leak in crypt_ctr_cipher_old() dm ioctl: fix alignment of event number in the device list
-rw-r--r--Documentation/device-mapper/dm-raid.txt1
-rw-r--r--drivers/md/dm-core.h1
-rw-r--r--drivers/md/dm-crypt.c5
-rw-r--r--drivers/md/dm-ioctl.c37
-rw-r--r--drivers/md/dm-raid.c11
-rw-r--r--drivers/md/dm.c10
-rw-r--r--include/uapi/linux/dm-ioctl.h4
7 files changed, 47 insertions, 22 deletions
diff --git a/Documentation/device-mapper/dm-raid.txt b/Documentation/device-mapper/dm-raid.txt
index 4a0a7469fdd7..32df07e29f68 100644
--- a/Documentation/device-mapper/dm-raid.txt
+++ b/Documentation/device-mapper/dm-raid.txt
@@ -344,3 +344,4 @@ Version History
344 (wrong raid10_copies/raid10_format sequence) 344 (wrong raid10_copies/raid10_format sequence)
3451.11.1 Add raid4/5/6 journal write-back support via journal_mode option 3451.11.1 Add raid4/5/6 journal write-back support via journal_mode option
3461.12.1 fix for MD deadlock between mddev_suspend() and md_write_start() available 3461.12.1 fix for MD deadlock between mddev_suspend() and md_write_start() available
3471.13.0 Fix dev_health status at end of "recover" (was 'a', now 'A')
diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h
index 24eddbdf2ab4..203144762f36 100644
--- a/drivers/md/dm-core.h
+++ b/drivers/md/dm-core.h
@@ -149,5 +149,6 @@ static inline bool dm_message_test_buffer_overflow(char *result, unsigned maxlen
149 149
150extern atomic_t dm_global_event_nr; 150extern atomic_t dm_global_event_nr;
151extern wait_queue_head_t dm_global_eventq; 151extern wait_queue_head_t dm_global_eventq;
152void dm_issue_global_event(void);
152 153
153#endif 154#endif
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index a55ffd4f5933..96ab46512e1f 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -2466,6 +2466,7 @@ static int crypt_ctr_cipher_old(struct dm_target *ti, char *cipher_in, char *key
2466 kfree(cipher_api); 2466 kfree(cipher_api);
2467 return ret; 2467 return ret;
2468 } 2468 }
2469 kfree(cipher_api);
2469 2470
2470 return 0; 2471 return 0;
2471bad_mem: 2472bad_mem:
@@ -2584,6 +2585,10 @@ static int crypt_ctr_optional(struct dm_target *ti, unsigned int argc, char **ar
2584 ti->error = "Invalid feature value for sector_size"; 2585 ti->error = "Invalid feature value for sector_size";
2585 return -EINVAL; 2586 return -EINVAL;
2586 } 2587 }
2588 if (ti->len & ((cc->sector_size >> SECTOR_SHIFT) - 1)) {
2589 ti->error = "Device size is not multiple of sector_size feature";
2590 return -EINVAL;
2591 }
2587 cc->sector_shift = __ffs(cc->sector_size) - SECTOR_SHIFT; 2592 cc->sector_shift = __ffs(cc->sector_size) - SECTOR_SHIFT;
2588 } else if (!strcasecmp(opt_string, "iv_large_sectors")) 2593 } else if (!strcasecmp(opt_string, "iv_large_sectors"))
2589 set_bit(CRYPT_IV_LARGE_SECTORS, &cc->cipher_flags); 2594 set_bit(CRYPT_IV_LARGE_SECTORS, &cc->cipher_flags);
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 8756a6850431..e52676fa9832 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -477,9 +477,13 @@ static int remove_all(struct file *filp, struct dm_ioctl *param, size_t param_si
477 * Round up the ptr to an 8-byte boundary. 477 * Round up the ptr to an 8-byte boundary.
478 */ 478 */
479#define ALIGN_MASK 7 479#define ALIGN_MASK 7
480static inline size_t align_val(size_t val)
481{
482 return (val + ALIGN_MASK) & ~ALIGN_MASK;
483}
480static inline void *align_ptr(void *ptr) 484static inline void *align_ptr(void *ptr)
481{ 485{
482 return (void *) (((size_t) (ptr + ALIGN_MASK)) & ~ALIGN_MASK); 486 return (void *)align_val((size_t)ptr);
483} 487}
484 488
485/* 489/*
@@ -505,7 +509,7 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_
505 struct hash_cell *hc; 509 struct hash_cell *hc;
506 size_t len, needed = 0; 510 size_t len, needed = 0;
507 struct gendisk *disk; 511 struct gendisk *disk;
508 struct dm_name_list *nl, *old_nl = NULL; 512 struct dm_name_list *orig_nl, *nl, *old_nl = NULL;
509 uint32_t *event_nr; 513 uint32_t *event_nr;
510 514
511 down_write(&_hash_lock); 515 down_write(&_hash_lock);
@@ -516,17 +520,15 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_
516 */ 520 */
517 for (i = 0; i < NUM_BUCKETS; i++) { 521 for (i = 0; i < NUM_BUCKETS; i++) {
518 list_for_each_entry (hc, _name_buckets + i, name_list) { 522 list_for_each_entry (hc, _name_buckets + i, name_list) {
519 needed += sizeof(struct dm_name_list); 523 needed += align_val(offsetof(struct dm_name_list, name) + strlen(hc->name) + 1);
520 needed += strlen(hc->name) + 1; 524 needed += align_val(sizeof(uint32_t));
521 needed += ALIGN_MASK;
522 needed += (sizeof(uint32_t) + ALIGN_MASK) & ~ALIGN_MASK;
523 } 525 }
524 } 526 }
525 527
526 /* 528 /*
527 * Grab our output buffer. 529 * Grab our output buffer.
528 */ 530 */
529 nl = get_result_buffer(param, param_size, &len); 531 nl = orig_nl = get_result_buffer(param, param_size, &len);
530 if (len < needed) { 532 if (len < needed) {
531 param->flags |= DM_BUFFER_FULL_FLAG; 533 param->flags |= DM_BUFFER_FULL_FLAG;
532 goto out; 534 goto out;
@@ -549,11 +551,16 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_
549 strcpy(nl->name, hc->name); 551 strcpy(nl->name, hc->name);
550 552
551 old_nl = nl; 553 old_nl = nl;
552 event_nr = align_ptr(((void *) (nl + 1)) + strlen(hc->name) + 1); 554 event_nr = align_ptr(nl->name + strlen(hc->name) + 1);
553 *event_nr = dm_get_event_nr(hc->md); 555 *event_nr = dm_get_event_nr(hc->md);
554 nl = align_ptr(event_nr + 1); 556 nl = align_ptr(event_nr + 1);
555 } 557 }
556 } 558 }
559 /*
560 * If mismatch happens, security may be compromised due to buffer
561 * overflow, so it's better to crash.
562 */
563 BUG_ON((char *)nl - (char *)orig_nl != needed);
557 564
558 out: 565 out:
559 up_write(&_hash_lock); 566 up_write(&_hash_lock);
@@ -1621,7 +1628,8 @@ static int target_message(struct file *filp, struct dm_ioctl *param, size_t para
1621 * which has a variable size, is not used by the function processing 1628 * which has a variable size, is not used by the function processing
1622 * the ioctl. 1629 * the ioctl.
1623 */ 1630 */
1624#define IOCTL_FLAGS_NO_PARAMS 1 1631#define IOCTL_FLAGS_NO_PARAMS 1
1632#define IOCTL_FLAGS_ISSUE_GLOBAL_EVENT 2
1625 1633
1626/*----------------------------------------------------------------- 1634/*-----------------------------------------------------------------
1627 * Implementation of open/close/ioctl on the special char 1635 * Implementation of open/close/ioctl on the special char
@@ -1635,12 +1643,12 @@ static ioctl_fn lookup_ioctl(unsigned int cmd, int *ioctl_flags)
1635 ioctl_fn fn; 1643 ioctl_fn fn;
1636 } _ioctls[] = { 1644 } _ioctls[] = {
1637 {DM_VERSION_CMD, 0, NULL}, /* version is dealt with elsewhere */ 1645 {DM_VERSION_CMD, 0, NULL}, /* version is dealt with elsewhere */
1638 {DM_REMOVE_ALL_CMD, IOCTL_FLAGS_NO_PARAMS, remove_all}, 1646 {DM_REMOVE_ALL_CMD, IOCTL_FLAGS_NO_PARAMS | IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, remove_all},
1639 {DM_LIST_DEVICES_CMD, 0, list_devices}, 1647 {DM_LIST_DEVICES_CMD, 0, list_devices},
1640 1648
1641 {DM_DEV_CREATE_CMD, IOCTL_FLAGS_NO_PARAMS, dev_create}, 1649 {DM_DEV_CREATE_CMD, IOCTL_FLAGS_NO_PARAMS | IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, dev_create},
1642 {DM_DEV_REMOVE_CMD, IOCTL_FLAGS_NO_PARAMS, dev_remove}, 1650 {DM_DEV_REMOVE_CMD, IOCTL_FLAGS_NO_PARAMS | IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, dev_remove},
1643 {DM_DEV_RENAME_CMD, 0, dev_rename}, 1651 {DM_DEV_RENAME_CMD, IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, dev_rename},
1644 {DM_DEV_SUSPEND_CMD, IOCTL_FLAGS_NO_PARAMS, dev_suspend}, 1652 {DM_DEV_SUSPEND_CMD, IOCTL_FLAGS_NO_PARAMS, dev_suspend},
1645 {DM_DEV_STATUS_CMD, IOCTL_FLAGS_NO_PARAMS, dev_status}, 1653 {DM_DEV_STATUS_CMD, IOCTL_FLAGS_NO_PARAMS, dev_status},
1646 {DM_DEV_WAIT_CMD, 0, dev_wait}, 1654 {DM_DEV_WAIT_CMD, 0, dev_wait},
@@ -1869,6 +1877,9 @@ static int ctl_ioctl(struct file *file, uint command, struct dm_ioctl __user *us
1869 unlikely(ioctl_flags & IOCTL_FLAGS_NO_PARAMS)) 1877 unlikely(ioctl_flags & IOCTL_FLAGS_NO_PARAMS))
1870 DMERR("ioctl %d tried to output some data but has IOCTL_FLAGS_NO_PARAMS set", cmd); 1878 DMERR("ioctl %d tried to output some data but has IOCTL_FLAGS_NO_PARAMS set", cmd);
1871 1879
1880 if (!r && ioctl_flags & IOCTL_FLAGS_ISSUE_GLOBAL_EVENT)
1881 dm_issue_global_event();
1882
1872 /* 1883 /*
1873 * Copy the results back to userland. 1884 * Copy the results back to userland.
1874 */ 1885 */
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 1ac58c5651b7..2245d06d2045 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -3297,11 +3297,10 @@ static const char *__raid_dev_status(struct raid_set *rs, struct md_rdev *rdev,
3297static sector_t rs_get_progress(struct raid_set *rs, 3297static sector_t rs_get_progress(struct raid_set *rs,
3298 sector_t resync_max_sectors, bool *array_in_sync) 3298 sector_t resync_max_sectors, bool *array_in_sync)
3299{ 3299{
3300 sector_t r, recovery_cp, curr_resync_completed; 3300 sector_t r, curr_resync_completed;
3301 struct mddev *mddev = &rs->md; 3301 struct mddev *mddev = &rs->md;
3302 3302
3303 curr_resync_completed = mddev->curr_resync_completed ?: mddev->recovery_cp; 3303 curr_resync_completed = mddev->curr_resync_completed ?: mddev->recovery_cp;
3304 recovery_cp = mddev->recovery_cp;
3305 *array_in_sync = false; 3304 *array_in_sync = false;
3306 3305
3307 if (rs_is_raid0(rs)) { 3306 if (rs_is_raid0(rs)) {
@@ -3330,9 +3329,11 @@ static sector_t rs_get_progress(struct raid_set *rs,
3330 } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) 3329 } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
3331 r = curr_resync_completed; 3330 r = curr_resync_completed;
3332 else 3331 else
3333 r = recovery_cp; 3332 r = mddev->recovery_cp;
3334 3333
3335 if (r == MaxSector) { 3334 if ((r == MaxSector) ||
3335 (test_bit(MD_RECOVERY_DONE, &mddev->recovery) &&
3336 (mddev->curr_resync_completed == resync_max_sectors))) {
3336 /* 3337 /*
3337 * Sync complete. 3338 * Sync complete.
3338 */ 3339 */
@@ -3892,7 +3893,7 @@ static void raid_resume(struct dm_target *ti)
3892 3893
3893static struct target_type raid_target = { 3894static struct target_type raid_target = {
3894 .name = "raid", 3895 .name = "raid",
3895 .version = {1, 12, 1}, 3896 .version = {1, 13, 0},
3896 .module = THIS_MODULE, 3897 .module = THIS_MODULE,
3897 .ctr = raid_ctr, 3898 .ctr = raid_ctr,
3898 .dtr = raid_dtr, 3899 .dtr = raid_dtr,
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 6e54145969c5..4be85324f44d 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -52,6 +52,12 @@ static struct workqueue_struct *deferred_remove_workqueue;
52atomic_t dm_global_event_nr = ATOMIC_INIT(0); 52atomic_t dm_global_event_nr = ATOMIC_INIT(0);
53DECLARE_WAIT_QUEUE_HEAD(dm_global_eventq); 53DECLARE_WAIT_QUEUE_HEAD(dm_global_eventq);
54 54
55void dm_issue_global_event(void)
56{
57 atomic_inc(&dm_global_event_nr);
58 wake_up(&dm_global_eventq);
59}
60
55/* 61/*
56 * One of these is allocated per bio. 62 * One of these is allocated per bio.
57 */ 63 */
@@ -1865,9 +1871,8 @@ static void event_callback(void *context)
1865 dm_send_uevents(&uevents, &disk_to_dev(md->disk)->kobj); 1871 dm_send_uevents(&uevents, &disk_to_dev(md->disk)->kobj);
1866 1872
1867 atomic_inc(&md->event_nr); 1873 atomic_inc(&md->event_nr);
1868 atomic_inc(&dm_global_event_nr);
1869 wake_up(&md->eventq); 1874 wake_up(&md->eventq);
1870 wake_up(&dm_global_eventq); 1875 dm_issue_global_event();
1871} 1876}
1872 1877
1873/* 1878/*
@@ -2283,6 +2288,7 @@ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table)
2283 } 2288 }
2284 2289
2285 map = __bind(md, table, &limits); 2290 map = __bind(md, table, &limits);
2291 dm_issue_global_event();
2286 2292
2287out: 2293out:
2288 mutex_unlock(&md->suspend_lock); 2294 mutex_unlock(&md->suspend_lock);
diff --git a/include/uapi/linux/dm-ioctl.h b/include/uapi/linux/dm-ioctl.h
index 412c06a624c8..ccaea525340b 100644
--- a/include/uapi/linux/dm-ioctl.h
+++ b/include/uapi/linux/dm-ioctl.h
@@ -269,9 +269,9 @@ enum {
269#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) 269#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
270 270
271#define DM_VERSION_MAJOR 4 271#define DM_VERSION_MAJOR 4
272#define DM_VERSION_MINOR 36 272#define DM_VERSION_MINOR 37
273#define DM_VERSION_PATCHLEVEL 0 273#define DM_VERSION_PATCHLEVEL 0
274#define DM_VERSION_EXTRA "-ioctl (2017-06-09)" 274#define DM_VERSION_EXTRA "-ioctl (2017-09-20)"
275 275
276/* Status bits */ 276/* Status bits */
277#define DM_READONLY_FLAG (1 << 0) /* In/Out */ 277#define DM_READONLY_FLAG (1 << 0) /* In/Out */