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