Skip to content

Commit

Permalink
Merge tag 'for-5.9/dm-changes' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/device-mapper/linux-dm

Pull device mapper updates from Mike Snitzer:

 - DM multipath locking fixes around m->flags tests and improvements to
   bio-based code so that it follows patterns established by
   request-based code.

 - Request-based DM core improvement to eliminate unnecessary call to
   blk_mq_queue_stopped().

 - Add "panic_on_corruption" error handling mode to DM verity target.

 - DM bufio fix to to perform buffer cleanup from a workqueue rather
   than wait for IO in reclaim context from shrinker.

 - DM crypt improvement to optionally avoid async processing via
   workqueues for reads and/or writes -- via "no_read_workqueue" and
   "no_write_workqueue" features. This more direct IO processing
   improves latency and throughput with faster storage. Avoiding
   workqueue IO submission for writes (DM_CRYPT_NO_WRITE_WORKQUEUE) is a
   requirement for adding zoned block device support to DM crypt.

 - Add zoned block device support to DM crypt. Makes use of
   DM_CRYPT_NO_WRITE_WORKQUEUE and a new optional feature
   (DM_CRYPT_WRITE_INLINE) that allows write completion to wait for
   encryption to complete. This allows write ordering to be preserved,
   which is needed for zoned block devices.

 - Fix DM ebs target's check for REQ_OP_FLUSH.

 - Fix DM core's report zones support to not report more zones than were
   requested.

 - A few small compiler warning fixes.

 - DM dust improvements to return output directly to the user rather
   than require they scrape the system log for output.

* tag 'for-5.9/dm-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm: don't call report zones for more than the user requested
  dm ebs: Fix incorrect checking for REQ_OP_FLUSH
  dm init: Set file local variable static
  dm ioctl: Fix compilation warning
  dm raid: Remove empty if statement
  dm verity: Fix compilation warning
  dm crypt: Enable zoned block device support
  dm crypt: add flags to optionally bypass kcryptd workqueues
  dm bufio: do buffer cleanup from a workqueue
  dm rq: don't call blk_mq_queue_stopped() in dm_stop_queue()
  dm dust: add interface to list all badblocks
  dm dust: report some message results directly back to user
  dm verity: add "panic_on_corruption" error handling mode
  dm mpath: use double checked locking in fast path
  dm mpath: rename current_pgpath to pgpath in multipath_prepare_ioctl
  dm mpath: rework __map_bio()
  dm mpath: factor out multipath_queue_bio
  dm mpath: push locking down to must_push_back_rq()
  dm mpath: take m->lock spinlock when testing QUEUE_IF_NO_PATH
  dm mpath: changes from initial m->flags locking audit
  • Loading branch information
torvalds committed Aug 7, 2020
2 parents fa73e21 + a9cb9f4 commit 2f12d44
Show file tree
Hide file tree
Showing 15 changed files with 355 additions and 118 deletions.
32 changes: 25 additions & 7 deletions Documentation/admin-guide/device-mapper/dm-dust.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,11 @@ Create the dm-dust device:
$ sudo dmsetup create dust1 --table '0 33552384 dust /dev/vdb1 0 4096'

Check the status of the read behavior ("bypass" indicates that all I/O
will be passed through to the underlying device)::
will be passed through to the underlying device; "verbose" indicates that
bad block additions, removals, and remaps will be verbosely logged)::

$ sudo dmsetup status dust1
0 33552384 dust 252:17 bypass
0 33552384 dust 252:17 bypass verbose

$ sudo dd if=/dev/mapper/dust1 of=/dev/null bs=512 count=128 iflag=direct
128+0 records in
Expand Down Expand Up @@ -164,7 +165,7 @@ following message command::
A message will print with the number of bad blocks currently
configured on the device::

kernel: device-mapper: dust: countbadblocks: 895 badblock(s) found
countbadblocks: 895 badblock(s) found

Querying for specific bad blocks
--------------------------------
Expand All @@ -176,11 +177,11 @@ following message command::

The following message will print if the block is in the list::

device-mapper: dust: queryblock: block 72 found in badblocklist
dust_query_block: block 72 found in badblocklist

The following message will print if the block is not in the list::

device-mapper: dust: queryblock: block 72 not found in badblocklist
dust_query_block: block 72 not found in badblocklist

The "queryblock" message command will work in both the "enabled"
and "disabled" modes, allowing the verification of whether a block
Expand All @@ -198,12 +199,28 @@ following message command::

After clearing the bad block list, the following message will appear::

kernel: device-mapper: dust: clearbadblocks: badblocks cleared
dust_clear_badblocks: badblocks cleared

If there were no bad blocks to clear, the following message will
appear::

kernel: device-mapper: dust: clearbadblocks: no badblocks found
dust_clear_badblocks: no badblocks found

Listing the bad block list
--------------------------

To list all bad blocks in the bad block list (using an example device
with blocks 1 and 2 in the bad block list), run the following message
command::

$ sudo dmsetup message dust1 0 listbadblocks
1
2

If there are no bad blocks in the bad block list, the command will
execute with no output::

$ sudo dmsetup message dust1 0 listbadblocks

Message commands list
---------------------
Expand All @@ -223,6 +240,7 @@ Single argument message commands::

countbadblocks
clearbadblocks
listbadblocks
disable
enable
quiet
Expand Down
4 changes: 4 additions & 0 deletions Documentation/admin-guide/device-mapper/verity.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ restart_on_corruption
not compatible with ignore_corruption and requires user space support to
avoid restart loops.

panic_on_corruption
Panic the device when a corrupted block is discovered. This option is
not compatible with ignore_corruption and restart_on_corruption.

ignore_zero_blocks
Do not verify blocks that are expected to contain zeroes and always return
zeroes instead. This may be useful if the partition contains unused blocks
Expand Down
60 changes: 41 additions & 19 deletions drivers/md/dm-bufio.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,10 @@ struct dm_bufio_client {
int async_write_error;

struct list_head client_list;

struct shrinker shrinker;
struct work_struct shrink_work;
atomic_long_t need_shrink;
};

/*
Expand Down Expand Up @@ -1634,8 +1637,7 @@ static unsigned long get_retain_buffers(struct dm_bufio_client *c)
return retain_bytes;
}

static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan,
gfp_t gfp_mask)
static void __scan(struct dm_bufio_client *c)
{
int l;
struct dm_buffer *b, *tmp;
Expand All @@ -1646,42 +1648,58 @@ static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan,

for (l = 0; l < LIST_SIZE; l++) {
list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list) {
if (__try_evict_buffer(b, gfp_mask))
if (count - freed <= retain_target)
atomic_long_set(&c->need_shrink, 0);
if (!atomic_long_read(&c->need_shrink))
return;
if (__try_evict_buffer(b, GFP_KERNEL)) {
atomic_long_dec(&c->need_shrink);
freed++;
if (!--nr_to_scan || ((count - freed) <= retain_target))
return freed;
}
cond_resched();
}
}
return freed;
}

static unsigned long
dm_bufio_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
static void shrink_work(struct work_struct *w)
{
struct dm_bufio_client *c = container_of(w, struct dm_bufio_client, shrink_work);

dm_bufio_lock(c);
__scan(c);
dm_bufio_unlock(c);
}

static unsigned long dm_bufio_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
{
struct dm_bufio_client *c;
unsigned long freed;

c = container_of(shrink, struct dm_bufio_client, shrinker);
if (sc->gfp_mask & __GFP_FS)
dm_bufio_lock(c);
else if (!dm_bufio_trylock(c))
return SHRINK_STOP;
atomic_long_add(sc->nr_to_scan, &c->need_shrink);
queue_work(dm_bufio_wq, &c->shrink_work);

freed = __scan(c, sc->nr_to_scan, sc->gfp_mask);
dm_bufio_unlock(c);
return freed;
return sc->nr_to_scan;
}

static unsigned long
dm_bufio_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
static unsigned long dm_bufio_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
{
struct dm_bufio_client *c = container_of(shrink, struct dm_bufio_client, shrinker);
unsigned long count = READ_ONCE(c->n_buffers[LIST_CLEAN]) +
READ_ONCE(c->n_buffers[LIST_DIRTY]);
unsigned long retain_target = get_retain_buffers(c);
unsigned long queued_for_cleanup = atomic_long_read(&c->need_shrink);

if (unlikely(count < retain_target))
count = 0;
else
count -= retain_target;

return (count < retain_target) ? 0 : (count - retain_target);
if (unlikely(count < queued_for_cleanup))
count = 0;
else
count -= queued_for_cleanup;

return count;
}

/*
Expand Down Expand Up @@ -1772,6 +1790,9 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
__free_buffer_wake(b);
}

INIT_WORK(&c->shrink_work, shrink_work);
atomic_long_set(&c->need_shrink, 0);

c->shrinker.count_objects = dm_bufio_shrink_count;
c->shrinker.scan_objects = dm_bufio_shrink_scan;
c->shrinker.seeks = 1;
Expand Down Expand Up @@ -1817,6 +1838,7 @@ void dm_bufio_client_destroy(struct dm_bufio_client *c)
drop_buffers(c);

unregister_shrinker(&c->shrinker);
flush_work(&c->shrink_work);

mutex_lock(&dm_bufio_clients_lock);

Expand Down
Loading

0 comments on commit 2f12d44

Please sign in to comment.