Add persistent and perf options to the luks_device (#434)
Read and write work queue significantly degrades performance on SSD/NVME devices[1]. In Debian 11 crypttab does not support no-read-workqueue and no-write-workqueue flags, so the persistent flag is workaround: once opened with perf parameters persists forever. [1] https://blog.cloudflare.com/speeding-up-linux-disk-encryption/ Signed-off-by: Yauhen Artsiukhou <jsirex@gmail.com>pull/444/head
parent
c7f581daad
commit
041fff5057
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
minor_changes:
|
||||||
|
- luks_devices - added ``persistent`` option when opening LUKS2 containers (https://github.com/ansible-collections/community.crypto/pull/434).
|
||||||
|
- luks_devices - added ``perf_same_cpu_crypt``, ``perf_submit_from_crypt_cpus``, ``perf_no_read_workqueue``, ``perf_no_write_workqueue`` for performance tuning when opening LUKS2 containers (https://github.com/ansible-collections/community.crypto/issues/427).
|
|
@ -217,6 +217,48 @@ options:
|
||||||
- "Will only be used on container creation."
|
- "Will only be used on container creation."
|
||||||
type: int
|
type: int
|
||||||
version_added: '1.5.0'
|
version_added: '1.5.0'
|
||||||
|
perf_same_cpu_crypt:
|
||||||
|
description:
|
||||||
|
- "Allows the user to perform encryption using the same CPU that IO was submitted on."
|
||||||
|
- "The default is to use an unbound workqueue so that encryption work is automatically balanced between available CPUs."
|
||||||
|
- "Will only be used when opening containers."
|
||||||
|
type: bool
|
||||||
|
default: false
|
||||||
|
version_added: '2.3.0'
|
||||||
|
perf_submit_from_crypt_cpus:
|
||||||
|
description:
|
||||||
|
- "Allows the user to disable offloading writes to a separate thread after encryption."
|
||||||
|
- "There are some situations where offloading block write IO operations from the encryption threads
|
||||||
|
to a single thread degrades performance significantly."
|
||||||
|
- "The default is to offload block write IO operations to the same thread."
|
||||||
|
- "Will only be used when opening containers."
|
||||||
|
type: bool
|
||||||
|
default: false
|
||||||
|
version_added: '2.3.0'
|
||||||
|
perf_no_read_workqueue:
|
||||||
|
description:
|
||||||
|
- "Allows the user to bypass dm-crypt internal workqueue and process read requests synchronously."
|
||||||
|
- "Will only be used when opening containers."
|
||||||
|
type: bool
|
||||||
|
default: false
|
||||||
|
version_added: '2.3.0'
|
||||||
|
perf_no_write_workqueue:
|
||||||
|
description:
|
||||||
|
- "Allows the user to bypass dm-crypt internal workqueue and process write requests synchronously."
|
||||||
|
- "Will only be used when opening containers."
|
||||||
|
type: bool
|
||||||
|
default: false
|
||||||
|
version_added: '2.3.0'
|
||||||
|
persistent:
|
||||||
|
description:
|
||||||
|
- "Allows the user to store options into container's metadata persistently and automatically use them next time.
|
||||||
|
Only I(perf_same_cpu_crypt), I(perf_submit_from_crypt_cpus), I(perf_no_read_workqueue), and I(perf_no_write_workqueue)
|
||||||
|
can be stored persistently."
|
||||||
|
- "Will only work with LUKS2 containers."
|
||||||
|
- "Will only be used when opening containers."
|
||||||
|
type: bool
|
||||||
|
default: false
|
||||||
|
version_added: '2.3.0'
|
||||||
|
|
||||||
requirements:
|
requirements:
|
||||||
- "cryptsetup"
|
- "cryptsetup"
|
||||||
|
@ -517,10 +559,21 @@ class CryptHandler(Handler):
|
||||||
raise ValueError('Error while creating LUKS on %s: %s'
|
raise ValueError('Error while creating LUKS on %s: %s'
|
||||||
% (device, result[STDERR]))
|
% (device, result[STDERR]))
|
||||||
|
|
||||||
def run_luks_open(self, device, keyfile, passphrase, name):
|
def run_luks_open(self, device, keyfile, passphrase, perf_same_cpu_crypt, perf_submit_from_crypt_cpus,
|
||||||
|
perf_no_read_workqueue, perf_no_write_workqueue, persistent, name):
|
||||||
args = [self._cryptsetup_bin]
|
args = [self._cryptsetup_bin]
|
||||||
if keyfile:
|
if keyfile:
|
||||||
args.extend(['--key-file', keyfile])
|
args.extend(['--key-file', keyfile])
|
||||||
|
if perf_same_cpu_crypt:
|
||||||
|
args.extend(['--perf-same_cpu_crypt'])
|
||||||
|
if perf_submit_from_crypt_cpus:
|
||||||
|
args.extend(['--perf-submit_from_crypt_cpus'])
|
||||||
|
if perf_no_read_workqueue:
|
||||||
|
args.extend(['--perf-no_read_workqueue'])
|
||||||
|
if perf_no_write_workqueue:
|
||||||
|
args.extend(['--perf-no_write_workqueue'])
|
||||||
|
if persistent:
|
||||||
|
args.extend(['--persistent'])
|
||||||
args.extend(['open', '--type', 'luks', device, name])
|
args.extend(['open', '--type', 'luks', device, name])
|
||||||
|
|
||||||
result = self._run_command(args, data=passphrase)
|
result = self._run_command(args, data=passphrase)
|
||||||
|
@ -802,6 +855,11 @@ def run_module():
|
||||||
mutually_exclusive=[('iteration_time', 'iteration_count')],
|
mutually_exclusive=[('iteration_time', 'iteration_count')],
|
||||||
),
|
),
|
||||||
sector_size=dict(type='int'),
|
sector_size=dict(type='int'),
|
||||||
|
perf_same_cpu_crypt=dict(type='bool', default=False),
|
||||||
|
perf_submit_from_crypt_cpus=dict(type='bool', default=False),
|
||||||
|
perf_no_read_workqueue=dict(type='bool', default=False),
|
||||||
|
perf_no_write_workqueue=dict(type='bool', default=False),
|
||||||
|
persistent=dict(type='bool', default=False),
|
||||||
)
|
)
|
||||||
|
|
||||||
mutually_exclusive = [
|
mutually_exclusive = [
|
||||||
|
@ -877,6 +935,11 @@ def run_module():
|
||||||
crypt.run_luks_open(conditions.device,
|
crypt.run_luks_open(conditions.device,
|
||||||
module.params['keyfile'],
|
module.params['keyfile'],
|
||||||
module.params['passphrase'],
|
module.params['passphrase'],
|
||||||
|
module.params['perf_same_cpu_crypt'],
|
||||||
|
module.params['perf_submit_from_crypt_cpus'],
|
||||||
|
module.params['perf_no_read_workqueue'],
|
||||||
|
module.params['perf_no_write_workqueue'],
|
||||||
|
module.params['persistent'],
|
||||||
name)
|
name)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
module.fail_json(msg="luks_device error: %s" % e)
|
module.fail_json(msg="luks_device error: %s" % e)
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
---
|
||||||
|
- name: Gather package facts
|
||||||
|
package_facts:
|
||||||
|
manager: auto
|
||||||
|
|
||||||
|
- name: On kernel >= 5.9 use performance flags
|
||||||
|
block:
|
||||||
|
- name: Create and open (check)
|
||||||
|
luks_device:
|
||||||
|
device: "{{ cryptfile_device }}"
|
||||||
|
state: opened
|
||||||
|
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||||
|
perf_same_cpu_crypt: true
|
||||||
|
perf_submit_from_crypt_cpus: true
|
||||||
|
perf_no_read_workqueue: true
|
||||||
|
perf_no_write_workqueue: true
|
||||||
|
persistent: true
|
||||||
|
pbkdf:
|
||||||
|
iteration_time: 0.1
|
||||||
|
check_mode: yes
|
||||||
|
become: yes
|
||||||
|
register: create_open_check
|
||||||
|
- name: Create and open
|
||||||
|
luks_device:
|
||||||
|
device: "{{ cryptfile_device }}"
|
||||||
|
state: opened
|
||||||
|
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||||
|
pbkdf:
|
||||||
|
iteration_time: 0.1
|
||||||
|
perf_same_cpu_crypt: true
|
||||||
|
perf_submit_from_crypt_cpus: true
|
||||||
|
perf_no_read_workqueue: true
|
||||||
|
perf_no_write_workqueue: true
|
||||||
|
persistent: true
|
||||||
|
become: yes
|
||||||
|
register: create_open
|
||||||
|
- name: Create and open (idempotent)
|
||||||
|
luks_device:
|
||||||
|
device: "{{ cryptfile_device }}"
|
||||||
|
state: opened
|
||||||
|
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||||
|
pbkdf:
|
||||||
|
iteration_time: 0.1
|
||||||
|
perf_same_cpu_crypt: true
|
||||||
|
perf_submit_from_crypt_cpus: true
|
||||||
|
perf_no_read_workqueue: true
|
||||||
|
perf_no_write_workqueue: true
|
||||||
|
persistent: true
|
||||||
|
become: yes
|
||||||
|
register: create_open_idem
|
||||||
|
- name: Create and open (idempotent, check)
|
||||||
|
luks_device:
|
||||||
|
device: "{{ cryptfile_device }}"
|
||||||
|
state: present
|
||||||
|
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||||
|
pbkdf:
|
||||||
|
iteration_time: 0.1
|
||||||
|
perf_same_cpu_crypt: true
|
||||||
|
perf_submit_from_crypt_cpus: true
|
||||||
|
perf_no_read_workqueue: true
|
||||||
|
perf_no_write_workqueue: true
|
||||||
|
persistent: true
|
||||||
|
check_mode: yes
|
||||||
|
become: yes
|
||||||
|
register: create_open_idem_check
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- create_open_check is changed
|
||||||
|
- create_open is changed
|
||||||
|
- create_open_idem is not changed
|
||||||
|
- create_open_idem_check is not changed
|
||||||
|
|
||||||
|
- name: Dump LUKS Header
|
||||||
|
command: "cryptsetup luksDump {{ cryptfile_device }}"
|
||||||
|
become: yes
|
||||||
|
register: luks_header
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "'no-read-workqueue' in luks_header.stdout"
|
||||||
|
- "'no-write-workqueue' in luks_header.stdout"
|
||||||
|
- "'same-cpu-crypt' in luks_header.stdout"
|
||||||
|
- "'submit-from-crypt-cpus' in luks_header.stdout"
|
||||||
|
|
||||||
|
- name: Dump device mapper table
|
||||||
|
command: "dmsetup table {{ create_open.name }}"
|
||||||
|
become: yes
|
||||||
|
register: dm_table
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "'no_read_workqueue' in dm_table.stdout"
|
||||||
|
- "'no_write_workqueue' in dm_table.stdout"
|
||||||
|
- "'same_cpu_crypt' in dm_table.stdout"
|
||||||
|
- "'submit_from_crypt_cpus' in dm_table.stdout"
|
||||||
|
|
||||||
|
- name: Closed and Removed
|
||||||
|
luks_device:
|
||||||
|
name: "{{ cryptfile_device }}"
|
||||||
|
state: absent
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
when:
|
||||||
|
- ansible_facts.kernel is version('5.9.0', '>=')
|
||||||
|
- ansible_facts.packages['cryptsetup'][0].version is version('2.3.4', '>=')
|
Loading…
Reference in New Issue