Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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
 23static const char memfd_content[] = "memfd-example-content";
 24static const char memfd_path[] = "/memfd";
 25
 26static 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
 44static 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
 60static 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
 74static 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
100static struct fuse_operations memfd_ops = {
101	.getattr	= memfd_getattr,
102	.readdir	= memfd_readdir,
103	.open		= memfd_open,
104	.read		= memfd_read,
105};
106
107int main(int argc, char *argv[])
108{
109	return fuse_main(argc, argv, &memfd_ops, NULL);
110}