Files
kernel_samsung_a71/drivers/md/dm-linear.c
Neeraj Soni 88205c5d99 Integrate the new file encryption framework
These changes integrate new file encryption framework to use new V2 encryption policies.

These changes were earlier reverted in 'commit 4211691d29 ("Reverting crypto and incrementalfs changes")',
as part of android-4.14.171 merge from Android common kernel. This patch attempts to bring them back
post validation.

commit a9a5450 ANDROID: dm: prevent default-key from being enabled without needed hooks
commit e1a94e6 ANDROID: dm: add dm-default-key target for metadata encryption
commit commit 232fd35 ANDROID: dm: enable may_passthrough_inline_crypto on some targets
commit 53bc059 ANDROID: dm: add support for passing through inline crypto support
commit aeed6db ANDROID: block: Introduce passthrough keyslot manager
commit 4f27c8b ANDROID: ext4, f2fs: enable direct I/O with inline encryption
commit c91db46 BACKPORT: FROMLIST: scsi: ufs: add program_key() variant op
commit f9a8e4a ANDROID: block: export symbols needed for modules to use inline crypto
commit 75fea5f ANDROID: block: fix some inline crypto bugs
commit 2871f73 ANDROID: fscrypt: add support for hardware-wrapped keys
commit bb5a657 ANDROID: block: add KSM op to derive software secret from wrapped key
commit d42ba87 ANDROID: block: provide key size as input to inline crypto APIs
commit 86646eb ANDROID: ufshcd-crypto: export cap find API
commit 83bc20e ANDROID: scsi: ufs-qcom: Enable BROKEN_CRYPTO quirk flag
commit c266a13 ANDROID: scsi: ufs: Add quirk bit for controllers that don't play well with inline crypto
commit ea09b99 ANDROID: cuttlefish_defconfig: Enable blk-crypto fallback
commit e12563c BACKPORT: FROMLIST: Update Inline Encryption from v5 to v6 of patch series
commit 8e8f55d ANDROID: scsi: ufs: UFS init should not require inline crypto
commit dae9899 ANDROID: scsi: ufs: UFS crypto variant operations API
commit a69516d ANDROID: cuttlefish_defconfig: enable inline encryption
commit b8f7b23 BACKPORT: FROMLIST: ext4: add inline encryption support
commit e64327f BACKPORT: FROMLIST: f2fs: add inline encryption support
commit a0dc8da BACKPORT: FROMLIST: fscrypt: add inline encryption support
commit 19c3c62 BACKPORT: FROMLIST: scsi: ufs: Add inline encryption support to UFS
commit f858a99 BACKPORT: FROMLIST: scsi: ufs: UFS crypto API
commit 011b834 BACKPORT: FROMLIST: scsi: ufs: UFS driver v2.1 spec crypto additions
commit ec0b569 BACKPORT: FROMLIST: block: blk-crypto for Inline Encryption
commit 760b328 ANDROID: block: Fix bio_crypt_should_process WARN_ON
commit 138adbb BACKPORT: FROMLIST: block: Add encryption context to struct bio
commit 66b5609 BACKPORT: FROMLIST: block: Keyslot Manager for Inline Encryption

Git-repo: https://android.googlesource.com/kernel/common/+/refs/heads/android-4.14-stable
Git-commit: a9a545067a
Git-commit: e1a94e6b17
Git-commit: 232fd353e4
Git-commit: 53bc059bc6
Git-commit: aeed6db424
Git-commit: 4f27c8b90b
Git-commit: c91db466b5
Git-commit: f9a8e4a5c5
Git-commit: 75fea5f605
Git-commit: 2871f73194
Git-commit: bb5a65771a
Git-commit: d42ba87e29
Git-commit: 86646ebb17
Git-commit: 83bc20ed4b
Git-commit: c266a1311e
Git-commit: ea09b9954c
Git-commit: e12563c18d
Git-commit: 8e8f55d1a7
Git-commit: dae9899044
Git-commit: a69516d091
Git-commit: b8f7b23674
Git-commit: e64327f571
Git-commit: a0dc8da519
Git-commit: 19c3c62836
Git-commit: f858a9981a
Git-commit: 011b8344c3
Git-commit: ec0b569b5c
Git-commit: 760b3283e8
Git-commit: 138adbbe5e
Git-commit: 66b5609826

Change-Id: I171d90de41185824e0c7515f3a3b43ab88f4e058
Signed-off-by: Neeraj Soni <neersoni@codeaurora.org>
2020-08-13 13:44:51 -07:00

227 lines
5.3 KiB
C

/*
* Copyright (C) 2001-2003 Sistina Software (UK) Limited.
*
* This file is released under the GPL.
*/
#include "dm.h"
#include <linux/module.h>
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/bio.h>
#include <linux/dax.h>
#include <linux/slab.h>
#include <linux/device-mapper.h>
#define DM_MSG_PREFIX "linear"
/*
* Linear: maps a linear range of a device.
*/
struct linear_c {
struct dm_dev *dev;
sector_t start;
};
/*
* Construct a linear mapping: <dev_path> <offset>
*/
int dm_linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
struct linear_c *lc;
unsigned long long tmp;
char dummy;
int ret;
if (argc != 2) {
ti->error = "Invalid argument count";
return -EINVAL;
}
lc = kmalloc(sizeof(*lc), GFP_KERNEL);
if (lc == NULL) {
ti->error = "Cannot allocate linear context";
return -ENOMEM;
}
ret = -EINVAL;
if (sscanf(argv[1], "%llu%c", &tmp, &dummy) != 1) {
ti->error = "Invalid device sector";
goto bad;
}
lc->start = tmp;
ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev);
if (ret) {
ti->error = "Device lookup failed";
goto bad;
}
ti->num_flush_bios = 1;
ti->num_discard_bios = 1;
ti->num_write_same_bios = 1;
ti->num_write_zeroes_bios = 1;
ti->may_passthrough_inline_crypto = true;
ti->private = lc;
return 0;
bad:
kfree(lc);
return ret;
}
EXPORT_SYMBOL_GPL(dm_linear_ctr);
void dm_linear_dtr(struct dm_target *ti)
{
struct linear_c *lc = (struct linear_c *) ti->private;
dm_put_device(ti, lc->dev);
kfree(lc);
}
EXPORT_SYMBOL_GPL(dm_linear_dtr);
static sector_t linear_map_sector(struct dm_target *ti, sector_t bi_sector)
{
struct linear_c *lc = ti->private;
return lc->start + dm_target_offset(ti, bi_sector);
}
static void linear_map_bio(struct dm_target *ti, struct bio *bio)
{
struct linear_c *lc = ti->private;
bio_set_dev(bio, lc->dev->bdev);
if (bio_sectors(bio) || bio_op(bio) == REQ_OP_ZONE_RESET)
bio->bi_iter.bi_sector =
linear_map_sector(ti, bio->bi_iter.bi_sector);
}
int dm_linear_map(struct dm_target *ti, struct bio *bio)
{
linear_map_bio(ti, bio);
return DM_MAPIO_REMAPPED;
}
EXPORT_SYMBOL_GPL(dm_linear_map);
int dm_linear_end_io(struct dm_target *ti, struct bio *bio,
blk_status_t *error)
{
struct linear_c *lc = ti->private;
if (!*error && bio_op(bio) == REQ_OP_ZONE_REPORT)
dm_remap_zone_report(ti, bio, lc->start);
return DM_ENDIO_DONE;
}
EXPORT_SYMBOL_GPL(dm_linear_end_io);
void dm_linear_status(struct dm_target *ti, status_type_t type,
unsigned status_flags, char *result, unsigned maxlen)
{
struct linear_c *lc = (struct linear_c *) ti->private;
switch (type) {
case STATUSTYPE_INFO:
result[0] = '\0';
break;
case STATUSTYPE_TABLE:
snprintf(result, maxlen, "%s %llu", lc->dev->name,
(unsigned long long)lc->start);
break;
}
}
EXPORT_SYMBOL_GPL(dm_linear_status);
int dm_linear_prepare_ioctl(struct dm_target *ti,
struct block_device **bdev, fmode_t *mode)
{
struct linear_c *lc = (struct linear_c *) ti->private;
struct dm_dev *dev = lc->dev;
*bdev = dev->bdev;
/*
* Only pass ioctls through if the device sizes match exactly.
*/
if (lc->start ||
ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
return 1;
return 0;
}
EXPORT_SYMBOL_GPL(dm_linear_prepare_ioctl);
int dm_linear_iterate_devices(struct dm_target *ti,
iterate_devices_callout_fn fn, void *data)
{
struct linear_c *lc = ti->private;
return fn(ti, lc->dev, lc->start, ti->len, data);
}
EXPORT_SYMBOL_GPL(dm_linear_iterate_devices);
long dm_linear_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
long nr_pages, void **kaddr, pfn_t *pfn)
{
long ret;
struct linear_c *lc = ti->private;
struct block_device *bdev = lc->dev->bdev;
struct dax_device *dax_dev = lc->dev->dax_dev;
sector_t dev_sector, sector = pgoff * PAGE_SECTORS;
dev_sector = linear_map_sector(ti, sector);
ret = bdev_dax_pgoff(bdev, dev_sector, nr_pages * PAGE_SIZE, &pgoff);
if (ret)
return ret;
return dax_direct_access(dax_dev, pgoff, nr_pages, kaddr, pfn);
}
EXPORT_SYMBOL_GPL(dm_linear_dax_direct_access);
size_t dm_linear_dax_copy_from_iter(struct dm_target *ti, pgoff_t pgoff,
void *addr, size_t bytes, struct iov_iter *i)
{
struct linear_c *lc = ti->private;
struct block_device *bdev = lc->dev->bdev;
struct dax_device *dax_dev = lc->dev->dax_dev;
sector_t dev_sector, sector = pgoff * PAGE_SECTORS;
dev_sector = linear_map_sector(ti, sector);
if (bdev_dax_pgoff(bdev, dev_sector, ALIGN(bytes, PAGE_SIZE), &pgoff))
return 0;
return dax_copy_from_iter(dax_dev, pgoff, addr, bytes, i);
}
EXPORT_SYMBOL_GPL(dm_linear_dax_copy_from_iter);
static struct target_type linear_target = {
.name = "linear",
.version = {1, 4, 0},
.features = DM_TARGET_PASSES_INTEGRITY | DM_TARGET_ZONED_HM,
.module = THIS_MODULE,
.ctr = dm_linear_ctr,
.dtr = dm_linear_dtr,
.map = dm_linear_map,
.status = dm_linear_status,
.end_io = dm_linear_end_io,
.prepare_ioctl = dm_linear_prepare_ioctl,
.iterate_devices = dm_linear_iterate_devices,
.direct_access = dm_linear_dax_direct_access,
.dax_copy_from_iter = dm_linear_dax_copy_from_iter,
};
int __init dm_linear_init(void)
{
int r = dm_register_target(&linear_target);
if (r < 0)
DMERR("register failed %d", r);
return r;
}
void dm_linear_exit(void)
{
dm_unregister_target(&linear_target);
}