On Tue, May 7, 2019 at 4:08 PM Pavel Bar <pbar@redhat.com> wrote:


On Tue, May 7, 2019 at 1:38 AM Nir Soffer <nirsof@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@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)


+@pytest.mark.skipif(
+    "SANLOCK_4K_PATH" not in os.environ,
+    reason="Requires user specified path using 4k block size")
+@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)


+@pytest.mark.skipif(
+    "SANLOCK_4K_PATH" not in os.environ,
+    reason="Requires user specified path using 4k block size")
+@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