diff --git a/CHANGELOG b/CHANGELOG index 94d918a..abcedf9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,9 @@ * Fixed handling of disks and volumes with 4k sectors (issue #45). + * Add an option to allow TRIM (discards) on the mapped volume + (issue #47). + 2013-07-31 Version 1.1 - Alex Hornung diff --git a/main.c b/main.c index 586a2a3..448ed73 100644 --- a/main.c +++ b/main.c @@ -155,6 +155,8 @@ usage(void) "\t Protect a hidden volume when mounting the outer volume.\n" " -s , --system-encryption=\n" "\t Specifies that the disk (e.g. /dev/da0) is using system encryption.\n" + " -t, --allow-trim\n" + "\t Allow discards (TRIM command) on mapped volume.\n" " --fde\n" "\t Specifies that the disk (e.g. /dev/da0) is using full disk encryption.\n" " --use-backup\n" @@ -192,6 +194,7 @@ static struct option longopts[] = { { "protect-hidden", no_argument, NULL, 'e' }, { "device", required_argument, NULL, 'd' }, { "system-encryption", required_argument, NULL, 's' }, + { "allow-trim", no_argument, NULL, 't' }, { "fde", no_argument, NULL, FLAG_LONG_FDE }, { "use-backup", no_argument, NULL, FLAG_LONG_USE_BACKUP }, { "modify", no_argument, NULL, FLAG_LONG_MOD }, @@ -242,7 +245,7 @@ main(int argc, char *argv[]) n_hkeyfiles = 0; n_newkeyfiles = 0; - while ((ch = getopt_long(argc, argv, "a:b:cd:ef:ghij:k:m:s:u:vwx:y:z", + while ((ch = getopt_long(argc, argv, "a:b:cd:ef:ghij:k:m:s:tu:vwx:y:z", longopts, NULL)) != -1) { switch(ch) { case 'a': @@ -300,6 +303,9 @@ main(int argc, char *argv[]) flags |= TC_FLAG_SYS; sys_dev = optarg; break; + case 't': + flags |= TC_FLAG_ALLOW_TRIM; + break; case 'u': unmap_vol = 1; map_name = optarg; diff --git a/tcplay.3 b/tcplay.3 index 62a8f46..8f33b5a 100644 --- a/tcplay.3 +++ b/tcplay.3 @@ -28,7 +28,7 @@ .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd July 30, 2013 +.Dd December 07, 2013 .Dt TCPLAY 3 .Os .Sh NAME @@ -115,6 +115,7 @@ typedef struct tc_api_opts { const char *tc_system_device; int tc_use_fde; int tc_use_backup; + int tc_allow_trim; /* Fields for modify */ const char *tc_new_passphrase; @@ -412,6 +413,11 @@ is specified, .Nm tcplay will use the backup headers at the end of a volume instead of the primary headers to access it. +If +.Fa tc_allow_trim +is specified, +.Nm tcplay +will allow TRIM (discards) on the mapped volume. .Pp The .Fn tc_api_unmap_volume diff --git a/tcplay.8 b/tcplay.8 index ad0a4cc..b63c9d7 100644 --- a/tcplay.8 +++ b/tcplay.8 @@ -29,7 +29,7 @@ .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd July 29, 2013 +.Dd December 07, 2013 .Dt TCPLAY 8 .Os .Sh NAME @@ -66,6 +66,7 @@ .Op Fl f Ar keyfile_hidden .Op Fl k Ar keyfile .Op Fl s Ar system_device +.Op Fl t .Op Fl -fde .Op Fl -use-backup .Nm @@ -271,6 +272,14 @@ to access the volume. .El .Pp Additional options only for the +.Fl -map +command are: +.Bl -tag -width indent +.It Fl t , Fl -allow-trim +This option enables TRIM (discard) support on the mapped volume. +.El +.Pp +Additional options only for the .Fl -modify command are: .Bl -tag -width indent diff --git a/tcplay.c b/tcplay.c index 0d65467..2228f02 100644 --- a/tcplay.c +++ b/tcplay.c @@ -1489,7 +1489,7 @@ dm_get_table(const char *name) ++c; } - if (c != 5) { + if (c < 5) { tc_log(1, "could not get all the info required from " "the table\n"); goto error; @@ -1796,12 +1796,13 @@ dm_setup(const char *mapname, struct tcplay_info *info) start = INFO_TO_DM_BLOCKS(info, offset); } - /* aes-cbc-essiv:sha256 7997f8af... 0 /dev/ad0s0a 8 */ - /* iv off---^ block off--^ */ - snprintf(params, 512, "%s %s %"PRIu64 " %s %"PRIu64, + /* aes-cbc-essiv:sha256 7997f8af... 0 /dev/ad0s0a 8 */ + /* iv off---^ block off--^ */ + snprintf(params, 512, "%s %s %"PRIu64 " %s %"PRIu64 " %s", cipher_chain->cipher->dm_crypt_str, cipher_chain->dm_key, (uint64_t)INFO_TO_DM_BLOCKS(info, skip), dev, - (uint64_t)offset); + (uint64_t)offset, + TC_FLAG_SET(info->flags, ALLOW_TRIM) ? "1 allow_discards" : ""); #ifdef DEBUG printf("Params: %s\n", params); #endif diff --git a/tcplay.h b/tcplay.h index 11e7082..c66305d 100644 --- a/tcplay.h +++ b/tcplay.h @@ -67,6 +67,7 @@ #define TC_FLAG_FDE 0x0002 #define TC_FLAG_BACKUP 0x0004 #define TC_FLAG_ONLY_RESTORE 0x0008 +#define TC_FLAG_ALLOW_TRIM 0x0010 #define TC_FLAG_SET(f, x) ((f & TC_FLAG_##x) == TC_FLAG_##x) diff --git a/tcplay_api.c b/tcplay_api.c index 5247cf5..aa28b17 100644 --- a/tcplay_api.c +++ b/tcplay_api.c @@ -178,6 +178,8 @@ tc_api_map_volume(tc_api_opts *api_opts) flags |= TC_FLAG_FDE; if (api_opts->tc_use_backup) flags |= TC_FLAG_BACKUP; + if (api_opts->tc_allow_trim) + flags |= TC_FLAG_ALLOW_TRIM; err = map_volume(api_opts->tc_map_name, api_opts->tc_device, flags, api_opts->tc_system_device, diff --git a/tcplay_api.h b/tcplay_api.h index 10001b1..6082799 100644 --- a/tcplay_api.h +++ b/tcplay_api.h @@ -61,6 +61,7 @@ typedef struct tc_api_opts { const char *tc_system_device; int tc_use_fde; int tc_use_backup; + int tc_allow_trim; /* Fields for modify */ const char *tc_new_passphrase; diff --git a/test/features/support/env.rb b/test/features/support/env.rb index 3ff0794..78c240e 100644 --- a/test/features/support/env.rb +++ b/test/features/support/env.rb @@ -28,6 +28,7 @@ class TCApiOpts < FFI::Struct :tc_system_device, :pointer, :tc_use_fde, :int, :tc_use_backup, :int, + :tc_allow_trim, :int, # Fields for modify :tc_new_passphrase, :pointer,