Commit 772ae5f54d69c38a5e3c4352c5fdbdaff141af21

Authored by Milan Broz
Committed by Alasdair G Kergon
1 parent 327372797c

dm crypt: optionally support discard requests

Add optional parameter field to dmcrypt table and support
"allow_discards" option.

Discard requests bypass crypt queue processing. Bio is simple remapped
to underlying device.

Note that discard will be never enabled by default because of security
consequences.  It is up to the administrator to enable it for encrypted
devices.

(Note that userspace cryptsetup does not understand new optional
parameters yet.  Support for this will come later.  Until then, you
should use 'dmsetup' to enable and disable this.)

Signed-off-by: Milan Broz <mbroz@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>

Showing 2 changed files with 65 additions and 5 deletions Side-by-side Diff

Documentation/device-mapper/dm-crypt.txt
... ... @@ -4,7 +4,8 @@
4 4 Device-Mapper's "crypt" target provides transparent encryption of block devices
5 5 using the kernel crypto API.
6 6  
7   -Parameters: <cipher> <key> <iv_offset> <device path> <offset>
  7 +Parameters: <cipher> <key> <iv_offset> <device path> \
  8 + <offset> [<#opt_params> <opt_params>]
8 9  
9 10 <cipher>
10 11 Encryption cipher and an optional IV generation mode.
... ... @@ -36,6 +37,24 @@
36 37  
37 38 <offset>
38 39 Starting sector within the device where the encrypted data begins.
  40 +
  41 +<#opt_params>
  42 + Number of optional parameters. If there are no optional parameters,
  43 + the optional paramaters section can be skipped or #opt_params can be zero.
  44 + Otherwise #opt_params is the number of following arguments.
  45 +
  46 + Example of optional parameters section:
  47 + 1 allow_discards
  48 +
  49 +allow_discards
  50 + Block discard requests (a.k.a. TRIM) are passed through the crypt device.
  51 + The default is to ignore discard requests.
  52 +
  53 + WARNING: Assess the specific security risks carefully before enabling this
  54 + option. For example, allowing discards on encrypted devices may lead to
  55 + the leak of information about the ciphertext device (filesystem type,
  56 + used space etc.) if the discarded blocks can be located easily on the
  57 + device later.
39 58  
40 59 Example scripts
41 60 ===============
drivers/md/dm-crypt.c
... ... @@ -1574,11 +1574,17 @@
1574 1574 static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
1575 1575 {
1576 1576 struct crypt_config *cc;
1577   - unsigned int key_size;
  1577 + unsigned int key_size, opt_params;
1578 1578 unsigned long long tmpll;
1579 1579 int ret;
  1580 + struct dm_arg_set as;
  1581 + const char *opt_string;
1580 1582  
1581   - if (argc != 5) {
  1583 + static struct dm_arg _args[] = {
  1584 + {0, 1, "Invalid number of feature args"},
  1585 + };
  1586 +
  1587 + if (argc < 5) {
1582 1588 ti->error = "Not enough arguments";
1583 1589 return -EINVAL;
1584 1590 }
... ... @@ -1647,6 +1653,30 @@
1647 1653 }
1648 1654 cc->start = tmpll;
1649 1655  
  1656 + argv += 5;
  1657 + argc -= 5;
  1658 +
  1659 + /* Optional parameters */
  1660 + if (argc) {
  1661 + as.argc = argc;
  1662 + as.argv = argv;
  1663 +
  1664 + ret = dm_read_arg_group(_args, &as, &opt_params, &ti->error);
  1665 + if (ret)
  1666 + goto bad;
  1667 +
  1668 + opt_string = dm_shift_arg(&as);
  1669 +
  1670 + if (opt_params == 1 && opt_string &&
  1671 + !strcasecmp(opt_string, "allow_discards"))
  1672 + ti->num_discard_requests = 1;
  1673 + else if (opt_params) {
  1674 + ret = -EINVAL;
  1675 + ti->error = "Invalid feature arguments";
  1676 + goto bad;
  1677 + }
  1678 + }
  1679 +
1650 1680 ret = -ENOMEM;
1651 1681 cc->io_queue = alloc_workqueue("kcryptd_io",
1652 1682 WQ_NON_REENTRANT|
1653 1683  
... ... @@ -1681,9 +1711,16 @@
1681 1711 struct dm_crypt_io *io;
1682 1712 struct crypt_config *cc;
1683 1713  
1684   - if (bio->bi_rw & REQ_FLUSH) {
  1714 + /*
  1715 + * If bio is REQ_FLUSH or REQ_DISCARD, just bypass crypt queues.
  1716 + * - for REQ_FLUSH device-mapper core ensures that no IO is in-flight
  1717 + * - for REQ_DISCARD caller must use flush if IO ordering matters
  1718 + */
  1719 + if (unlikely(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD))) {
1685 1720 cc = ti->private;
1686 1721 bio->bi_bdev = cc->dev->bdev;
  1722 + if (bio_sectors(bio))
  1723 + bio->bi_sector = cc->start + dm_target_offset(ti, bio->bi_sector);
1687 1724 return DM_MAPIO_REMAPPED;
1688 1725 }
1689 1726  
... ... @@ -1726,6 +1763,10 @@
1726 1763  
1727 1764 DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset,
1728 1765 cc->dev->name, (unsigned long long)cc->start);
  1766 +
  1767 + if (ti->num_discard_requests)
  1768 + DMEMIT(" 1 allow_discards");
  1769 +
1729 1770 break;
1730 1771 }
1731 1772 return 0;
... ... @@ -1822,7 +1863,7 @@
1822 1863  
1823 1864 static struct target_type crypt_target = {
1824 1865 .name = "crypt",
1825   - .version = {1, 10, 0},
  1866 + .version = {1, 11, 0},
1826 1867 .module = THIS_MODULE,
1827 1868 .ctr = crypt_ctr,
1828 1869 .dtr = crypt_dtr,