2 * FUSE: Filesystem in Userspace
3 * Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
5 * This program can be distributed under the terms of the GNU GPLv2.
6 * See the file COPYING.
11 * This file system mirrors the existing file system hierarchy of the
12 * system, starting at the root file system. This is implemented by
13 * just "passing through" all requests to the corresponding user-space
14 * libc functions. In contrast to passthrough.c and passthrough_fh.c,
15 * this implementation uses the low-level API. Its performance should
16 * be the least bad among the three, but many operations are not
17 * implemented. In particular, it is not possible to remove files (or
18 * directories) because the code necessary to defer actual removal
19 * until the file is not opened anymore would make the example much
22 * When writeback caching is enabled (-o writeback mount option), it
23 * is only possible to write to files for which the mounting user has
24 * read permissions. This is because the writeback cache requires the
25 * kernel to be able to issue read requests for all files (which the
26 * passthrough filesystem cannot satisfy if it can't read the file in
27 * the underlying filesystem).
31 * gcc -Wall passthrough_ll.c `pkg-config fuse3 --cflags --libs` -o
35 * \include passthrough_ll.c
38 #include "qemu/osdep.h"
39 #include "fuse_virtio.h"
40 #include "fuse_lowlevel.h"
53 #include <sys/syscall.h>
54 #include <sys/xattr.h>
57 #include "passthrough_helpers.h"
60 * We are re-using pointers to our `struct lo_inode`
61 * elements as inodes. This means that we must be able to
62 * store uintptr_t values in a fuse_ino_t variable. The following
63 * incantation checks this condition at compile time.
65 #if defined(__GNUC__) && \
66 (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 6) && \
68 _Static_assert(sizeof(fuse_ino_t
) >= sizeof(uintptr_t),
69 "fuse_ino_t too small to hold uintptr_t values!");
71 struct _uintptr_to_must_hold_fuse_ino_t_dummy_struct
{
72 unsigned _uintptr_to_must_hold_fuse_ino_t
73 : ((sizeof(fuse_ino_t
) >= sizeof(uintptr_t)) ? 1 : -1);
79 struct lo_inode
*inode
;
85 /* Maps FUSE fh or ino values to internal objects */
87 struct lo_map_elem
*elems
;
93 struct lo_inode
*next
; /* protected by lo->mutex */
94 struct lo_inode
*prev
; /* protected by lo->mutex */
99 uint64_t refcount
; /* protected by lo->mutex */
115 pthread_mutex_t mutex
;
124 struct lo_inode root
; /* protected by lo->mutex */
125 struct lo_map ino_map
; /* protected by lo->mutex */
128 static const struct fuse_opt lo_opts
[] = {
129 { "writeback", offsetof(struct lo_data
, writeback
), 1 },
130 { "no_writeback", offsetof(struct lo_data
, writeback
), 0 },
131 { "source=%s", offsetof(struct lo_data
, source
), 0 },
132 { "flock", offsetof(struct lo_data
, flock
), 1 },
133 { "no_flock", offsetof(struct lo_data
, flock
), 0 },
134 { "xattr", offsetof(struct lo_data
, xattr
), 1 },
135 { "no_xattr", offsetof(struct lo_data
, xattr
), 0 },
136 { "timeout=%lf", offsetof(struct lo_data
, timeout
), 0 },
137 { "timeout=", offsetof(struct lo_data
, timeout_set
), 1 },
138 { "cache=never", offsetof(struct lo_data
, cache
), CACHE_NEVER
},
139 { "cache=auto", offsetof(struct lo_data
, cache
), CACHE_NORMAL
},
140 { "cache=always", offsetof(struct lo_data
, cache
), CACHE_ALWAYS
},
145 static struct lo_data
*lo_data(fuse_req_t req
)
147 return (struct lo_data
*)fuse_req_userdata(req
);
150 static void lo_map_init(struct lo_map
*map
)
157 static void lo_map_destroy(struct lo_map
*map
)
162 static int lo_map_grow(struct lo_map
*map
, size_t new_nelems
)
164 struct lo_map_elem
*new_elems
;
167 if (new_nelems
<= map
->nelems
) {
171 new_elems
= realloc(map
->elems
, sizeof(map
->elems
[0]) * new_nelems
);
176 for (i
= map
->nelems
; i
< new_nelems
; i
++) {
177 new_elems
[i
].freelist
= i
+ 1;
178 new_elems
[i
].in_use
= false;
180 new_elems
[new_nelems
- 1].freelist
= -1;
182 map
->elems
= new_elems
;
183 map
->freelist
= map
->nelems
;
184 map
->nelems
= new_nelems
;
188 static struct lo_map_elem
*lo_map_alloc_elem(struct lo_map
*map
)
190 struct lo_map_elem
*elem
;
192 if (map
->freelist
== -1 && !lo_map_grow(map
, map
->nelems
+ 256)) {
196 elem
= &map
->elems
[map
->freelist
];
197 map
->freelist
= elem
->freelist
;
204 static struct lo_map_elem
*lo_map_reserve(struct lo_map
*map
, size_t key
)
208 if (!lo_map_grow(map
, key
+ 1)) {
212 for (prev
= &map
->freelist
; *prev
!= -1;
213 prev
= &map
->elems
[*prev
].freelist
) {
215 struct lo_map_elem
*elem
= &map
->elems
[key
];
217 *prev
= elem
->freelist
;
225 static struct lo_map_elem
*lo_map_get(struct lo_map
*map
, size_t key
)
227 if (key
>= map
->nelems
) {
230 if (!map
->elems
[key
].in_use
) {
233 return &map
->elems
[key
];
236 static void lo_map_remove(struct lo_map
*map
, size_t key
)
238 struct lo_map_elem
*elem
;
240 if (key
>= map
->nelems
) {
244 elem
= &map
->elems
[key
];
249 elem
->in_use
= false;
251 elem
->freelist
= map
->freelist
;
255 /* Assumes lo->mutex is held */
256 static ssize_t
lo_add_inode_mapping(fuse_req_t req
, struct lo_inode
*inode
)
258 struct lo_map_elem
*elem
;
260 elem
= lo_map_alloc_elem(&lo_data(req
)->ino_map
);
266 return elem
- lo_data(req
)->ino_map
.elems
;
269 static struct lo_inode
*lo_inode(fuse_req_t req
, fuse_ino_t ino
)
271 struct lo_data
*lo
= lo_data(req
);
272 struct lo_map_elem
*elem
;
274 pthread_mutex_lock(&lo
->mutex
);
275 elem
= lo_map_get(&lo
->ino_map
, ino
);
276 pthread_mutex_unlock(&lo
->mutex
);
285 static int lo_fd(fuse_req_t req
, fuse_ino_t ino
)
287 struct lo_inode
*inode
= lo_inode(req
, ino
);
288 return inode
? inode
->fd
: -1;
291 static bool lo_debug(fuse_req_t req
)
293 return lo_data(req
)->debug
!= 0;
296 static void lo_init(void *userdata
, struct fuse_conn_info
*conn
)
298 struct lo_data
*lo
= (struct lo_data
*)userdata
;
300 if (conn
->capable
& FUSE_CAP_EXPORT_SUPPORT
) {
301 conn
->want
|= FUSE_CAP_EXPORT_SUPPORT
;
304 if (lo
->writeback
&& conn
->capable
& FUSE_CAP_WRITEBACK_CACHE
) {
306 fuse_log(FUSE_LOG_DEBUG
, "lo_init: activating writeback\n");
308 conn
->want
|= FUSE_CAP_WRITEBACK_CACHE
;
310 if (lo
->flock
&& conn
->capable
& FUSE_CAP_FLOCK_LOCKS
) {
312 fuse_log(FUSE_LOG_DEBUG
, "lo_init: activating flock locks\n");
314 conn
->want
|= FUSE_CAP_FLOCK_LOCKS
;
318 static void lo_getattr(fuse_req_t req
, fuse_ino_t ino
,
319 struct fuse_file_info
*fi
)
323 struct lo_data
*lo
= lo_data(req
);
328 fstatat(lo_fd(req
, ino
), "", &buf
, AT_EMPTY_PATH
| AT_SYMLINK_NOFOLLOW
);
330 return (void)fuse_reply_err(req
, errno
);
333 fuse_reply_attr(req
, &buf
, lo
->timeout
);
336 static int utimensat_empty_nofollow(struct lo_inode
*inode
,
337 const struct timespec
*tv
)
342 if (inode
->is_symlink
) {
343 res
= utimensat(inode
->fd
, "", tv
, AT_EMPTY_PATH
| AT_SYMLINK_NOFOLLOW
);
344 if (res
== -1 && errno
== EINVAL
) {
345 /* Sorry, no race free way to set times on symlink. */
350 sprintf(procname
, "/proc/self/fd/%i", inode
->fd
);
352 return utimensat(AT_FDCWD
, procname
, tv
, 0);
355 static void lo_setattr(fuse_req_t req
, fuse_ino_t ino
, struct stat
*attr
,
356 int valid
, struct fuse_file_info
*fi
)
360 struct lo_inode
*inode
;
364 inode
= lo_inode(req
, ino
);
366 fuse_reply_err(req
, EBADF
);
372 if (valid
& FUSE_SET_ATTR_MODE
) {
374 res
= fchmod(fi
->fh
, attr
->st_mode
);
376 sprintf(procname
, "/proc/self/fd/%i", ifd
);
377 res
= chmod(procname
, attr
->st_mode
);
383 if (valid
& (FUSE_SET_ATTR_UID
| FUSE_SET_ATTR_GID
)) {
384 uid_t uid
= (valid
& FUSE_SET_ATTR_UID
) ? attr
->st_uid
: (uid_t
)-1;
385 gid_t gid
= (valid
& FUSE_SET_ATTR_GID
) ? attr
->st_gid
: (gid_t
)-1;
387 res
= fchownat(ifd
, "", uid
, gid
, AT_EMPTY_PATH
| AT_SYMLINK_NOFOLLOW
);
392 if (valid
& FUSE_SET_ATTR_SIZE
) {
394 res
= ftruncate(fi
->fh
, attr
->st_size
);
396 sprintf(procname
, "/proc/self/fd/%i", ifd
);
397 res
= truncate(procname
, attr
->st_size
);
403 if (valid
& (FUSE_SET_ATTR_ATIME
| FUSE_SET_ATTR_MTIME
)) {
404 struct timespec tv
[2];
408 tv
[0].tv_nsec
= UTIME_OMIT
;
409 tv
[1].tv_nsec
= UTIME_OMIT
;
411 if (valid
& FUSE_SET_ATTR_ATIME_NOW
) {
412 tv
[0].tv_nsec
= UTIME_NOW
;
413 } else if (valid
& FUSE_SET_ATTR_ATIME
) {
414 tv
[0] = attr
->st_atim
;
417 if (valid
& FUSE_SET_ATTR_MTIME_NOW
) {
418 tv
[1].tv_nsec
= UTIME_NOW
;
419 } else if (valid
& FUSE_SET_ATTR_MTIME
) {
420 tv
[1] = attr
->st_mtim
;
424 res
= futimens(fi
->fh
, tv
);
426 res
= utimensat_empty_nofollow(inode
, tv
);
433 return lo_getattr(req
, ino
, fi
);
437 fuse_reply_err(req
, saverr
);
440 static struct lo_inode
*lo_find(struct lo_data
*lo
, struct stat
*st
)
443 struct lo_inode
*ret
= NULL
;
445 pthread_mutex_lock(&lo
->mutex
);
446 for (p
= lo
->root
.next
; p
!= &lo
->root
; p
= p
->next
) {
447 if (p
->ino
== st
->st_ino
&& p
->dev
== st
->st_dev
) {
448 assert(p
->refcount
> 0);
454 pthread_mutex_unlock(&lo
->mutex
);
458 static int lo_do_lookup(fuse_req_t req
, fuse_ino_t parent
, const char *name
,
459 struct fuse_entry_param
*e
)
464 struct lo_data
*lo
= lo_data(req
);
465 struct lo_inode
*inode
;
467 memset(e
, 0, sizeof(*e
));
468 e
->attr_timeout
= lo
->timeout
;
469 e
->entry_timeout
= lo
->timeout
;
471 newfd
= openat(lo_fd(req
, parent
), name
, O_PATH
| O_NOFOLLOW
);
476 res
= fstatat(newfd
, "", &e
->attr
, AT_EMPTY_PATH
| AT_SYMLINK_NOFOLLOW
);
481 inode
= lo_find(lo_data(req
), &e
->attr
);
486 struct lo_inode
*prev
, *next
;
489 inode
= calloc(1, sizeof(struct lo_inode
));
494 inode
->is_symlink
= S_ISLNK(e
->attr
.st_mode
);
497 inode
->ino
= e
->attr
.st_ino
;
498 inode
->dev
= e
->attr
.st_dev
;
500 pthread_mutex_lock(&lo
->mutex
);
501 inode
->fuse_ino
= lo_add_inode_mapping(req
, inode
);
508 pthread_mutex_unlock(&lo
->mutex
);
510 e
->ino
= inode
->fuse_ino
;
513 fuse_log(FUSE_LOG_DEBUG
, " %lli/%s -> %lli\n",
514 (unsigned long long)parent
, name
, (unsigned long long)e
->ino
);
527 static void lo_lookup(fuse_req_t req
, fuse_ino_t parent
, const char *name
)
529 struct fuse_entry_param e
;
533 fuse_log(FUSE_LOG_DEBUG
, "lo_lookup(parent=%" PRIu64
", name=%s)\n",
537 err
= lo_do_lookup(req
, parent
, name
, &e
);
539 fuse_reply_err(req
, err
);
541 fuse_reply_entry(req
, &e
);
546 * On some archs, setres*id is limited to 2^16 but they
547 * provide setres*id32 variants that allow 2^32.
548 * Others just let setres*id do 2^32 anyway.
550 #ifdef SYS_setresgid32
551 #define OURSYS_setresgid SYS_setresgid32
553 #define OURSYS_setresgid SYS_setresgid
556 #ifdef SYS_setresuid32
557 #define OURSYS_setresuid SYS_setresuid32
559 #define OURSYS_setresuid SYS_setresuid
563 * Change to uid/gid of caller so that file is created with
564 * ownership of caller.
565 * TODO: What about selinux context?
567 static int lo_change_cred(fuse_req_t req
, struct lo_cred
*old
)
571 old
->euid
= geteuid();
572 old
->egid
= getegid();
574 res
= syscall(OURSYS_setresgid
, -1, fuse_req_ctx(req
)->gid
, -1);
579 res
= syscall(OURSYS_setresuid
, -1, fuse_req_ctx(req
)->uid
, -1);
581 int errno_save
= errno
;
583 syscall(OURSYS_setresgid
, -1, old
->egid
, -1);
590 /* Regain Privileges */
591 static void lo_restore_cred(struct lo_cred
*old
)
595 res
= syscall(OURSYS_setresuid
, -1, old
->euid
, -1);
597 fuse_log(FUSE_LOG_ERR
, "seteuid(%u): %m\n", old
->euid
);
601 res
= syscall(OURSYS_setresgid
, -1, old
->egid
, -1);
603 fuse_log(FUSE_LOG_ERR
, "setegid(%u): %m\n", old
->egid
);
608 static void lo_mknod_symlink(fuse_req_t req
, fuse_ino_t parent
,
609 const char *name
, mode_t mode
, dev_t rdev
,
614 struct lo_inode
*dir
;
615 struct fuse_entry_param e
;
616 struct lo_cred old
= {};
618 dir
= lo_inode(req
, parent
);
620 fuse_reply_err(req
, EBADF
);
626 saverr
= lo_change_cred(req
, &old
);
631 res
= mknod_wrapper(dir
->fd
, name
, link
, mode
, rdev
);
635 lo_restore_cred(&old
);
641 saverr
= lo_do_lookup(req
, parent
, name
, &e
);
647 fuse_log(FUSE_LOG_DEBUG
, " %lli/%s -> %lli\n",
648 (unsigned long long)parent
, name
, (unsigned long long)e
.ino
);
651 fuse_reply_entry(req
, &e
);
655 fuse_reply_err(req
, saverr
);
658 static void lo_mknod(fuse_req_t req
, fuse_ino_t parent
, const char *name
,
659 mode_t mode
, dev_t rdev
)
661 lo_mknod_symlink(req
, parent
, name
, mode
, rdev
, NULL
);
664 static void lo_mkdir(fuse_req_t req
, fuse_ino_t parent
, const char *name
,
667 lo_mknod_symlink(req
, parent
, name
, S_IFDIR
| mode
, 0, NULL
);
670 static void lo_symlink(fuse_req_t req
, const char *link
, fuse_ino_t parent
,
673 lo_mknod_symlink(req
, parent
, name
, S_IFLNK
, 0, link
);
676 static int linkat_empty_nofollow(struct lo_inode
*inode
, int dfd
,
682 if (inode
->is_symlink
) {
683 res
= linkat(inode
->fd
, "", dfd
, name
, AT_EMPTY_PATH
);
684 if (res
== -1 && (errno
== ENOENT
|| errno
== EINVAL
)) {
685 /* Sorry, no race free way to hard-link a symlink. */
691 sprintf(procname
, "/proc/self/fd/%i", inode
->fd
);
693 return linkat(AT_FDCWD
, procname
, dfd
, name
, AT_SYMLINK_FOLLOW
);
696 static void lo_link(fuse_req_t req
, fuse_ino_t ino
, fuse_ino_t parent
,
700 struct lo_data
*lo
= lo_data(req
);
701 struct lo_inode
*inode
;
702 struct fuse_entry_param e
;
705 inode
= lo_inode(req
, ino
);
707 fuse_reply_err(req
, EBADF
);
711 memset(&e
, 0, sizeof(struct fuse_entry_param
));
712 e
.attr_timeout
= lo
->timeout
;
713 e
.entry_timeout
= lo
->timeout
;
715 res
= linkat_empty_nofollow(inode
, lo_fd(req
, parent
), name
);
720 res
= fstatat(inode
->fd
, "", &e
.attr
, AT_EMPTY_PATH
| AT_SYMLINK_NOFOLLOW
);
725 pthread_mutex_lock(&lo
->mutex
);
727 pthread_mutex_unlock(&lo
->mutex
);
728 e
.ino
= inode
->fuse_ino
;
731 fuse_log(FUSE_LOG_DEBUG
, " %lli/%s -> %lli\n",
732 (unsigned long long)parent
, name
, (unsigned long long)e
.ino
);
735 fuse_reply_entry(req
, &e
);
740 fuse_reply_err(req
, saverr
);
743 static void lo_rmdir(fuse_req_t req
, fuse_ino_t parent
, const char *name
)
747 res
= unlinkat(lo_fd(req
, parent
), name
, AT_REMOVEDIR
);
749 fuse_reply_err(req
, res
== -1 ? errno
: 0);
752 static void lo_rename(fuse_req_t req
, fuse_ino_t parent
, const char *name
,
753 fuse_ino_t newparent
, const char *newname
,
759 fuse_reply_err(req
, EINVAL
);
763 res
= renameat(lo_fd(req
, parent
), name
, lo_fd(req
, newparent
), newname
);
765 fuse_reply_err(req
, res
== -1 ? errno
: 0);
768 static void lo_unlink(fuse_req_t req
, fuse_ino_t parent
, const char *name
)
772 res
= unlinkat(lo_fd(req
, parent
), name
, 0);
774 fuse_reply_err(req
, res
== -1 ? errno
: 0);
777 static void unref_inode(struct lo_data
*lo
, struct lo_inode
*inode
, uint64_t n
)
783 pthread_mutex_lock(&lo
->mutex
);
784 assert(inode
->refcount
>= n
);
785 inode
->refcount
-= n
;
786 if (!inode
->refcount
) {
787 struct lo_inode
*prev
, *next
;
794 lo_map_remove(&lo
->ino_map
, inode
->fuse_ino
);
795 pthread_mutex_unlock(&lo
->mutex
);
799 pthread_mutex_unlock(&lo
->mutex
);
803 static void lo_forget_one(fuse_req_t req
, fuse_ino_t ino
, uint64_t nlookup
)
805 struct lo_data
*lo
= lo_data(req
);
806 struct lo_inode
*inode
;
808 inode
= lo_inode(req
, ino
);
814 fuse_log(FUSE_LOG_DEBUG
, " forget %lli %lli -%lli\n",
815 (unsigned long long)ino
, (unsigned long long)inode
->refcount
,
816 (unsigned long long)nlookup
);
819 unref_inode(lo
, inode
, nlookup
);
822 static void lo_forget(fuse_req_t req
, fuse_ino_t ino
, uint64_t nlookup
)
824 lo_forget_one(req
, ino
, nlookup
);
825 fuse_reply_none(req
);
828 static void lo_forget_multi(fuse_req_t req
, size_t count
,
829 struct fuse_forget_data
*forgets
)
833 for (i
= 0; i
< count
; i
++) {
834 lo_forget_one(req
, forgets
[i
].ino
, forgets
[i
].nlookup
);
836 fuse_reply_none(req
);
839 static void lo_readlink(fuse_req_t req
, fuse_ino_t ino
)
841 char buf
[PATH_MAX
+ 1];
844 res
= readlinkat(lo_fd(req
, ino
), "", buf
, sizeof(buf
));
846 return (void)fuse_reply_err(req
, errno
);
849 if (res
== sizeof(buf
)) {
850 return (void)fuse_reply_err(req
, ENAMETOOLONG
);
855 fuse_reply_readlink(req
, buf
);
860 struct dirent
*entry
;
864 static struct lo_dirp
*lo_dirp(struct fuse_file_info
*fi
)
866 return (struct lo_dirp
*)(uintptr_t)fi
->fh
;
869 static void lo_opendir(fuse_req_t req
, fuse_ino_t ino
,
870 struct fuse_file_info
*fi
)
873 struct lo_data
*lo
= lo_data(req
);
877 d
= calloc(1, sizeof(struct lo_dirp
));
882 fd
= openat(lo_fd(req
, ino
), ".", O_RDONLY
);
887 d
->dp
= fdopendir(fd
);
895 fi
->fh
= (uintptr_t)d
;
896 if (lo
->cache
== CACHE_ALWAYS
) {
899 fuse_reply_open(req
, fi
);
911 fuse_reply_err(req
, error
);
914 static int is_dot_or_dotdot(const char *name
)
916 return name
[0] == '.' &&
917 (name
[1] == '\0' || (name
[1] == '.' && name
[2] == '\0'));
920 static void lo_do_readdir(fuse_req_t req
, fuse_ino_t ino
, size_t size
,
921 off_t offset
, struct fuse_file_info
*fi
, int plus
)
923 struct lo_dirp
*d
= lo_dirp(fi
);
931 buf
= calloc(1, size
);
938 if (offset
!= d
->offset
) {
939 seekdir(d
->dp
, offset
);
950 d
->entry
= readdir(d
->dp
);
952 if (errno
) { /* Error */
955 } else { /* End of stream */
960 nextoff
= d
->entry
->d_off
;
961 name
= d
->entry
->d_name
;
962 fuse_ino_t entry_ino
= 0;
964 struct fuse_entry_param e
;
965 if (is_dot_or_dotdot(name
)) {
966 e
= (struct fuse_entry_param
){
967 .attr
.st_ino
= d
->entry
->d_ino
,
968 .attr
.st_mode
= d
->entry
->d_type
<< 12,
971 err
= lo_do_lookup(req
, ino
, name
, &e
);
978 entsize
= fuse_add_direntry_plus(req
, p
, rem
, name
, &e
, nextoff
);
981 .st_ino
= d
->entry
->d_ino
,
982 .st_mode
= d
->entry
->d_type
<< 12,
984 entsize
= fuse_add_direntry(req
, p
, rem
, name
, &st
, nextoff
);
987 if (entry_ino
!= 0) {
988 lo_forget_one(req
, entry_ino
, 1);
1003 * If there's an error, we can only signal it if we haven't stored
1004 * any entries yet - otherwise we'd end up with wrong lookup
1005 * counts for the entries that are already in the buffer. So we
1006 * return what we've collected until that point.
1008 if (err
&& rem
== size
) {
1009 fuse_reply_err(req
, err
);
1011 fuse_reply_buf(req
, buf
, size
- rem
);
1016 static void lo_readdir(fuse_req_t req
, fuse_ino_t ino
, size_t size
,
1017 off_t offset
, struct fuse_file_info
*fi
)
1019 lo_do_readdir(req
, ino
, size
, offset
, fi
, 0);
1022 static void lo_readdirplus(fuse_req_t req
, fuse_ino_t ino
, size_t size
,
1023 off_t offset
, struct fuse_file_info
*fi
)
1025 lo_do_readdir(req
, ino
, size
, offset
, fi
, 1);
1028 static void lo_releasedir(fuse_req_t req
, fuse_ino_t ino
,
1029 struct fuse_file_info
*fi
)
1031 struct lo_dirp
*d
= lo_dirp(fi
);
1035 fuse_reply_err(req
, 0);
1038 static void lo_create(fuse_req_t req
, fuse_ino_t parent
, const char *name
,
1039 mode_t mode
, struct fuse_file_info
*fi
)
1042 struct lo_data
*lo
= lo_data(req
);
1043 struct fuse_entry_param e
;
1045 struct lo_cred old
= {};
1047 if (lo_debug(req
)) {
1048 fuse_log(FUSE_LOG_DEBUG
, "lo_create(parent=%" PRIu64
", name=%s)\n",
1052 err
= lo_change_cred(req
, &old
);
1057 fd
= openat(lo_fd(req
, parent
), name
, (fi
->flags
| O_CREAT
) & ~O_NOFOLLOW
,
1059 err
= fd
== -1 ? errno
: 0;
1060 lo_restore_cred(&old
);
1064 err
= lo_do_lookup(req
, parent
, name
, &e
);
1066 if (lo
->cache
== CACHE_NEVER
) {
1068 } else if (lo
->cache
== CACHE_ALWAYS
) {
1074 fuse_reply_err(req
, err
);
1076 fuse_reply_create(req
, &e
, fi
);
1080 static void lo_fsyncdir(fuse_req_t req
, fuse_ino_t ino
, int datasync
,
1081 struct fuse_file_info
*fi
)
1084 int fd
= dirfd(lo_dirp(fi
)->dp
);
1087 res
= fdatasync(fd
);
1091 fuse_reply_err(req
, res
== -1 ? errno
: 0);
1094 static void lo_open(fuse_req_t req
, fuse_ino_t ino
, struct fuse_file_info
*fi
)
1098 struct lo_data
*lo
= lo_data(req
);
1100 if (lo_debug(req
)) {
1101 fuse_log(FUSE_LOG_DEBUG
, "lo_open(ino=%" PRIu64
", flags=%d)\n", ino
,
1106 * With writeback cache, kernel may send read requests even
1107 * when userspace opened write-only
1109 if (lo
->writeback
&& (fi
->flags
& O_ACCMODE
) == O_WRONLY
) {
1110 fi
->flags
&= ~O_ACCMODE
;
1111 fi
->flags
|= O_RDWR
;
1115 * With writeback cache, O_APPEND is handled by the kernel.
1116 * This breaks atomicity (since the file may change in the
1117 * underlying filesystem, so that the kernel's idea of the
1118 * end of the file isn't accurate anymore). In this example,
1119 * we just accept that. A more rigorous filesystem may want
1120 * to return an error here
1122 if (lo
->writeback
&& (fi
->flags
& O_APPEND
)) {
1123 fi
->flags
&= ~O_APPEND
;
1126 sprintf(buf
, "/proc/self/fd/%i", lo_fd(req
, ino
));
1127 fd
= open(buf
, fi
->flags
& ~O_NOFOLLOW
);
1129 return (void)fuse_reply_err(req
, errno
);
1133 if (lo
->cache
== CACHE_NEVER
) {
1135 } else if (lo
->cache
== CACHE_ALWAYS
) {
1138 fuse_reply_open(req
, fi
);
1141 static void lo_release(fuse_req_t req
, fuse_ino_t ino
,
1142 struct fuse_file_info
*fi
)
1147 fuse_reply_err(req
, 0);
1150 static void lo_flush(fuse_req_t req
, fuse_ino_t ino
, struct fuse_file_info
*fi
)
1154 res
= close(dup(fi
->fh
));
1155 fuse_reply_err(req
, res
== -1 ? errno
: 0);
1158 static void lo_fsync(fuse_req_t req
, fuse_ino_t ino
, int datasync
,
1159 struct fuse_file_info
*fi
)
1166 fuse_log(FUSE_LOG_DEBUG
, "lo_fsync(ino=%" PRIu64
", fi=0x%p)\n", ino
,
1170 res
= asprintf(&buf
, "/proc/self/fd/%i", lo_fd(req
, ino
));
1172 return (void)fuse_reply_err(req
, errno
);
1175 fd
= open(buf
, O_RDWR
);
1178 return (void)fuse_reply_err(req
, errno
);
1185 res
= fdatasync(fd
);
1192 fuse_reply_err(req
, res
== -1 ? errno
: 0);
1195 static void lo_read(fuse_req_t req
, fuse_ino_t ino
, size_t size
, off_t offset
,
1196 struct fuse_file_info
*fi
)
1198 struct fuse_bufvec buf
= FUSE_BUFVEC_INIT(size
);
1200 if (lo_debug(req
)) {
1201 fuse_log(FUSE_LOG_DEBUG
,
1202 "lo_read(ino=%" PRIu64
", size=%zd, "
1204 ino
, size
, (unsigned long)offset
);
1207 buf
.buf
[0].flags
= FUSE_BUF_IS_FD
| FUSE_BUF_FD_SEEK
;
1208 buf
.buf
[0].fd
= fi
->fh
;
1209 buf
.buf
[0].pos
= offset
;
1211 fuse_reply_data(req
, &buf
);
1214 static void lo_write_buf(fuse_req_t req
, fuse_ino_t ino
,
1215 struct fuse_bufvec
*in_buf
, off_t off
,
1216 struct fuse_file_info
*fi
)
1220 struct fuse_bufvec out_buf
= FUSE_BUFVEC_INIT(fuse_buf_size(in_buf
));
1222 out_buf
.buf
[0].flags
= FUSE_BUF_IS_FD
| FUSE_BUF_FD_SEEK
;
1223 out_buf
.buf
[0].fd
= fi
->fh
;
1224 out_buf
.buf
[0].pos
= off
;
1226 if (lo_debug(req
)) {
1227 fuse_log(FUSE_LOG_DEBUG
,
1228 "lo_write(ino=%" PRIu64
", size=%zd, off=%lu)\n", ino
,
1229 out_buf
.buf
[0].size
, (unsigned long)off
);
1232 res
= fuse_buf_copy(&out_buf
, in_buf
);
1234 fuse_reply_err(req
, -res
);
1236 fuse_reply_write(req
, (size_t)res
);
1240 static void lo_statfs(fuse_req_t req
, fuse_ino_t ino
)
1243 struct statvfs stbuf
;
1245 res
= fstatvfs(lo_fd(req
, ino
), &stbuf
);
1247 fuse_reply_err(req
, errno
);
1249 fuse_reply_statfs(req
, &stbuf
);
1253 static void lo_fallocate(fuse_req_t req
, fuse_ino_t ino
, int mode
, off_t offset
,
1254 off_t length
, struct fuse_file_info
*fi
)
1256 int err
= EOPNOTSUPP
;
1259 #ifdef CONFIG_FALLOCATE
1260 err
= fallocate(fi
->fh
, mode
, offset
, length
);
1265 #elif defined(CONFIG_POSIX_FALLOCATE)
1267 fuse_reply_err(req
, EOPNOTSUPP
);
1271 err
= posix_fallocate(fi
->fh
, offset
, length
);
1274 fuse_reply_err(req
, err
);
1277 static void lo_flock(fuse_req_t req
, fuse_ino_t ino
, struct fuse_file_info
*fi
,
1283 res
= flock(fi
->fh
, op
);
1285 fuse_reply_err(req
, res
== -1 ? errno
: 0);
1288 static void lo_getxattr(fuse_req_t req
, fuse_ino_t ino
, const char *name
,
1293 struct lo_inode
*inode
;
1297 inode
= lo_inode(req
, ino
);
1299 fuse_reply_err(req
, EBADF
);
1304 if (!lo_data(req
)->xattr
) {
1308 if (lo_debug(req
)) {
1309 fuse_log(FUSE_LOG_DEBUG
,
1310 "lo_getxattr(ino=%" PRIu64
", name=%s size=%zd)\n", ino
, name
,
1314 if (inode
->is_symlink
) {
1315 /* Sorry, no race free way to getxattr on symlink. */
1320 sprintf(procname
, "/proc/self/fd/%i", inode
->fd
);
1323 value
= malloc(size
);
1328 ret
= getxattr(procname
, name
, value
, size
);
1337 fuse_reply_buf(req
, value
, ret
);
1339 ret
= getxattr(procname
, name
, NULL
, 0);
1344 fuse_reply_xattr(req
, ret
);
1353 fuse_reply_err(req
, saverr
);
1357 static void lo_listxattr(fuse_req_t req
, fuse_ino_t ino
, size_t size
)
1361 struct lo_inode
*inode
;
1365 inode
= lo_inode(req
, ino
);
1367 fuse_reply_err(req
, EBADF
);
1372 if (!lo_data(req
)->xattr
) {
1376 if (lo_debug(req
)) {
1377 fuse_log(FUSE_LOG_DEBUG
, "lo_listxattr(ino=%" PRIu64
", size=%zd)\n",
1381 if (inode
->is_symlink
) {
1382 /* Sorry, no race free way to listxattr on symlink. */
1387 sprintf(procname
, "/proc/self/fd/%i", inode
->fd
);
1390 value
= malloc(size
);
1395 ret
= listxattr(procname
, value
, size
);
1404 fuse_reply_buf(req
, value
, ret
);
1406 ret
= listxattr(procname
, NULL
, 0);
1411 fuse_reply_xattr(req
, ret
);
1420 fuse_reply_err(req
, saverr
);
1424 static void lo_setxattr(fuse_req_t req
, fuse_ino_t ino
, const char *name
,
1425 const char *value
, size_t size
, int flags
)
1428 struct lo_inode
*inode
;
1432 inode
= lo_inode(req
, ino
);
1434 fuse_reply_err(req
, EBADF
);
1439 if (!lo_data(req
)->xattr
) {
1443 if (lo_debug(req
)) {
1444 fuse_log(FUSE_LOG_DEBUG
,
1445 "lo_setxattr(ino=%" PRIu64
", name=%s value=%s size=%zd)\n",
1446 ino
, name
, value
, size
);
1449 if (inode
->is_symlink
) {
1450 /* Sorry, no race free way to setxattr on symlink. */
1455 sprintf(procname
, "/proc/self/fd/%i", inode
->fd
);
1457 ret
= setxattr(procname
, name
, value
, size
, flags
);
1458 saverr
= ret
== -1 ? errno
: 0;
1461 fuse_reply_err(req
, saverr
);
1464 static void lo_removexattr(fuse_req_t req
, fuse_ino_t ino
, const char *name
)
1467 struct lo_inode
*inode
;
1471 inode
= lo_inode(req
, ino
);
1473 fuse_reply_err(req
, EBADF
);
1478 if (!lo_data(req
)->xattr
) {
1482 if (lo_debug(req
)) {
1483 fuse_log(FUSE_LOG_DEBUG
, "lo_removexattr(ino=%" PRIu64
", name=%s)\n",
1487 if (inode
->is_symlink
) {
1488 /* Sorry, no race free way to setxattr on symlink. */
1493 sprintf(procname
, "/proc/self/fd/%i", inode
->fd
);
1495 ret
= removexattr(procname
, name
);
1496 saverr
= ret
== -1 ? errno
: 0;
1499 fuse_reply_err(req
, saverr
);
1502 #ifdef HAVE_COPY_FILE_RANGE
1503 static void lo_copy_file_range(fuse_req_t req
, fuse_ino_t ino_in
, off_t off_in
,
1504 struct fuse_file_info
*fi_in
, fuse_ino_t ino_out
,
1505 off_t off_out
, struct fuse_file_info
*fi_out
,
1506 size_t len
, int flags
)
1511 fuse_log(FUSE_LOG_DEBUG
,
1512 "lo_copy_file_range(ino=%" PRIu64
"/fd=%lu, "
1513 "off=%lu, ino=%" PRIu64
"/fd=%lu, "
1514 "off=%lu, size=%zd, flags=0x%x)\n",
1515 ino_in
, fi_in
->fh
, off_in
, ino_out
, fi_out
->fh
, off_out
, len
,
1518 res
= copy_file_range(fi_in
->fh
, &off_in
, fi_out
->fh
, &off_out
, len
, flags
);
1520 fuse_reply_err(req
, -errno
);
1522 fuse_reply_write(req
, res
);
1527 static void lo_lseek(fuse_req_t req
, fuse_ino_t ino
, off_t off
, int whence
,
1528 struct fuse_file_info
*fi
)
1533 res
= lseek(fi
->fh
, off
, whence
);
1535 fuse_reply_lseek(req
, res
);
1537 fuse_reply_err(req
, errno
);
1541 static struct fuse_lowlevel_ops lo_oper
= {
1543 .lookup
= lo_lookup
,
1546 .symlink
= lo_symlink
,
1548 .unlink
= lo_unlink
,
1550 .rename
= lo_rename
,
1551 .forget
= lo_forget
,
1552 .forget_multi
= lo_forget_multi
,
1553 .getattr
= lo_getattr
,
1554 .setattr
= lo_setattr
,
1555 .readlink
= lo_readlink
,
1556 .opendir
= lo_opendir
,
1557 .readdir
= lo_readdir
,
1558 .readdirplus
= lo_readdirplus
,
1559 .releasedir
= lo_releasedir
,
1560 .fsyncdir
= lo_fsyncdir
,
1561 .create
= lo_create
,
1563 .release
= lo_release
,
1567 .write_buf
= lo_write_buf
,
1568 .statfs
= lo_statfs
,
1569 .fallocate
= lo_fallocate
,
1571 .getxattr
= lo_getxattr
,
1572 .listxattr
= lo_listxattr
,
1573 .setxattr
= lo_setxattr
,
1574 .removexattr
= lo_removexattr
,
1575 #ifdef HAVE_COPY_FILE_RANGE
1576 .copy_file_range
= lo_copy_file_range
,
1581 /* Print vhost-user.json backend program capabilities */
1582 static void print_capabilities(void)
1585 printf(" \"type\": \"fs\"\n");
1589 int main(int argc
, char *argv
[])
1591 struct fuse_args args
= FUSE_ARGS_INIT(argc
, argv
);
1592 struct fuse_session
*se
;
1593 struct fuse_cmdline_opts opts
;
1594 struct lo_data lo
= { .debug
= 0, .writeback
= 0 };
1595 struct lo_map_elem
*root_elem
;
1598 /* Don't mask creation mode, kernel already did that */
1601 pthread_mutex_init(&lo
.mutex
, NULL
);
1602 lo
.root
.next
= lo
.root
.prev
= &lo
.root
;
1604 lo
.root
.fuse_ino
= FUSE_ROOT_ID
;
1605 lo
.cache
= CACHE_NORMAL
;
1608 * Set up the ino map like this:
1609 * [0] Reserved (will not be used)
1612 lo_map_init(&lo
.ino_map
);
1613 lo_map_reserve(&lo
.ino_map
, 0)->in_use
= false;
1614 root_elem
= lo_map_reserve(&lo
.ino_map
, lo
.root
.fuse_ino
);
1615 root_elem
->inode
= &lo
.root
;
1617 if (fuse_parse_cmdline(&args
, &opts
) != 0) {
1620 if (opts
.show_help
) {
1621 printf("usage: %s [options]\n\n", argv
[0]);
1622 fuse_cmdline_help();
1623 printf(" -o source=PATH shared directory tree\n");
1624 fuse_lowlevel_help();
1627 } else if (opts
.show_version
) {
1628 fuse_lowlevel_version();
1631 } else if (opts
.print_capabilities
) {
1632 print_capabilities();
1637 if (fuse_opt_parse(&args
, &lo
, lo_opts
, NULL
) == -1) {
1641 lo
.debug
= opts
.debug
;
1642 lo
.root
.refcount
= 2;
1647 res
= lstat(lo
.source
, &stat
);
1649 fuse_log(FUSE_LOG_ERR
, "failed to stat source (\"%s\"): %m\n",
1653 if (!S_ISDIR(stat
.st_mode
)) {
1654 fuse_log(FUSE_LOG_ERR
, "source is not a directory\n");
1661 lo
.root
.is_symlink
= false;
1662 if (!lo
.timeout_set
) {
1673 lo
.timeout
= 86400.0;
1676 } else if (lo
.timeout
< 0) {
1677 fuse_log(FUSE_LOG_ERR
, "timeout is negative (%lf)\n", lo
.timeout
);
1681 lo
.root
.fd
= open(lo
.source
, O_PATH
);
1682 if (lo
.root
.fd
== -1) {
1683 fuse_log(FUSE_LOG_ERR
, "open(\"%s\", O_PATH): %m\n", lo
.source
);
1687 se
= fuse_session_new(&args
, &lo_oper
, sizeof(lo_oper
), &lo
);
1692 if (fuse_set_signal_handlers(se
) != 0) {
1696 if (fuse_session_mount(se
) != 0) {
1700 fuse_daemonize(opts
.foreground
);
1702 /* Block until ctrl+c or fusermount -u */
1703 ret
= virtio_loop(se
);
1705 fuse_session_unmount(se
);
1707 fuse_remove_signal_handlers(se
);
1709 fuse_session_destroy(se
);
1711 fuse_opt_free_args(&args
);
1713 lo_map_destroy(&lo
.ino_map
);
1715 if (lo
.root
.fd
>= 0) {