fuse_mnt.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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. #define FUSE_USE_VERSION 26
  14. #include <fuse.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <errno.h>
  18. #include <fcntl.h>
  19. #include <unistd.h>
  20. static const char memfd_content[] = "memfd-example-content";
  21. static const char memfd_path[] = "/memfd";
  22. static int memfd_getattr(const char *path, struct stat *st)
  23. {
  24. memset(st, 0, sizeof(*st));
  25. if (!strcmp(path, "/")) {
  26. st->st_mode = S_IFDIR | 0755;
  27. st->st_nlink = 2;
  28. } else if (!strcmp(path, memfd_path)) {
  29. st->st_mode = S_IFREG | 0444;
  30. st->st_nlink = 1;
  31. st->st_size = strlen(memfd_content);
  32. } else {
  33. return -ENOENT;
  34. }
  35. return 0;
  36. }
  37. static int memfd_readdir(const char *path,
  38. void *buf,
  39. fuse_fill_dir_t filler,
  40. off_t offset,
  41. struct fuse_file_info *fi)
  42. {
  43. if (strcmp(path, "/"))
  44. return -ENOENT;
  45. filler(buf, ".", NULL, 0);
  46. filler(buf, "..", NULL, 0);
  47. filler(buf, memfd_path + 1, NULL, 0);
  48. return 0;
  49. }
  50. static int memfd_open(const char *path, struct fuse_file_info *fi)
  51. {
  52. if (strcmp(path, memfd_path))
  53. return -ENOENT;
  54. if ((fi->flags & 3) != O_RDONLY)
  55. return -EACCES;
  56. /* force direct-IO */
  57. fi->direct_io = 1;
  58. return 0;
  59. }
  60. static int memfd_read(const char *path,
  61. char *buf,
  62. size_t size,
  63. off_t offset,
  64. struct fuse_file_info *fi)
  65. {
  66. size_t len;
  67. if (strcmp(path, memfd_path) != 0)
  68. return -ENOENT;
  69. sleep(1);
  70. len = strlen(memfd_content);
  71. if (offset < len) {
  72. if (offset + size > len)
  73. size = len - offset;
  74. memcpy(buf, memfd_content + offset, size);
  75. } else {
  76. size = 0;
  77. }
  78. return size;
  79. }
  80. static struct fuse_operations memfd_ops = {
  81. .getattr = memfd_getattr,
  82. .readdir = memfd_readdir,
  83. .open = memfd_open,
  84. .read = memfd_read,
  85. };
  86. int main(int argc, char *argv[])
  87. {
  88. return fuse_main(argc, argv, &memfd_ops, NULL);
  89. }