diff --git a/test/fs/ext4l.c b/test/fs/ext4l.c
index 7548c3049bb..9e4c8823f2f 100644
--- a/test/fs/ext4l.c
+++ b/test/fs/ext4l.c
@@ -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 });
diff --git a/test/py/tests/test_fs/test_ext4l.py b/test/py/tests/test_fs/test_ext4l.py
index eb332d1b154..e029539572f 100644
--- a/test/py/tests/test_fs/test_ext4l.py
+++ b/test/py/tests/test_fs/test_ext4l.py
@@ -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)
