diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/virtiofsd/fuse_lowlevel.c | 98 | ||||
-rw-r--r-- | tools/virtiofsd/fuse_virtio.c | 36 | ||||
-rw-r--r-- | tools/virtiofsd/passthrough_ll.c | 91 |
3 files changed, 99 insertions, 126 deletions
diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c index d4119e92ab..e94b71110b 100644 --- a/tools/virtiofsd/fuse_lowlevel.c +++ b/tools/virtiofsd/fuse_lowlevel.c @@ -2143,104 +2143,6 @@ static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, send_reply_ok(req, NULL, 0); } -static int send_notify_iov(struct fuse_session *se, int notify_code, - struct iovec *iov, int count) -{ - struct fuse_out_header out = { - .error = notify_code, - }; - - if (!se->got_init) { - return -ENOTCONN; - } - - iov[0].iov_base = &out; - iov[0].iov_len = sizeof(struct fuse_out_header); - - return fuse_send_msg(se, NULL, iov, count); -} - -int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph) -{ - if (ph != NULL) { - struct fuse_notify_poll_wakeup_out outarg = { - .kh = ph->kh, - }; - struct iovec iov[2]; - - iov[1].iov_base = &outarg; - iov[1].iov_len = sizeof(outarg); - - return send_notify_iov(ph->se, FUSE_NOTIFY_POLL, iov, 2); - } else { - return 0; - } -} - -int fuse_lowlevel_notify_inval_inode(struct fuse_session *se, fuse_ino_t ino, - off_t off, off_t len) -{ - struct fuse_notify_inval_inode_out outarg = { - .ino = ino, - .off = off, - .len = len, - }; - struct iovec iov[2]; - - if (!se) { - return -EINVAL; - } - - iov[1].iov_base = &outarg; - iov[1].iov_len = sizeof(outarg); - - return send_notify_iov(se, FUSE_NOTIFY_INVAL_INODE, iov, 2); -} - -int fuse_lowlevel_notify_inval_entry(struct fuse_session *se, fuse_ino_t parent, - const char *name, size_t namelen) -{ - struct fuse_notify_inval_entry_out outarg = { - .parent = parent, - .namelen = namelen, - }; - struct iovec iov[3]; - - if (!se) { - return -EINVAL; - } - - iov[1].iov_base = &outarg; - iov[1].iov_len = sizeof(outarg); - iov[2].iov_base = (void *)name; - iov[2].iov_len = namelen + 1; - - return send_notify_iov(se, FUSE_NOTIFY_INVAL_ENTRY, iov, 3); -} - -int fuse_lowlevel_notify_delete(struct fuse_session *se, fuse_ino_t parent, - fuse_ino_t child, const char *name, - size_t namelen) -{ - struct fuse_notify_delete_out outarg = { - .parent = parent, - .child = child, - .namelen = namelen, - }; - struct iovec iov[3]; - - if (!se) { - return -EINVAL; - } - - iov[1].iov_base = &outarg; - iov[1].iov_len = sizeof(outarg); - iov[2].iov_base = (void *)name; - iov[2].iov_len = namelen + 1; - - return send_notify_iov(se, FUSE_NOTIFY_DELETE, iov, 3); -} - int fuse_lowlevel_notify_store(struct fuse_session *se, fuse_ino_t ino, off_t offset, struct fuse_bufvec *bufv) { diff --git a/tools/virtiofsd/fuse_virtio.c b/tools/virtiofsd/fuse_virtio.c index b264dcbd18..ddcefee427 100644 --- a/tools/virtiofsd/fuse_virtio.c +++ b/tools/virtiofsd/fuse_virtio.c @@ -578,13 +578,18 @@ static void *fv_queue_thread(void *opaque) struct VuDev *dev = &qi->virtio_dev->dev; struct VuVirtq *q = vu_get_queue(dev, qi->qidx); struct fuse_session *se = qi->virtio_dev->se; - GThreadPool *pool; - - pool = g_thread_pool_new(fv_queue_worker, qi, se->thread_pool_size, FALSE, - NULL); - if (!pool) { - fuse_log(FUSE_LOG_ERR, "%s: g_thread_pool_new failed\n", __func__); - return NULL; + GThreadPool *pool = NULL; + GList *req_list = NULL; + + if (se->thread_pool_size) { + fuse_log(FUSE_LOG_DEBUG, "%s: Creating thread pool for Queue %d\n", + __func__, qi->qidx); + pool = g_thread_pool_new(fv_queue_worker, qi, se->thread_pool_size, + FALSE, NULL); + if (!pool) { + fuse_log(FUSE_LOG_ERR, "%s: g_thread_pool_new failed\n", __func__); + return NULL; + } } fuse_log(FUSE_LOG_INFO, "%s: Start for queue %d kick_fd %d\n", __func__, @@ -659,14 +664,27 @@ static void *fv_queue_thread(void *opaque) req->reply_sent = false; - g_thread_pool_push(pool, req, NULL); + if (!se->thread_pool_size) { + req_list = g_list_prepend(req_list, req); + } else { + g_thread_pool_push(pool, req, NULL); + } } pthread_mutex_unlock(&qi->vq_lock); pthread_rwlock_unlock(&qi->virtio_dev->vu_dispatch_rwlock); + + /* Process all the requests. */ + if (!se->thread_pool_size && req_list != NULL) { + g_list_foreach(req_list, fv_queue_worker, qi); + g_list_free(req_list); + req_list = NULL; + } } - g_thread_pool_free(pool, FALSE, TRUE); + if (pool) { + g_thread_pool_free(pool, FALSE, TRUE); + } return NULL; } diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c index 12de321745..5fb36d9407 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -101,7 +101,7 @@ struct lo_inode { * This counter keeps the inode alive during the FUSE session. * Incremented when the FUSE inode number is sent in a reply * (FUSE_LOOKUP, FUSE_READDIRPLUS, etc). Decremented when an inode is - * released by requests like FUSE_FORGET, FUSE_RMDIR, FUSE_RENAME, etc. + * released by a FUSE_FORGET request. * * Note that this value is untrusted because the client can manipulate * it arbitrarily using FUSE_FORGET requests. @@ -902,10 +902,11 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name, inode->key.ino = e->attr.st_ino; inode->key.dev = e->attr.st_dev; inode->key.mnt_id = mnt_id; - pthread_mutex_init(&inode->plock_mutex, NULL); - inode->posix_locks = g_hash_table_new_full( - g_direct_hash, g_direct_equal, NULL, posix_locks_value_destroy); - + if (lo->posix_lock) { + pthread_mutex_init(&inode->plock_mutex, NULL); + inode->posix_locks = g_hash_table_new_full( + g_direct_hash, g_direct_equal, NULL, posix_locks_value_destroy); + } pthread_mutex_lock(&lo->mutex); inode->fuse_ino = lo_add_inode_mapping(req, inode); g_hash_table_insert(lo->inodes, &inode->key, inode); @@ -1291,12 +1292,13 @@ static void unref_inode(struct lo_data *lo, struct lo_inode *inode, uint64_t n) if (!inode->nlookup) { lo_map_remove(&lo->ino_map, inode->fuse_ino); g_hash_table_remove(lo->inodes, &inode->key); - if (g_hash_table_size(inode->posix_locks)) { - fuse_log(FUSE_LOG_WARNING, "Hash table is not empty\n"); + if (lo->posix_lock) { + if (g_hash_table_size(inode->posix_locks)) { + fuse_log(FUSE_LOG_WARNING, "Hash table is not empty\n"); + } + g_hash_table_destroy(inode->posix_locks); + pthread_mutex_destroy(&inode->plock_mutex); } - g_hash_table_destroy(inode->posix_locks); - pthread_mutex_destroy(&inode->plock_mutex); - /* Drop our refcount from lo_do_lookup() */ lo_inode_put(lo, &inode); } @@ -1772,6 +1774,11 @@ static void lo_getlk(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, ino, fi->flags, fi->lock_owner, lock->l_type, lock->l_start, lock->l_len); + if (!lo->posix_lock) { + fuse_reply_err(req, ENOSYS); + return; + } + inode = lo_inode(req, ino); if (!inode) { fuse_reply_err(req, EBADF); @@ -1817,6 +1824,11 @@ static void lo_setlk(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, ino, fi->flags, lock->l_type, lock->l_pid, fi->lock_owner, sleep, lock->l_whence, lock->l_start, lock->l_len); + if (!lo->posix_lock) { + fuse_reply_err(req, ENOSYS); + return; + } + if (sleep) { fuse_reply_err(req, EOPNOTSUPP); return; @@ -1941,6 +1953,7 @@ static void lo_flush(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) int res; (void)ino; struct lo_inode *inode; + struct lo_data *lo = lo_data(req); inode = lo_inode(req, ino); if (!inode) { @@ -1948,13 +1961,21 @@ static void lo_flush(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) return; } - /* An fd is going away. Cleanup associated posix locks */ - pthread_mutex_lock(&inode->plock_mutex); - g_hash_table_remove(inode->posix_locks, GUINT_TO_POINTER(fi->lock_owner)); - pthread_mutex_unlock(&inode->plock_mutex); + if (!S_ISREG(inode->filetype)) { + lo_inode_put(lo, &inode); + fuse_reply_err(req, EBADF); + return; + } + /* An fd is going away. Cleanup associated posix locks */ + if (lo->posix_lock) { + pthread_mutex_lock(&inode->plock_mutex); + g_hash_table_remove(inode->posix_locks, + GUINT_TO_POINTER(fi->lock_owner)); + pthread_mutex_unlock(&inode->plock_mutex); + } res = close(dup(lo_fi_fd(req, fi))); - lo_inode_put(lo_data(req), &inode); + lo_inode_put(lo, &inode); fuse_reply_err(req, res == -1 ? errno : 0); } @@ -3284,18 +3305,38 @@ static void setup_nofile_rlimit(unsigned long rlimit_nofile) static void log_func(enum fuse_log_level level, const char *fmt, va_list ap) { g_autofree char *localfmt = NULL; + struct timespec ts; + struct tm tm; + char sec_fmt[sizeof "2020-12-07 18:17:54"]; + char zone_fmt[sizeof "+0100"]; if (current_log_level < level) { return; } if (current_log_level == FUSE_LOG_DEBUG) { - if (!use_syslog) { - localfmt = g_strdup_printf("[%" PRId64 "] [ID: %08ld] %s", - get_clock(), syscall(__NR_gettid), fmt); - } else { + if (use_syslog) { + /* no timestamp needed */ localfmt = g_strdup_printf("[ID: %08ld] %s", syscall(__NR_gettid), fmt); + } else { + /* try formatting a broken-down timestamp */ + if (clock_gettime(CLOCK_REALTIME, &ts) != -1 && + localtime_r(&ts.tv_sec, &tm) != NULL && + strftime(sec_fmt, sizeof sec_fmt, "%Y-%m-%d %H:%M:%S", + &tm) != 0 && + strftime(zone_fmt, sizeof zone_fmt, "%z", &tm) != 0) { + localfmt = g_strdup_printf("[%s.%02ld%s] [ID: %08ld] %s", + sec_fmt, + ts.tv_nsec / (10L * 1000 * 1000), + zone_fmt, syscall(__NR_gettid), + fmt); + } else { + /* fall back to a flat timestamp */ + localfmt = g_strdup_printf("[%" PRId64 "] [ID: %08ld] %s", + get_clock(), syscall(__NR_gettid), + fmt); + } } fmt = localfmt; } @@ -3360,6 +3401,11 @@ static void setup_root(struct lo_data *lo, struct lo_inode *root) root->key.mnt_id = mnt_id; root->nlookup = 2; g_atomic_int_set(&root->refcount, 2); + if (lo->posix_lock) { + pthread_mutex_init(&root->plock_mutex, NULL); + root->posix_locks = g_hash_table_new_full( + g_direct_hash, g_direct_equal, NULL, posix_locks_value_destroy); + } } static guint lo_key_hash(gconstpointer key) @@ -3382,6 +3428,10 @@ static void fuse_lo_data_cleanup(struct lo_data *lo) if (lo->inodes) { g_hash_table_destroy(lo->inodes); } + + if (lo->root.posix_locks) { + g_hash_table_destroy(lo->root.posix_locks); + } lo_map_destroy(&lo->fd_map); lo_map_destroy(&lo->dirp_map); lo_map_destroy(&lo->ino_map); @@ -3416,6 +3466,9 @@ int main(int argc, char *argv[]) struct lo_map_elem *reserve_elem; int ret = -1; + /* Initialize time conversion information for localtime_r(). */ + tzset(); + /* Don't mask creation mode, kernel already did that */ umask(0); |