Enable allow_discards if dm-crypt supports it
dm-crypt version 1.11.0 and later supports the allow_discards option
when setting up a crypto device. This passes discard requests from
the filesytem to the underlying block device. This helps make flash
based storage faster. So query the dm-crypt version, and pass the
option if the version is 1.11.0 or greater.
Change-Id: If30e9db5a2dbd6ea0281d91344e5b2c35e75131e
diff --git a/cryptfs.c b/cryptfs.c
index bcacc39..7da84bc 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -377,6 +377,86 @@
}
+static int load_crypto_mapping_table(struct crypt_mnt_ftr *crypt_ftr, unsigned char *master_key,
+ char *real_blk_name, const char *name, int fd,
+ char *extra_params)
+{
+ char buffer[DM_CRYPT_BUF_SIZE];
+ struct dm_ioctl *io;
+ struct dm_target_spec *tgt;
+ char *crypt_params;
+ char master_key_ascii[129]; /* Large enough to hold 512 bit key and null */
+ int i;
+
+ io = (struct dm_ioctl *) buffer;
+
+ /* Load the mapping table for this device */
+ tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
+
+ ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
+ io->target_count = 1;
+ tgt->status = 0;
+ tgt->sector_start = 0;
+ tgt->length = crypt_ftr->fs_size;
+ strcpy(tgt->target_type, "crypt");
+
+ crypt_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
+ convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii);
+ sprintf(crypt_params, "%s %s 0 %s 0 %s", crypt_ftr->crypto_type_name,
+ master_key_ascii, real_blk_name, extra_params);
+ crypt_params += strlen(crypt_params) + 1;
+ crypt_params = (char *) (((unsigned long)crypt_params + 7) & ~8); /* Align to an 8 byte boundary */
+ tgt->next = crypt_params - buffer;
+
+ for (i = 0; i < TABLE_LOAD_RETRIES; i++) {
+ if (! ioctl(fd, DM_TABLE_LOAD, io)) {
+ break;
+ }
+ usleep(500000);
+ }
+
+ if (i == TABLE_LOAD_RETRIES) {
+ /* We failed to load the table, return an error */
+ return -1;
+ } else {
+ return i + 1;
+ }
+}
+
+
+static int get_dm_crypt_version(int fd, const char *name, int *version)
+{
+ char buffer[DM_CRYPT_BUF_SIZE];
+ struct dm_ioctl *io;
+ struct dm_target_versions *v;
+ int i;
+
+ io = (struct dm_ioctl *) buffer;
+
+ ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
+
+ if (ioctl(fd, DM_LIST_VERSIONS, io)) {
+ return -1;
+ }
+
+ /* Iterate over the returned versions, looking for name of "crypt".
+ * When found, get and return the version.
+ */
+ v = (struct dm_target_versions *) &buffer[sizeof(struct dm_ioctl)];
+ while (v->next) {
+ if (! strcmp(v->name, "crypt")) {
+ /* We found the crypt driver, return the version, and get out */
+ version[0] = v->version[0];
+ version[1] = v->version[1];
+ version[2] = v->version[2];
+ return 0;
+ }
+ v = (struct dm_target_versions *)(((char *)v) + v->next);
+ }
+
+ return -1;
+}
+
static int create_crypto_blk_dev(struct crypt_mnt_ftr *crypt_ftr, unsigned char *master_key,
char *real_blk_name, char *crypto_blk_name, const char *name)
{
@@ -389,6 +469,9 @@
int fd;
int i;
int retval = -1;
+ int version[3];
+ char *extra_params;
+ int load_count;
if ((fd = open("/dev/device-mapper", O_RDWR)) < 0 ) {
SLOGE("Cannot open device-mapper\n");
@@ -412,40 +495,27 @@
minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
snprintf(crypto_blk_name, MAXPATHLEN, "/dev/block/dm-%u", minor);
- /* Load the mapping table for this device */
- tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
-
- ioctl_init(io, 4096, name, 0);
- io->target_count = 1;
- tgt->status = 0;
- tgt->sector_start = 0;
- tgt->length = crypt_ftr->fs_size;
- strcpy(tgt->target_type, "crypt");
-
- crypt_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
- convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii);
- sprintf(crypt_params, "%s %s 0 %s 0", crypt_ftr->crypto_type_name,
- master_key_ascii, real_blk_name);
- crypt_params += strlen(crypt_params) + 1;
- crypt_params = (char *) (((unsigned long)crypt_params + 7) & ~8); /* Align to an 8 byte boundary */
- tgt->next = crypt_params - buffer;
-
- for (i = 0; i < TABLE_LOAD_RETRIES; i++) {
- if (! ioctl(fd, DM_TABLE_LOAD, io)) {
- break;
- }
- usleep(500000);
+ extra_params = "";
+ if (! get_dm_crypt_version(fd, name, version)) {
+ /* Support for allow_discards was added in version 1.11.0 */
+ if ((version[0] >= 2) ||
+ ((version[0] == 1) && (version[1] >= 11))) {
+ extra_params = "1 allow_discards";
+ SLOGI("Enabling support for allow_discards in dmcrypt.\n");
+ }
}
- if (i == TABLE_LOAD_RETRIES) {
+ load_count = load_crypto_mapping_table(crypt_ftr, master_key, real_blk_name, name,
+ fd, extra_params);
+ if (load_count < 0) {
SLOGE("Cannot load dm-crypt mapping table.\n");
goto errout;
- } else if (i) {
- SLOGI("Took %d tries to load dmcrypt table.\n", i + 1);
+ } else if (load_count > 1) {
+ SLOGI("Took %d tries to load dmcrypt table.\n", load_count);
}
/* Resume this device to activate it */
- ioctl_init(io, 4096, name, 0);
+ ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
if (ioctl(fd, DM_DEV_SUSPEND, io)) {
SLOGE("Cannot resume the dm-crypt device\n");