2023-01-25 20:00:44 +00:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
2008-04-24 20:43:52 +00:00
|
|
|
* Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
2005-04-16 22:20:36 +00:00
|
|
|
*
|
|
|
|
* This file is released under the LGPL.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _LINUX_DEVICE_MAPPER_H
|
|
|
|
#define _LINUX_DEVICE_MAPPER_H
|
|
|
|
|
2008-04-24 20:43:35 +00:00
|
|
|
#include <linux/bio.h>
|
2008-07-21 11:00:37 +00:00
|
|
|
#include <linux/blkdev.h>
|
dm: add support to directly boot to a mapped device
Add a "create" module parameter, which allows device-mapper targets to
be configured at boot time. This enables early use of DM targets in the
boot process (as the root device or otherwise) without the need of an
initramfs.
The syntax used in the boot param is based on the concise format from
the dmsetup tool to follow the rule of least surprise:
dmsetup table --concise /dev/mapper/lroot
Which is:
dm-mod.create=<name>,<uuid>,<minor>,<flags>,<table>[,<table>+][;<name>,<uuid>,<minor>,<flags>,<table>[,<table>+]+]
Where,
<name> ::= The device name.
<uuid> ::= xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | ""
<minor> ::= The device minor number | ""
<flags> ::= "ro" | "rw"
<table> ::= <start_sector> <num_sectors> <target_type> <target_args>
<target_type> ::= "verity" | "linear" | ...
For example, the following could be added in the boot parameters:
dm-mod.create="lroot,,,rw, 0 4096 linear 98:16 0, 4096 4096 linear 98:32 0" root=/dev/dm-0
Only the targets that were tested are allowed and the ones that don't
change any block device when the device is create as read-only. For
example, mirror and cache targets are not allowed. The rationale behind
this is that if the user makes a mistake, choosing the wrong device to
be the mirror or the cache can corrupt data.
The only targets initially allowed are:
* crypt
* delay
* linear
* snapshot-origin
* striped
* verity
Co-developed-by: Will Drewry <wad@chromium.org>
Co-developed-by: Kees Cook <keescook@chromium.org>
Co-developed-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Signed-off-by: Helen Koike <helen.koike@collabora.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
2019-02-21 20:33:34 +00:00
|
|
|
#include <linux/dm-ioctl.h>
|
2013-08-16 14:54:23 +00:00
|
|
|
#include <linux/math64.h>
|
2011-10-31 20:18:54 +00:00
|
|
|
#include <linux/ratelimit.h>
|
2008-04-24 20:43:35 +00:00
|
|
|
|
2009-06-22 09:12:33 +00:00
|
|
|
struct dm_dev;
|
2005-04-16 22:20:36 +00:00
|
|
|
struct dm_target;
|
|
|
|
struct dm_table;
|
2019-11-11 02:39:30 +00:00
|
|
|
struct dm_report_zones_args;
|
2006-06-26 07:27:33 +00:00
|
|
|
struct mapped_device;
|
2008-07-21 11:00:37 +00:00
|
|
|
struct bio_vec;
|
2022-05-13 22:10:58 +00:00
|
|
|
enum dax_access_mode;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2016-05-25 01:16:51 +00:00
|
|
|
/*
|
|
|
|
* Type of table, mapped_device's mempool and request_queue
|
|
|
|
*/
|
2017-04-27 17:11:23 +00:00
|
|
|
enum dm_queue_mode {
|
|
|
|
DM_TYPE_NONE = 0,
|
|
|
|
DM_TYPE_BIO_BASED = 1,
|
|
|
|
DM_TYPE_REQUEST_BASED = 2,
|
2018-10-11 15:06:29 +00:00
|
|
|
DM_TYPE_DAX_BIO_BASED = 3,
|
2017-04-27 17:11:23 +00:00
|
|
|
};
|
2016-05-25 01:16:51 +00:00
|
|
|
|
dm ima: measure data on table load
DM configures a block device with various target specific attributes
passed to it as a table. DM loads the table, and calls each target’s
respective constructors with the attributes as input parameters.
Some of these attributes are critical to ensure the device meets
certain security bar. Thus, IMA should measure these attributes, to
ensure they are not tampered with, during the lifetime of the device.
So that the external services can have high confidence in the
configuration of the block-devices on a given system.
Some devices may have large tables. And a given device may change its
state (table-load, suspend, resume, rename, remove, table-clear etc.)
many times. Measuring these attributes each time when the device
changes its state will significantly increase the size of the IMA logs.
Further, once configured, these attributes are not expected to change
unless a new table is loaded, or a device is removed and recreated.
Therefore the clear-text of the attributes should only be measured
during table load, and the hash of the active/inactive table should be
measured for the remaining device state changes.
Export IMA function ima_measure_critical_data() to allow measurement
of DM device parameters, as well as target specific attributes, during
table load. Compute the hash of the inactive table and store it for
measurements during future state change. If a load is called multiple
times, update the inactive table hash with the hash of the latest
populated table. So that the correct inactive table hash is measured
when the device transitions to different states like resume, remove,
rename, etc.
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: Colin Ian King <colin.king@canonical.com> # leak fix
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
2021-07-13 00:48:58 +00:00
|
|
|
typedef enum { STATUSTYPE_INFO, STATUSTYPE_TABLE, STATUSTYPE_IMA } status_type_t;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
union map_info {
|
|
|
|
void *ptr;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* In the constructor the target parameter will already have the
|
|
|
|
* table, type, begin and len fields filled in.
|
|
|
|
*/
|
|
|
|
typedef int (*dm_ctr_fn) (struct dm_target *target,
|
|
|
|
unsigned int argc, char **argv);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The destructor doesn't need to free the dm_target, just
|
|
|
|
* anything hidden ti->private.
|
|
|
|
*/
|
|
|
|
typedef void (*dm_dtr_fn) (struct dm_target *ti);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The map function must return:
|
|
|
|
* < 0: error
|
|
|
|
* = 0: The target will handle the io by resubmitting it later
|
2006-12-08 10:41:05 +00:00
|
|
|
* = 1: simple remap complete
|
[PATCH] dm: suspend: add noflush pushback
In device-mapper I/O is sometimes queued within targets for later processing.
For example the multipath target can be configured to store I/O when no paths
are available instead of returning it -EIO.
This patch allows the device-mapper core to instruct a target to transfer the
contents of any such in-target queue back into the core. This frees up the
resources used by the target so the core can replace that target with an
alternative one and then resend the I/O to it. Without this patch the only
way to change the target in such circumstances involves returning the I/O with
an error back to the filesystem/application. In the multipath case, this
patch will let us add new paths for existing I/O to try after all the existing
paths have failed.
DMF_NOFLUSH_SUSPENDING
----------------------
If the DM_NOFLUSH_FLAG ioctl option is specified at suspend time, the
DMF_NOFLUSH_SUSPENDING flag is set in md->flags during dm_suspend(). It
is always cleared before dm_suspend() returns.
The flag must be visible while the target is flushing pending I/Os so it
is set before presuspend where the flush starts and unset after the wait
for md->pending where the flush ends.
Target drivers can check this flag by calling dm_noflush_suspending().
DM_MAPIO_REQUEUE / DM_ENDIO_REQUEUE
-----------------------------------
A target's map() function can now return DM_MAPIO_REQUEUE to request the
device mapper core queue the bio.
Similarly, a target's end_io() function can return DM_ENDIO_REQUEUE to request
the same. This has been labelled 'pushback'.
The __map_bio() and clone_endio() functions in the core treat these return
values as errors and call dec_pending() to end the I/O.
dec_pending
-----------
dec_pending() saves the pushback request in struct dm_io->error. Once all
the split clones have ended, dec_pending() will put the original bio on
the md->pushback list. Note that this supercedes any I/O errors.
It is possible for the suspend with DM_NOFLUSH_FLAG to be aborted while
in progress (e.g. by user interrupt). dec_pending() checks for this and
returns -EIO if it happened.
pushdback list and pushback_lock
--------------------------------
The bio is queued on md->pushback temporarily in dec_pending(), and after
all pending I/Os return, md->pushback is merged into md->deferred in
dm_suspend() for re-issuing at resume time.
md->pushback_lock protects md->pushback.
The lock should be held with irq disabled because dec_pending() can be
called from interrupt context.
Queueing bios to md->pushback in dec_pending() must be done atomically
with the check for DMF_NOFLUSH_SUSPENDING flag. So md->pushback_lock is
held when checking the flag. Otherwise dec_pending() may queue a bio to
md->pushback after the interrupted dm_suspend() flushes md->pushback.
Then the bio would be left in md->pushback.
Flag setting in dm_suspend() can be done without md->pushback_lock because
the flag is checked only after presuspend and the set value is already
made visible via the target's presuspend function.
The flag can be checked without md->pushback_lock (e.g. the first part of
the dec_pending() or target drivers), because the flag is checked again
with md->pushback_lock held when the bio is really queued to md->pushback
as described above. So even if the flag is cleared after the lockless
checkings, the bio isn't left in md->pushback but returned to applications
with -EIO.
Other notes on the current patch
--------------------------------
- md->pushback is added to the struct mapped_device instead of using
md->deferred directly because md->io_lock which protects md->deferred is
rw_semaphore and can't be used in interrupt context like dec_pending(),
and md->io_lock protects the DMF_BLOCK_IO flag of md->flags too.
- Don't issue lock_fs() in dm_suspend() if the DM_NOFLUSH_FLAG
ioctl option is specified, because I/Os generated by lock_fs() would be
pushed back and never return if there were no valid devices.
- If an error occurs in dm_suspend() after the DMF_NOFLUSH_SUSPENDING
flag is set, md->pushback must be flushed because I/Os may be queued to
the list already. (flush_and_out label in dm_suspend())
Test results
------------
I have tested using multipath target with the next patch.
The following tests are for regression/compatibility:
- I/Os succeed when valid paths exist;
- I/Os fail when there are no valid paths and queue_if_no_path is not
set;
- I/Os are queued in the multipath target when there are no valid paths and
queue_if_no_path is set;
- The queued I/Os above fail when suspend is issued without the
DM_NOFLUSH_FLAG ioctl option. I/Os spanning 2 multipath targets also
fail.
The following tests are for the normal code path of new pushback feature:
- Queued I/Os in the multipath target are flushed from the target
but don't return when suspend is issued with the DM_NOFLUSH_FLAG
ioctl option;
- The I/Os above are queued in the multipath target again when
resume is issued without path recovery;
- The I/Os above succeed when resume is issued after path recovery
or table load;
- Queued I/Os in the multipath target succeed when resume is issued
with the DM_NOFLUSH_FLAG ioctl option after table load. I/Os
spanning 2 multipath targets also succeed.
The following tests are for the error paths of the new pushback feature:
- When the bdget_disk() fails in dm_suspend(), the
DMF_NOFLUSH_SUSPENDING flag is cleared and I/Os already queued to the
pushback list are flushed properly.
- When suspend with the DM_NOFLUSH_FLAG ioctl option is interrupted,
o I/Os which had already been queued to the pushback list
at the time don't return, and are re-issued at resume time;
o I/Os which hadn't been returned at the time return with EIO.
Signed-off-by: Kiyoshi Ueda <k-ueda@ct.jp.nec.com>
Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Cc: dm-devel@redhat.com
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-08 10:41:09 +00:00
|
|
|
* = 2: The target wants to push back the io
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2012-12-21 20:23:41 +00:00
|
|
|
typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio);
|
2014-12-18 02:08:12 +00:00
|
|
|
typedef int (*dm_clone_and_map_request_fn) (struct dm_target *ti,
|
|
|
|
struct request *rq,
|
|
|
|
union map_info *map_context,
|
|
|
|
struct request **clone);
|
2019-04-24 15:19:05 +00:00
|
|
|
typedef void (*dm_release_clone_request_fn) (struct request *clone,
|
|
|
|
union map_info *map_context);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns:
|
|
|
|
* < 0 : error (currently ignored)
|
|
|
|
* 0 : ended successfully
|
|
|
|
* 1 : for some reason the io has still not completed (eg,
|
|
|
|
* multipath target might want to requeue a failed io).
|
[PATCH] dm: suspend: add noflush pushback
In device-mapper I/O is sometimes queued within targets for later processing.
For example the multipath target can be configured to store I/O when no paths
are available instead of returning it -EIO.
This patch allows the device-mapper core to instruct a target to transfer the
contents of any such in-target queue back into the core. This frees up the
resources used by the target so the core can replace that target with an
alternative one and then resend the I/O to it. Without this patch the only
way to change the target in such circumstances involves returning the I/O with
an error back to the filesystem/application. In the multipath case, this
patch will let us add new paths for existing I/O to try after all the existing
paths have failed.
DMF_NOFLUSH_SUSPENDING
----------------------
If the DM_NOFLUSH_FLAG ioctl option is specified at suspend time, the
DMF_NOFLUSH_SUSPENDING flag is set in md->flags during dm_suspend(). It
is always cleared before dm_suspend() returns.
The flag must be visible while the target is flushing pending I/Os so it
is set before presuspend where the flush starts and unset after the wait
for md->pending where the flush ends.
Target drivers can check this flag by calling dm_noflush_suspending().
DM_MAPIO_REQUEUE / DM_ENDIO_REQUEUE
-----------------------------------
A target's map() function can now return DM_MAPIO_REQUEUE to request the
device mapper core queue the bio.
Similarly, a target's end_io() function can return DM_ENDIO_REQUEUE to request
the same. This has been labelled 'pushback'.
The __map_bio() and clone_endio() functions in the core treat these return
values as errors and call dec_pending() to end the I/O.
dec_pending
-----------
dec_pending() saves the pushback request in struct dm_io->error. Once all
the split clones have ended, dec_pending() will put the original bio on
the md->pushback list. Note that this supercedes any I/O errors.
It is possible for the suspend with DM_NOFLUSH_FLAG to be aborted while
in progress (e.g. by user interrupt). dec_pending() checks for this and
returns -EIO if it happened.
pushdback list and pushback_lock
--------------------------------
The bio is queued on md->pushback temporarily in dec_pending(), and after
all pending I/Os return, md->pushback is merged into md->deferred in
dm_suspend() for re-issuing at resume time.
md->pushback_lock protects md->pushback.
The lock should be held with irq disabled because dec_pending() can be
called from interrupt context.
Queueing bios to md->pushback in dec_pending() must be done atomically
with the check for DMF_NOFLUSH_SUSPENDING flag. So md->pushback_lock is
held when checking the flag. Otherwise dec_pending() may queue a bio to
md->pushback after the interrupted dm_suspend() flushes md->pushback.
Then the bio would be left in md->pushback.
Flag setting in dm_suspend() can be done without md->pushback_lock because
the flag is checked only after presuspend and the set value is already
made visible via the target's presuspend function.
The flag can be checked without md->pushback_lock (e.g. the first part of
the dec_pending() or target drivers), because the flag is checked again
with md->pushback_lock held when the bio is really queued to md->pushback
as described above. So even if the flag is cleared after the lockless
checkings, the bio isn't left in md->pushback but returned to applications
with -EIO.
Other notes on the current patch
--------------------------------
- md->pushback is added to the struct mapped_device instead of using
md->deferred directly because md->io_lock which protects md->deferred is
rw_semaphore and can't be used in interrupt context like dec_pending(),
and md->io_lock protects the DMF_BLOCK_IO flag of md->flags too.
- Don't issue lock_fs() in dm_suspend() if the DM_NOFLUSH_FLAG
ioctl option is specified, because I/Os generated by lock_fs() would be
pushed back and never return if there were no valid devices.
- If an error occurs in dm_suspend() after the DMF_NOFLUSH_SUSPENDING
flag is set, md->pushback must be flushed because I/Os may be queued to
the list already. (flush_and_out label in dm_suspend())
Test results
------------
I have tested using multipath target with the next patch.
The following tests are for regression/compatibility:
- I/Os succeed when valid paths exist;
- I/Os fail when there are no valid paths and queue_if_no_path is not
set;
- I/Os are queued in the multipath target when there are no valid paths and
queue_if_no_path is set;
- The queued I/Os above fail when suspend is issued without the
DM_NOFLUSH_FLAG ioctl option. I/Os spanning 2 multipath targets also
fail.
The following tests are for the normal code path of new pushback feature:
- Queued I/Os in the multipath target are flushed from the target
but don't return when suspend is issued with the DM_NOFLUSH_FLAG
ioctl option;
- The I/Os above are queued in the multipath target again when
resume is issued without path recovery;
- The I/Os above succeed when resume is issued after path recovery
or table load;
- Queued I/Os in the multipath target succeed when resume is issued
with the DM_NOFLUSH_FLAG ioctl option after table load. I/Os
spanning 2 multipath targets also succeed.
The following tests are for the error paths of the new pushback feature:
- When the bdget_disk() fails in dm_suspend(), the
DMF_NOFLUSH_SUSPENDING flag is cleared and I/Os already queued to the
pushback list are flushed properly.
- When suspend with the DM_NOFLUSH_FLAG ioctl option is interrupted,
o I/Os which had already been queued to the pushback list
at the time don't return, and are re-issued at resume time;
o I/Os which hadn't been returned at the time return with EIO.
Signed-off-by: Kiyoshi Ueda <k-ueda@ct.jp.nec.com>
Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Cc: dm-devel@redhat.com
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-08 10:41:09 +00:00
|
|
|
* 2 : The target wants to push back the io
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
typedef int (*dm_endio_fn) (struct dm_target *ti,
|
2017-06-03 07:38:06 +00:00
|
|
|
struct bio *bio, blk_status_t *error);
|
2009-01-06 03:05:07 +00:00
|
|
|
typedef int (*dm_request_endio_fn) (struct dm_target *ti,
|
2017-06-03 07:38:04 +00:00
|
|
|
struct request *clone, blk_status_t error,
|
2009-01-06 03:05:07 +00:00
|
|
|
union map_info *map_context);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
typedef void (*dm_presuspend_fn) (struct dm_target *ti);
|
2014-10-29 00:13:31 +00:00
|
|
|
typedef void (*dm_presuspend_undo_fn) (struct dm_target *ti);
|
2005-04-16 22:20:36 +00:00
|
|
|
typedef void (*dm_postsuspend_fn) (struct dm_target *ti);
|
2006-10-03 08:15:36 +00:00
|
|
|
typedef int (*dm_preresume_fn) (struct dm_target *ti);
|
2005-04-16 22:20:36 +00:00
|
|
|
typedef void (*dm_resume_fn) (struct dm_target *ti);
|
|
|
|
|
2013-03-01 22:45:44 +00:00
|
|
|
typedef void (*dm_status_fn) (struct dm_target *ti, status_type_t status_type,
|
2023-01-25 20:14:58 +00:00
|
|
|
unsigned int status_flags, char *result, unsigned int maxlen);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2023-01-25 20:14:58 +00:00
|
|
|
typedef int (*dm_message_fn) (struct dm_target *ti, unsigned int argc, char **argv,
|
|
|
|
char *result, unsigned int maxlen);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2018-04-03 20:54:10 +00:00
|
|
|
typedef int (*dm_prepare_ioctl_fn) (struct dm_target *ti, struct block_device **bdev);
|
2006-10-03 08:15:15 +00:00
|
|
|
|
2021-02-10 22:38:30 +00:00
|
|
|
#ifdef CONFIG_BLK_DEV_ZONED
|
2019-11-11 02:39:30 +00:00
|
|
|
typedef int (*dm_report_zones_fn) (struct dm_target *ti,
|
|
|
|
struct dm_report_zones_args *args,
|
|
|
|
unsigned int nr_zones);
|
2021-02-10 22:38:30 +00:00
|
|
|
#else
|
|
|
|
/*
|
|
|
|
* Define dm_report_zones_fn so that targets can assign to NULL if
|
|
|
|
* CONFIG_BLK_DEV_ZONED disabled. Otherwise each target needs to do
|
|
|
|
* awkward #ifdefs in their target_type, etc.
|
|
|
|
*/
|
|
|
|
typedef int (*dm_report_zones_fn) (struct dm_target *dummy);
|
|
|
|
#endif
|
2018-10-12 10:08:49 +00:00
|
|
|
|
2013-05-10 13:37:17 +00:00
|
|
|
/*
|
|
|
|
* These iteration functions are typically used to check (and combine)
|
|
|
|
* properties of underlying devices.
|
|
|
|
* E.g. Does at least one underlying device support flush?
|
|
|
|
* Does any underlying device not support WRITE_SAME?
|
|
|
|
*
|
|
|
|
* The callout function is called once for each contiguous section of
|
|
|
|
* an underlying device. State can be maintained in *data.
|
|
|
|
* Return non-zero to stop iterating through any further devices.
|
|
|
|
*/
|
2009-06-22 09:12:33 +00:00
|
|
|
typedef int (*iterate_devices_callout_fn) (struct dm_target *ti,
|
|
|
|
struct dm_dev *dev,
|
2009-07-23 19:30:42 +00:00
|
|
|
sector_t start, sector_t len,
|
2009-06-22 09:12:33 +00:00
|
|
|
void *data);
|
|
|
|
|
2013-05-10 13:37:17 +00:00
|
|
|
/*
|
|
|
|
* This function must iterate through each section of device used by the
|
|
|
|
* target until it encounters a non-zero return code, which it then returns.
|
|
|
|
* Returns zero if no callout returned non-zero.
|
|
|
|
*/
|
2009-06-22 09:12:33 +00:00
|
|
|
typedef int (*dm_iterate_devices_fn) (struct dm_target *ti,
|
|
|
|
iterate_devices_callout_fn fn,
|
|
|
|
void *data);
|
|
|
|
|
2009-09-04 19:40:25 +00:00
|
|
|
typedef void (*dm_io_hints_fn) (struct dm_target *ti,
|
|
|
|
struct queue_limits *limits);
|
|
|
|
|
2009-01-06 03:05:07 +00:00
|
|
|
/*
|
|
|
|
* Returns:
|
|
|
|
* 0: The target can handle the next I/O immediately.
|
|
|
|
* 1: The target can't handle the next I/O immediately.
|
|
|
|
*/
|
|
|
|
typedef int (*dm_busy_fn) (struct dm_target *ti);
|
|
|
|
|
2016-06-22 23:54:53 +00:00
|
|
|
/*
|
|
|
|
* Returns:
|
|
|
|
* < 0 : error
|
|
|
|
* >= 0 : the number of bytes accessible at the address
|
|
|
|
*/
|
2017-04-12 20:37:44 +00:00
|
|
|
typedef long (*dm_dax_direct_access_fn) (struct dm_target *ti, pgoff_t pgoff,
|
2022-05-13 22:10:58 +00:00
|
|
|
long nr_pages, enum dax_access_mode node, void **kaddr,
|
|
|
|
pfn_t *pfn);
|
2020-02-28 16:34:54 +00:00
|
|
|
typedef int (*dm_dax_zero_page_range_fn)(struct dm_target *ti, pgoff_t pgoff,
|
|
|
|
size_t nr_pages);
|
2016-06-22 23:54:53 +00:00
|
|
|
|
2022-04-22 22:45:06 +00:00
|
|
|
/*
|
|
|
|
* Returns:
|
|
|
|
* != 0 : number of bytes transferred
|
|
|
|
* 0 : recovery write failed
|
|
|
|
*/
|
|
|
|
typedef size_t (*dm_dax_recovery_write_fn)(struct dm_target *ti, pgoff_t pgoff,
|
|
|
|
void *addr, size_t bytes, struct iov_iter *i);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
void dm_error(const char *message);
|
|
|
|
|
2008-10-10 12:37:09 +00:00
|
|
|
struct dm_dev {
|
|
|
|
struct block_device *bdev;
|
2017-04-12 20:37:44 +00:00
|
|
|
struct dax_device *dax_dev;
|
2023-06-08 11:02:55 +00:00
|
|
|
blk_mode_t mode;
|
2008-10-10 12:37:09 +00:00
|
|
|
char name[16];
|
|
|
|
};
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Constructors should call these functions to ensure destination devices
|
|
|
|
* are opened/closed correctly.
|
|
|
|
*/
|
2023-06-08 11:02:55 +00:00
|
|
|
int dm_get_device(struct dm_target *ti, const char *path, blk_mode_t mode,
|
2014-06-03 14:30:28 +00:00
|
|
|
struct dm_dev **result);
|
2005-04-16 22:20:36 +00:00
|
|
|
void dm_put_device(struct dm_target *ti, struct dm_dev *d);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Information about a target type
|
|
|
|
*/
|
2009-01-06 03:05:09 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
struct target_type {
|
2009-01-06 03:05:09 +00:00
|
|
|
uint64_t features;
|
2005-04-16 22:20:36 +00:00
|
|
|
const char *name;
|
|
|
|
struct module *module;
|
2023-01-25 20:14:58 +00:00
|
|
|
unsigned int version[3];
|
2005-04-16 22:20:36 +00:00
|
|
|
dm_ctr_fn ctr;
|
|
|
|
dm_dtr_fn dtr;
|
|
|
|
dm_map_fn map;
|
2014-12-18 02:08:12 +00:00
|
|
|
dm_clone_and_map_request_fn clone_and_map_rq;
|
|
|
|
dm_release_clone_request_fn release_clone_rq;
|
2005-04-16 22:20:36 +00:00
|
|
|
dm_endio_fn end_io;
|
2009-01-06 03:05:07 +00:00
|
|
|
dm_request_endio_fn rq_end_io;
|
2005-04-16 22:20:36 +00:00
|
|
|
dm_presuspend_fn presuspend;
|
2014-10-29 00:13:31 +00:00
|
|
|
dm_presuspend_undo_fn presuspend_undo;
|
2005-04-16 22:20:36 +00:00
|
|
|
dm_postsuspend_fn postsuspend;
|
2006-10-03 08:15:36 +00:00
|
|
|
dm_preresume_fn preresume;
|
2005-04-16 22:20:36 +00:00
|
|
|
dm_resume_fn resume;
|
|
|
|
dm_status_fn status;
|
|
|
|
dm_message_fn message;
|
2015-10-15 12:10:50 +00:00
|
|
|
dm_prepare_ioctl_fn prepare_ioctl;
|
2018-10-12 10:08:49 +00:00
|
|
|
dm_report_zones_fn report_zones;
|
2009-01-06 03:05:07 +00:00
|
|
|
dm_busy_fn busy;
|
2009-06-22 09:12:33 +00:00
|
|
|
dm_iterate_devices_fn iterate_devices;
|
2009-09-04 19:40:25 +00:00
|
|
|
dm_io_hints_fn io_hints;
|
2017-04-12 20:37:44 +00:00
|
|
|
dm_dax_direct_access_fn direct_access;
|
2020-02-28 16:34:54 +00:00
|
|
|
dm_dax_zero_page_range_fn dax_zero_page_range;
|
2022-04-22 22:45:06 +00:00
|
|
|
dm_dax_recovery_write_fn dax_recovery_write;
|
2009-04-02 18:55:28 +00:00
|
|
|
|
|
|
|
/* For internal device-mapper use. */
|
|
|
|
struct list_head list;
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
2011-10-31 20:19:00 +00:00
|
|
|
/*
|
|
|
|
* Target features
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Any table that contains an instance of this target must have only one.
|
|
|
|
*/
|
|
|
|
#define DM_TARGET_SINGLETON 0x00000001
|
|
|
|
#define dm_target_needs_singleton(type) ((type)->features & DM_TARGET_SINGLETON)
|
|
|
|
|
2011-10-31 20:19:02 +00:00
|
|
|
/*
|
|
|
|
* Indicates that a target does not support read-only devices.
|
|
|
|
*/
|
|
|
|
#define DM_TARGET_ALWAYS_WRITEABLE 0x00000002
|
|
|
|
#define dm_target_always_writeable(type) \
|
|
|
|
((type)->features & DM_TARGET_ALWAYS_WRITEABLE)
|
|
|
|
|
2011-10-31 20:19:04 +00:00
|
|
|
/*
|
|
|
|
* Any device that contains a table with an instance of this target may never
|
|
|
|
* have tables containing any different target type.
|
|
|
|
*/
|
|
|
|
#define DM_TARGET_IMMUTABLE 0x00000004
|
|
|
|
#define dm_target_is_immutable(type) ((type)->features & DM_TARGET_IMMUTABLE)
|
|
|
|
|
2016-02-06 23:38:46 +00:00
|
|
|
/*
|
|
|
|
* Indicates that a target may replace any target; even immutable targets.
|
|
|
|
* .map, .map_rq, .clone_and_map_rq and .release_clone_rq are all defined.
|
|
|
|
*/
|
|
|
|
#define DM_TARGET_WILDCARD 0x00000008
|
|
|
|
#define dm_target_is_wildcard(type) ((type)->features & DM_TARGET_WILDCARD)
|
|
|
|
|
2017-01-04 19:23:51 +00:00
|
|
|
/*
|
|
|
|
* A target implements own bio data integrity.
|
|
|
|
*/
|
|
|
|
#define DM_TARGET_INTEGRITY 0x00000010
|
|
|
|
#define dm_target_has_integrity(type) ((type)->features & DM_TARGET_INTEGRITY)
|
|
|
|
|
2017-04-18 20:51:48 +00:00
|
|
|
/*
|
|
|
|
* A target passes integrity data to the lower device.
|
|
|
|
*/
|
|
|
|
#define DM_TARGET_PASSES_INTEGRITY 0x00000020
|
|
|
|
#define dm_target_passes_integrity(type) ((type)->features & DM_TARGET_PASSES_INTEGRITY)
|
|
|
|
|
2017-05-08 23:40:43 +00:00
|
|
|
/*
|
2021-03-16 04:36:02 +00:00
|
|
|
* Indicates support for zoned block devices:
|
|
|
|
* - DM_TARGET_ZONED_HM: the target also supports host-managed zoned
|
|
|
|
* block devices but does not support combining different zoned models.
|
|
|
|
* - DM_TARGET_MIXED_ZONED_MODEL: the target supports combining multiple
|
|
|
|
* devices with different zoned models.
|
2017-05-08 23:40:43 +00:00
|
|
|
*/
|
2021-02-10 22:38:30 +00:00
|
|
|
#ifdef CONFIG_BLK_DEV_ZONED
|
2017-05-08 23:40:43 +00:00
|
|
|
#define DM_TARGET_ZONED_HM 0x00000040
|
|
|
|
#define dm_target_supports_zoned_hm(type) ((type)->features & DM_TARGET_ZONED_HM)
|
2021-02-10 22:38:30 +00:00
|
|
|
#else
|
|
|
|
#define DM_TARGET_ZONED_HM 0x00000000
|
|
|
|
#define dm_target_supports_zoned_hm(type) (false)
|
|
|
|
#endif
|
2017-05-08 23:40:43 +00:00
|
|
|
|
2020-09-23 20:06:52 +00:00
|
|
|
/*
|
|
|
|
* A target handles REQ_NOWAIT
|
|
|
|
*/
|
|
|
|
#define DM_TARGET_NOWAIT 0x00000080
|
|
|
|
#define dm_target_supports_nowait(type) ((type)->features & DM_TARGET_NOWAIT)
|
|
|
|
|
2021-02-01 05:10:17 +00:00
|
|
|
/*
|
|
|
|
* A target supports passing through inline crypto support.
|
|
|
|
*/
|
|
|
|
#define DM_TARGET_PASSES_CRYPTO 0x00000100
|
|
|
|
#define dm_target_passes_crypto(type) ((type)->features & DM_TARGET_PASSES_CRYPTO)
|
|
|
|
|
2021-03-16 04:36:02 +00:00
|
|
|
#ifdef CONFIG_BLK_DEV_ZONED
|
|
|
|
#define DM_TARGET_MIXED_ZONED_MODEL 0x00000200
|
|
|
|
#define dm_target_supports_mixed_zoned_model(type) \
|
|
|
|
((type)->features & DM_TARGET_MIXED_ZONED_MODEL)
|
|
|
|
#else
|
|
|
|
#define DM_TARGET_MIXED_ZONED_MODEL 0x00000000
|
|
|
|
#define dm_target_supports_mixed_zoned_model(type) (false)
|
|
|
|
#endif
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
struct dm_target {
|
|
|
|
struct dm_table *table;
|
|
|
|
struct target_type *type;
|
|
|
|
|
|
|
|
/* target limits */
|
|
|
|
sector_t begin;
|
|
|
|
sector_t len;
|
|
|
|
|
2012-07-27 14:08:00 +00:00
|
|
|
/* If non-zero, maximum size of I/O submitted to a target. */
|
|
|
|
uint32_t max_io_len;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-06-22 09:12:20 +00:00
|
|
|
/*
|
2013-03-01 22:45:47 +00:00
|
|
|
* A number of zero-length barrier bios that will be submitted
|
2009-06-22 09:12:20 +00:00
|
|
|
* to the target for the purpose of flushing cache.
|
|
|
|
*
|
2013-03-01 22:45:47 +00:00
|
|
|
* The bio number can be accessed with dm_bio_get_target_bio_nr.
|
|
|
|
* It is a responsibility of the target driver to remap these bios
|
2009-06-22 09:12:20 +00:00
|
|
|
* to the real underlying devices.
|
|
|
|
*/
|
2023-01-25 20:14:58 +00:00
|
|
|
unsigned int num_flush_bios;
|
2009-06-22 09:12:20 +00:00
|
|
|
|
2010-08-12 03:14:08 +00:00
|
|
|
/*
|
2013-03-01 22:45:47 +00:00
|
|
|
* The number of discard bios that will be submitted to the target.
|
|
|
|
* The bio number can be accessed with dm_bio_get_target_bio_nr.
|
2010-08-12 03:14:08 +00:00
|
|
|
*/
|
2023-01-25 20:14:58 +00:00
|
|
|
unsigned int num_discard_bios;
|
2010-08-12 03:14:08 +00:00
|
|
|
|
2018-03-13 09:23:45 +00:00
|
|
|
/*
|
|
|
|
* The number of secure erase bios that will be submitted to the target.
|
|
|
|
* The bio number can be accessed with dm_bio_get_target_bio_nr.
|
|
|
|
*/
|
2023-01-25 20:14:58 +00:00
|
|
|
unsigned int num_secure_erase_bios;
|
2018-03-13 09:23:45 +00:00
|
|
|
|
2017-04-05 17:21:05 +00:00
|
|
|
/*
|
|
|
|
* The number of WRITE ZEROES bios that will be submitted to the target.
|
|
|
|
* The bio number can be accessed with dm_bio_get_target_bio_nr.
|
|
|
|
*/
|
2023-01-25 20:14:58 +00:00
|
|
|
unsigned int num_write_zeroes_bios;
|
2017-04-05 17:21:05 +00:00
|
|
|
|
2012-12-21 20:23:38 +00:00
|
|
|
/*
|
2016-01-31 18:28:26 +00:00
|
|
|
* The minimum number of extra bytes allocated in each io for the
|
|
|
|
* target to use.
|
2012-12-21 20:23:38 +00:00
|
|
|
*/
|
2023-01-25 20:14:58 +00:00
|
|
|
unsigned int per_io_data_size;
|
2012-12-21 20:23:38 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* target specific data */
|
|
|
|
void *private;
|
|
|
|
|
|
|
|
/* Used to provide an error string from the ctr */
|
|
|
|
char *error;
|
2011-05-29 11:52:55 +00:00
|
|
|
|
2012-07-27 14:08:07 +00:00
|
|
|
/*
|
|
|
|
* Set if this target needs to receive flushes regardless of
|
|
|
|
* whether or not its underlying devices have support.
|
|
|
|
*/
|
|
|
|
bool flush_supported:1;
|
|
|
|
|
2011-05-29 11:52:55 +00:00
|
|
|
/*
|
|
|
|
* Set if this target needs to receive discards regardless of
|
|
|
|
* whether or not its underlying devices have support.
|
|
|
|
*/
|
2012-07-27 14:08:08 +00:00
|
|
|
bool discards_supported:1;
|
2021-02-10 20:26:23 +00:00
|
|
|
|
2023-03-01 17:48:43 +00:00
|
|
|
/*
|
2023-04-14 16:07:27 +00:00
|
|
|
* Set if this target requires that discards be split on
|
|
|
|
* 'max_discard_sectors' boundaries.
|
2023-03-01 17:48:43 +00:00
|
|
|
*/
|
|
|
|
bool max_discard_granularity:1;
|
|
|
|
|
2023-04-14 16:07:27 +00:00
|
|
|
/*
|
|
|
|
* Set if this target requires that secure_erases be split on
|
|
|
|
* 'max_secure_erase_sectors' boundaries.
|
|
|
|
*/
|
|
|
|
bool max_secure_erase_granularity:1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set if this target requires that write_zeroes be split on
|
|
|
|
* 'max_write_zeroes_sectors' boundaries.
|
|
|
|
*/
|
|
|
|
bool max_write_zeroes_granularity:1;
|
|
|
|
|
2021-02-10 20:26:23 +00:00
|
|
|
/*
|
|
|
|
* Set if we need to limit the number of in-flight bios when swapping.
|
|
|
|
*/
|
|
|
|
bool limit_swap_bios:1;
|
dm: introduce zone append emulation
For zoned targets that cannot support zone append operations, implement
an emulation using regular write operations. If the original BIO
submitted by the user is a zone append operation, change its clone into
a regular write operation directed at the target zone write pointer
position.
To do so, an array of write pointer offsets (write pointer position
relative to the start of a zone) is added to struct mapped_device. All
operations that modify a sequential zone write pointer (writes, zone
reset, zone finish and zone append) are intersepted in __map_bio() and
processed using the new functions dm_zone_map_bio().
Detection of the target ability to natively support zone append
operations is done from dm_table_set_restrictions() by calling the
function dm_set_zones_restrictions(). A target that does not support
zone append operation, either by explicitly declaring it using the new
struct dm_target field zone_append_not_supported, or because the device
table contains a non-zoned device, has its mapped device marked with the
new flag DMF_ZONE_APPEND_EMULATED. The helper function
dm_emulate_zone_append() is introduced to test a mapped device for this
new flag.
Atomicity of the zones write pointer tracking and updates is done using
a zone write locking mechanism based on a bitmap. This is similar to
the block layer method but based on BIOs rather than struct request.
A zone write lock is taken in dm_zone_map_bio() for any clone BIO with
an operation type that changes the BIO target zone write pointer
position. The zone write lock is released if the clone BIO is failed
before submission or when dm_zone_endio() is called when the clone BIO
completes.
The zone write lock bitmap of the mapped device, together with a bitmap
indicating zone types (conv_zones_bitmap) and the write pointer offset
array (zwp_offset) are allocated and initialized with a full device zone
report in dm_set_zones_restrictions() using the function
dm_revalidate_zones().
For failed operations that may have modified a zone write pointer, the
zone write pointer offset is marked as invalid in dm_zone_endio().
Zones with an invalid write pointer offset are checked and the write
pointer updated using an internal report zone operation when the
faulty zone is accessed again by the user.
All functions added for this emulation have a minimal overhead for
zoned targets natively supporting zone append operations. Regular
device targets are also not affected. The added code also does not
impact builds with CONFIG_BLK_DEV_ZONED disabled by stubbing out all
dm zone related functions.
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
2021-05-25 21:25:00 +00:00
|
|
|
|
|
|
|
/*
|
2022-01-26 13:18:26 +00:00
|
|
|
* Set if this target implements a zoned device and needs emulation of
|
dm: introduce zone append emulation
For zoned targets that cannot support zone append operations, implement
an emulation using regular write operations. If the original BIO
submitted by the user is a zone append operation, change its clone into
a regular write operation directed at the target zone write pointer
position.
To do so, an array of write pointer offsets (write pointer position
relative to the start of a zone) is added to struct mapped_device. All
operations that modify a sequential zone write pointer (writes, zone
reset, zone finish and zone append) are intersepted in __map_bio() and
processed using the new functions dm_zone_map_bio().
Detection of the target ability to natively support zone append
operations is done from dm_table_set_restrictions() by calling the
function dm_set_zones_restrictions(). A target that does not support
zone append operation, either by explicitly declaring it using the new
struct dm_target field zone_append_not_supported, or because the device
table contains a non-zoned device, has its mapped device marked with the
new flag DMF_ZONE_APPEND_EMULATED. The helper function
dm_emulate_zone_append() is introduced to test a mapped device for this
new flag.
Atomicity of the zones write pointer tracking and updates is done using
a zone write locking mechanism based on a bitmap. This is similar to
the block layer method but based on BIOs rather than struct request.
A zone write lock is taken in dm_zone_map_bio() for any clone BIO with
an operation type that changes the BIO target zone write pointer
position. The zone write lock is released if the clone BIO is failed
before submission or when dm_zone_endio() is called when the clone BIO
completes.
The zone write lock bitmap of the mapped device, together with a bitmap
indicating zone types (conv_zones_bitmap) and the write pointer offset
array (zwp_offset) are allocated and initialized with a full device zone
report in dm_set_zones_restrictions() using the function
dm_revalidate_zones().
For failed operations that may have modified a zone write pointer, the
zone write pointer offset is marked as invalid in dm_zone_endio().
Zones with an invalid write pointer offset are checked and the write
pointer updated using an internal report zone operation when the
faulty zone is accessed again by the user.
All functions added for this emulation have a minimal overhead for
zoned targets natively supporting zone append operations. Regular
device targets are also not affected. The added code also does not
impact builds with CONFIG_BLK_DEV_ZONED disabled by stubbing out all
dm zone related functions.
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
2021-05-25 21:25:00 +00:00
|
|
|
* zone append operations using regular writes.
|
|
|
|
*/
|
|
|
|
bool emulate_zone_append:1;
|
2022-02-18 04:40:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set if the target will submit IO using dm_submit_bio_remap()
|
|
|
|
* after returning DM_MAPIO_SUBMITTED from its map function.
|
|
|
|
*/
|
|
|
|
bool accounts_remapped_io:1;
|
2022-07-20 17:58:04 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set if the target will submit the DM bio without first calling
|
|
|
|
* bio_set_dev(). NOTE: ideally a target should _not_ need this.
|
|
|
|
*/
|
|
|
|
bool needs_bio_set_dev:1;
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
2017-12-12 04:17:47 +00:00
|
|
|
void *dm_per_bio_data(struct bio *bio, size_t data_size);
|
|
|
|
struct bio *dm_bio_from_per_bio_data(void *data, size_t data_size);
|
2023-01-25 20:14:58 +00:00
|
|
|
unsigned int dm_bio_get_target_bio_nr(const struct bio *bio);
|
2012-12-21 20:23:39 +00:00
|
|
|
|
2020-04-30 20:48:29 +00:00
|
|
|
u64 dm_start_time_ns_from_clone(struct bio *bio);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
int dm_register_target(struct target_type *t);
|
2009-01-06 03:04:58 +00:00
|
|
|
void dm_unregister_target(struct target_type *t);
|
2006-06-26 07:27:33 +00:00
|
|
|
|
2011-08-02 11:32:04 +00:00
|
|
|
/*
|
|
|
|
* Target argument parsing.
|
|
|
|
*/
|
|
|
|
struct dm_arg_set {
|
2023-01-25 20:14:58 +00:00
|
|
|
unsigned int argc;
|
2011-08-02 11:32:04 +00:00
|
|
|
char **argv;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The minimum and maximum value of a numeric argument, together with
|
|
|
|
* the error message to use if the number is found to be outside that range.
|
|
|
|
*/
|
|
|
|
struct dm_arg {
|
2023-01-25 20:14:58 +00:00
|
|
|
unsigned int min;
|
|
|
|
unsigned int max;
|
2011-08-02 11:32:04 +00:00
|
|
|
char *error;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Validate the next argument, either returning it as *value or, if invalid,
|
|
|
|
* returning -EINVAL and setting *error.
|
|
|
|
*/
|
2017-06-22 18:32:45 +00:00
|
|
|
int dm_read_arg(const struct dm_arg *arg, struct dm_arg_set *arg_set,
|
2023-01-25 20:14:58 +00:00
|
|
|
unsigned int *value, char **error);
|
2011-08-02 11:32:04 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Process the next argument as the start of a group containing between
|
|
|
|
* arg->min and arg->max further arguments. Either return the size as
|
|
|
|
* *num_args or, if invalid, return -EINVAL and set *error.
|
|
|
|
*/
|
2017-06-22 18:32:45 +00:00
|
|
|
int dm_read_arg_group(const struct dm_arg *arg, struct dm_arg_set *arg_set,
|
2023-01-25 20:14:58 +00:00
|
|
|
unsigned int *num_args, char **error);
|
2011-08-02 11:32:04 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Return the current argument and shift to the next.
|
|
|
|
*/
|
|
|
|
const char *dm_shift_arg(struct dm_arg_set *as);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Move through num_args arguments.
|
|
|
|
*/
|
2023-01-25 20:14:58 +00:00
|
|
|
void dm_consume_args(struct dm_arg_set *as, unsigned int num_args);
|
2011-08-02 11:32:04 +00:00
|
|
|
|
2023-01-26 14:48:30 +00:00
|
|
|
/*
|
|
|
|
*----------------------------------------------------------------
|
2006-06-26 07:27:33 +00:00
|
|
|
* Functions for creating and manipulating mapped devices.
|
|
|
|
* Drop the reference with dm_put when you finish with the object.
|
2023-01-26 14:48:30 +00:00
|
|
|
*----------------------------------------------------------------
|
|
|
|
*/
|
2006-06-26 07:27:33 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* DM_ANY_MINOR chooses the next available minor number.
|
|
|
|
*/
|
|
|
|
#define DM_ANY_MINOR (-1)
|
|
|
|
int dm_create(int minor, struct mapped_device **md);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reference counting for md.
|
|
|
|
*/
|
|
|
|
struct mapped_device *dm_get_md(dev_t dev);
|
|
|
|
void dm_get(struct mapped_device *md);
|
dm snapshot: suspend merging snapshot when doing exception handover
The "dm snapshot: suspend origin when doing exception handover" commit
fixed a exception store handover bug associated with pending exceptions
to the "snapshot-origin" target.
However, a similar problem exists in snapshot merging. When snapshot
merging is in progress, we use the target "snapshot-merge" instead of
"snapshot-origin". Consequently, during exception store handover, we
must find the snapshot-merge target and suspend its associated
mapped_device.
To avoid lockdep warnings, the target must be suspended and resumed
without holding _origins_lock.
Introduce a dm_hold() function that grabs a reference on a
mapped_device, but unlike dm_get(), it doesn't crash if the device has
the DMF_FREEING flag set, it returns an error in this case.
In snapshot_resume() we grab the reference to the origin device using
dm_hold() while holding _origins_lock (_origins_lock guarantees that the
device won't disappear). Then we release _origins_lock, suspend the
device and grab _origins_lock again.
NOTE to stable@ people:
When backporting to kernels 3.18 and older, use dm_internal_suspend and
dm_internal_resume instead of dm_internal_suspend_fast and
dm_internal_resume_fast.
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Cc: stable@vger.kernel.org
2015-02-26 16:41:28 +00:00
|
|
|
int dm_hold(struct mapped_device *md);
|
2006-06-26 07:27:33 +00:00
|
|
|
void dm_put(struct mapped_device *md);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* An arbitrary pointer may be stored alongside a mapped device.
|
|
|
|
*/
|
|
|
|
void dm_set_mdptr(struct mapped_device *md, void *ptr);
|
|
|
|
void *dm_get_mdptr(struct mapped_device *md);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A device can still be used while suspended, but I/O is deferred.
|
|
|
|
*/
|
2023-01-25 20:14:58 +00:00
|
|
|
int dm_suspend(struct mapped_device *md, unsigned int suspend_flags);
|
2006-06-26 07:27:33 +00:00
|
|
|
int dm_resume(struct mapped_device *md);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Event functions.
|
|
|
|
*/
|
|
|
|
uint32_t dm_get_event_nr(struct mapped_device *md);
|
|
|
|
int dm_wait_event(struct mapped_device *md, int event_nr);
|
2007-10-19 21:48:01 +00:00
|
|
|
uint32_t dm_next_uevent_seq(struct mapped_device *md);
|
|
|
|
void dm_uevent_add(struct mapped_device *md, struct list_head *elist);
|
2006-06-26 07:27:33 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Info functions.
|
|
|
|
*/
|
2006-06-26 07:27:35 +00:00
|
|
|
const char *dm_device_name(struct mapped_device *md);
|
2007-10-19 21:47:59 +00:00
|
|
|
int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid);
|
2006-06-26 07:27:33 +00:00
|
|
|
struct gendisk *dm_disk(struct mapped_device *md);
|
2009-12-10 23:52:27 +00:00
|
|
|
int dm_suspended(struct dm_target *ti);
|
2020-07-23 14:42:09 +00:00
|
|
|
int dm_post_suspending(struct dm_target *ti);
|
[PATCH] dm: suspend: add noflush pushback
In device-mapper I/O is sometimes queued within targets for later processing.
For example the multipath target can be configured to store I/O when no paths
are available instead of returning it -EIO.
This patch allows the device-mapper core to instruct a target to transfer the
contents of any such in-target queue back into the core. This frees up the
resources used by the target so the core can replace that target with an
alternative one and then resend the I/O to it. Without this patch the only
way to change the target in such circumstances involves returning the I/O with
an error back to the filesystem/application. In the multipath case, this
patch will let us add new paths for existing I/O to try after all the existing
paths have failed.
DMF_NOFLUSH_SUSPENDING
----------------------
If the DM_NOFLUSH_FLAG ioctl option is specified at suspend time, the
DMF_NOFLUSH_SUSPENDING flag is set in md->flags during dm_suspend(). It
is always cleared before dm_suspend() returns.
The flag must be visible while the target is flushing pending I/Os so it
is set before presuspend where the flush starts and unset after the wait
for md->pending where the flush ends.
Target drivers can check this flag by calling dm_noflush_suspending().
DM_MAPIO_REQUEUE / DM_ENDIO_REQUEUE
-----------------------------------
A target's map() function can now return DM_MAPIO_REQUEUE to request the
device mapper core queue the bio.
Similarly, a target's end_io() function can return DM_ENDIO_REQUEUE to request
the same. This has been labelled 'pushback'.
The __map_bio() and clone_endio() functions in the core treat these return
values as errors and call dec_pending() to end the I/O.
dec_pending
-----------
dec_pending() saves the pushback request in struct dm_io->error. Once all
the split clones have ended, dec_pending() will put the original bio on
the md->pushback list. Note that this supercedes any I/O errors.
It is possible for the suspend with DM_NOFLUSH_FLAG to be aborted while
in progress (e.g. by user interrupt). dec_pending() checks for this and
returns -EIO if it happened.
pushdback list and pushback_lock
--------------------------------
The bio is queued on md->pushback temporarily in dec_pending(), and after
all pending I/Os return, md->pushback is merged into md->deferred in
dm_suspend() for re-issuing at resume time.
md->pushback_lock protects md->pushback.
The lock should be held with irq disabled because dec_pending() can be
called from interrupt context.
Queueing bios to md->pushback in dec_pending() must be done atomically
with the check for DMF_NOFLUSH_SUSPENDING flag. So md->pushback_lock is
held when checking the flag. Otherwise dec_pending() may queue a bio to
md->pushback after the interrupted dm_suspend() flushes md->pushback.
Then the bio would be left in md->pushback.
Flag setting in dm_suspend() can be done without md->pushback_lock because
the flag is checked only after presuspend and the set value is already
made visible via the target's presuspend function.
The flag can be checked without md->pushback_lock (e.g. the first part of
the dec_pending() or target drivers), because the flag is checked again
with md->pushback_lock held when the bio is really queued to md->pushback
as described above. So even if the flag is cleared after the lockless
checkings, the bio isn't left in md->pushback but returned to applications
with -EIO.
Other notes on the current patch
--------------------------------
- md->pushback is added to the struct mapped_device instead of using
md->deferred directly because md->io_lock which protects md->deferred is
rw_semaphore and can't be used in interrupt context like dec_pending(),
and md->io_lock protects the DMF_BLOCK_IO flag of md->flags too.
- Don't issue lock_fs() in dm_suspend() if the DM_NOFLUSH_FLAG
ioctl option is specified, because I/Os generated by lock_fs() would be
pushed back and never return if there were no valid devices.
- If an error occurs in dm_suspend() after the DMF_NOFLUSH_SUSPENDING
flag is set, md->pushback must be flushed because I/Os may be queued to
the list already. (flush_and_out label in dm_suspend())
Test results
------------
I have tested using multipath target with the next patch.
The following tests are for regression/compatibility:
- I/Os succeed when valid paths exist;
- I/Os fail when there are no valid paths and queue_if_no_path is not
set;
- I/Os are queued in the multipath target when there are no valid paths and
queue_if_no_path is set;
- The queued I/Os above fail when suspend is issued without the
DM_NOFLUSH_FLAG ioctl option. I/Os spanning 2 multipath targets also
fail.
The following tests are for the normal code path of new pushback feature:
- Queued I/Os in the multipath target are flushed from the target
but don't return when suspend is issued with the DM_NOFLUSH_FLAG
ioctl option;
- The I/Os above are queued in the multipath target again when
resume is issued without path recovery;
- The I/Os above succeed when resume is issued after path recovery
or table load;
- Queued I/Os in the multipath target succeed when resume is issued
with the DM_NOFLUSH_FLAG ioctl option after table load. I/Os
spanning 2 multipath targets also succeed.
The following tests are for the error paths of the new pushback feature:
- When the bdget_disk() fails in dm_suspend(), the
DMF_NOFLUSH_SUSPENDING flag is cleared and I/Os already queued to the
pushback list are flushed properly.
- When suspend with the DM_NOFLUSH_FLAG ioctl option is interrupted,
o I/Os which had already been queued to the pushback list
at the time don't return, and are re-issued at resume time;
o I/Os which hadn't been returned at the time return with EIO.
Signed-off-by: Kiyoshi Ueda <k-ueda@ct.jp.nec.com>
Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Cc: dm-devel@redhat.com
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-08 10:41:09 +00:00
|
|
|
int dm_noflush_suspending(struct dm_target *ti);
|
2023-01-25 20:14:58 +00:00
|
|
|
void dm_accept_partial_bio(struct bio *bio, unsigned int n_sectors);
|
2022-03-10 16:45:58 +00:00
|
|
|
void dm_submit_bio_remap(struct bio *clone, struct bio *tgt_clone);
|
dm: prepare for request based option
This patch adds core functions for request-based dm.
When struct mapped device (md) is initialized, md->queue has
an I/O scheduler and the following functions are used for
request-based dm as the queue functions:
make_request_fn: dm_make_request()
pref_fn: dm_prep_fn()
request_fn: dm_request_fn()
softirq_done_fn: dm_softirq_done()
lld_busy_fn: dm_lld_busy()
Actual initializations are done in another patch (PATCH 2).
Below is a brief summary of how request-based dm behaves, including:
- making request from bio
- cloning, mapping and dispatching request
- completing request and bio
- suspending md
- resuming md
bio to request
==============
md->queue->make_request_fn() (dm_make_request()) calls __make_request()
for a bio submitted to the md.
Then, the bio is kept in the queue as a new request or merged into
another request in the queue if possible.
Cloning and Mapping
===================
Cloning and mapping are done in md->queue->request_fn() (dm_request_fn()),
when requests are dispatched after they are sorted by the I/O scheduler.
dm_request_fn() checks busy state of underlying devices using
target's busy() function and stops dispatching requests to keep them
on the dm device's queue if busy.
It helps better I/O merging, since no merge is done for a request
once it is dispatched to underlying devices.
Actual cloning and mapping are done in dm_prep_fn() and map_request()
called from dm_request_fn().
dm_prep_fn() clones not only request but also bios of the request
so that dm can hold bio completion in error cases and prevent
the bio submitter from noticing the error.
(See the "Completion" section below for details.)
After the cloning, the clone is mapped by target's map_rq() function
and inserted to underlying device's queue using
blk_insert_cloned_request().
Completion
==========
Request completion can be hooked by rq->end_io(), but then, all bios
in the request will have been completed even error cases, and the bio
submitter will have noticed the error.
To prevent the bio completion in error cases, request-based dm clones
both bio and request and hooks both bio->bi_end_io() and rq->end_io():
bio->bi_end_io(): end_clone_bio()
rq->end_io(): end_clone_request()
Summary of the request completion flow is below:
blk_end_request() for a clone request
=> blk_update_request()
=> bio->bi_end_io() == end_clone_bio() for each clone bio
=> Free the clone bio
=> Success: Complete the original bio (blk_update_request())
Error: Don't complete the original bio
=> blk_finish_request()
=> rq->end_io() == end_clone_request()
=> blk_complete_request()
=> dm_softirq_done()
=> Free the clone request
=> Success: Complete the original request (blk_end_request())
Error: Requeue the original request
end_clone_bio() completes the original request on the size of
the original bio in successful cases.
Even if all bios in the original request are completed by that
completion, the original request must not be completed yet to keep
the ordering of request completion for the stacking.
So end_clone_bio() uses blk_update_request() instead of
blk_end_request().
In error cases, end_clone_bio() doesn't complete the original bio.
It just frees the cloned bio and gives over the error handling to
end_clone_request().
end_clone_request(), which is called with queue lock held, completes
the clone request and the original request in a softirq context
(dm_softirq_done()), which has no queue lock, to avoid a deadlock
issue on submission of another request during the completion:
- The submitted request may be mapped to the same device
- Request submission requires queue lock, but the queue lock
has been held by itself and it doesn't know that
The clone request has no clone bio when dm_softirq_done() is called.
So target drivers can't resubmit it again even error cases.
Instead, they can ask dm core for requeueing and remapping
the original request in that cases.
suspend
=======
Request-based dm uses stopping md->queue as suspend of the md.
For noflush suspend, just stops md->queue.
For flush suspend, inserts a marker request to the tail of md->queue.
And dispatches all requests in md->queue until the marker comes to
the front of md->queue. Then, stops dispatching request and waits
for the all dispatched requests to complete.
After that, completes the marker request, stops md->queue and
wake up the waiter on the suspend queue, md->wait.
resume
======
Starts md->queue.
Signed-off-by: Kiyoshi Ueda <k-ueda@ct.jp.nec.com>
Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
2009-06-22 09:12:35 +00:00
|
|
|
union map_info *dm_get_rq_mapinfo(struct request *rq);
|
2006-06-26 07:27:33 +00:00
|
|
|
|
2019-11-11 02:39:30 +00:00
|
|
|
#ifdef CONFIG_BLK_DEV_ZONED
|
|
|
|
struct dm_report_zones_args {
|
|
|
|
struct dm_target *tgt;
|
|
|
|
sector_t next_sector;
|
|
|
|
|
|
|
|
void *orig_data;
|
|
|
|
report_zones_cb orig_cb;
|
|
|
|
unsigned int zone_idx;
|
|
|
|
|
|
|
|
/* must be filled by ->report_zones before calling dm_report_zones_cb */
|
|
|
|
sector_t start;
|
|
|
|
};
|
2021-05-25 21:24:57 +00:00
|
|
|
int dm_report_zones(struct block_device *bdev, sector_t start, sector_t sector,
|
|
|
|
struct dm_report_zones_args *args, unsigned int nr_zones);
|
2019-11-11 02:39:30 +00:00
|
|
|
#endif /* CONFIG_BLK_DEV_ZONED */
|
|
|
|
|
dm: add support to directly boot to a mapped device
Add a "create" module parameter, which allows device-mapper targets to
be configured at boot time. This enables early use of DM targets in the
boot process (as the root device or otherwise) without the need of an
initramfs.
The syntax used in the boot param is based on the concise format from
the dmsetup tool to follow the rule of least surprise:
dmsetup table --concise /dev/mapper/lroot
Which is:
dm-mod.create=<name>,<uuid>,<minor>,<flags>,<table>[,<table>+][;<name>,<uuid>,<minor>,<flags>,<table>[,<table>+]+]
Where,
<name> ::= The device name.
<uuid> ::= xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | ""
<minor> ::= The device minor number | ""
<flags> ::= "ro" | "rw"
<table> ::= <start_sector> <num_sectors> <target_type> <target_args>
<target_type> ::= "verity" | "linear" | ...
For example, the following could be added in the boot parameters:
dm-mod.create="lroot,,,rw, 0 4096 linear 98:16 0, 4096 4096 linear 98:32 0" root=/dev/dm-0
Only the targets that were tested are allowed and the ones that don't
change any block device when the device is create as read-only. For
example, mirror and cache targets are not allowed. The rationale behind
this is that if the user makes a mistake, choosing the wrong device to
be the mirror or the cache can corrupt data.
The only targets initially allowed are:
* crypt
* delay
* linear
* snapshot-origin
* striped
* verity
Co-developed-by: Will Drewry <wad@chromium.org>
Co-developed-by: Kees Cook <keescook@chromium.org>
Co-developed-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Signed-off-by: Helen Koike <helen.koike@collabora.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
2019-02-21 20:33:34 +00:00
|
|
|
/*
|
|
|
|
* Device mapper functions to parse and create devices specified by the
|
|
|
|
* parameter "dm-mod.create="
|
|
|
|
*/
|
|
|
|
int __init dm_early_create(struct dm_ioctl *dmi,
|
|
|
|
struct dm_target_spec **spec_array,
|
|
|
|
char **target_params_array);
|
|
|
|
|
2006-06-26 07:27:33 +00:00
|
|
|
/*
|
|
|
|
* Geometry functions.
|
|
|
|
*/
|
|
|
|
int dm_get_geometry(struct mapped_device *md, struct hd_geometry *geo);
|
|
|
|
int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo);
|
|
|
|
|
2023-01-26 14:48:30 +00:00
|
|
|
/*
|
|
|
|
*---------------------------------------------------------------
|
2006-06-26 07:27:33 +00:00
|
|
|
* Functions for manipulating device-mapper tables.
|
2023-01-26 14:48:30 +00:00
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
2006-06-26 07:27:33 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* First create an empty table.
|
|
|
|
*/
|
2023-06-08 11:02:55 +00:00
|
|
|
int dm_table_create(struct dm_table **result, blk_mode_t mode,
|
2023-01-25 20:14:58 +00:00
|
|
|
unsigned int num_targets, struct mapped_device *md);
|
2006-06-26 07:27:33 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Then call this once for each target.
|
|
|
|
*/
|
|
|
|
int dm_table_add_target(struct dm_table *t, const char *type,
|
|
|
|
sector_t start, sector_t len, char *params);
|
|
|
|
|
2016-05-25 01:16:51 +00:00
|
|
|
/*
|
|
|
|
* Target can use this to set the table's type.
|
|
|
|
* Can only ever be called from a target's ctr.
|
|
|
|
* Useful for "hybrid" target (supports both bio-based
|
|
|
|
* and request-based).
|
|
|
|
*/
|
2017-04-27 17:11:23 +00:00
|
|
|
void dm_table_set_type(struct dm_table *t, enum dm_queue_mode type);
|
2011-01-13 20:00:01 +00:00
|
|
|
|
2006-06-26 07:27:33 +00:00
|
|
|
/*
|
|
|
|
* Finally call this to make the table ready for use.
|
|
|
|
*/
|
|
|
|
int dm_table_complete(struct dm_table *t);
|
|
|
|
|
2017-03-28 18:31:02 +00:00
|
|
|
/*
|
|
|
|
* Destroy the table when finished.
|
|
|
|
*/
|
|
|
|
void dm_table_destroy(struct dm_table *t);
|
|
|
|
|
2012-07-27 14:08:00 +00:00
|
|
|
/*
|
|
|
|
* Target may require that it is never sent I/O larger than len.
|
|
|
|
*/
|
|
|
|
int __must_check dm_set_target_max_io_len(struct dm_target *ti, sector_t len);
|
|
|
|
|
2006-06-26 07:27:33 +00:00
|
|
|
/*
|
|
|
|
* Table reference counting.
|
|
|
|
*/
|
2013-07-10 22:41:18 +00:00
|
|
|
struct dm_table *dm_get_live_table(struct mapped_device *md, int *srcu_idx);
|
|
|
|
void dm_put_live_table(struct mapped_device *md, int srcu_idx);
|
|
|
|
void dm_sync_table(struct mapped_device *md);
|
2006-06-26 07:27:33 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Queries
|
|
|
|
*/
|
|
|
|
sector_t dm_table_get_size(struct dm_table *t);
|
2023-06-08 11:02:55 +00:00
|
|
|
blk_mode_t dm_table_get_mode(struct dm_table *t);
|
2006-06-26 07:27:33 +00:00
|
|
|
struct mapped_device *dm_table_get_md(struct dm_table *t);
|
2018-10-09 20:13:42 +00:00
|
|
|
const char *dm_table_device_name(struct dm_table *t);
|
2006-06-26 07:27:33 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Trigger an event.
|
|
|
|
*/
|
|
|
|
void dm_table_event(struct dm_table *t);
|
|
|
|
|
2014-02-28 14:33:43 +00:00
|
|
|
/*
|
|
|
|
* Run the queue for request-based targets.
|
|
|
|
*/
|
|
|
|
void dm_table_run_md_queue_async(struct dm_table *t);
|
|
|
|
|
2006-06-26 07:27:33 +00:00
|
|
|
/*
|
|
|
|
* The device must be suspended before calling this method.
|
2009-12-10 23:52:24 +00:00
|
|
|
* Returns the previous table, which the caller must destroy.
|
2006-06-26 07:27:33 +00:00
|
|
|
*/
|
2009-12-10 23:52:24 +00:00
|
|
|
struct dm_table *dm_swap_table(struct mapped_device *md,
|
|
|
|
struct dm_table *t);
|
2006-06-26 07:27:33 +00:00
|
|
|
|
2021-02-01 05:10:17 +00:00
|
|
|
/*
|
blk-crypto: rename blk_keyslot_manager to blk_crypto_profile
blk_keyslot_manager is misnamed because it doesn't necessarily manage
keyslots. It actually does several different things:
- Contains the crypto capabilities of the device.
- Provides functions to control the inline encryption hardware.
Originally these were just for programming/evicting keyslots;
however, new functionality (hardware-wrapped keys) will require new
functions here which are unrelated to keyslots. Moreover,
device-mapper devices already (ab)use "keyslot_evict" to pass key
eviction requests to their underlying devices even though
device-mapper devices don't have any keyslots themselves (so it
really should be "evict_key", not "keyslot_evict").
- Sometimes (but not always!) it manages keyslots. Originally it
always did, but device-mapper devices don't have keyslots
themselves, so they use a "passthrough keyslot manager" which
doesn't actually manage keyslots. This hack works, but the
terminology is unnatural. Also, some hardware doesn't have keyslots
and thus also uses a "passthrough keyslot manager" (support for such
hardware is yet to be upstreamed, but it will happen eventually).
Let's stop having keyslot managers which don't actually manage keyslots.
Instead, rename blk_keyslot_manager to blk_crypto_profile.
This is a fairly big change, since for consistency it also has to update
keyslot manager-related function names, variable names, and comments --
not just the actual struct name. However it's still a fairly
straightforward change, as it doesn't change any actual functionality.
Acked-by: Ulf Hansson <ulf.hansson@linaro.org> # For MMC
Reviewed-by: Mike Snitzer <snitzer@redhat.com>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
Link: https://lore.kernel.org/r/20211018180453.40441-4-ebiggers@kernel.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2021-10-18 18:04:52 +00:00
|
|
|
* Table blk_crypto_profile functions
|
2021-02-01 05:10:17 +00:00
|
|
|
*/
|
blk-crypto: rename blk_keyslot_manager to blk_crypto_profile
blk_keyslot_manager is misnamed because it doesn't necessarily manage
keyslots. It actually does several different things:
- Contains the crypto capabilities of the device.
- Provides functions to control the inline encryption hardware.
Originally these were just for programming/evicting keyslots;
however, new functionality (hardware-wrapped keys) will require new
functions here which are unrelated to keyslots. Moreover,
device-mapper devices already (ab)use "keyslot_evict" to pass key
eviction requests to their underlying devices even though
device-mapper devices don't have any keyslots themselves (so it
really should be "evict_key", not "keyslot_evict").
- Sometimes (but not always!) it manages keyslots. Originally it
always did, but device-mapper devices don't have keyslots
themselves, so they use a "passthrough keyslot manager" which
doesn't actually manage keyslots. This hack works, but the
terminology is unnatural. Also, some hardware doesn't have keyslots
and thus also uses a "passthrough keyslot manager" (support for such
hardware is yet to be upstreamed, but it will happen eventually).
Let's stop having keyslot managers which don't actually manage keyslots.
Instead, rename blk_keyslot_manager to blk_crypto_profile.
This is a fairly big change, since for consistency it also has to update
keyslot manager-related function names, variable names, and comments --
not just the actual struct name. However it's still a fairly
straightforward change, as it doesn't change any actual functionality.
Acked-by: Ulf Hansson <ulf.hansson@linaro.org> # For MMC
Reviewed-by: Mike Snitzer <snitzer@redhat.com>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
Link: https://lore.kernel.org/r/20211018180453.40441-4-ebiggers@kernel.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2021-10-18 18:04:52 +00:00
|
|
|
void dm_destroy_crypto_profile(struct blk_crypto_profile *profile);
|
2021-02-01 05:10:17 +00:00
|
|
|
|
2023-01-26 14:48:30 +00:00
|
|
|
/*
|
|
|
|
*---------------------------------------------------------------
|
2008-04-24 20:43:52 +00:00
|
|
|
* Macros.
|
2023-01-26 14:48:30 +00:00
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
2008-04-24 20:43:52 +00:00
|
|
|
#define DM_NAME "device-mapper"
|
|
|
|
|
2017-04-20 17:46:07 +00:00
|
|
|
#define DM_FMT(fmt) DM_NAME ": " DM_MSG_PREFIX ": " fmt "\n"
|
|
|
|
|
|
|
|
#define DMCRIT(fmt, ...) pr_crit(DM_FMT(fmt), ##__VA_ARGS__)
|
|
|
|
|
|
|
|
#define DMERR(fmt, ...) pr_err(DM_FMT(fmt), ##__VA_ARGS__)
|
2019-07-17 16:57:06 +00:00
|
|
|
#define DMERR_LIMIT(fmt, ...) pr_err_ratelimited(DM_FMT(fmt), ##__VA_ARGS__)
|
2017-04-20 17:46:07 +00:00
|
|
|
#define DMWARN(fmt, ...) pr_warn(DM_FMT(fmt), ##__VA_ARGS__)
|
2019-07-17 16:57:06 +00:00
|
|
|
#define DMWARN_LIMIT(fmt, ...) pr_warn_ratelimited(DM_FMT(fmt), ##__VA_ARGS__)
|
2017-04-20 17:46:07 +00:00
|
|
|
#define DMINFO(fmt, ...) pr_info(DM_FMT(fmt), ##__VA_ARGS__)
|
2019-07-17 16:57:06 +00:00
|
|
|
#define DMINFO_LIMIT(fmt, ...) pr_info_ratelimited(DM_FMT(fmt), ##__VA_ARGS__)
|
2008-04-24 20:43:52 +00:00
|
|
|
|
2020-05-14 06:09:28 +00:00
|
|
|
#define DMDEBUG(fmt, ...) pr_debug(DM_FMT(fmt), ##__VA_ARGS__)
|
2019-07-17 16:57:06 +00:00
|
|
|
#define DMDEBUG_LIMIT(fmt, ...) pr_debug_ratelimited(DM_FMT(fmt), ##__VA_ARGS__)
|
2008-04-24 20:43:52 +00:00
|
|
|
|
2023-02-01 20:51:04 +00:00
|
|
|
#define DMEMIT(x...) (sz += ((sz >= maxlen) ? 0 : scnprintf(result + sz, maxlen - sz, x)))
|
2008-04-24 20:43:52 +00:00
|
|
|
|
2021-07-13 00:49:03 +00:00
|
|
|
#define DMEMIT_TARGET_NAME_VERSION(y) \
|
|
|
|
DMEMIT("target_name=%s,target_version=%u.%u.%u", \
|
|
|
|
(y)->name, (y)->version[0], (y)->version[1], (y)->version[2])
|
|
|
|
|
2023-04-09 16:43:37 +00:00
|
|
|
/**
|
|
|
|
* module_dm() - Helper macro for DM targets that don't do anything
|
|
|
|
* special in their module_init and module_exit.
|
|
|
|
* Each module may only use this macro once, and calling it replaces
|
|
|
|
* module_init() and module_exit().
|
|
|
|
*
|
|
|
|
* @name: DM target's name
|
|
|
|
*/
|
|
|
|
#define module_dm(name) \
|
|
|
|
static int __init dm_##name##_init(void) \
|
|
|
|
{ \
|
|
|
|
return dm_register_target(&(name##_target)); \
|
|
|
|
} \
|
|
|
|
module_init(dm_##name##_init) \
|
|
|
|
static void __exit dm_##name##_exit(void) \
|
|
|
|
{ \
|
|
|
|
dm_unregister_target(&(name##_target)); \
|
|
|
|
} \
|
|
|
|
module_exit(dm_##name##_exit)
|
|
|
|
|
2008-04-24 20:43:52 +00:00
|
|
|
/*
|
|
|
|
* Definitions of return values from target end_io function.
|
|
|
|
*/
|
2017-04-26 07:40:37 +00:00
|
|
|
#define DM_ENDIO_DONE 0
|
2008-04-24 20:43:52 +00:00
|
|
|
#define DM_ENDIO_INCOMPLETE 1
|
|
|
|
#define DM_ENDIO_REQUEUE 2
|
2018-01-13 00:53:40 +00:00
|
|
|
#define DM_ENDIO_DELAY_REQUEUE 3
|
2008-04-24 20:43:52 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Definitions of return values from target map function.
|
|
|
|
*/
|
|
|
|
#define DM_MAPIO_SUBMITTED 0
|
|
|
|
#define DM_MAPIO_REMAPPED 1
|
|
|
|
#define DM_MAPIO_REQUEUE DM_ENDIO_REQUEUE
|
2018-01-13 00:53:40 +00:00
|
|
|
#define DM_MAPIO_DELAY_REQUEUE DM_ENDIO_DELAY_REQUEUE
|
2017-04-26 07:40:39 +00:00
|
|
|
#define DM_MAPIO_KILL 4
|
2008-04-24 20:43:52 +00:00
|
|
|
|
2013-08-16 14:54:23 +00:00
|
|
|
#define dm_sector_div64(x, y)( \
|
|
|
|
{ \
|
|
|
|
u64 _res; \
|
|
|
|
(x) = div64_u64_rem(x, y, &_res); \
|
|
|
|
_res; \
|
|
|
|
} \
|
|
|
|
)
|
|
|
|
|
2008-04-24 20:43:52 +00:00
|
|
|
/*
|
|
|
|
* Ceiling(n / sz)
|
|
|
|
*/
|
|
|
|
#define dm_div_up(n, sz) (((n) + (sz) - 1) / (sz))
|
|
|
|
|
|
|
|
#define dm_sector_div_up(n, sz) ( \
|
|
|
|
{ \
|
|
|
|
sector_t _r = ((n) + (sz) - 1); \
|
|
|
|
sector_div(_r, (sz)); \
|
|
|
|
_r; \
|
|
|
|
} \
|
|
|
|
)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ceiling(n / size) * size
|
|
|
|
*/
|
|
|
|
#define dm_round_up(n, sz) (dm_div_up((n), (sz)) * (sz))
|
|
|
|
|
2010-08-12 03:14:10 +00:00
|
|
|
/*
|
|
|
|
* Sector offset taken relative to the start of the target instead of
|
|
|
|
* relative to the start of the device.
|
|
|
|
*/
|
|
|
|
#define dm_target_offset(ti, sector) ((sector) - (ti)->begin)
|
|
|
|
|
2019-01-06 10:06:25 +00:00
|
|
|
static inline sector_t to_sector(unsigned long long n)
|
2008-04-24 20:43:52 +00:00
|
|
|
{
|
|
|
|
return (n >> SECTOR_SHIFT);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned long to_bytes(sector_t n)
|
|
|
|
{
|
|
|
|
return (n << SECTOR_SHIFT);
|
|
|
|
}
|
|
|
|
|
2006-06-26 07:27:33 +00:00
|
|
|
#endif /* _LINUX_DEVICE_MAPPER_H */
|