On Fri, Jan 26, 2018 at 02:07:10PM -0500, Martin Brandenburg wrote: > I have also written a "fakecore" which does about the bare minimum to > start up and respond to mount requests. I intend to use this as a > vehicle for experimentation with fuzzing and testing performance through > our kernel code without the rest of OrangeFS running. #include <sys/ioctl.h> #include <sys/stat.h> #include <errno.h> #include <fcntl.h> #include <stdint.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include "linux/include/uapi/linux/orangefs.h" #define ORANGEFS_REQDEVICE_NAME "pvfs2-req" struct downcall { int32_t proto_ver; int32_t magic; int32_t tag; struct orangefs_downcall_s d; }; struct upcall { int32_t proto_ver; int32_t magic; int32_t tag; struct orangefs_upcall_s u; }; static int mounted = 0; int process_request(struct upcall *upcall, struct downcall *downcall) { struct stat sb; switch (upcall->u.type) { case ORANGEFS_VFS_OP_GETATTR: downcall->d.resp.getattr.attributes.objtype = ORANGEFS_TYPE_DIRECTORY; return 0; case ORANGEFS_VFS_OP_FS_MOUNT: if (mounted) { downcall->d.status = -(ORANGEFS_ERROR_BIT|EPERM); return 0; } downcall->d.resp.fs_mount.fs_id = 1; downcall->d.resp.fs_mount.id = mounted; downcall->d.resp.fs_mount.root_khandle.u[0] = 1; if (stat(".", &sb)) { downcall->d.status = -(ORANGEFS_ERROR_BIT|errno); return 0; } memcpy(downcall->d.resp.fs_mount.root_khandle.u, &sb.st_ino, sizeof sb.st_ino); mounted = 1; return 0; case ORANGEFS_VFS_OP_FS_UMOUNT: mounted = 0; return 0; default: downcall->d.status = -(ORANGEFS_ERROR_BIT|EPERM); return 0; } } int main(void) { int32_t magic, max_upsize, max_downsize; struct downcall downcall; struct upcall upcall; int fd, upstream; fd = open("/dev/" ORANGEFS_REQDEVICE_NAME, O_RDWR|O_NONBLOCK); if (fd == -1) { perror("open"); return 1; } if (ioctl(fd, ORANGEFS_DEV_GET_MAGIC, &magic)) { perror("ioctl"); return 1; } if (ioctl(fd, ORANGEFS_DEV_GET_MAX_UPSIZE, &max_upsize)) { perror("ioctl"); return 1; } if (ioctl(fd, ORANGEFS_DEV_GET_MAX_DOWNSIZE, &max_downsize)) { perror("ioctl"); return 1; } if (ioctl(fd, ORANGEFS_DEV_UPSTREAM, &upstream)) { perror("ioctl"); return 1; } printf("magic: %d\n", magic); printf("max_upsize: %d, sizeof upcall: %d\n", max_upsize, sizeof upcall); printf("max_downsize: %d, sizeof downcall: %d\n", max_downsize, sizeof downcall); printf("upstream: %d\n", upstream); while (1) { int r; r = read(fd, &upcall, sizeof upcall); if (r == -1) { if (errno == EAGAIN) continue; perror("read"); return 1; } else if (r < sizeof upcall) { fprintf(stderr, "short read\n"); return 1; } downcall.proto_ver = ORANGEFS_MINIMUM_USERSPACE_VERSION; downcall.magic = upcall.magic; downcall.tag = upcall.tag; memset(&downcall.d, 0, sizeof downcall.d); downcall.d.type = upcall.u.type; downcall.d.status = 0; printf("read tag type %d\n", upcall.tag, upcall.u.type); if (process_request(&upcall, &downcall)) { fprintf(stderr, "process_request failed\n"); return 1; } r = write(fd, &downcall, sizeof downcall); if (r == -1) { perror("write"); return 1; } else if (r < sizeof downcall) { perror("short write"); return 1; } printf("wrote tag %d status %d\n", downcall.tag, downcall.d.status); } if (close(fd)) { perror("close"); return 1; } return 0; }