@@ -6,13 +6,19 @@
* Written by Simon Glass <simon.glass@canonical.com>
*/
+#include <blk.h>
#include <command.h>
+#include <dm.h>
#include <env.h>
#include <ext4l.h>
#include <fs.h>
#include <fs_legacy.h>
#include <linux/sizes.h>
+#include <mapmem.h>
+#include <sandbox_host.h>
#include <u-boot/uuid.h>
+#include <vfs.h>
+#include <dm/device-internal.h>
#include <test/test.h>
#include <test/ut.h>
#include <test/fs.h>
@@ -650,3 +656,79 @@ static int fs_test_ext4l_rename_norun(struct unit_test_state *uts)
}
FS_TEST_ARGS(fs_test_ext4l_rename_norun, UTF_SCAN_FDT | UTF_CONSOLE | UTF_MANUAL,
{ "fs_image", UT_ARG_STR });
+
+#define EXT4L_ARG_IMAGE_A 0
+#define EXT4L_ARG_IMAGE_B 1
+#define BUF_ADDR 0x10000
+
+/**
+ * fs_test_ext4l_dual_mount_norun() - Test two ext4l mounts simultaneously
+ *
+ * Mount two different ext4 images at /mnt and /mnt2, read a file from
+ * each, and verify they return different content.
+ *
+ * Arguments:
+ * fs_image_a: Path to first ext4 filesystem image (contains "alpha\n")
+ * fs_image_b: Path to second ext4 filesystem image (contains "bravo\n")
+ */
+static int fs_test_ext4l_dual_mount_norun(struct unit_test_state *uts)
+{
+ const char *image_a = ut_str(EXT4L_ARG_IMAGE_A);
+ const char *image_b = ut_str(EXT4L_ARG_IMAGE_B);
+ struct udevice *dev_a, *dev_b, *blk;
+ struct blk_desc *desc;
+ char *buf;
+
+ ut_assertok(vfs_init());
+
+ /* Mount first image at /mnt */
+ ut_assertok(host_create_device("ext4a", true, DEFAULT_BLKSZ, &dev_a));
+ ut_assertok(host_attach_file(dev_a, image_a));
+ ut_assertok(blk_get_from_parent(dev_a, &blk));
+ ut_assertok(device_probe(blk));
+ desc = dev_get_uclass_plat(blk);
+ ut_assertok(run_commandf("mount host %x:0 /mnt", desc->devnum));
+ ut_assert_console_end();
+
+ /* Mount second image at /mnt2 */
+ ut_assertok(host_create_device("ext4b", true, DEFAULT_BLKSZ, &dev_b));
+ ut_assertok(host_attach_file(dev_b, image_b));
+ ut_assertok(blk_get_from_parent(dev_b, &blk));
+ ut_assertok(device_probe(blk));
+ desc = dev_get_uclass_plat(blk);
+ ut_assertok(run_commandf("mount host %x:0 /mnt2", desc->devnum));
+ ut_assert_console_end();
+
+ /* Read from first mount */
+ buf = map_sysmem(BUF_ADDR, 0x100);
+ memset(buf, '\0', 0x100);
+ ut_assertok(run_commandf("load %x /mnt/id.txt", BUF_ADDR));
+ ut_assert_nextline("6 bytes read");
+ ut_assert_console_end();
+ ut_asserteq_str("alpha\n", buf);
+
+ /* Read from second mount */
+ memset(buf, '\0', 0x100);
+ ut_assertok(run_commandf("load %x /mnt2/id.txt", BUF_ADDR));
+ ut_assert_nextline("6 bytes read");
+ ut_assert_console_end();
+ ut_asserteq_str("bravo\n", buf);
+ unmap_sysmem(buf);
+
+ /* Unmount both */
+ ut_assertok(run_command("umount /mnt2", 0));
+ ut_assert_console_end();
+ ut_assertok(run_command("umount /mnt", 0));
+ ut_assert_console_end();
+
+ ut_assertok(host_detach_file(dev_b));
+ ut_assertok(device_unbind(dev_b));
+ ut_assertok(host_detach_file(dev_a));
+ ut_assertok(device_unbind(dev_a));
+
+ return 0;
+}
+FS_TEST_ARGS(fs_test_ext4l_dual_mount_norun,
+ UTF_SCAN_FDT | UTF_CONSOLE | UTF_MANUAL,
+ { "fs_image_a", UT_ARG_STR },
+ { "fs_image_b", UT_ARG_STR });
@@ -14,6 +14,8 @@ from tempfile import NamedTemporaryFile
import pytest
+from tests.fs_helper import FsHelper
+
@pytest.mark.buildconfigspec('sandbox')
@pytest.mark.buildconfigspec('fs_ext4l')
@@ -146,3 +148,35 @@ class TestExt4l:
"""Test that ext4l can rename files and directories."""
with ubman.log.section('Test ext4l rename'):
ubman.run_ut('fs', 'fs_test_ext4l_rename', fs_image=ext4_image)
+
+ @pytest.fixture(scope='class')
+ def dual_images(self, u_boot_config):
+ """Create two ext4 images with different content.
+
+ Image A contains id.txt with "alpha\\n".
+ Image B contains id.txt with "bravo\\n".
+
+ Yields:
+ tuple: (path_a, path_b) paths to the two images
+ """
+ helpers = []
+ for label, content in [('a', 'alpha'), ('b', 'bravo')]:
+ fsh = FsHelper(u_boot_config, 'ext4', 64, f'dual_{label}')
+ fsh.setup()
+ with open(os.path.join(fsh.srcdir, 'id.txt'), 'w') as f:
+ f.write(content + '\n')
+ fsh.mk_fs()
+ helpers.append(fsh)
+
+ yield tuple(fsh.fs_img for fsh in helpers)
+
+ for fsh in helpers:
+ fsh.cleanup()
+
+ @pytest.mark.buildconfigspec('cmd_vfs')
+ def test_dual_mount(self, ubman, dual_images):
+ """Test that two ext4l filesystems can be mounted simultaneously."""
+ image_a, image_b = dual_images
+ with ubman.log.section('Test ext4l dual mount'):
+ ubman.run_ut('fs', 'fs_test_ext4l_dual_mount',
+ fs_image_a=image_a, fs_image_b=image_b)