From f8b483fb4d2b7042f051fb3a832926310f40e477 Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Wed, 15 Nov 2023 14:29:23 -0800 Subject: [PATCH] ANDROID: fuse-bpf: Ignore readaheads unless they go to the daemon readpages will be triggered on the fuse fs in passthrough mode though system calls like fadvise. If the daemon isn't aware of the file, this will likely cause a hang. For the moment, simply ignore fadvise in this situation Bug: 301201239 Test: fuse_test, atest ScopedStorageDeviceTest both pass Signed-off-by: Paul Lawrence Change-Id: I524a84aeeb1b1593e51264fcc37f7cfa66757168 (cherry picked from commit cfdfc17a46d0310b2cbe3e654bd8796bf4c75ba2) --- fs/fuse/file.c | 10 ++++++ .../selftests/filesystems/fuse/fuse_test.c | 36 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index e739f25e6f8d..2ea3592d758f 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1045,6 +1045,16 @@ static void fuse_readahead(struct readahead_control *rac) struct fuse_conn *fc = get_fuse_conn(inode); unsigned int i, max_pages, nr_pages = 0; +#ifdef CONFIG_FUSE_BPF + /* + * Currently no meaningful readahead is possible with fuse-bpf within + * the kernel, so unless the daemon is aware of this file, ignore this + * call. + */ + if (!get_fuse_inode(inode)->nodeid) + return; +#endif + if (fuse_is_bad(inode)) return; diff --git a/tools/testing/selftests/filesystems/fuse/fuse_test.c b/tools/testing/selftests/filesystems/fuse/fuse_test.c index bdbe135f8b68..6fad38ccc69b 100644 --- a/tools/testing/selftests/filesystems/fuse/fuse_test.c +++ b/tools/testing/selftests/filesystems/fuse/fuse_test.c @@ -2079,6 +2079,41 @@ out: return result; } +static int bpf_test_readahead(const char *mount_dir) +{ + const char *file_name = "file"; + + int result = TEST_FAILURE; + int file_fd = -1; + int src_fd = -1; + int fuse_dev = -1; + + TEST(file_fd = s_creat(s_path(s(ft_src), s(file_name)), 0777), + file_fd != -1); + TESTSYSCALL(fallocate(file_fd, 0, 0, 4096)); + TESTSYSCALL(close(file_fd)); + file_fd = -1; + + TEST(src_fd = open(ft_src, O_DIRECTORY | O_RDONLY | O_CLOEXEC), + src_fd != -1); + TEST(fuse_dev = open("/dev/fuse", O_RDWR | O_CLOEXEC), fuse_dev != -1); + TESTEQUAL(mount_fuse(mount_dir, -1, src_fd, &fuse_dev), 0); + + TEST(file_fd = s_open(s_path(s(mount_dir), s(file_name)), O_RDONLY), + file_fd != -1); + TESTSYSCALL(posix_fadvise(file_fd, 0, 4096, POSIX_FADV_WILLNEED)); + usleep(1000); + TESTSYSCALL(close(file_fd)); + file_fd = -1; + result = TEST_SUCCESS; +out: + umount(mount_dir); + close(fuse_dev); + close(src_fd); + close(file_fd); + return result; +} + static void parse_range(const char *ranges, bool *run_test, size_t tests) { size_t i; @@ -2208,6 +2243,7 @@ int main(int argc, char *argv[]) MAKE_TEST(flock_test), MAKE_TEST(bpf_test_create_and_remove_bpf), MAKE_TEST(bpf_test_mkdir_and_remove_bpf), + MAKE_TEST(bpf_test_readahead), }; #undef MAKE_TEST