简体   繁体   English

我可以在FUSE中使用打开的文件表实现文件系统吗?

[英]Can I implement a filesystem with an open file table in FUSE?

I'm writing a filesystem in C for homework that interfaces with FUSE. 我正在用C编写一个用于与FUSE交互的作业文件系统。 So far I can mount my filesystem, create and delete files, list files in the directory, etc., but I'm having a few problems with the read() and write() functions. 到目前为止,我可以挂载文件系统,创建和删除文件,在目录中列出文件等,但是read()write()函数存在一些问题。

My assignment stipulates that my filesystem keep two kinds of open file tables, one per process (so each process with an open file has its own table of open files), and one systemwide (that each entry in the per process table links to for information that can be shared). 我的任务规定,我的文件系统保留两种打开文件表,每个进程一个(因此,每个带有打开文件的进程都有自己的打开文件表),以及一个系统范围的文件(每个进程表中的每个条目都链接到此信息)。可以共享)。 When a call to read() or write() is made, the appropriate table entry is looked up with pid of the calling process and the file descriptor parameter passed in the system call. 调用read()write() ,将使用调用进程的pid和系统调用中传递的文件描述符参数来查找适当的表条目。

My issue is that FUSE does not pass file descriptors in calls to read() or write() , only the path of the file, so I cannot look up the appropriate entry in my open file tables. 我的问题是FUSE不会在对read()write()调用read()仅文件路径write()传递文件描述符,因此我无法在打开的文件表中查找适当的条目。 As suggested here , I can put the file decriptor returned by open() in the file handle field of the struct fuse_file_info argument, but I believe the struct fuse_file_info has a one-to-one relationship with my file, so then the file descriptor in there will always be the one made by the most recent call to open() , which is not necessarily the one related to a subsequent call to read() or write() . 作为建议在这里 ,我可以把返回的文件decriptor open()在的文件句柄场struct fuse_file_info的说法,但我相信struct fuse_file_info有我的档案一比一的关系,所以后来的文件描述符总是会有最近一次对open()调用产生的,而不一定与随后对read()write()调用有关。

The only way I can think to solve the problem is to force calls to my filesystem's open() and close() functions to create and remove table entries for every call to the FUSE operations read() and write() . 我认为可以解决问题的唯一方法是强制调用文件系统的open()close()函数,以针对每次对FUSE操作read()write()调用创建和删除表条目。 Then I can pass the file descriptor returned by that call to open() to my filesystem's read() or write() function, but this hardly seems reasonable. 然后,我可以将对open()调用返回的文件描述符传递给文件系统的read()write()函数,但这似乎不合理。 If possible, I'd like calls to my filesystem's open() and close() to have a one-to-one relationship with the FUSE operations open() and release() . 如果可能,我希望对文件系统的open()close()调用与FUSE操作open()release()具有一对一的关系。

My main fuse interface is listed below, and if interested the rest can be found here : 我的主保险丝接口在下面列出,如果有兴趣,可以在这里找到:

#include "abfs.h"

static int abfs_unlink(const char* name) {
    struct fuse_context* fc = fuse_get_context();

    return fs_unlink(name, fc->uid, fc->gid);
}

static int abfs_readdir(const char* name, void* buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info* fi) {
    if(strcmp(name, "/"))
        return -ENOENT;

    filler(buf, ".", NULL, 0);
    filler(buf, "..", NULL, 0);

    for (int i = 0; i < DIRECTORY_SIZE; i++) {
        GList* l = fileSystem->directory[i];
        while (l) {
            printf("i == %d\n", i);
            struct stat st;
            MetaDataNode* mdn = &fileSystem->storage[GPOINTER_TO_UINT(l->data)].mdn;
            abfs_getattr(mdn->name, &st);
            /* call to fs_access?*/
            if (filler(buf, mdn->name + 1, &st, 0))
                return -ENOMEM;
            l = l->next;
        }
    }

    return 0;
}

static int abfs_getattr(const char* name, struct stat* buf) {
    memset(buf, 0, sizeof *buf);

    if (!strcmp(name, "/")) {
        buf->st_mode = S_IFDIR | 0755;
        buf->st_nlink = 2;
    } else {
        MetaDataNode* mdn = findFile(name, NULL, NULL);
        if (!mdn)
            return -ENOENT;

        buf->st_mode = mdn->fileMode;
        buf->st_nlink = mdn->linkCount;
        buf->st_uid = mdn->uid;
        buf->st_gid = mdn->gid;
        buf->st_size = mdn->size;
        buf->st_atime = mdn->atime;
        buf->st_mtime = mdn->mtime;
        buf->st_ctime = mdn->ctime;
    }

    return 0;
}

static int abfs_create(const char* name, mode_t mode, struct fuse_file_info* fi) {
    struct fuse_context* fc = fuse_get_context();

    int i = fs_create(name, mode, fc->uid, fc->gid);
    if (i < 0)
        return i;

    // int fd = fs_open(name, fi->flags, fc->uid, fc->gid, fc->pid);
    // fi->fh = fd;

    return i;
}

static int abfs_access(const char* name, int mask) {
    struct fuse_context* fc = fuse_get_context();

    return fs_access(name, mask, fc->uid, fc->gid);
}

static int abfs_open(const char* name, struct fuse_file_info* fi) {
    struct fuse_context* fc = fuse_get_context();

    int fd = fs_open(name, fi->flags, fc->uid, fc->gid, fc->pid);

    if (fd >= 0) {
        fi->fh = fd;
        return 0;
    } else
        return fd;
}

static int abfs_read(const char* name, char* buf, size_t size, off_t offset, struct fuse_file_info* fi) {
    struct fuse_context* fc = fuse_get_context();

    return fs_read(fi->fh, buf, size, fc->pid);
}

static int abfs_write(const char* name, const char* buf, size_t size, off_t offset, struct fuse_file_info* fi) {
    struct fuse_context* fc = fuse_get_context();

    return fs_write(fi->fh, buf, size, fc->pid);
}

static int abfs_release(const char* name, struct fuse_file_info* fi) {
    struct fuse_context* fc = fuse_get_context();

    return fs_release(name, fi->fh, fc->pid);
}

static struct fuse_operations abfs_oper = {
    .getattr = abfs_getattr,
    .readdir = abfs_readdir,
    .create = abfs_create,
    .access = abfs_access,
    .unlink = abfs_unlink,
    .open = abfs_open,
    .destroy = freeFileSystem,
    .release = abfs_release,
    .read = abfs_read,
    .write = abfs_write,
};

int main(int argc, char *argv[])
{
    newFileSystem();
    // printf("size mdn: %lud\n", sizeof (MetaDataNode));

    return fuse_main(argc, argv, &abfs_oper, NULL);
}

I was wondering if anyone could offer any insight into my problem or about implementing open file tables with FUSE in general. 我想知道是否有人可以对我的问题或有关使用FUSE实施打开文件表提供任何见解。 Many thanks in advance. 提前谢谢了。

I just double checked the FUSE source, and it looks like FUSE allocates fuse_file_info once per open file handle, so that it is one to one with an open handle, not a file path. 我只是仔细检查了FUSE源,它看起来像FUSE为每个打开的文件句柄分配一次fuse_file_info,因此它与打开的句柄是一对一的,而不是文件路径。

However, in the spirit of teaching you to fish, there is an easy way for you to check it yourself. 但是,本着教您钓鱼的精神,您可以轻松地自行检查一下。 Write yourself a small C test application. 给自己写一个小的C测试应用程序。 Open the same file twice in your test, and put two different numbers in the fh field in FUSE, then read from each of the open file handles, and see what is in the fh field. 在测试中两次打开同一个文件,然后在FUSE的fh字段中放入两个不同的数字,然后从每个打开的文件句柄中读取,并查看fh字段中的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM