diff --git a/sys/include/vfs.h b/sys/include/vfs.h index 62714afc9f..1f3ebedbd9 100644 --- a/sys/include/vfs.h +++ b/sys/include/vfs.h @@ -1014,8 +1014,8 @@ const vfs_mount_t *vfs_iterate_mounts(const vfs_mount_t *cur); * access to the mount point's stats through @ref vfs_dstatvfs. If mounts or * unmounts happen while iterating, this is guaranteed to report all file * systems that stayed mounted, and may report any that are transiently - * mounted. Note that the volume being reported can not be unmounted as @p dir - * is an open directory. + * mounted for up to as often as they are (re)mounted. Note that the volume + * being reported can not be unmounted as @p dir is an open directory. * * Zero-initialize @p dir to start. As long as @c true is returned, @p dir is a * valid directory on which the user can call @ref vfs_readdir or @ref diff --git a/tests/vfs_iterate_mount/Makefile b/tests/vfs_iterate_mount/Makefile new file mode 100644 index 0000000000..c05a41a42b --- /dev/null +++ b/tests/vfs_iterate_mount/Makefile @@ -0,0 +1,6 @@ +include ../Makefile.tests_common + +USEMODULE += vfs +USEMODULE += constfs + +include $(RIOTBASE)/Makefile.include diff --git a/tests/vfs_iterate_mount/Makefile.ci b/tests/vfs_iterate_mount/Makefile.ci new file mode 100644 index 0000000000..b9ff275375 --- /dev/null +++ b/tests/vfs_iterate_mount/Makefile.ci @@ -0,0 +1,3 @@ +BOARD_INSUFFICIENT_MEMORY := \ + nucleo-l011k4 \ + # diff --git a/tests/vfs_iterate_mount/main.c b/tests/vfs_iterate_mount/main.c new file mode 100644 index 0000000000..6d415fa4bd --- /dev/null +++ b/tests/vfs_iterate_mount/main.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) Christian Amsüss + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * Mount and unmount a few file systems, demonstrating that + * vfs_iterate_mount_dirs performs as advertised. + * + * @author Christian Amsüss + */ + +#include +#include +#include + +#include +#include + +static constfs_file_t constfs_files[1] = { + /* Not completely empty -- that'd be a hassle around empty arrays and + * their size */ + { + .path = "some-file", + .size = 0, + .data = (void*)"", + }, +}; + +static constfs_t constfs_desc = { + .nfiles = ARRAY_SIZE(constfs_files), + .files = constfs_files, +}; + +static vfs_mount_t mount1 = { + .fs = &constfs_file_system, + .mount_point = "/const1", + .private_data = &constfs_desc, +}; + +static vfs_mount_t mount2 = { + .fs = &constfs_file_system, + .mount_point = "/const2", + .private_data = &constfs_desc, +}; + +static vfs_mount_t mount3 = { + .fs = &constfs_file_system, + .mount_point = "/const3", + .private_data = &constfs_desc, +}; + +static vfs_mount_t mount4 = { + .fs = &constfs_file_system, + .mount_point = "/const4", + .private_data = &constfs_desc, +}; + +/* Crank the iterator, reporting "N%s" for the next entry, or "O\n" for the end + * of the iterator (avoiding the letter "E" which may be misread for an error + * in a casual look at the error output) */ +static void iter_and_report(vfs_DIR *iter) { + bool result = vfs_iterate_mount_dirs(iter); + if (result) { + printf("N(%s)", iter->mp->mount_point); + } else { + printf("O\n"); + /* Zero out so we're ready for next round immediately */ + memset(iter, 0, sizeof(*iter)); + } +} + +int main(void) { + int res = 0; + + vfs_DIR iter; + memset(&iter, 0, sizeof(iter)); + + res |= vfs_mount(&mount1); + res |= vfs_mount(&mount2); + res |= vfs_mount(&mount3); + res |= vfs_mount(&mount4); + assert(res == 0); + printf("Mounted 1234\n"); + + /* N1N2N3N4E */ + iter_and_report(&iter); + iter_and_report(&iter); + iter_and_report(&iter); + iter_and_report(&iter); + iter_and_report(&iter); + + /* N1N2, unmount 3, N4E */ + iter_and_report(&iter); + iter_and_report(&iter); + res |= vfs_umount(&mount3); + iter_and_report(&iter); + iter_and_report(&iter); + + /* N1, unmount 2, (3 is already unmounted), N4, mount 3 N3, unmount 1 and remount it at the end N1, O */ + /* It is OK that 1 is reported twice, because its first occurrence is its + * old mounting, and later it reappears */ + iter_and_report(&iter); + res |= vfs_umount(&mount2); + iter_and_report(&iter); + res |= vfs_mount(&mount3); + iter_and_report(&iter); + res |= vfs_umount(&mount1); + res |= vfs_mount(&mount1); + iter_and_report(&iter); + iter_and_report(&iter); + + /* This ensures we're not leaking locks */ + res |= vfs_umount(&mount1); + res |= vfs_umount(&mount3); + res |= vfs_umount(&mount4); + printf("All unmounted\n"); + + /* Only O */ + iter_and_report(&iter); +} diff --git a/tests/vfs_iterate_mount/tests/01-run.py b/tests/vfs_iterate_mount/tests/01-run.py new file mode 100755 index 0000000000..5a705e8d86 --- /dev/null +++ b/tests/vfs_iterate_mount/tests/01-run.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2021 Christian Amsüss +# +# This file is subject to the terms and conditions of the GNU Lesser +# General Public License v2.1. See the file LICENSE in the top level +# directory for more details. + +import sys +from testrunner import run + + +def testfunc(child): + child.expect_exact("Mounted 1234") + child.expect_exact("N(/const1)N(/const2)N(/const3)N(/const4)O") + child.expect_exact("N(/const1)N(/const2)N(/const4)O") + child.expect_exact("N(/const1)N(/const4)N(/const3)N(/const1)O") + child.expect_exact("All unmounted") + child.expect_exact("O") + + +if __name__ == "__main__": + sys.exit(run(testfunc))