Ask / Submit
26

[How-to] Creating partitions on SD-card, optionally encrypted

asked 2018-02-11 23:20:08 +0200

olf gravatar image

updated 2018-02-19 03:29:26 +0200

Although there are a couple of guides for extending the internal mass storage (eMMC) of devices running SailfishOS (in general; this is not addressing the "tiny system partition issue" of SailfishOS on the Xperia X and Jolla C / Intex Aquafish) with a SD-card (on TMO and here on TJC), IMO none of them completely satisfactory (technically, by functionality and usability), but they provided valuable ideas.

This is part 1 "Creating partitions on SD-card, optionally encrypted", you may want to continue with part 2 "Externalising android_storage and other directories / files to SD-card" to utilise the space on SD-card thereafter.

0. Objectives and preface

  1. Only rely on SailfishOS provided tools, including Mer-Tools (but without third party software, e.g. on a PC or from OpenRepos), so the whole configuration can be carried out directly on the SailfishOS device.
  2. Not altering SailfishOS' basic filesystem structure or existing files.
    Thus no /home/nemo etc. on SD-card; as SailfishOS is a classic Linux distribution, thus one can and should use symlinks (i.e. symbolic / "soft" links created with ln -s) to put specific directories or files somewhere under /home/nemo/ (but not android_storage or anything under it) onto the encrypted EXT4 partition on the SD-card.
  3. But with the ability to move android_storage and other files and directories under /home/nemo to an (optionally encrypted) partition on the SD-card.
  4. One solution for all devices with SailfishOS, so a SD-card can be moved between different SailfishOS devices, while keeping data on it accessible. This excludes the use explicit (i.e. inherent) use of BTRFS, as it currently is only available on the Jolla 1 phone (i.e. in its kernel). Hence the filesystems used are primarily EXT4 and vFAT32, because this is what Jolla officially supports and the SailfishOS kernel practically supports (use cat /proc/filesystems: As of SailfishOS 2.1.3.7, none suitable for SD-cards besides vFAT and EXTx).
  5. Optionally protect a partition on the SD-card by encrypting it, in order to keep the data on it safe, when the device is lost. I.e. the keys for DM-Crypt are based on a file stored at the internal mass store, which is accessible, when the SailfishOS device is unlocked. Additionally, with access to that file, one can copy it to another SailfishOS device or a Linux PC to access the data on the SD-card there, too.
  6. Optionally create an additional FAT- or EXT4-formatted partition(s) (unencrypted) for data exchange with any device and OS (by moving the SD-card).
  7. Applicable to SDHC- and SDXC-cards of at least 4 GB (up to the maximum size the device hardware supports, as the technical limit of this scheme is 2 TBytes).
  8. Keep the reserved area of the SD-card intact.
  9. Align partition, DM-Crypt and filesystem data-structures to erase-block size / alignment size.

Background on aligning data-structures on FLASH-based mass storage:
Write accesses to any NAND-FLASH based mass storage must write whole (complete) pages internally (typically 2^n multiples of 4 KBytes large), while for deleting data structures whole erase-blocks must be deleted. Note that the logical sector size such media exposes externally (usually 512 Bytes per logical sector) is much smaller. Recent NAND-FLASH memory chips (all FLASH-based mass storage is built with NAND-FLASH, plus a controller circuitry) have erase-block sizes of 1, 2, 4, 8, ... MBytes (while the numbers at Wikipedia refer to NAND-FLASH a couple of years ago, citing e.g. 512 KBytes; see also e.g. this explanation).
Not aligning data-structures to the erase-block size (or multiples of it) results in a much higher write amplification, leading to vastly degraded lifetime and lower performance of a reformatted SD-card.

README 1st:
Before you start, read the following sections completely and decide thereafter, if you (at least) roughly understand what these commands do (you may read their man pages, to be sure); if you don't, better leave it.
Mistyping (e.g. /dev/mmcblk0 instead of /dev/mmcblk1) may brick your SailfishOS device or quickly wear out your SD-card!
All this was tested on two Jolla 1 phones under SailfishOS 2.1.3.7 with two different SD-cards, so if things turn out to look different with other devices or SD-cards, you may have to adapt the following sections (thus some understanding of the commands issued is crucial); and last but not least this description may be faulty. Please report your experiences and adaptations in these cases, but do not blame anyone (e.g. me) for any mishaps.
Contributions and constructive suggestions are welcome.

1. Installing the needed utilities

Starting as user nemo in /home/nemo.
mkdir sd-card_layouts # Create a directory for backing up the original and altered partition and file system layouts of the SD-card
devel-su # Become root user
ssu ar mer-tools # Add Jolla's mer-tools repository to /etc/ssu/ssu.ini
pkcon refresh # As usual, after adding a new repository
pkcon install fdisk dosfstools # These are both needed, regardless of planning to create an optional FAT partition lateron

2. Analyse the specific SD-card partition layout

cd sd-card_layouts # Change to the backup directory created in section 1

First take a look at the partition layout with fdisk:
fdisk -l /dev/mmcblk1 | tee fdisk-l_mmcblk1-original.txt
Output of a 32 GB SDHC-card as an example:

Disk /dev/mmcblk1: 29 GiB, 31104958464 bytes, 60751872 sectors
Units: sectors of 1 * 512 = 512 bytes

Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000

Device         Boot Start      End  Sectors Size Id Type
/dev/mmcblk1p1       8192 60751871 60743680  29G  c W95 FAT32 (LBA)

Note that there is (typically) a single FAT partition at /dev/mmcblk1p1 (some SD-cards may have a different partition layout, though) and the first LBA sector of this FAT partition is 8192 (which may vary depending upon the specific SD-card). One should retain this offset for the first partition (in this example of 8192 * 512 Bytes = 4 MBytes) for optimal alignment (see below).
Also note, that SD-cards usually "lie" about their internal page size for compatibility reasons and just report their externally provided logical sector size as physical sector size and optimal I/O size, even though the true page size is optimal for read and write accesses (while the erase-block size is optimal for deleting data).

2.1 Analysing an existing FAT32-filesystem on a SDHC-card

To analyse a SDHC-card's pre-formatted FAT32-filesystem (advertised size typically "4 GB" to "32 GB"), use dosfsck (from the dosfstools installed in section 1):
dosfsck -nv /dev/mmcblk1p1 | tee dosfsck-nv_mmcblk1p1-original.txt
Exemplary output of aforementioned 32 GB SD-card:

dosfsck 3.0.10 (12 Sep 2010)
dosfsck 3.0.10, 12 Sep 2010, FAT32, LFN
Checking we can access the last sector of the filesystem
Boot sector contents:
System ID "        "
Media byte 0xf8 (hard disk)
       512 bytes per logical sector
     32768 bytes per cluster
     1556 reserved sectors
First FAT starts at byte 796672 (sector 1556)
         2 FATs, 32 bit entries
   3795968 bytes per FAT (= 7414 sectors)
Root directory start at cluster 2 (arbitrary size)
Data area starts at byte 8388608 (sector 16384)
    948864 data clusters (31092375552 bytes)
63 sectors/track, 255 heads
      8192 hidden sectors
  60743680 sectors total
Checking for unused clusters.
Checking free cluster summary.
/dev/mmcblk1p1: 3 files, 2507/948864 clusters

Note that the two File Allocation Tables (FATs) of 7414 sectors each plus the 1556 reserved sectors make up for the file system internal offset of 16384 sectors, at which the data area of this FAT partition starts.
To check that the whole calculation matches, multiply the size of the data area with the cluster size in sectors (i.e. 64 for the typical 32 KBytes cluster size and 512 Bytes logical sector size) and add the file system internal offset: 948864 * 64 + 16384 = 60743680, which is the number of total sectors reported by fdisk and dosfsck for this partition.
Note that the number of hidden sectors refers to the number of sectors preceding this FAT partition (i.e. outside and before the FAT partition proper) and hence shall equal its first sector number (i.e. its offset).

2.2 Analysing an existing exFAT-filesystem on a SDXC-card

To analyse a SDHC-card's pre-formatted exFAT-filesystem (advertised size typically "64 GB" or larger), use dumpexfat (from the exfat-utils):
Install exfat-utils (preferably via Storeman or Warehouse), then execute:
dumpexfat /dev/mmcblk1p1 | tee dumpexfat_mmcblk1p1-original.txt
Exemplary output of a 128 GB SD-card:

Volume label                        
Volume serial number      0x64323432
FS version                       1.0
Sector size                      512
Cluster size                  131072
Sectors count              249704448
Free sectors               249670912
Clusters count                975280
Free clusters                 975277
First sector                   32768
FAT first sector               16384
FAT sectors count              16384
First cluster sector           32768
Root directory cluster             4
Volume state                  0x0000
FATs count                         1
Drive number                    0x80
Allocated space                   0%

The values correspond to the ones described in section 2.2 (for dosfsck): "First sector" (dumpexfat) equals "hidden sectors" (dosfsck) (i.e. partition offset), "FAT first sector" equals "First FAT starts at ... (sector X)" (i.e. "reserved sectors"), "FAT sectors count" equals "Y bytes per FAT (= X sectors)", "First cluster sector" equals "Data area starts at byte Y (sector X)" and the cluster size is provided by both in Bytes (not sectors!).
Note that typically just a single FAT is used for exFAT-filesystems, as this is sufficient for FLASH-based media (using typically two FATs for pre-formatted FAT32-filesystems on SD-cards is primarily a compatibility measure).
Check your understanding of the original filesystem layout as described in section 2.1.

2.3 Determining the optimal alignment size for a specific SD-card

A good estimate for the SD-card's optimal alignment size is the smaller of these two offsets, the partition offset (in this example: 8192 sectors = 4 MB) and the FAT file system internal offset for its data area (in this example: 16384 sectors = 8 MB, due to the FATs occupying more than 4 MB in this case). The data area offset should be a multiple (1, 2, 3, ...) of the partition offset, otherwise your SD-card is strangely formatted.
To determine the SD-card's erase-block size, look at the output of cat /sys/block/mmcblk1/queue/discard_granularity and especially cat /sys/block/mmcblk1/device/preferred_erase_size, if your SD-card provides these values (in Bytes).
Note that the SD-card's optimal alignment size is a 2^n multiple (i.e. times 1, 2, 4, 8, ...) of the erase-block size, so they are not necessarily the same.

All in all it should be plausible and fit together:

  • For the exemplary 32 GB SD-card, the partition offset is 4 MB, the data area offset 8 MB (due to the size of the FATs), discard_granularity is 4 MB and preferred_erase_size 4 MB: Hence the optimal alignment size is clearly 4 MB for this SD-card.
  • For the 128 GB SD-card mentioned above, the partition offset is 16 MB, the data area offset 16 MB too, but discard_granularity and preferred_erase_size are 4 MB: So, while the erase-block size is 4 MB, the manufacturer clearly prefers an alignment size of 16 MB for this SD-card.

Thus one goal is to align all significant data-structures to the determined optimal alignment size (e.g. for the exemplary 32 GB SD-card: 8192 sectors with 512 Bytes = 4 MBytes; for the aforementioned 128 GB SD-card: 32768 sectors with 512 Bytes = 16 MBytes) in the following sections.

Check, if your SD-card supports discards:
When cat /sys/block/mmcblk1/queue/discard_zeroes_data outputs "1" it definitely does, otherwise it likely does not.

Note, that all files on the SD-card will become inaccessible when carrying out the next steps, so now is the last chance to backup the data residing on your SD-card.

3. Re-partition the SD-card

3.1 Preparation for re-partitioning

Empty the existing filesystem(s) on SD-card completely in order to free the used blocks on the filesystem and the SD-card internally:
cd /media/sdcard/XXXXXXXX/ # Assure that you changed to this directory successfully, before proceeding:
pwd # O.K.?
rm -rf * .[^.]* # !
fstrim -v /media/sdcard/XXXXXXXX/ # For all filesystems other than FAT, as SailfishOS only mounts these with the mount option "discard" (see /usr/sbin/mount-sd.sh); fstrim does not work on FAT filesystems, but for FAT the mount option "discard" shall discard all empty blocks when executing the rm command.
Alternatively or additionally (preferably after having carried out the following paragraph: the unmounting), a blkdiscard /dev/mmcblk1pX can be used on the raw, logical partitions (but be careful with the whole device /dev/mmcblk1).

Check, which partition(s) is actually mounted and how often:
mount | grep mmcblk1 # Each partition is mounted twice (at different locations), if you have AlienDalvik running
Unmount the mounted partition(s) on the SD-card by issuing, e.g.:
umount /dev/mmcblk1p1 # If the output is "umount: /dev/mmcblkXXX: not mounted", you picked the wrong partition
mount | grep mmcblk1 # Check again, it should be mounted once less, now
Continue to issue umount /dev/mmcblk1p1 until the output is "umount: /dev/mmcblkXXX: not mounted" (and consequently mount | grep mmcblk1 outputs nothing).

Become familiar with the fdisk tool:
fdisk /dev/mmcblk1

  • p lists the partition layout as obtained in section 2
  • m provides the list of available commands
  • Do not set the "DOS compatibility flag" (with the command c), which is solely needed for computers running a real MS-DOS and will result in maximised write-amplification when activated (but it defaults to "off" in GNU fdisk since very long ago: more than 15 years).
  • If you have the impression anything went wrong, you simply exit fdisk (without writing the altered partition table) via q and start anew.

3.2.a Setting up a single FAT32, Linux-native (e.g. EXT4) or encrypted partition

If you do not want to create two or three partitions, just leave the partition layout as it is and solely alter the partition type (even that is optional): Hit t, by default the only existing partition is selected and set its partition type to 83 ("Linux") or if you just want to reformat an SDXC-card (pre-formatted with exFAT) with FAT32 to c. Alternatively (e.g. for maximising plausible deniability when planning to set up encryption on this partition and facing the danger to be forced to reveal the encryption scheme / key-file, e.g. in the UK) you may leave it as it is (i.e. not changing anything with fdisk) or set it to 0 ("Unpartitioned"), which both should work, although other devices and operating systems may fail to recognise and to mount them automatically then (but e.g. SailfishOS has absolutely no issues automatically mounting a filesystem on a partition with a wrong type, as it probes them).
Check by entering p that the partition table now looks as it should, and finally write it to the SD-card (and exit fdisk) via w (or q, if unaltered).

3.2.b Setting up two or three partitions: A FAT32 or native one plus a native or / and encrypted one

Prerequisites:

  • When creating a FAT32 partition (type 0c) on a SD-card, it must become at least 16450560 sectors (with 512 Bytes each, i.e. 7,8 GBytes) large. Note that, although smaller size is theoretically possible, it does not make much sense to create such a small FAT partition IMO and requires a different partition type (0b) (to conform to the SD-card specification), which may provide additional hurdles, as that partition type usually indicates a non-LBA FAT32 disk (hence untested).
  • The maximum size for a FAT32-partition is 2 TB (no exFAT necessary for this, but the latter allows for file sizes larger than 2 GB).
  • A FAT-partition should be the first primary partition on the SD-card, otherwise other operating systems may not recognise it.
  • Thus for a dual partition layout including a FAT-partition, the SD-card should be at least a "16 GB" one.

Continue in the fdisk /dev/mmcblk1 and delete the existing partition with d.

Create a new, smaller first primary partition:

  • Create a new first primary partition by entering n, then p, then use the default of "1". Recreate this partition with the same starting LBA-sector the original partition had (which has been obtained and saved in section 2, in the example of the aforementioned 32 GB SD-card 8192).
  • As an easy optimisation (without any drawbacks), determine the last sector for the first partition (especially if it is going to be a FAT-partition) by subtracting 1 from a desired size of n GBytes in sectors (hence the multiplier is 1024 * 1024 * 2 = 2097152 for 512 Byte sectors) for obtaining the last sector of the first partition: In my example (still with that 32 GB SD-card with an offset of 8192 sectors for the first partition) and aiming at creating a first primary partition of slightly less than 8 GBytes, this results in 8 * 2097152 - 1 = 16777215 as the last sector for the new partition (and a partition size of 16777215 +1 - 8192 = 16769024 sectors = 7,996 GBytes). This measure also ensures that the second partition starts at a n GByte boundary.
  • Then enter this calculated value as the last sector for the new first partition.
  • As Linux fdisk always sets the partition type of newly created partitions to 83 ("Linux"), hit t afterwards and set the partition type to c ("W95 FAT32 (LBA)"), if you want a FAT32-partition. If you want a native, unencrypted partition as first primary partition, leave it as it is (on 83).

Create a new, second partition (which will be configured later to be used either natively or with DM-Crypt):

  • Start creating a new, second primary partition by entering n, then p for another primary partition (default, you may as well hit the Return key), then use the suggestion of "2".
  • Create this partition with the last LBA-sector of the first primary partition plus 1 as starting LBA-sector (e.g. with the exemplary 32 GB SD-card: 16777216). Note that fdisk will usually suggest a low sector number in the reserved ("hidden") area (e.g. 2048), which must not be used.
  • Use the value obtained for the last sector of the original partition (in section 2; this is usually, but not necessarily the last sector of the SD-card) as last sector (on my exemplary 32 GB SD-card it was the last available sector, so if that was the case for your original partition layout too, you may as well just hit the Return key to avoid mishaps by mistyping).
    If a third partition is going to be created, use +nG (e.g. +10G) to set size of the second partition in GBytes.
  • Optionally, only for maximising plausible deniability, you may set the partition type by hitting t to 0 (not tested).

If a third partition is wanted, repeat the steps for the second partition with fdisk for it: n, p, 3, <last sector of second partition + 1>, <noted last sector of original partition on sd-card>.

Finally check by entering p that the partition table now looks as it should, and write it to the SD-card (and exit fdisk) via w.

Save the altered partition layout for reference / as a backup and perform a final check:
fdisk -l /dev/mmcblk1 | tee fdisk-l_mmcblk1-altered.txt

3.3 Checks and balances, when calculating the partition layout

However you may deviate from this guide, you should follow these rules:

  • The first sector of any partition must be an even number, which must be evenly divisible by the estimated erase-block size (or 0, if this indeed has been the starting sector of the original partition on the SD-card) and should be evenly divisible by the optimal alignment size.
  • The last sector of any partition must be an odd number.
  • The last sector of any partition plus 1 must be evenly divisible by the erase-block size (in sectors) and should be evenly divisible by the optimal alignment size.
  • Consequently any partition size will be evenly divisible by the erase-block / optimal alignment size, too (just to double-check).

4. Create file systems

4.1 vFAT32 / FAT32 LFN (unencrypted)

Mind that FAT filesystems do not support access rights, hence are unsuited for putting android_storage on them (and for many other use cases), plus its anachronistic design, which does not fit well to FLASH-based mass storage. Furthermore FAT32 only supports files up to 2 GBytes size (though up to 2 TB filesystem size).
Thus a FAT partition is primarily suited for data exchange by physically moving the SD-card to other devices. The same applies to exFAT, except for the file size limit.

Mimic the output of dosfsck from section 2 as much as possible:

  • Cluster size is 32, mostly 64 or 128 sectors, set with option -s; note that dosfsck outputs the cluster size in Bytes, not sectors. (If the partition is primarily used as an archive, i.e. not very often written to and not with many small files, as an optimisation for FLASH-media you may consider setting the cluster size to its maximum value of 128 sectors, but this may introduce interoperability issues with other operating systems / firmwares, especially digital cameras etc.)
  • Logical sector size is usually 512 Bytes, set with option -S; needed for the file-based simulations, but do not use when creating a filesystem on a SD-card (as its sector size shall be implicitly used, then).
  • Hidden sectors count as obtained in section 2 is set with -h
  • A optimisation for FLASH-based memory is to use a single FAT instead of two with -f 1, but this may also introduce interoperability issues with other operating systems / firmwares, especially digital cameras etc.

As the FATs are smaller now (due to the smaller capacity of the newly created filesystem and FATs), the number of reserved sectors (set with option -R) has to be adapted. As mkfs.vfat knows no "dry run" and I found no formula for calculating the exact size of a FAT according to the size of the complete file system, one simply starts a "trial run" within a sparse file on /tmp:
mkfs.vfat -S 512 -v -s 64 -h 8192 -C /tmp/fat-test.img <filesystem size in KBytes> # "Trial run 1", divide the intended number of 512 Bytes sectors by two for the filesystem size and set cluster size, hidden sectors count and sector size to the original values obtained in section 2 (if the cluster size of an pre-formatted exFAT-partition on the SD-card was larger than 128 sectors, use 128 sectors)
dosfsck -nv /tmp/fat-test.img # Compare to the output generated in section 2 (sector and cluster size) and check, if the resulting filesystem size (e.g. in sectors) in the image file is the intended one for the freshly created (in section 3) real partition
Now calculate the number of reserved sectors, which are needed to add up with the FATs (one or two) to any multiple (e.g. times 1, 2, 3, ...) of the determined alignment size. Note that the number of reserved sectors must be at least 8 (for FAT32) and shall be at least 32 or the number of sectors per cluster (whichever is higher); in above example of an almost 8 GBytes large partition on my exemplary 32GB SD-card, each FAT occupies 2048 sectors, so it takes 4096 reserved sectors to sum up to the alignment size of 8192 sectors.
Now check, if this calculation is correct:
rm /tmp/fat-test.img # Delete the test file
mkfs.vfat -S 512 -v -s 64 -h 8192 -R 4096 -C /tmp/fat-test.img 8384512 # "Trial run 2" with 4096 reserved blocks as an example, for a filesystem slightly smaller than 8 GB ending on sector 16777215
(As a different example, also for slightly smaller than 8 GB filesystem ending on sector 16777215, but for the aforementioned 128 GB SD-card: mkfs.vfat -S 512 -v -f 1 -s 128 -h 32768 -R 31744 -C /tmp/fat-test.img 8372224 # Note that the offsets and consequently the filesystem size differ slightly)
dosfsck -nv /tmp/fat-test.img # Check if everything looks as intended
rm /tmp/fat-test.img # Delete the test file

Then do the real creation of the FAT filesystem on the SD-card:
mkfs.vfat -v -s 64 -h 8192 -R 4096 /dev/mmcblk1p1 # "Real run" with example values
dosfsck -nv /dev/mmcblk1p1 | tee dosfsck-nv_mmcblk1p1-altered.txt # Last check, if everything is as intended, and backup

Side note: Whatever you may consider to do, never use the mkdosfs / mkfs.vfat options -a or -c on FLASH-based media as a SD-card!

4.2 EXT4 (unencrypted)

For creating an unencrypted EXT4 filesystem, the defaults in /etc/mk2fs.conf are fine. You may consider formatting your EXT4 filesystem without a journal per option "-O ^has_journal", although IMO the drawbacks (fsck time and corrupted files, when writing has been interrupted) outweigh the advantage of being slightly nicer to FLASH-based memory.

Hence simply enter:
mkfs.ext4 -v /dev/mmcblk1pX# Substitute "X" with 1 or 2
Such EXT4 partitions will be automatically mounted after a reboot.

Side note: Whatever you may consider to do, never use the mkfs.extX option "-c -c" on FLASH-based media as a SD-card!

4.3 DM-Crypt (encrypted)

Encrypted volumes / partitions are a technically hard usage for NAND-FLASH based mass storage in some aspects. Nevertheless, this is one of the objectives, a desired general use case, relies on common components (DM-Crypt / cryptsetup and its volume format) and the hardness can be mostly alleviated by proper setup parameters.
It is easier for a FLASH-memory controller to handle this situation, the more "spare area" to "maneuver" (alike BTRFS) it has. Though this can be achieved by an unused (i.e. unformatted) partition with typically 12 - 20% of the SD-card's total capacity, a functional, unencrypted partition (of up to 20% of the SD-card's total capacity), which is only lightly used, is equally suited and hence preferable. This optimisation provides an additional incentive to use (at least) two partitions, e.g. an unencrypted and an encrypted one.

Unfortunately Jolla's mer-tools currently (as of 2018-02-11) provide cryptsetup version 1.1.3 (2010-07-03, see pkcon search name cryptsetup-luks), which does not support the option "--enable-discards" (2011-07-07) and misses the fix "If device is not rotational, do not use Gutmann wipe method." (2011-10-05), both released with cryptsetup 1.4.0 and both important for FLASH-based memory.
Thus it is strongly recommended (deviating from objective 1, but it is only used once, for setup) to install the newer cryptsetup 1.6.4 from OpenRepos.net (compiled and published by NielDK) until Jolla updates its cryptsetup to at least version 1.4.0 (Update: SailfishOS 2.1.4 will provide cryptsetup 1.7.5):
curl -O https://openrepos.net/sites/default/files/packages/500/cryptsetup-1.6.4-1.armv7hl.rpm
curl -O https://openrepos.net/sites/default/files/packages/500/libcryptsetup4-1.6.4-1.armv7hl.rpm
pkcon install-local libcryptsetup4-1.6.4-1.armv7hl.rpm cryptsetup-1.6.4-1.armv7hl.rpm # Enter "y" to confirm installing
(This cryptsetup 1.6.4 will be automatically upgraded to version 1.7.5 when installing SFOS 2.1.4.)

Create a "key file", e.g. by creating a random passphrase file on the root partition: dd if=/dev/urandom of=/etc/mmcblk1p3.key bs=64 count=1 # Mind to adapt the partition number
It can be well shorter than 64 Bytes and manually created or half-automatically (and much easier to memorize) with pwgen (e.g. from OpenRepos), just as it fulfills your needs (i.e. it does not need to be cryptographically strong, but nevertheless should be a well chosen / "strong" passphrase), in general it can be any absolutely static file on the root partition up to a few KBytes long.
Back up the "key file": cp /etc/mmcblk1p3.key .

For information on cryptography options:
cryptsetup --help # To see version and defaults; dmsetup targets and cat /proc/crypto are also interesting and relevant

For experimenting with cryptsetup, create a image file for testing:
cd /media/sdcard/XXXXXXXX/# As fallocate does not work on tmpfs with old kernel and fallocate versions, use it on an already mounted partition on the SD-card (need to mount manually or reboot and become root again) or alternatively in /home/nemo or somewhere else on the internal eMMC, e.g. /media/sdcard/).
fallocate -v -l 64M cryptsetup-test.img

4.3.1.a ... with CryptSetup-LUKS (modern, recommended)

cryptsetup -v -c aes-cbc-essiv:sha256 --align-payload=8192 luksFormat cryptsetup-test.img /etc/mmcblk1p3.key # Set "--align-payload" to the alignment size in 512 Byte sectors (here with the usual example of 4MB), the cipher is the classic default for Luks (while the modern one is aes-xts-plain64)
Unfortunately XTS is not supported (see /proc/crypto), otherwise "-s 256 -c aes-xts-plain" would be an excellent choice ("plain64" is only needed for partitions larger than 2TB and XTS is faster than CBC, especially at random accesses, plus needs no external IV-generation algorithm, as it implicitly uses AES for that).
DD-"benchmarks" reading / writing 32 MB from / to an image file on internal eMMC of a Jolla 1 phone:
"-s 256 -c aes-cbc-essiv:sha256" ~ 13 MB/s (11.6 - 15.7) # "Classic defaults"
"-s 128 -c aes-cbc-essiv:sha256" ~ 16 MB/s (13.3 - 18.7) # ca. 25% faster with AES-128
"-s 128 -c aes-cbc-plain" ~ 20 MB/s (18.5 - 22.3) # CBC without ESSIV does not protect against the watermarking attack!
Side note: You may also override the passphrase file hashing default algorithm (sha1) with "-h sha256" at a small boot performance loss, although no real gain in security in this use case.
Hence my preferred cryptography options are "-h sha1 -s 128 -c aes-cbc-essiv:sha256".
cryptsetup -v --allow-discards -d /etc/mmcblk1p3.key luksOpen cryptsetup-test.img luks-test # Create DM-device file /dev/mapper/luks-test
cryptsetup -v luksDump cryptsetup-test.img # Check, if everything is O.K. and as expected
You may test the DM-device "luks-test", e.g. by creating, mounting and using a filesystem on it or dd'ing directly to / from it (e.g. with time dd if=/dev/zero of=/dev/mapper/luks-test bs=4M count=8 && time dd if=/dev/mapper/luks-test of=/dev/null bs=4M count=8).
cryptsetup -v luksClose luks-test # Close DM-device
rm cryptsetup-test.img # Remove image file, when finished with testing

Ultimately do the real thing:
cryptsetup -v -h sha1 -s 128 -c aes-cbc-essiv:sha256 --align-payload=8192 luksFormat /dev/mmcblk1p3 /etc/mmcblk1p3.key # Set "--align-payload" to the alignment size in 512 Byte sectors, pick the right partition (#3 in this example) etc.
cryptsetup -v luksDump /dev/mmcblk1p3 | tee ~nemo/sd-card_layouts/luksdump_mmcblk1p3.txt # Last check & backup
cryptsetup -v --header-backup-file ~nemo/sd-card_layouts/luks-header-backup_mmcblk1p3.bin luksHeaderBackup /dev/mmcblk1p3 # Backup the Luks header, as without it being intact all encrypted data is inaccessible (e.g. when the Luks header on the SD-card is damaged).
cryptsetup -v --allow-discards -d /etc/mmcblk1p3.key luksOpen /dev/mmcblk1p3 mmcblk1p3-crypt # Create DM-device file

4.3.1.b ... with CryptSetup plain (prone to administrative errors, but maximising plausible deniability, as without a Luks-header on the SD-card the encrypted partition appears to contain only random data)

For considerations of parameters and options, see "4.3 1. Luks".
Note that the "key" file shall provide sufficient entropy for plain mode, i.e. 64 Bytes of random data or usual, regular files of a couple of hundred Bytes up to few KBytes are O.K., regular passphrases are not.
Also note, that plain mode does not allow to align data structures (as it has none) and one should specify a kernel supported (see /proc/crypto) passphrase hashing algorithm explicitly, as the default RIPEMD160 is not in the kernel.
cryptsetup -v -h sha1 -s 128 -c aes-cbc-essiv:sha256 --allow-discards -d /etc/mmcblk1p3.key --type plain open cryptsetup-test.img plain-test # You may want to adapt
You may test the DM-device "plain-test" now (see section 4.3.1.a).
cryptsetup -v close plain-test # Close dm-mapper device
rm cryptsetup-test.img # Remove image file, when finished with testing

Ultimately do the real thing:
cryptsetup -v -h sha1 -s 128 -c aes-cbc-essiv:sha256 --allow-discards -d /etc/mmcblk1p3.key --type plain open /dev/mmcblk1p3 mmcblk1p3-crypt # Mind to pick the right partition (#3 in this example) etc.

4.3.2 Create a filesystem on encrypted partition

mkfs.ext4 -v /dev/mapper/mmcblk1p3-crypt# See "4.2 EXT4" for details cryptsetup -v close mmcblk1p3-crypt # Finishing setup steps by closing the DM-crypt mapper-file

4.3.3 Let SailfishOS automatically mount the encrypted partition

Currently there seems to be no proper way for integrating filesystems on DM-crypt partitions residing on SD-card seamlessly into SailfishOS without adapting one of its shell scripts.

Hence edit the shell script /usr/sbin/mount-sd.sh (backup first):
cd /usr/sbin
cp -p mount-sd.sh mount-sd.sh.orig

For use with DM-crypt, add the following lines at the appropriate places ("diff -C 2" output; for cutting and pasting multiple lines, see complete script in section 8.1):

*** mount-sd.sh.orig
--- mount-sd.sh
***************
*** 28,31 ****
      eval "$(/sbin/blkid -c /dev/null -o export /dev/$2)"

+     if [ "${TYPE}" = "crypto_LUKS" ]; then
+        if cryptsetup --allow-discards -d /etc/$(basename ${DEVNAME}).key luksOpen ${DEVNAME} $(basename ${DEVNAME})-crypt 
+         then
+             eval "$(/sbin/blkid -c /dev/null -o export /dev/mapper/$(basename ${DEVNAME})-crypt)"  # Reassigning DEVNAME, TYPE and UUID
+             if [ "${TYPE}" = "crypto_LUKS" ]  # Still?!?
+             then
+                 systemd-cat -t mount-sd /bin/echo "ERROR: Filesystem type missing for DM-crypt (LUKS) device ${DEVNAME}"
+                 cryptsetup close "$(basename ${DEVNAME})-crypt"
+                 exit 1
+             else systemd-cat -t mount-sd /bin/echo "Successfully opened DM-crypt (LUKS) device ${DEVNAME}"
+             fi
+         else 
+             systemd-cat -t mount-sd /bin/echo "ERROR: Failed to open ${DEVNAME} with cryptsetup (LUKS)"
+             exit 1
+         fi
+     fi
+     if [ -z "${TYPE}" ] && [ -z "${UUID}" ] && [ "${DEVNAME}" = "$2" ]; then  # trying cryptsetup "plain"
+         cryptsetup -h sha1 -s 128 -c aes-cbc-essiv:sha256 --allow-discards -d /etc/$(basename $2).key --type plain open /dev/$2 $(basename $2)-crypt  # Cryptsetup "plain" will always succeed, when the key-file is readable and the device is accessible
+         eval "$(/sbin/blkid -c /dev/null -o export /dev/mapper/$(basename $2)-crypt)"  # Reassigning DEVNAME, TYPE and UUID
+         if [ -z "${TYPE}" ]  # Still?!
+         then
+             systemd-cat -t mount-sd /bin/echo "NOTICE: Tried opening ${DEVNAME} as DM-crypt \"plain\" device, but failed to obtain a filesystem type"
+             cryptsetup close "$(basename $2)-crypt"
+             DEVNAME="$2" ; unset UUID  # Revert to state before trying cryptsetup "plain"
+         else systemd-cat -t mount-sd /bin/echo "Successfully opened DM-crypt (\"plain\") device ${DEVNAME}"
+           fi 
+     fi
+ 
      if [ -z "${TYPE}" ]; then

***************
*** 99,102 ****
fi
umount $DIR || umount -l $DIR
+         if [ -e "/dev/mapper/$(basename ${DEVNAME})-crypt" ]; then
+             if cryptsetup close "$(basename ${DEVNAME})-crypt"
+             then systemd-cat -t mount-sd /bin/echo "Cryptsetup closed ${DEVNAME} successfully"
+             else systemd-cat -t mount-sd /bin/echo "WARNING: Cryptsetup failed to close ${DEVNAME}"
+             fi
+         fi
systemd-cat -t mount-sd /bin/echo "Finished ${ACTION}ing ${DEVNAME} at ${DIR}"
fi

When finished editing the shell script, back it up:
cp -p mount-sd.sh mount-sd.sh.patched

Mind that the altered shell script may be overwritten by SailfishOS updates, hence check for this then and reestablish the changes (in the newly updated file!), if overwritten (see timestamps with ls -l).

Ultimately reboot to see, if everything working as intended: Issue as user nemo mount | grep mmcblk1
If not, debug with journalctl -r as root user, while having less installed (e.g. per pkcon install less): Search with "/" (e.g. for mount-sd or mmcblk1), use "n" to jump to the next hit and press PageUp / PageDown to look at adjacent messages.
Note that due to a flaw in older Linux kernels you may see journal messages as follows WRT mapped DM-crypt partitions, which are harmless and should be ignored:

systemd-udevd[ZZZZ]: conflicting device node '/dev/mapper/mmcblk1pX-crypt' found, link to '/dev/dm-0' will not be created
systemd-udevd[YYYY]: inotify_add_watch(9, /dev/dm-0, 10) failed: No such file or directory

5 . Finishing up

Reboot (if not done in previous section 4.3.3) and finally "donate" all mountpoints and filesystems on the SD-card to user nemo, else you cannot use them as nemo:
devel-su
cd /media/sdcard/
chown -v nemo:nemo * */.

You can check that discards are correctly configured with lsblk -D /dev/mmcblk1 (crypto-devices do not return zeroes).

6. Notes

  • Multiple unencrypted partitions on a SD-card with filesystems supported by the SailfishOS kernel (e.g. EXT4, vFAT32) are all automatically mounted by SailfishOS (and with aforementioned changes to mount-sd.sh encrypted ones, too).
  • Note that the SailfishOS backup tool (in the SailfishOS settings) currently (as of SFOS 2.1.3.7) will store backups only on the first and unencrypted (stating it cannot write to it, although untrue, if encrypted) partition of a SD-card: If you rely on backing up your contacts etc. with SailfishOS' backup tool onto SD-card, create an unencrypted partition (formatted with any supported filesystem) at /dev/mmcblk1p1 (a few GBytes is sufficient, if a large encrypted partition is wanted).
  • While deviating from objective 2, there are special use cases for which you may consider the mount option "discard" (see the following section 7 "Additional notes" for details), just as SailfishOS does for FAT by default. To achieve this add in /usr-sbin/mount-sd.sh (which has to be altered for seamlessly using encrypted partitions on the SD-card under SailfishOS, anyway; see section 8.1 below for the complete patched file, but with this change disabled by comment marks "#" there):

    ext4)
    mount ${DEVNAME} $MNT/${UUID} -o "$MOUNT_OPTS",discard || /bin/rmdir $MNT/${UUID}
    ;;
    
  • If you insist on using BTRFS, check and ensure that the mount options "noacl", "space_cache" and "ssd" are active (they are on a Jolla 1 under SFOS 2.1.3.7). You may also consider using the mount options "autodefrag" (as on Jolla 1's internal filesystems, see mount), "ssd_spread" (superseding / instead of "ssd", especially when "ssd" is not automatically detected and enabled), "compress=lzo" (promising size and speed improvements) and / or "enospc_debug", but do read its wiki-page for the mount options first.
    Mind, that you may still have to create BTRFS filesystems with "-O ^extref" under SailfishOS to work properly.
  • The mount option "dirsync" for SD-cards in the "header" of /usr/sbin/mount-sd.sh is debatable (synchronous writes are "hard" to SSDs) and SailfishOS does not use it for internal eMMC, so I prefer to disable it (see script in section 8.1), consequently the "noatime" option also affects directories. If you really need directory access times to be recorded, use "diratime" in conjunction with "noatime" (or "relatime", if you need correct access times for files, too); both options ("diratime" and "relatime") are "hard" to SSDs (but less than "atime", "dirsync" or even "sync").
  • One reason for objective 1 is, that all third party (FUSE-based) filesystems appear to be somewhat unmaintained, hence one cannot rely on them being updated, if incompatibilities with newer SailfishOS versions should arise: F2FS has been retracted on Openrepos and for encfs_sailfish a precompiled archive or a RPM and a page at OpenRepos are also missing. The same has been the case throughout 2016 & 2017 for exFAT, although it was newly compiled and published 2018-01-15.
    I wonder, if there are any hurdles to utilise the filesystem related kernel modules in /lib/modules/"latest"/kernel/fs/ (as provided by SailfishOS), which cover CIFS (SMB), NFS and eCryptFS. Answer: No hurdles, as FishNetMount does that for CIFS and NFS, so does cifs-utils for CIFS, but unfortunately I still have not found anything WRT eCryptFS.

7. Additional notes

(Originally planned as foreword, but it grew too large.)

  • Use quality SD-cards, e.g. from SanDisk (any series, the "Ultra" series is reasonably priced and reasonably fast, or alternatively one from Samsung). I personally regard all other brands as low quality (as e.g. they do not manufacture controller, flash memory and firmware by themselves, in contrast to SanDisk and Samsung) and "Noname" cards as rubbish.
  • If the SD-card has been heavily used before (especially if the partition layout was altered before), it may make sense to format it with the SD-card formatter from the SD Association (Windows and MacOS only, unfortunately), which is supposed to put the SD-card into a (more or less) juvenile state by issuing a "Secure erase" (likely addressing the "Security erase enhanced" command per ATA8-ACS3 specification, not the simple "Security erase") command to it and partition the SD-card anew with a layout conformant to the SD-card specification. The former can also be achieved with hdparm under e.g. Linux, but the options --security-erase-enhanced / --security-erase are still marked as "dangerous", while the option --trim-sectors (which sounds spot on) is still marked as "extremely dangerous" (all three for many years, already?!?), and I have not found a hdparm RPM for SailfishOS.
    Hence under SailfishOS and Linux in general blkdiscard -v /dev/mmcblk1pX does that well (discarding all sectors of a partition / logical block device), without altering the SD-card's partition layout (as long as not used on the whole, physical device, e.g. /dev/mmcblk1). If a filesystem is recreated anyway, blkdiscard on its partition is a complementary / additional measure to issuing a fstrim command to its mount point when the old (non-FAT) filesystem still exists (i.e. fstrim -v /media/sdcard/XXXXXXXX).
    Do not use any tool or tool-option (e.g. blkdiscard -z), which overwrites every sector on the SD-card: These were meant for older HDDs and are absolutely detrimental to a SD-card's lifetime and performance.
  • It is generally not recommended to use the mount option "discard" for non-FAT partitions (as the synchronous nature of implementations of the discard / trim command in many SD-card firmwares slows down file-overwrite and -remove operations significantly), rather rely on SailfishOS issuing fstrim occasionally (Does it? Check in section 8.2 unsuccessful, yet.) and / or manually issue fstrim -v /media/sdcard/XXXXXXXX (working fine with fstrim from util-linux 2.28.1 under SailfishOS 2.1.3.7 on a Jolla 1, using check in section 8.2) every now and then (thus making this an asynchronous operation, plus some other advantages). Note that a fstrim -av seems to only trim mountpoints on internal eMMC. FAT-filesystems are not supported by fstrim, hence they should be mounted with "discard".
    You may still consider using "discard" for non-FAT filesystems on SD-card, if you do not put android_storage on SD-card and use it solely as an archive (e.g. for media files or backups), so slow erase and overwrite operations are irrelevant.
    For further details, see e.g.

8. Appendix:

8.1 /usr/sbin/mount-sd.sh.patched

#!/bin/bash

# The only case where this script would fail is:
# mkfs.vfat /dev/mmcblk1 then repartitioning to create an empty ext2 partition
# And (!) when partitions are encrypted with DM-crypt.

# This script relies on devices being mounted (at most) once under /media/scard/ (originally and patched).

DEF_UID=$(grep "^UID_MIN" /etc/login.defs |  tr -s " " | cut -d " " -f2)
DEF_GID=$(grep "^GID_MIN" /etc/login.defs |  tr -s " " | cut -d " " -f2)
DEVICEUSER=$(getent passwd $DEF_UID | sed 's/:.*//')
MNT=/media/sdcard
MOUNT_OPTS="noatime,users"  # "dirsync" removed
ACTION=$1
DEVNAME=$2

if [ -z "${ACTION}" ]; then
    systemd-cat -t mount-sd /bin/echo "ERROR: Action needs to be defined."
    exit 1
fi

if [ -z "${DEVNAME}" ]; then
    systemd-cat -t mount-sd /bin/echo "ERROR: Device name needs to be defined."
    exit 1
fi

systemd-cat -t mount-sd /bin/echo "Called to ${ACTION} ${DEVNAME}"

if [ "$ACTION" = "add" ]; then
    # Setting variables DEVNAME (anew!), UUID and TYPE (but all three will be not set for "plain" DM-crypt devices):
    eval "$(/sbin/blkid -c /dev/null -o export /dev/$2)"

    if [ "${TYPE}" = "crypto_LUKS" ]; then
        if cryptsetup --allow-discards -d /etc/$(basename ${DEVNAME}).key luksOpen ${DEVNAME} $(basename ${DEVNAME})-crypt 
        then
            eval "$(/sbin/blkid -c /dev/null -o export /dev/mapper/$(basename ${DEVNAME})-crypt)"  # Reassigning DEVNAME, TYPE and UUID
            if [ "${TYPE}" = "crypto_LUKS" ]  # Still?  Then blkid did not output anything.
            then
                systemd-cat -t mount-sd /bin/echo "ERROR: Filesystem type missing for DM-crypt (LUKS) device ${DEVNAME}"
                cryptsetup close "$(basename ${DEVNAME})-crypt"
                exit 1
            else systemd-cat -t mount-sd /bin/echo "Successfully opened DM-crypt (LUKS) device ${DEVNAME}"
            fi
        else 
            systemd-cat -t mount-sd /bin/echo "ERROR: Failed to open ${DEVNAME} with cryptsetup (LUKS)"
            exit 1
        fi
    fi
    if [ -z "${TYPE}" ] && [ -z "${UUID}" ] && [ "${DEVNAME}" = "$2" ]; then  # trying cryptsetup "plain"
        cryptsetup -h sha1 -s 128 -c aes-cbc-essiv:sha256 --allow-discards -d /etc/$(basename $2).key --type plain open /dev/$2 $(basename $2)-crypt  # Cryptsetup "plain" will always succeed, when the key-file is readable and the device is accessible
        eval "$(/sbin/blkid -c /dev/null -o export /dev/mapper/$(basename $2)-crypt)"  # Reassigning DEVNAME, TYPE and UUID
        if [ -z "${TYPE}" ]  # Still?!
        then
            systemd-cat -t mount-sd /bin/echo "NOTICE: Tried opening ${DEVNAME} as DM-crypt \"plain\" device, but failed to obtain a filesystem type"
            cryptsetup close "$(basename $2)-crypt"
            DEVNAME="$2" ; unset UUID  # Revert to state before trying cryptsetup "plain"; consider "exit 1" instead
        else systemd-cat -t mount-sd /bin/echo "Successfully opened DM-crypt (\"plain\") device ${DEVNAME}"
        fi 
    fi

    if [ -z "${TYPE}" ]; then

        # In case filesystem type is missing, try reading it.
        TYPE=$(lsblk -n -o FSTYPE ${DEVNAME} | tail -n 1)  # Fails grossly when called for basic device (e.g. $2 = mmcblk1) with multiple partitions on it: Picks the type of last partition (e.g. from /dev/mmcblk1pX) then!  Still no harm done, as subsequent mounting usually fails, consequently.

        if [ -z "${TYPE}" ]; then
            systemd-cat -t mount-sd /bin/echo "ERROR: Filesystem type missing for ${DEVNAME}"
            exit 1
        fi
    fi

    if [ -z "${UUID}" ]; then
        # In case device does not have UUID lets create one for it based on
        # the card identification.
        PKNAME=$(lsblk -n -o PKNAME ${DEVNAME} | tail -n 1)

        # If there is no PKNAME try NAME instead.
        if [ -z "${PKNAME}" ]; then
            PKNAME=$(lsblk -n -o NAME ${DEVNAME} | head -n 1)
        fi

        if [ -e "/sys/block/${PKNAME}/device/cid" ]; then
            CID=$(cat /sys/block/${PKNAME}/device/cid)
            if [ -n "${CID}" ]; then
                IDNAME=$(lsblk -n -o NAME ${DEVNAME} | tail -1 | cut -d "-" -f2)
                UUID="${CID}-${IDNAME}"
            fi
        fi

        if [ -z "${UUID}" ]; then
            # Exit here as in the future there might be things like USB OTG disks or
            # sdcards attached via adapter that might behave differently and needs special case
            # in case such happens fail so we don't break anything.
            systemd-cat -t mount-sd /bin/echo "ERROR: Could not find or generate UUID for device ${DEVNAME}."
            exit 1
        fi
    fi

    DIR=$(grep -w ${DEVNAME} /proc/mounts | cut -d \  -f 2)
    if [ -n "$DIR" ]; then
        systemd-cat -t mount-sd /bin/echo "${DEVNAME} already mounted on ${DIR}, ignoring"
        exit 0
    fi

    test -d $MNT/${UUID} || mkdir -p $MNT/${UUID}
    chown $DEF_UID:$DEF_GID $MNT $MNT/${UUID}
    touch $MNT/${UUID}

    case "${TYPE}" in
    vfat|exfat)
        mount ${DEVNAME} $MNT/${UUID} -o uid=$DEF_UID,gid=$DEF_GID,$MOUNT_OPTS,utf8,flush,discard || /bin/rmdir $MNT/${UUID}
        ;;
    # NTFS support has not been tested but it's being left to please the ego of an engineer!
    ntfs)
        mount ${DEVNAME} $MNT/${UUID} -o uid=$DEF_UID,gid=$DEF_GID,$MOUNT_OPTS,utf8 || /bin/rmdir $MNT/${UUID}
        ;;
#   ext4)
#       mount ${DEVNAME} $MNT/${UUID} -o $MOUNT_OPTS,discard || /bin/rmdir $MNT/${UUID}
#       ;;
#   btrfs)
#       mount ${DEVNAME} $MNT/${UUID} -o $MOUNT_OPTS,enospc_debug || /bin/rmdir $MNT/${UUID}  # plus "autodefrag" and / or "compress=lzo"?
#       ;;
    *)
        mount ${DEVNAME} $MNT/${UUID} -o $MOUNT_OPTS || /bin/rmdir $MNT/${UUID}
        ;;
    esac
    test -d $MNT/${UUID} && touch $MNT/${UUID}
    systemd-cat -t mount-sd /bin/echo "Finished ${ACTION}ing ${DEVNAME} of type ${TYPE} at $MNT/${UUID}"

else
    DIR=$(grep -w ${DEVNAME} /proc/mounts | cut -d \  -f 2)
    if [ -n "${DIR}" ] ; then
        if [ "${DIR##$MNT}" = "${DIR}" ]; then
            systemd-cat -t mount-sd /bin/echo "${DEVNAME} mountpoint ${DIR} is not under ${MNT}, ignoring"
            exit 0
        fi
        umount $DIR || umount -l $DIR
        if [ -e "/dev/mapper/$(basename ${DEVNAME})-crypt" ]; then
            if cryptsetup close "$(basename ${DEVNAME})-crypt" 
            then systemd-cat -t mount-sd /bin/echo "Cryptsetup closed ${DEVNAME} successfully" 
            else systemd-cat -t mount-sd /bin/echo "WARNING: Cryptsetup failed to close ${DEVNAME}" 
            fi
        fi
        systemd-cat -t mount-sd /bin/echo "Finished ${ACTION}ing ${DEVNAME} at ${DIR}"
    fi
fi

8.2 Practical trim / discard test

(adapted for SailfishOS, only usable without filesystem compression etc.)

devel-su
cat /sys/block/mmcblk1/queue/discard_zeroes_data # "1", if discard / trim is supported
lsblk -D /dev/mmcblk1 # See, if discards are correctly configured
cd /media/sdcard/XXXXXXXX/
yes | dd bs=4K count=1K of=trim.test # 4 MB; must consist of whole erase-blocks (at least one; if not, increase count)
sync ; echo 1 > /proc/sys/vm/drop_caches
hexdump trim.test # outputs only "0a79"
filefrag -s -v trim.test
df trim.test
dd bs=<blocksize_from_filefrag> skip=<starting-offset_from_filefrag> count=<nuber-of-blocks_from_filefrag> if=<underlying-device_from_df> | hexdump # outputs only "0a79"
rm trim.test
sync ; echo 1 > /proc/sys/vm/drop_caches

Then perform tests (fstrim, reboot, just wait etc.), issue sync ; echo 1 > /proc/sys/vm/drop_caches thereafter (if not rebooted) and ultimately repeat dd bs=<blocksize_from_filefrag> skip=<starting-offset_from_filefrag> count=<number-of-blocks_from_filefrag> if=<underlying-device_from_df> | hexdump: If it still only outputs "0a79", no discard / trim occurred, if successful the output should be all zeroes (or random data for encrypted devices).

edit retag flag offensive close delete

Comments

WOW! Amazing how-to. Don't get me wrong, but I hope this get partially obsolete with the announced encryption for SD card and filesystem ;-)

bomo ( 2018-02-12 22:34:12 +0200 )edit
1

So do I, but no ETA announced, no exact feature set defined, in the past features took "Jolla time" to materialise (i.e. late or never) and I was finishing this last week after months of research (while most older guides have significant flaws and / or do not work anymore due to SailfishOS updates):
So for the time being, this seems to be the only practical solution.

olf ( 2018-02-13 01:42:29 +0200 )edit

Great work! Thumbs up! I know what I will do tomorrow with my empty 64GB-SD-card. :-)

ds1979 ( 2018-02-14 19:39:41 +0200 )edit

1 Answer

Sort by » oldest newest most voted
0

answered 2018-02-18 00:21:01 +0200

Holger gravatar image

Hi, I have successfully created an ext4 formatted sdcard (unencrypted) with this guide. Thanks! However, I found one glitch: in step 5 "Finishing up" the chown command is not complete: the option "-R" is missing (recursive), so that all files and all directories in all subdirectories are changed to nemo:nemo as well. Bye

edit flag offensive delete publish link more

Comments

The chown nemo:nemo * */. in section 5 adapts the (user- and group-) ownership of each mountpoint (i.e. the directory named UUID) in /media/sdcard/ and each root directory of mounted filesystem (/media/sdcard/XXXXXXXX/.): Nothing more is needed for nemo to have full access, other existing directories (e.g. the "lost+found" directory) should stay untouched.
Any copying of data should be done as user nemo.

@Holger: What was your issue, which you resolved by changing the ownership recursively?

olf ( 2018-02-18 01:44:33 +0200 )edit

I used my pc for copying the files to the card, and on the pc I had no nemo user. So file ownership had to be changed.

Holger ( 2018-02-18 08:28:26 +0200 )edit
Login/Signup to Answer

Question tools

Follow
15 followers

Stats

Asked: 2018-02-11 23:20:08 +0200

Seen: 448 times

Last updated: 8 hours ago