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;
}

Reply via email to