root/tools/testing/selftests/memfd/fuse_mnt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. memfd_getattr
  2. memfd_readdir
  3. memfd_open
  4. memfd_read
  5. main

   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 
  24 static const char memfd_content[] = "memfd-example-content";
  25 static const char memfd_path[] = "/memfd";
  26 
  27 static 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 
  45 static 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 
  61 static 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 
  75 static 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 
 101 static struct fuse_operations memfd_ops = {
 102         .getattr        = memfd_getattr,
 103         .readdir        = memfd_readdir,
 104         .open           = memfd_open,
 105         .read           = memfd_read,
 106 };
 107 
 108 int main(int argc, char *argv[])
 109 {
 110         return fuse_main(argc, argv, &memfd_ops, NULL);
 111 }

/* [<][>][^][v][top][bottom][index][help] */