- Fix DM integrity shrink crash due to journal entry not being marked

unused.
 
 - Fix DM bio polling to handle possibility that underlying device(s)
   return BLK_STS_AGAIN during submission.
 
 - Fix dm_io and dm_target_io flags race condition on Alpha.
 
 - Add some pr_err debugging to help debug cases when DM ioctl
   structure is corrupted.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCAAdFiEEJfWUX4UqZ4x1O2wixSPxCi2dA1oFAmJHUFIACgkQxSPxCi2d
 A1qclwf/binqM95fkE2PW6Uvqm7EEsiWXj8Bu+5NQqvlhrLhVTeMdxOKYLClOZ0o
 eY0TLmkCCtrzveHZYbVcV/HM/tUY5qFT4gZbsXwW+HTSxOPeiOx5ZOOthP3kZbU0
 zKpu4N1udfg7m8wSnE7o0cJKBrea6fUf5YDpUT+9EmMhoL0a8IJ3Y1TSJZ/CDJEm
 OptDS2QH+pFeiIt+lCPL18BT+KnW48Cofpx6ZAGnphLTfSeu8ZiMCew0LhQcepCf
 L6jfnQQmyGYBydTVSTzP3bbP/GNxPjDZuMT/z/sdMGrQmIxZT+/UqCl+kzD/jC7q
 1Sjha+8gYo5a2cMTJZSKmFBKjvLYJQ==
 =dWLx
 -----END PGP SIGNATURE-----

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

Pull device mapper fixes from Mike Snitzer:

 - Fix DM integrity shrink crash due to journal entry not being marked
   unused.

 - Fix DM bio polling to handle possibility that underlying device(s)
   return BLK_STS_AGAIN during submission.

 - Fix dm_io and dm_target_io flags race condition on Alpha.

 - Add some pr_err debugging to help debug cases when DM ioctl structure
   is corrupted.

* tag 'for-5.18/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm: fix bio polling to handle possibile BLK_STS_AGAIN
  dm: fix dm_io and dm_target_io flags race condition on Alpha
  dm integrity: set journal entry unused when shrinking device
  dm ioctl: log an error if the ioctl structure is corrupted
This commit is contained in:
Linus Torvalds 2022-04-01 15:57:27 -07:00
commit fe35fdb305
5 changed files with 33 additions and 14 deletions

View File

@ -210,7 +210,7 @@ struct dm_table {
#define DM_TIO_MAGIC 28714 #define DM_TIO_MAGIC 28714
struct dm_target_io { struct dm_target_io {
unsigned short magic; unsigned short magic;
unsigned short flags; blk_short_t flags;
unsigned int target_bio_nr; unsigned int target_bio_nr;
struct dm_io *io; struct dm_io *io;
struct dm_target *ti; struct dm_target *ti;
@ -244,7 +244,7 @@ static inline void dm_tio_set_flag(struct dm_target_io *tio, unsigned int bit)
#define DM_IO_MAGIC 19577 #define DM_IO_MAGIC 19577
struct dm_io { struct dm_io {
unsigned short magic; unsigned short magic;
unsigned short flags; blk_short_t flags;
atomic_t io_count; atomic_t io_count;
struct mapped_device *md; struct mapped_device *md;
struct bio *orig_bio; struct bio *orig_bio;

View File

@ -2472,9 +2472,11 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
dm_integrity_io_error(ic, "invalid sector in journal", -EIO); dm_integrity_io_error(ic, "invalid sector in journal", -EIO);
sec &= ~(sector_t)(ic->sectors_per_block - 1); sec &= ~(sector_t)(ic->sectors_per_block - 1);
} }
if (unlikely(sec >= ic->provided_data_sectors)) {
journal_entry_set_unused(je);
continue;
}
} }
if (unlikely(sec >= ic->provided_data_sectors))
continue;
get_area_and_offset(ic, sec, &area, &offset); get_area_and_offset(ic, sec, &area, &offset);
restore_last_bytes(ic, access_journal_data(ic, i, j), je); restore_last_bytes(ic, access_journal_data(ic, i, j), je);
for (k = j + 1; k < ic->journal_section_entries; k++) { for (k = j + 1; k < ic->journal_section_entries; k++) {

View File

@ -891,15 +891,21 @@ static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
struct hash_cell *hc = NULL; struct hash_cell *hc = NULL;
if (*param->uuid) { if (*param->uuid) {
if (*param->name || param->dev) if (*param->name || param->dev) {
DMERR("Invalid ioctl structure: uuid %s, name %s, dev %llx",
param->uuid, param->name, (unsigned long long)param->dev);
return NULL; return NULL;
}
hc = __get_uuid_cell(param->uuid); hc = __get_uuid_cell(param->uuid);
if (!hc) if (!hc)
return NULL; return NULL;
} else if (*param->name) { } else if (*param->name) {
if (param->dev) if (param->dev) {
DMERR("Invalid ioctl structure: name %s, dev %llx",
param->name, (unsigned long long)param->dev);
return NULL; return NULL;
}
hc = __get_name_cell(param->name); hc = __get_name_cell(param->name);
if (!hc) if (!hc)
@ -1851,8 +1857,11 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
if (copy_from_user(param_kernel, user, minimum_data_size)) if (copy_from_user(param_kernel, user, minimum_data_size))
return -EFAULT; return -EFAULT;
if (param_kernel->data_size < minimum_data_size) if (param_kernel->data_size < minimum_data_size) {
DMERR("Invalid data size in the ioctl structure: %u",
param_kernel->data_size);
return -EINVAL; return -EINVAL;
}
secure_data = param_kernel->flags & DM_SECURE_DATA_FLAG; secure_data = param_kernel->flags & DM_SECURE_DATA_FLAG;

View File

@ -892,13 +892,19 @@ static void dm_io_complete(struct dm_io *io)
if (unlikely(wq_has_sleeper(&md->wait))) if (unlikely(wq_has_sleeper(&md->wait)))
wake_up(&md->wait); wake_up(&md->wait);
if (io_error == BLK_STS_DM_REQUEUE) { if (io_error == BLK_STS_DM_REQUEUE || io_error == BLK_STS_AGAIN) {
/* if (bio->bi_opf & REQ_POLLED) {
* Upper layer won't help us poll split bio, io->orig_bio /*
* may only reflect a subset of the pre-split original, * Upper layer won't help us poll split bio (io->orig_bio
* so clear REQ_POLLED in case of requeue * may only reflect a subset of the pre-split original)
*/ * so clear REQ_POLLED in case of requeue.
bio->bi_opf &= ~REQ_POLLED; */
bio->bi_opf &= ~REQ_POLLED;
if (io_error == BLK_STS_AGAIN) {
/* io_uring doesn't handle BLK_STS_AGAIN (yet) */
queue_io(md, bio);
}
}
return; return;
} }

View File

@ -85,8 +85,10 @@ struct block_device {
*/ */
#if defined(CONFIG_ALPHA) && !defined(__alpha_bwx__) #if defined(CONFIG_ALPHA) && !defined(__alpha_bwx__)
typedef u32 __bitwise blk_status_t; typedef u32 __bitwise blk_status_t;
typedef u32 blk_short_t;
#else #else
typedef u8 __bitwise blk_status_t; typedef u8 __bitwise blk_status_t;
typedef u16 blk_short_t;
#endif #endif
#define BLK_STS_OK 0 #define BLK_STS_OK 0
#define BLK_STS_NOTSUPP ((__force blk_status_t)1) #define BLK_STS_NOTSUPP ((__force blk_status_t)1)