Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * memfd test file-system
0004  * This file uses FUSE to create a dummy file-system with only one file /memfd.
0005  * This file is read-only and takes 1s per read.
0006  *
0007  * This file-system is used by the memfd test-cases to force the kernel to pin
0008  * pages during reads(). Due to the 1s delay of this file-system, this is a
0009  * nice way to test race-conditions against get_user_pages() in the kernel.
0010  *
0011  * We use direct_io==1 to force the kernel to use direct-IO for this
0012  * file-system.
0013  */
0014 
0015 #define FUSE_USE_VERSION 26
0016 
0017 #include <fuse.h>
0018 #include <stdio.h>
0019 #include <string.h>
0020 #include <errno.h>
0021 #include <fcntl.h>
0022 #include <unistd.h>
0023 
0024 static const char memfd_content[] = "memfd-example-content";
0025 static const char memfd_path[] = "/memfd";
0026 
0027 static int memfd_getattr(const char *path, struct stat *st)
0028 {
0029     memset(st, 0, sizeof(*st));
0030 
0031     if (!strcmp(path, "/")) {
0032         st->st_mode = S_IFDIR | 0755;
0033         st->st_nlink = 2;
0034     } else if (!strcmp(path, memfd_path)) {
0035         st->st_mode = S_IFREG | 0444;
0036         st->st_nlink = 1;
0037         st->st_size = strlen(memfd_content);
0038     } else {
0039         return -ENOENT;
0040     }
0041 
0042     return 0;
0043 }
0044 
0045 static int memfd_readdir(const char *path,
0046              void *buf,
0047              fuse_fill_dir_t filler,
0048              off_t offset,
0049              struct fuse_file_info *fi)
0050 {
0051     if (strcmp(path, "/"))
0052         return -ENOENT;
0053 
0054     filler(buf, ".", NULL, 0);
0055     filler(buf, "..", NULL, 0);
0056     filler(buf, memfd_path + 1, NULL, 0);
0057 
0058     return 0;
0059 }
0060 
0061 static int memfd_open(const char *path, struct fuse_file_info *fi)
0062 {
0063     if (strcmp(path, memfd_path))
0064         return -ENOENT;
0065 
0066     if ((fi->flags & 3) != O_RDONLY)
0067         return -EACCES;
0068 
0069     /* force direct-IO */
0070     fi->direct_io = 1;
0071 
0072     return 0;
0073 }
0074 
0075 static int memfd_read(const char *path,
0076               char *buf,
0077               size_t size,
0078               off_t offset,
0079               struct fuse_file_info *fi)
0080 {
0081     size_t len;
0082 
0083     if (strcmp(path, memfd_path) != 0)
0084         return -ENOENT;
0085 
0086     sleep(1);
0087 
0088     len = strlen(memfd_content);
0089     if (offset < len) {
0090         if (offset + size > len)
0091             size = len - offset;
0092 
0093         memcpy(buf, memfd_content + offset, size);
0094     } else {
0095         size = 0;
0096     }
0097 
0098     return size;
0099 }
0100 
0101 static struct fuse_operations memfd_ops = {
0102     .getattr    = memfd_getattr,
0103     .readdir    = memfd_readdir,
0104     .open       = memfd_open,
0105     .read       = memfd_read,
0106 };
0107 
0108 int main(int argc, char *argv[])
0109 {
0110     return fuse_main(argc, argv, &memfd_ops, NULL);
0111 }