diff options
Diffstat (limited to 'lib/fuse_lowlevel.c')
-rw-r--r-- | lib/fuse_lowlevel.c | 53 |
1 files changed, 34 insertions, 19 deletions
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 459fca5..aee22b4 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -156,7 +156,7 @@ static struct fuse_req *fuse_ll_alloc_req(struct fuse_session *se) req->se = se; req->ctr = 1; list_init_req(req); - fuse_mutex_init(&req->lock); + pthread_mutex_init(&req->lock, NULL); } return req; @@ -168,6 +168,7 @@ static int fuse_send_msg(struct fuse_session *se, struct fuse_chan *ch, { struct fuse_out_header *out = iov[0].iov_base; + assert(se != NULL); out->len = iov_length(iov, count); if (se->debug) { if (out->unique == 0) { @@ -190,8 +191,6 @@ static int fuse_send_msg(struct fuse_session *se, struct fuse_chan *ch, int err = errno; if (res == -1) { - assert(se != NULL); - /* ENOENT means the operation was interrupted */ if (!fuse_session_exited(se) && err != ENOENT) perror("fuse: writing device"); @@ -755,7 +754,7 @@ static int fuse_send_data_iov(struct fuse_session *se, struct fuse_chan *ch, struct fuse_ll_pipe *llp; int splice_flags; size_t pipesize; - size_t total_fd_size; + size_t total_buf_size; size_t idx; size_t headerlen; struct fuse_bufvec pipe_buf = FUSE_BUFVEC_INIT(len); @@ -766,15 +765,13 @@ static int fuse_send_data_iov(struct fuse_session *se, struct fuse_chan *ch, if (flags & FUSE_BUF_NO_SPLICE) goto fallback; - total_fd_size = 0; + total_buf_size = 0; for (idx = buf->idx; idx < buf->count; idx++) { - if (buf->buf[idx].flags & FUSE_BUF_IS_FD) { - total_fd_size = buf->buf[idx].size; - if (idx == buf->idx) - total_fd_size -= buf->off; - } + total_buf_size += buf->buf[idx].size; + if (idx == buf->idx) + total_buf_size -= buf->off; } - if (total_fd_size < 2 * pagesize) + if (total_buf_size < 2 * pagesize) goto fallback; if (se->conn.proto_minor < 14 || @@ -2006,7 +2003,10 @@ static void do_lseek(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) fuse_reply_err(req, ENOSYS); } -static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +/* Prevent bogus data races (bogus since "init" is called before + * multi-threading becomes relevant */ +static __attribute__((no_sanitize("thread"))) +void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { struct fuse_init_in *arg = (struct fuse_init_in *) inarg; struct fuse_init_out outarg; @@ -2078,8 +2078,12 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) se->conn.capable |= FUSE_CAP_POSIX_ACL; if (arg->flags & FUSE_HANDLE_KILLPRIV) se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV; + if (arg->flags & FUSE_CACHE_SYMLINKS) + se->conn.capable |= FUSE_CAP_CACHE_SYMLINKS; if (arg->flags & FUSE_NO_OPENDIR_SUPPORT) se->conn.capable |= FUSE_CAP_NO_OPENDIR_SUPPORT; + if (arg->flags & FUSE_EXPLICIT_INVAL_DATA) + se->conn.capable |= FUSE_CAP_EXPLICIT_INVAL_DATA; if (!(arg->flags & FUSE_MAX_PAGES)) { size_t max_bufsize = FUSE_DEFAULT_MAX_PAGES_PER_REQ * getpagesize() @@ -2204,6 +2208,10 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) outarg.flags |= FUSE_POSIX_ACL; if (se->conn.want & FUSE_CAP_PASSTHROUGH) outarg.flags |= FUSE_PASSTHROUGH; + if (se->conn.want & FUSE_CAP_CACHE_SYMLINKS) + outarg.flags |= FUSE_CACHE_SYMLINKS; + if (se->conn.want & FUSE_CAP_EXPLICIT_INVAL_DATA) + outarg.flags |= FUSE_EXPLICIT_INVAL_DATA; outarg.max_readahead = se->conn.max_readahead; outarg.max_write = se->conn.max_write; if (se->conn.proto_minor >= 13) { @@ -2344,7 +2352,7 @@ int fuse_lowlevel_notify_inval_inode(struct fuse_session *se, fuse_ino_t ino, if (!se) return -EINVAL; - if (se->conn.proto_major < 6 || se->conn.proto_minor < 12) + if (se->conn.proto_minor < 12) return -ENOSYS; outarg.ino = ino; @@ -2366,7 +2374,7 @@ int fuse_lowlevel_notify_inval_entry(struct fuse_session *se, fuse_ino_t parent, if (!se) return -EINVAL; - if (se->conn.proto_major < 6 || se->conn.proto_minor < 12) + if (se->conn.proto_minor < 12) return -ENOSYS; outarg.parent = parent; @@ -2391,7 +2399,7 @@ int fuse_lowlevel_notify_delete(struct fuse_session *se, if (!se) return -EINVAL; - if (se->conn.proto_major < 6 || se->conn.proto_minor < 18) + if (se->conn.proto_minor < 18) return -ENOSYS; outarg.parent = parent; @@ -2420,7 +2428,7 @@ int fuse_lowlevel_notify_store(struct fuse_session *se, fuse_ino_t ino, if (!se) return -EINVAL; - if (se->conn.proto_major < 6 || se->conn.proto_minor < 15) + if (se->conn.proto_minor < 15) return -ENOSYS; out.unique = 0; @@ -2498,7 +2506,7 @@ int fuse_lowlevel_notify_retrieve(struct fuse_session *se, fuse_ino_t ino, if (!se) return -EINVAL; - if (se->conn.proto_major < 6 || se->conn.proto_minor < 15) + if (se->conn.proto_minor < 15) return -ENOSYS; rreq = malloc(sizeof(*rreq)); @@ -3092,7 +3100,7 @@ struct fuse_session *fuse_session_new(struct fuse_args *args, list_init_req(&se->interrupts); list_init_nreq(&se->notify_list); se->notify_ctr = 1; - fuse_mutex_init(&se->lock); + pthread_mutex_init(&se->lock, NULL); err = pthread_key_create(&se->pipe_key, fuse_ll_pipe_destructor); if (err) { @@ -3113,7 +3121,8 @@ out5: out4: fuse_opt_free_args(args); out3: - free(mo); + if (mo != NULL) + destroy_mount_opts(mo); out2: free(se); out1: @@ -3179,6 +3188,7 @@ void fuse_session_unmount(struct fuse_session *se) { if (se->mountpoint != NULL) { fuse_kern_unmount(se->mountpoint, se->fd); + se->fd = -1; free(se->mountpoint); se->mountpoint = NULL; } @@ -3254,17 +3264,22 @@ int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[]) } #endif +/* Prevent spurious data race warning - we don't care + * about races for this flag */ +__attribute__((no_sanitize_thread)) void fuse_session_exit(struct fuse_session *se) { se->exited = 1; } +__attribute__((no_sanitize_thread)) void fuse_session_reset(struct fuse_session *se) { se->exited = 0; se->error = 0; } +__attribute__((no_sanitize_thread)) int fuse_session_exited(struct fuse_session *se) { return se->exited; |