diff options
Diffstat (limited to 'drivers/md/dm-crypt.c')
-rw-r--r-- | drivers/md/dm-crypt.c | 62 |
1 files changed, 51 insertions, 11 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index bae6c4e23d3f..49da55c1528a 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/device-mapper.h> | 30 | #include <linux/device-mapper.h> |
31 | 31 | ||
32 | #define DM_MSG_PREFIX "crypt" | 32 | #define DM_MSG_PREFIX "crypt" |
33 | #define MESG_STR(x) x, sizeof(x) | ||
34 | 33 | ||
35 | /* | 34 | /* |
36 | * context holding the current state of a multi-part conversion | 35 | * context holding the current state of a multi-part conversion |
@@ -239,7 +238,7 @@ static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv, | |||
239 | struct dm_crypt_request *dmreq) | 238 | struct dm_crypt_request *dmreq) |
240 | { | 239 | { |
241 | memset(iv, 0, cc->iv_size); | 240 | memset(iv, 0, cc->iv_size); |
242 | *(u32 *)iv = cpu_to_le32(dmreq->iv_sector & 0xffffffff); | 241 | *(__le32 *)iv = cpu_to_le32(dmreq->iv_sector & 0xffffffff); |
243 | 242 | ||
244 | return 0; | 243 | return 0; |
245 | } | 244 | } |
@@ -248,7 +247,7 @@ static int crypt_iv_plain64_gen(struct crypt_config *cc, u8 *iv, | |||
248 | struct dm_crypt_request *dmreq) | 247 | struct dm_crypt_request *dmreq) |
249 | { | 248 | { |
250 | memset(iv, 0, cc->iv_size); | 249 | memset(iv, 0, cc->iv_size); |
251 | *(u64 *)iv = cpu_to_le64(dmreq->iv_sector); | 250 | *(__le64 *)iv = cpu_to_le64(dmreq->iv_sector); |
252 | 251 | ||
253 | return 0; | 252 | return 0; |
254 | } | 253 | } |
@@ -415,7 +414,7 @@ static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, | |||
415 | struct crypto_cipher *essiv_tfm = this_crypt_config(cc)->iv_private; | 414 | struct crypto_cipher *essiv_tfm = this_crypt_config(cc)->iv_private; |
416 | 415 | ||
417 | memset(iv, 0, cc->iv_size); | 416 | memset(iv, 0, cc->iv_size); |
418 | *(u64 *)iv = cpu_to_le64(dmreq->iv_sector); | 417 | *(__le64 *)iv = cpu_to_le64(dmreq->iv_sector); |
419 | crypto_cipher_encrypt_one(essiv_tfm, iv, iv); | 418 | crypto_cipher_encrypt_one(essiv_tfm, iv, iv); |
420 | 419 | ||
421 | return 0; | 420 | return 0; |
@@ -1575,11 +1574,17 @@ bad_mem: | |||
1575 | static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | 1574 | static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) |
1576 | { | 1575 | { |
1577 | struct crypt_config *cc; | 1576 | struct crypt_config *cc; |
1578 | unsigned int key_size; | 1577 | unsigned int key_size, opt_params; |
1579 | unsigned long long tmpll; | 1578 | unsigned long long tmpll; |
1580 | int ret; | 1579 | int ret; |
1580 | struct dm_arg_set as; | ||
1581 | const char *opt_string; | ||
1582 | |||
1583 | static struct dm_arg _args[] = { | ||
1584 | {0, 1, "Invalid number of feature args"}, | ||
1585 | }; | ||
1581 | 1586 | ||
1582 | if (argc != 5) { | 1587 | if (argc < 5) { |
1583 | ti->error = "Not enough arguments"; | 1588 | ti->error = "Not enough arguments"; |
1584 | return -EINVAL; | 1589 | return -EINVAL; |
1585 | } | 1590 | } |
@@ -1648,6 +1653,30 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1648 | } | 1653 | } |
1649 | cc->start = tmpll; | 1654 | cc->start = tmpll; |
1650 | 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 | |||
1651 | ret = -ENOMEM; | 1680 | ret = -ENOMEM; |
1652 | cc->io_queue = alloc_workqueue("kcryptd_io", | 1681 | cc->io_queue = alloc_workqueue("kcryptd_io", |
1653 | WQ_NON_REENTRANT| | 1682 | WQ_NON_REENTRANT| |
@@ -1682,9 +1711,16 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, | |||
1682 | struct dm_crypt_io *io; | 1711 | struct dm_crypt_io *io; |
1683 | struct crypt_config *cc; | 1712 | struct crypt_config *cc; |
1684 | 1713 | ||
1685 | 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))) { | ||
1686 | cc = ti->private; | 1720 | cc = ti->private; |
1687 | bio->bi_bdev = cc->dev->bdev; | 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); | ||
1688 | return DM_MAPIO_REMAPPED; | 1724 | return DM_MAPIO_REMAPPED; |
1689 | } | 1725 | } |
1690 | 1726 | ||
@@ -1727,6 +1763,10 @@ static int crypt_status(struct dm_target *ti, status_type_t type, | |||
1727 | 1763 | ||
1728 | DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset, | 1764 | DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset, |
1729 | cc->dev->name, (unsigned long long)cc->start); | 1765 | cc->dev->name, (unsigned long long)cc->start); |
1766 | |||
1767 | if (ti->num_discard_requests) | ||
1768 | DMEMIT(" 1 allow_discards"); | ||
1769 | |||
1730 | break; | 1770 | break; |
1731 | } | 1771 | } |
1732 | return 0; | 1772 | return 0; |
@@ -1770,12 +1810,12 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv) | |||
1770 | if (argc < 2) | 1810 | if (argc < 2) |
1771 | goto error; | 1811 | goto error; |
1772 | 1812 | ||
1773 | if (!strnicmp(argv[0], MESG_STR("key"))) { | 1813 | if (!strcasecmp(argv[0], "key")) { |
1774 | if (!test_bit(DM_CRYPT_SUSPENDED, &cc->flags)) { | 1814 | if (!test_bit(DM_CRYPT_SUSPENDED, &cc->flags)) { |
1775 | DMWARN("not suspended during key manipulation."); | 1815 | DMWARN("not suspended during key manipulation."); |
1776 | return -EINVAL; | 1816 | return -EINVAL; |
1777 | } | 1817 | } |
1778 | if (argc == 3 && !strnicmp(argv[1], MESG_STR("set"))) { | 1818 | if (argc == 3 && !strcasecmp(argv[1], "set")) { |
1779 | ret = crypt_set_key(cc, argv[2]); | 1819 | ret = crypt_set_key(cc, argv[2]); |
1780 | if (ret) | 1820 | if (ret) |
1781 | return ret; | 1821 | return ret; |
@@ -1783,7 +1823,7 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv) | |||
1783 | ret = cc->iv_gen_ops->init(cc); | 1823 | ret = cc->iv_gen_ops->init(cc); |
1784 | return ret; | 1824 | return ret; |
1785 | } | 1825 | } |
1786 | if (argc == 2 && !strnicmp(argv[1], MESG_STR("wipe"))) { | 1826 | if (argc == 2 && !strcasecmp(argv[1], "wipe")) { |
1787 | if (cc->iv_gen_ops && cc->iv_gen_ops->wipe) { | 1827 | if (cc->iv_gen_ops && cc->iv_gen_ops->wipe) { |
1788 | ret = cc->iv_gen_ops->wipe(cc); | 1828 | ret = cc->iv_gen_ops->wipe(cc); |
1789 | if (ret) | 1829 | if (ret) |
@@ -1823,7 +1863,7 @@ static int crypt_iterate_devices(struct dm_target *ti, | |||
1823 | 1863 | ||
1824 | static struct target_type crypt_target = { | 1864 | static struct target_type crypt_target = { |
1825 | .name = "crypt", | 1865 | .name = "crypt", |
1826 | .version = {1, 10, 0}, | 1866 | .version = {1, 11, 0}, |
1827 | .module = THIS_MODULE, | 1867 | .module = THIS_MODULE, |
1828 | .ctr = crypt_ctr, | 1868 | .ctr = crypt_ctr, |
1829 | .dtr = crypt_dtr, | 1869 | .dtr = crypt_dtr, |