diff --git a/changelog/64310.added.md b/changelog/64310.added.md new file mode 100644 index 000000000000..d81c037c9348 --- /dev/null +++ b/changelog/64310.added.md @@ -0,0 +1 @@ +Added ``discard`` parameter to ``disk.format_`` and ``blockdev.formatted`` to allow opting out of block discard during filesystem creation, preventing sparse inflation of disk images on host filesystems. diff --git a/salt/modules/disk.py b/salt/modules/disk.py index 4725e09c65e3..74cd66066382 100644 --- a/salt/modules/disk.py +++ b/salt/modules/disk.py @@ -481,6 +481,7 @@ def format_( lazy_itable_init=None, fat=None, force=False, + discard=True, ): """ Format a filesystem onto a device @@ -519,6 +520,15 @@ def format_( This option is dangerous, use it with caution. + discard + Attempt to discard blocks at mkfs time (enabled by default). Set to + ``False`` to disable block discard, which prevents sparse file + inflation when formatting disk images on a host filesystem. + + This option is only supported for ext and xfs filesystems. + + .. versionadded:: 3009.0 + CLI Example: .. code-block:: bash @@ -534,6 +544,11 @@ def format_( if lazy_itable_init is not None: if fs_type[:3] == "ext": cmd.extend(["-E", f"lazy_itable_init={lazy_itable_init}"]) + if not discard: + if fs_type[:3] == "ext": + cmd.extend(["-E", "nodiscard"]) + elif fs_type == "xfs": + cmd.append("-K") if fat is not None and fat in (12, 16, 32): if fs_type[-3:] == "fat": cmd.extend(["-F", fat]) diff --git a/tests/pytests/unit/modules/test_disk.py b/tests/pytests/unit/modules/test_disk.py index b7a73226ac99..162832e600b4 100644 --- a/tests/pytests/unit/modules/test_disk.py +++ b/tests/pytests/unit/modules/test_disk.py @@ -382,6 +382,34 @@ def test_format_(): mock.assert_any_call(["mkfs", "-t", "ext4", device], ignore_retcode=True) +@pytest.mark.skip_on_windows(reason="Skip on Windows") +@pytest.mark.skip_if_binaries_missing("mkfs") +def test_format__nodiscard_ext(): + """ + unit tests for disk.format_ with discard=False on an ext filesystem + """ + device = "/dev/sdX1" + mock = MagicMock(return_value=0) + with patch.dict(disk.__salt__, {"cmd.retcode": mock}): + disk.format_(device=device, fs_type="ext4", discard=False) + mock.assert_any_call( + ["mkfs", "-t", "ext4", "-E", "nodiscard", device], ignore_retcode=True + ) + + +@pytest.mark.skip_on_windows(reason="Skip on Windows") +@pytest.mark.skip_if_binaries_missing("mkfs") +def test_format__nodiscard_xfs(): + """ + unit tests for disk.format_ with discard=False on an xfs filesystem + """ + device = "/dev/sdX1" + mock = MagicMock(return_value=0) + with patch.dict(disk.__salt__, {"cmd.retcode": mock}): + disk.format_(device=device, fs_type="xfs", discard=False) + mock.assert_any_call(["mkfs", "-t", "xfs", "-K", device], ignore_retcode=True) + + @pytest.mark.skip_on_windows(reason="Skip on Windows") @pytest.mark.skip_if_binaries_missing("mkfs") def test_format__fat():