brintos

brintos / linux-shallow public Read only

0
0
Text · 2.2 KiB · 6936f2a Raw
112 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * memfd test file-system4 * 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 pin8 * pages during reads(). Due to the 1s delay of this file-system, this is a9 * 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 this12 * file-system.13 */14 15#define FUSE_USE_VERSION 2616 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 24static const char memfd_content[] = "memfd-example-content";25static const char memfd_path[] = "/memfd";26 27static 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 45static 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 61static 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 75static 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 101static struct fuse_operations memfd_ops = {102	.getattr	= memfd_getattr,103	.readdir	= memfd_readdir,104	.open		= memfd_open,105	.read		= memfd_read,106};107 108int main(int argc, char *argv[])109{110	return fuse_main(argc, argv, &memfd_ops, NULL);111}112