fuse_mnt.c (2284B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * memfd test file-system 4 * This file uses FUSE to create a dummy file-system with only one file /memfd. 5 * This file is read-only and takes 1s per read. 6 * 7 * This file-system is used by the memfd test-cases to force the kernel to pin 8 * pages during reads(). Due to the 1s delay of this file-system, this is a 9 * nice way to test race-conditions against get_user_pages() in the kernel. 10 * 11 * We use direct_io==1 to force the kernel to use direct-IO for this 12 * file-system. 13 */ 14 15#define FUSE_USE_VERSION 26 16 17#include <fuse.h> 18#include <stdio.h> 19#include <string.h> 20#include <errno.h> 21#include <fcntl.h> 22#include <unistd.h> 23 24static const char memfd_content[] = "memfd-example-content"; 25static const char memfd_path[] = "/memfd"; 26 27static int memfd_getattr(const char *path, struct stat *st) 28{ 29 memset(st, 0, sizeof(*st)); 30 31 if (!strcmp(path, "/")) { 32 st->st_mode = S_IFDIR | 0755; 33 st->st_nlink = 2; 34 } else if (!strcmp(path, memfd_path)) { 35 st->st_mode = S_IFREG | 0444; 36 st->st_nlink = 1; 37 st->st_size = strlen(memfd_content); 38 } else { 39 return -ENOENT; 40 } 41 42 return 0; 43} 44 45static int memfd_readdir(const char *path, 46 void *buf, 47 fuse_fill_dir_t filler, 48 off_t offset, 49 struct fuse_file_info *fi) 50{ 51 if (strcmp(path, "/")) 52 return -ENOENT; 53 54 filler(buf, ".", NULL, 0); 55 filler(buf, "..", NULL, 0); 56 filler(buf, memfd_path + 1, NULL, 0); 57 58 return 0; 59} 60 61static int memfd_open(const char *path, struct fuse_file_info *fi) 62{ 63 if (strcmp(path, memfd_path)) 64 return -ENOENT; 65 66 if ((fi->flags & 3) != O_RDONLY) 67 return -EACCES; 68 69 /* force direct-IO */ 70 fi->direct_io = 1; 71 72 return 0; 73} 74 75static int memfd_read(const char *path, 76 char *buf, 77 size_t size, 78 off_t offset, 79 struct fuse_file_info *fi) 80{ 81 size_t len; 82 83 if (strcmp(path, memfd_path) != 0) 84 return -ENOENT; 85 86 sleep(1); 87 88 len = strlen(memfd_content); 89 if (offset < len) { 90 if (offset + size > len) 91 size = len - offset; 92 93 memcpy(buf, memfd_content + offset, size); 94 } else { 95 size = 0; 96 } 97 98 return size; 99} 100 101static struct fuse_operations memfd_ops = { 102 .getattr = memfd_getattr, 103 .readdir = memfd_readdir, 104 .open = memfd_open, 105 .read = memfd_read, 106}; 107 108int main(int argc, char *argv[]) 109{ 110 return fuse_main(argc, argv, &memfd_ops, NULL); 111}