Browse Source

Merge tag 'for-4.19/dm-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm

Mike writes:
  "device mapper fixes

   - Fix a DM thinp __udivdi3 undefined on 32-bit bug introduced during
     4.19 merge window.

   - Fix leak and dangling pointer in DM multipath's scsi_dh related code.

   - A couple stable@ fixes for DM cache's resize support.

   - A DM raid fix to remove "const" from decipher_sync_action()'s return
     type."

* tag 'for-4.19/dm-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm cache: fix resize crash if user doesn't reload cache table
  dm cache metadata: ignore hints array being too small during resize
  dm raid: remove bogus const from decipher_sync_action() return type
  dm mpath: fix attached_handler_name leak and dangling hw_handler_name pointer
  dm thin metadata: fix __udivdi3 undefined on 32-bit
Greg Kroah-Hartman 6 years ago
parent
commit
b98d6cb80b

+ 2 - 2
drivers/md/dm-cache-metadata.c

@@ -1455,8 +1455,8 @@ static int __load_mappings(struct dm_cache_metadata *cmd,
 		if (hints_valid) {
 		if (hints_valid) {
 			r = dm_array_cursor_next(&cmd->hint_cursor);
 			r = dm_array_cursor_next(&cmd->hint_cursor);
 			if (r) {
 			if (r) {
-				DMERR("dm_array_cursor_next for hint failed");
-				goto out;
+				dm_array_cursor_end(&cmd->hint_cursor);
+				hints_valid = false;
 			}
 			}
 		}
 		}
 
 

+ 7 - 2
drivers/md/dm-cache-target.c

@@ -3009,8 +3009,13 @@ static dm_cblock_t get_cache_dev_size(struct cache *cache)
 
 
 static bool can_resize(struct cache *cache, dm_cblock_t new_size)
 static bool can_resize(struct cache *cache, dm_cblock_t new_size)
 {
 {
-	if (from_cblock(new_size) > from_cblock(cache->cache_size))
-		return true;
+	if (from_cblock(new_size) > from_cblock(cache->cache_size)) {
+		if (cache->sized) {
+			DMERR("%s: unable to extend cache due to missing cache table reload",
+			      cache_device_name(cache));
+			return false;
+		}
+	}
 
 
 	/*
 	/*
 	 * We can't drop a dirty block when shrinking the cache.
 	 * We can't drop a dirty block when shrinking the cache.

+ 8 - 6
drivers/md/dm-mpath.c

@@ -806,19 +806,19 @@ static int parse_path_selector(struct dm_arg_set *as, struct priority_group *pg,
 }
 }
 
 
 static int setup_scsi_dh(struct block_device *bdev, struct multipath *m,
 static int setup_scsi_dh(struct block_device *bdev, struct multipath *m,
-			 const char *attached_handler_name, char **error)
+			 const char **attached_handler_name, char **error)
 {
 {
 	struct request_queue *q = bdev_get_queue(bdev);
 	struct request_queue *q = bdev_get_queue(bdev);
 	int r;
 	int r;
 
 
 	if (test_bit(MPATHF_RETAIN_ATTACHED_HW_HANDLER, &m->flags)) {
 	if (test_bit(MPATHF_RETAIN_ATTACHED_HW_HANDLER, &m->flags)) {
 retain:
 retain:
-		if (attached_handler_name) {
+		if (*attached_handler_name) {
 			/*
 			/*
 			 * Clear any hw_handler_params associated with a
 			 * Clear any hw_handler_params associated with a
 			 * handler that isn't already attached.
 			 * handler that isn't already attached.
 			 */
 			 */
-			if (m->hw_handler_name && strcmp(attached_handler_name, m->hw_handler_name)) {
+			if (m->hw_handler_name && strcmp(*attached_handler_name, m->hw_handler_name)) {
 				kfree(m->hw_handler_params);
 				kfree(m->hw_handler_params);
 				m->hw_handler_params = NULL;
 				m->hw_handler_params = NULL;
 			}
 			}
@@ -830,7 +830,8 @@ retain:
 			 * handler instead of the original table passed in.
 			 * handler instead of the original table passed in.
 			 */
 			 */
 			kfree(m->hw_handler_name);
 			kfree(m->hw_handler_name);
-			m->hw_handler_name = attached_handler_name;
+			m->hw_handler_name = *attached_handler_name;
+			*attached_handler_name = NULL;
 		}
 		}
 	}
 	}
 
 
@@ -867,7 +868,7 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps
 	struct pgpath *p;
 	struct pgpath *p;
 	struct multipath *m = ti->private;
 	struct multipath *m = ti->private;
 	struct request_queue *q;
 	struct request_queue *q;
-	const char *attached_handler_name;
+	const char *attached_handler_name = NULL;
 
 
 	/* we need at least a path arg */
 	/* we need at least a path arg */
 	if (as->argc < 1) {
 	if (as->argc < 1) {
@@ -890,7 +891,7 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps
 	attached_handler_name = scsi_dh_attached_handler_name(q, GFP_KERNEL);
 	attached_handler_name = scsi_dh_attached_handler_name(q, GFP_KERNEL);
 	if (attached_handler_name || m->hw_handler_name) {
 	if (attached_handler_name || m->hw_handler_name) {
 		INIT_DELAYED_WORK(&p->activate_path, activate_path_work);
 		INIT_DELAYED_WORK(&p->activate_path, activate_path_work);
-		r = setup_scsi_dh(p->path.dev->bdev, m, attached_handler_name, &ti->error);
+		r = setup_scsi_dh(p->path.dev->bdev, m, &attached_handler_name, &ti->error);
 		if (r) {
 		if (r) {
 			dm_put_device(ti, p->path.dev);
 			dm_put_device(ti, p->path.dev);
 			goto bad;
 			goto bad;
@@ -905,6 +906,7 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps
 
 
 	return p;
 	return p;
  bad:
  bad:
+	kfree(attached_handler_name);
 	free_pgpath(p);
 	free_pgpath(p);
 	return ERR_PTR(r);
 	return ERR_PTR(r);
 }
 }

+ 1 - 1
drivers/md/dm-raid.c

@@ -3353,7 +3353,7 @@ static const char *sync_str(enum sync_state state)
 };
 };
 
 
 /* Return enum sync_state for @mddev derived from @recovery flags */
 /* Return enum sync_state for @mddev derived from @recovery flags */
-static const enum sync_state decipher_sync_action(struct mddev *mddev, unsigned long recovery)
+static enum sync_state decipher_sync_action(struct mddev *mddev, unsigned long recovery)
 {
 {
 	if (test_bit(MD_RECOVERY_FROZEN, &recovery))
 	if (test_bit(MD_RECOVERY_FROZEN, &recovery))
 		return st_frozen;
 		return st_frozen;

+ 2 - 4
drivers/md/dm-thin-metadata.c

@@ -832,10 +832,8 @@ static void __set_metadata_reserve(struct dm_pool_metadata *pmd)
 	if (r) {
 	if (r) {
 		DMERR("could not get size of metadata device");
 		DMERR("could not get size of metadata device");
 		pmd->metadata_reserve = max_blocks;
 		pmd->metadata_reserve = max_blocks;
-	} else {
-		sector_div(total, 10);
-		pmd->metadata_reserve = min(max_blocks, total);
-	}
+	} else
+		pmd->metadata_reserve = min(max_blocks, div_u64(total, 10));
 }
 }
 
 
 struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
 struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,