aboutsummaryrefslogtreecommitdiffstats
path: root/example/passthrough_ll.c
diff options
context:
space:
mode:
authorHorst Birthelmer <hbirthelmer@ddn.com>2024-11-20 16:14:43 +0100
committerBernd Schubert <bernd.schubert@fastmail.fm>2024-11-27 13:38:56 +0100
commit4ec109d1c447bbf5be05854e32d8683bb1df5a80 (patch)
tree4283922b8aee6846ea111499285174232ed062b8 /example/passthrough_ll.c
parent8b34ed03682bb7806a6083b05187c4fc5475a135 (diff)
downloadlibfuse-4ec109d1c447bbf5be05854e32d8683bb1df5a80.tar.gz
support FUSE_TMPFILE in the low level API
Note that name hashes and using paths as parameters makes it very hard to support anonymous files in the high level API. Known Issues: - tests have to bail out when O_TMPFILE is not supported. This will always be the case with high level passthrough implementations. - test_create_and_link_tmpfile has to be skipped due to unidentified problems with github runner
Diffstat (limited to 'example/passthrough_ll.c')
-rw-r--r--example/passthrough_ll.c106
1 files changed, 87 insertions, 19 deletions
diff --git a/example/passthrough_ll.c b/example/passthrough_ll.c
index 62a42f4..309d8dd 100644
--- a/example/passthrough_ll.c
+++ b/example/passthrough_ll.c
@@ -308,6 +308,55 @@ static struct lo_inode *lo_find(struct lo_data *lo, struct stat *st)
return ret;
}
+
+static struct lo_inode *create_new_inode(int fd, struct fuse_entry_param *e, struct lo_data* lo)
+{
+ struct lo_inode *inode = NULL;
+ struct lo_inode *prev, *next;
+
+ inode = calloc(1, sizeof(struct lo_inode));
+ if (!inode)
+ return NULL;
+
+ inode->refcount = 1;
+ inode->fd = fd;
+ inode->ino = e->attr.st_ino;
+ inode->dev = e->attr.st_dev;
+
+ pthread_mutex_lock(&lo->mutex);
+ prev = &lo->root;
+ next = prev->next;
+ next->prev = inode;
+ inode->next = next;
+ inode->prev = prev;
+ prev->next = inode;
+ pthread_mutex_unlock(&lo->mutex);
+ return inode;
+}
+
+static int fill_entry_param_new_inode(fuse_req_t req, fuse_ino_t parent, int fd, struct fuse_entry_param *e)
+{
+ int res;
+ struct lo_data *lo = lo_data(req);
+
+ memset(e, 0, sizeof(*e));
+ e->attr_timeout = lo->timeout;
+ e->entry_timeout = lo->timeout;
+
+ res = fstatat(fd, "", &e->attr, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
+ if (res == -1)
+ return errno;
+
+ e->ino = (uintptr_t) create_new_inode(dup(fd), e, lo);
+
+ if (lo_debug(req))
+ fuse_log(FUSE_LOG_DEBUG, " %lli/%lli -> %lli\n",
+ (unsigned long long) parent, fd, (unsigned long long) e->ino);
+
+ return 0;
+
+}
+
static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
struct fuse_entry_param *e)
{
@@ -334,26 +383,9 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
close(newfd);
newfd = -1;
} else {
- struct lo_inode *prev, *next;
-
- saverr = ENOMEM;
- inode = calloc(1, sizeof(struct lo_inode));
+ inode = create_new_inode(newfd, e, lo);
if (!inode)
goto out_err;
-
- inode->refcount = 1;
- inode->fd = newfd;
- inode->ino = e->attr.st_ino;
- inode->dev = e->attr.st_dev;
-
- pthread_mutex_lock(&lo->mutex);
- prev = &lo->root;
- next = prev->next;
- next->prev = inode;
- inode->next = next;
- inode->prev = prev;
- prev->next = inode;
- pthread_mutex_unlock(&lo->mutex);
}
e->ino = (uintptr_t) inode;
@@ -754,7 +786,7 @@ static void lo_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info
fuse_reply_err(req, 0);
}
-static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
+static void lo_tmpfile(fuse_req_t req, fuse_ino_t parent,
mode_t mode, struct fuse_file_info *fi)
{
int fd;
@@ -763,6 +795,41 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
int err;
if (lo_debug(req))
+ fuse_log(FUSE_LOG_DEBUG, "lo_tmpfile(parent=%" PRIu64 ")\n",
+ parent);
+
+ fd = openat(lo_fd(req, parent), ".",
+ (fi->flags | O_TMPFILE) & ~O_NOFOLLOW, mode);
+ if (fd == -1)
+ return (void) fuse_reply_err(req, errno);
+
+ fi->fh = fd;
+ if (lo->cache == CACHE_NEVER)
+ fi->direct_io = 1;
+ else if (lo->cache == CACHE_ALWAYS)
+ fi->keep_cache = 1;
+
+ /* parallel_direct_writes feature depends on direct_io features.
+ To make parallel_direct_writes valid, need set fi->direct_io
+ in current function. */
+ fi->parallel_direct_writes = 1;
+
+ err = fill_entry_param_new_inode(req, parent, fd, &e);
+ if (err)
+ fuse_reply_err(req, err);
+ else
+ fuse_reply_create(req, &e, fi);
+}
+
+static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
+ mode_t mode, struct fuse_file_info *fi)
+{
+ int fd;
+ struct lo_data *lo = lo_data(req);
+ struct fuse_entry_param e;
+ int err;
+
+ if (lo_debug(req))
fuse_log(FUSE_LOG_DEBUG, "lo_create(parent=%" PRIu64 ", name=%s)\n",
parent, name);
@@ -1178,6 +1245,7 @@ static const struct fuse_lowlevel_ops lo_oper = {
.releasedir = lo_releasedir,
.fsyncdir = lo_fsyncdir,
.create = lo_create,
+ .tmpfile = lo_tmpfile,
.open = lo_open,
.release = lo_release,
.flush = lo_flush,