aboutsummaryrefslogtreecommitdiffstats
path: root/example
diff options
context:
space:
mode:
Diffstat (limited to 'example')
-rw-r--r--example/passthrough_hp.cc81
-rw-r--r--example/passthrough_ll.c106
2 files changed, 168 insertions, 19 deletions
diff --git a/example/passthrough_hp.cc b/example/passthrough_hp.cc
index c393f04..41904e5 100644
--- a/example/passthrough_hp.cc
+++ b/example/passthrough_hp.cc
@@ -914,6 +914,86 @@ static void sfs_create(fuse_req_t req, fuse_ino_t parent, const char *name,
fuse_reply_create(req, &e, fi);
}
+static Inode *create_new_inode(int fd, fuse_entry_param *e)
+{
+ memset(e, 0, sizeof(*e));
+ e->attr_timeout = fs.timeout;
+ e->entry_timeout = fs.timeout;
+
+ auto res = fstatat(fd, "", &e->attr, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
+ if (res == -1) {
+ if (fs.debug)
+ cerr << "DEBUG: lookup(): fstatat failed" << endl;
+ return NULL;
+ }
+
+ SrcId id {e->attr.st_ino, e->attr.st_dev};
+ unique_lock<mutex> fs_lock {fs.mutex};
+ Inode* p_inode;
+ try {
+ p_inode = &fs.inodes[id];
+ } catch (std::bad_alloc&) {
+ return NULL;
+ }
+
+ e->ino = reinterpret_cast<fuse_ino_t>(p_inode);
+ e->generation = p_inode->generation;
+
+ lock_guard<mutex> g {p_inode->m};
+ p_inode->src_ino = e->attr.st_ino;
+ p_inode->src_dev = e->attr.st_dev;
+
+ p_inode->nlookup++;
+ if (fs.debug)
+ cerr << "DEBUG:" << __func__ << ":" << __LINE__ << " "
+ << "inode " << p_inode->src_ino
+ << " count " << p_inode->nlookup << endl;
+
+ p_inode->fd = fd;
+ fs_lock.unlock();
+
+ if (fs.debug)
+ cerr << "DEBUG: lookup(): created userspace inode " << e->attr.st_ino
+ << "; fd = " << p_inode->fd << endl;
+ return p_inode;
+}
+
+static void sfs_tmpfile(fuse_req_t req, fuse_ino_t parent,
+ mode_t mode, fuse_file_info *fi) {
+ Inode& parent_inode = get_inode(parent);
+
+ auto fd = openat(parent_inode.fd, ".",
+ (fi->flags | O_TMPFILE) & ~O_NOFOLLOW, mode);
+ if (fd == -1) {
+ auto err = errno;
+ if (err == ENFILE || err == EMFILE)
+ cerr << "ERROR: Reached maximum number of file descriptors." << endl;
+ fuse_reply_err(req, err);
+ return;
+ }
+
+ fi->fh = fd;
+ fuse_entry_param e;
+
+ Inode *inode = create_new_inode(dup(fd), &e);
+ if (inode == NULL) {
+ auto err = errno;
+ cerr << "ERROR: could not create new inode." << endl;
+ close(fd);
+ fuse_reply_err(req, err);
+ return;
+ }
+
+ lock_guard<mutex> g {inode->m};
+
+ sfs_create_open_flags(fi);
+
+ if (fs.passthrough)
+ do_passthrough_open(req, e.ino, fd, fi);
+
+ fuse_reply_create(req, &e, fi);
+}
+
static void sfs_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
fuse_file_info *fi) {
@@ -1237,6 +1317,7 @@ static void assign_operations(fuse_lowlevel_ops &sfs_oper) {
sfs_oper.releasedir = sfs_releasedir;
sfs_oper.fsyncdir = sfs_fsyncdir;
sfs_oper.create = sfs_create;
+ sfs_oper.tmpfile = sfs_tmpfile;
sfs_oper.open = sfs_open;
sfs_oper.release = sfs_release;
sfs_oper.flush = sfs_flush;
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,