On Tue, May 7, 2019 at 4:08 PM Pavel Bar <pbar(a)redhat.com> wrote:
On Tue, May 7, 2019 at 1:38 AM Nir Soffer <nirsof(a)gmail.com> wrote:
> We added API for using 4k sector size and various alignments, but there
> are no tests for the new APIs with disks using 4k sector size. Testing
> this is complicated since creating a block device and mounting file
> systems requires root, and we like to run the tests as a regular user.
>
> Add new tests for writing and reading lockspace and resource using 4k
> storage provided by the user. If a path is not specified the tests are
> skipped.
>
> To run the tests, you need to create a block device using 4k sector size
> and optionally create a file system and mount it. The process is
> explained in README.dev.
>
> Then pass the path of the block device or file on the new file system to
> the tests:
>
> SANLOCK_4K_PATH=/dev/loop2 tox -e py27
>
> Adding and removing lockspace and acquiring resources is not tested yet
> with 4k storage.
>
> Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
> ---
> README.dev | 44 ++++++++++++++++++++++++++
> tests/python_test.py | 74 ++++++++++++++++++++++++++++++++++++++++++++
> tox.ini | 2 +-
> 3 files changed, 119 insertions(+), 1 deletion(-)
>
> diff --git a/README.dev b/README.dev
> index 3519993..04617aa 100644
> --- a/README.dev
> +++ b/README.dev
> @@ -22,5 +22,49 @@ To run only test from some modules:
> $ tox tests/daemon_test.py
>
> To run only tests matching the substring "foo":
>
> $ tox -- -k foo
> +
> +
> +Testing 4K support
> +==================
> +
> +This requires manual setup for creating a block device using 4k sector
> size,
> +optionally creating and mounting a file system, and passing the test
> path to
> +tests. The setup must be done as root, but the tests can run later as the
> +current user.
> +
> +Common setup
> +------------
> +
> +1. Create a backing file:
> +
> + $ truncate -s 1G /var/tmp/backing
> +
> +2. Create a loop device with 4k sector size:
> +
> + $ sudo losetup -f /var/tmp/backing --show --sector-size=4096
> + /dev/loop2
> +
> +3. Change the device (or mountpoint) owner to current user
> +
> + $ sudo chown $USER:$USER /dev/loop2
> +
> +Testing 4k block device
> +-----------------------
> +
> +Run the tests with SANLOCK_4K_PATH environment variable:
> +
> + $ SANLOCK_4K_PATH=/dev/loop2 tox -e py27
> +
> +Testing 4k file system
> +----------------------
> +
> +To test file system on top of 4k block device, create a file system on
> the
> +device, mount it, and create a file for testing lockspace or resources:
> +
> + $ sudo mkfs.xfs /dev/loop2
> + $ sudo mount /dev/loop2 /tmp/sanlock-4k
> + $ sudo chown $USER:$USER /tmp/sanlock-4k
> + $ truncate -s 128m /tmp/sanlock-4k/disk
> + $ SANLOCK_4K_PATH=/tmp/sanlock-4k/disk tox -e py27
> diff --git a/tests/python_test.py b/tests/python_test.py
> index 1a6bbbd..f0ecd06 100644
> --- a/tests/python_test.py
> +++ b/tests/python_test.py
> @@ -2,10 +2,11 @@
> Test sanlock python binding with sanlock daemon.
> """
>
> import errno
> import io
> +import os
> import struct
> import time
>
> import pytest
>
> @@ -23,10 +24,11 @@ LARGE_FILE_SIZE = 1024**4
> LOCKSPACE_SIZE = 1024**2
> MIN_RES_SIZE = 1024**2
>
> ALIGNMENT_1M = 1024**2
> SECTOR_SIZE_512 = 512
> +SECTOR_SIZE_4K = 4096
>
I already have a PR ready with new constants (for Kibibyte, Mebibyte,
Gibibyte & Tebibyte). When my PR is merged, need to remember to change the
"SECTOR_SIZE_4K" to use new constants.
LOCKSPACE_SIZE = constants.MiB
MIN_RES_SIZE = constants.MiB
ALIGNMENT_1M = constants.MiB
SECTOR_SIZE_512 = 512
SECTOR_SIZE_4K = 4*constants.KiB <--- Remember to change
Cool, your PR on my queue.
>
> @pytest.mark.parametrize("size,offset", [
> # Smallest offset.
> (LOCKSPACE_SIZE, 0),
> @@ -64,10 +66,43 @@ def test_write_lockspace(tmpdir, sanlock_daemon,
> size, offset):
> # TODO: check more stuff here...
>
> util.check_guard(path, size)
>
>
> +(a)pytest.mark.skipif(
> + "SANLOCK_4K_PATH" not in os.environ,
> + reason="Requires user specified path using 4k block size")
> +(a)pytest.mark.parametrize("align", sanlock.ALIGN_SIZE)
> +def test_write_lockspace_4k(sanlock_daemon, align):
> + path = os.environ["SANLOCK_4K_PATH"]
> +
> + # Postion lockspace area, ensuring that previous tests will not
> break this
> + # test, and sanlock does not write after the lockspace area.
> + with io.open(path, "rb+") as f:
> + f.write(align * b"x")
> + f.write(4096 * b"X")
> +
> + sanlock.write_lockspace(
> + "name", path, iotimeout=1, align=align, sector=SECTOR_SIZE_4K)
> +
> + ls = sanlock.read_lockspace(path, align=align, sector=SECTOR_SIZE_4K)
> +
> + assert ls == {"iotimeout": 1, "lockspace":
"name"}
> +
> + acquired = sanlock.inq_lockspace("name", 1, path, wait=False)
> + assert acquired is False
> +
> + with io.open(path, "rb") as f:
> + # Verify that lockspace was written.
> + magic, = struct.unpack("< I", f.read(4))
> + assert magic == constants.DELTA_DISK_MAGIC
> +
> + # Check that sanlock did not write after the lockspace area.
> + f.seek(align)
> + assert f.read(4096) == b"X" * 4096
> +
> +
> @pytest.mark.parametrize("size,offset", [
> # Smallest offset.
> (MIN_RES_SIZE, 0),
> # Large offset.
> (LARGE_FILE_SIZE, LARGE_FILE_SIZE - MIN_RES_SIZE),
> @@ -111,10 +146,49 @@ def test_write_resource(tmpdir, sanlock_daemon,
> size, offset):
> # TODO: check more stuff here...
>
> util.check_guard(path, size)
>
>
> +(a)pytest.mark.skipif(
> + "SANLOCK_4K_PATH" not in os.environ,
> + reason="Requires user specified path using 4k block size")
> +(a)pytest.mark.parametrize("align", sanlock.ALIGN_SIZE)
> +def test_write_resource_4k(sanlock_daemon, align):
> + path = os.environ["SANLOCK_4K_PATH"]
> + disks = [(path, 0)]
> +
> + # Postion resource area, ensuring that previous tests will not break
> this
> + # test, and sanlock does not write after the lockspace area.
> + with io.open(path, "rb+") as f:
> + f.write(align * b"x")
> + f.write(4096 * b"X")
> +
> + sanlock.write_resource(
> + "ls_name", "res_name", disks, align=align,
sector=SECTOR_SIZE_4K)
> +
> + res = sanlock.read_resource(path, align=align, sector=SECTOR_SIZE_4K)
> +
> + assert res == {
> + "lockspace": "ls_name",
> + "resource": "res_name",
> + "version": 0
> + }
> +
> + owners = sanlock.read_resource_owners(
> + "ls_name", "res_name", disks, align=align,
sector=SECTOR_SIZE_4K)
> + assert owners == []
> +
> + with io.open(path, "rb") as f:
> + # Verify that resource was written.
> + magic, = struct.unpack("< I", f.read(4))
> + assert magic == constants.PAXOS_DISK_MAGIC
> +
> + # Check that sanlock did not write after the resource area.
> + f.seek(align)
> + assert f.read(4096) == b"X" * 4096
> +
> +
> @pytest.mark.parametrize("size,offset", [
> # Smallest offset.
> (MIN_RES_SIZE, 0),
> # Large offset.
> (LARGE_FILE_SIZE, LARGE_FILE_SIZE - MIN_RES_SIZE),
> diff --git a/tox.ini b/tox.ini
> index 1c2349e..d21f2f3 100644
> --- a/tox.ini
> +++ b/tox.ini
> @@ -7,11 +7,11 @@
> envlist = py27,py36
> skipsdist = True
> skip_missing_interpreters = True
>
> [testenv]
> -passenv = USER
> +passenv = *
> setenv =
> LD_LIBRARY_PATH={env:PWD}/wdmd:{env:PWD}/src
> SANLOCK_PRIVILEGED=0
> SANLOCK_RUN_DIR=/tmp/sanlock
> whitelist_externals = make
> --
> 2.17.2
>
>