virtiofs and migration pull 2021-03-15

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEERfXHG0oMt/uXep+pBRYzHrxb/ecFAmBPvXcACgkQBRYzHrxb
 /edQLhAAt12aD4LfEHVzm2Z0KestZvGMJ6rzb84gv44MumfDAHoVvGxT7c12DsnW
 1ct9gG3P7ri4+pDulycOlO1dk2V8c1tX4gGeeShARwAL7UWVwJ6kBxA83kJ+HD5u
 xUMKpzRC2vOhYQW81FHY4NZsZjrmeWsR4rxS8FJbmEpNUYw5KMn3rTYVWEuyXMla
 fQRM1Sge7O//eCgtzK8FNL5TR1v1yaP+HF2lfzSq2mlAb389QzcDRwll9xS/7onP
 8VNhIWqZfCIo6EmaFEzG+E0/9gjD14cDhFb3vMBuhKoEky4M7m0IAkeSMy7spf+N
 AIF6x0Rv28hpgC750q9XySnxSvojl8Dg9hYI6GKl3GYpRw54YDUFH7EYOeP1JDEc
 svAq0dz4CCD0tN5FZXlpkYkvUyi8W07wE1UsjLe6jZS42V9zRu4E0gM42zpB/CBn
 aTuUDQ+ErbK/mdMrlTPFG06fyh7HBXTcyGYdpoz555d7BoUQKMU1bo9PaeRv7S+C
 bEqGAONK8FBDciL+YkjPIhb9GnFmZvrtHFlSVHkD23xZFy/G4EtkZqiXQsd2X2x5
 OitZJZc8Lo90b2azAMfrqn96iMr+y+HmujYU897Wr/zqz+0a676s38fXmkNAylh0
 XRvwtdYXeM0sTcenc3g3bNfg44X9F0XaJfIowYYS9BXZbQ60e0s=
 =9k2c
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/dgilbert-gitlab/tags/pull-virtiofs-20210315' into staging

virtiofs and migration pull 2021-03-15

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

# gpg: Signature made Mon 15 Mar 2021 20:03:03 GMT
# gpg:                using RSA key 45F5C71B4A0CB7FB977A9FA90516331EBC5BFDE7
# gpg: Good signature from "Dr. David Alan Gilbert (RH2) <dgilbert@redhat.com>" [full]
# Primary key fingerprint: 45F5 C71B 4A0C B7FB 977A  9FA9 0516 331E BC5B FDE7

* remotes/dgilbert-gitlab/tags/pull-virtiofs-20210315:
  migration: Replaced qemu_mutex_lock calls with QEMU_LOCK_GUARD
  monitor: Replaced qemu_mutex_lock calls with QEMU_LOCK_GUARD
  migration/tls: add error handling in multifd_tls_handshake_thread
  migration/tls: fix inverted semantics in multifd_channel_connect
  virtiofsd: Convert some functions to return bool
  virtiofsd: Don't allow empty paths in lookup_name()
  virtiofsd: Don't allow empty filenames
  virtiofsd: Add qemu version and copyright info
  virtiofsd: Release vu_dispatch_lock when stopping queue

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-03-17 09:07:28 +00:00
commit 5d1428d6c4
7 changed files with 98 additions and 52 deletions

View File

@ -323,7 +323,7 @@ static int migrate_send_rp_message(MigrationIncomingState *mis,
int ret = 0;
trace_migrate_send_rp_message((int)message_type, len);
qemu_mutex_lock(&mis->rp_mutex);
QEMU_LOCK_GUARD(&mis->rp_mutex);
/*
* It's possible that the file handle got lost due to network
@ -331,7 +331,7 @@ static int migrate_send_rp_message(MigrationIncomingState *mis,
*/
if (!mis->to_src_file) {
ret = -EIO;
goto error;
return ret;
}
qemu_put_be16(mis->to_src_file, (unsigned int)message_type);
@ -342,8 +342,6 @@ static int migrate_send_rp_message(MigrationIncomingState *mis,
/* It's possible that qemu file got error during sending */
ret = qemu_file_get_error(mis->to_src_file);
error:
qemu_mutex_unlock(&mis->rp_mutex);
return ret;
}

View File

@ -739,7 +739,16 @@ static void multifd_tls_outgoing_handshake(QIOTask *task,
} else {
trace_multifd_tls_outgoing_handshake_complete(ioc);
}
multifd_channel_connect(p, ioc, err);
if (!multifd_channel_connect(p, ioc, err)) {
/*
* Error happen, mark multifd_send_thread status as 'quit' although it
* is not created, and then tell who pay attention to me.
*/
p->quit = true;
qemu_sem_post(&multifd_send_state->channels_ready);
qemu_sem_post(&p->sem_sync);
}
}
static void *multifd_tls_handshake_thread(void *opaque)
@ -798,9 +807,9 @@ static bool multifd_channel_connect(MultiFDSendParams *p,
* function after the TLS handshake,
* so we mustn't call multifd_send_thread until then
*/
return false;
} else {
return true;
} else {
return false;
}
} else {
/* update for tls qio channel */
@ -808,10 +817,10 @@ static bool multifd_channel_connect(MultiFDSendParams *p,
qemu_thread_create(&p->thread, p->name, multifd_send_thread, p,
QEMU_THREAD_JOINABLE);
}
return false;
return true;
}
return true;
return false;
}
static void multifd_new_send_channel_cleanup(MultiFDSendParams *p,
@ -844,7 +853,7 @@ static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque)
p->c = QIO_CHANNEL(sioc);
qio_channel_set_delay(p->c, false);
p->running = true;
if (multifd_channel_connect(p, sioc, local_err)) {
if (!multifd_channel_connect(p, sioc, local_err)) {
goto cleanup;
}
return;

View File

@ -819,7 +819,7 @@ static inline bool migration_bitmap_clear_dirty(RAMState *rs,
{
bool ret;
qemu_mutex_lock(&rs->bitmap_mutex);
QEMU_LOCK_GUARD(&rs->bitmap_mutex);
/*
* Clear dirty bitmap if needed. This _must_ be called before we
@ -852,7 +852,6 @@ static inline bool migration_bitmap_clear_dirty(RAMState *rs,
if (ret) {
rs->migration_dirty_pages--;
}
qemu_mutex_unlock(&rs->bitmap_mutex);
return ret;
}
@ -3275,7 +3274,7 @@ static void decompress_data_with_multi_threads(QEMUFile *f,
int idx, thread_count;
thread_count = migrate_decompress_threads();
qemu_mutex_lock(&decomp_done_lock);
QEMU_LOCK_GUARD(&decomp_done_lock);
while (true) {
for (idx = 0; idx < thread_count; idx++) {
if (decomp_param[idx].done) {
@ -3295,7 +3294,6 @@ static void decompress_data_with_multi_threads(QEMUFile *f,
qemu_cond_wait(&decomp_done_cond, &decomp_done_lock);
}
}
qemu_mutex_unlock(&decomp_done_lock);
}
/*

View File

@ -349,7 +349,7 @@ monitor_qapi_event_queue_no_reenter(QAPIEvent event, QDict *qdict)
evconf = &monitor_qapi_event_conf[event];
trace_monitor_protocol_event_queue(event, qdict, evconf->rate);
qemu_mutex_lock(&monitor_lock);
QEMU_LOCK_GUARD(&monitor_lock);
if (!evconf->rate) {
/* Unthrottled event */
@ -391,8 +391,6 @@ monitor_qapi_event_queue_no_reenter(QAPIEvent event, QDict *qdict)
timer_mod_ns(evstate->timer, now + evconf->rate);
}
}
qemu_mutex_unlock(&monitor_lock);
}
void qapi_event_emit(QAPIEvent event, QDict *qdict)
@ -447,7 +445,7 @@ static void monitor_qapi_event_handler(void *opaque)
MonitorQAPIEventConf *evconf = &monitor_qapi_event_conf[evstate->event];
trace_monitor_protocol_event_handler(evstate->event, evstate->qdict);
qemu_mutex_lock(&monitor_lock);
QEMU_LOCK_GUARD(&monitor_lock);
if (evstate->qdict) {
int64_t now = qemu_clock_get_ns(monitor_get_event_clock());
@ -462,8 +460,6 @@ static void monitor_qapi_event_handler(void *opaque)
timer_free(evstate->timer);
g_free(evstate);
}
qemu_mutex_unlock(&monitor_lock);
}
static unsigned int qapi_event_throttle_hash(const void *key)

View File

@ -76,7 +76,7 @@ static void monitor_qmp_cleanup_req_queue_locked(MonitorQMP *mon)
static void monitor_qmp_cleanup_queue_and_resume(MonitorQMP *mon)
{
qemu_mutex_lock(&mon->qmp_queue_lock);
QEMU_LOCK_GUARD(&mon->qmp_queue_lock);
/*
* Same condition as in monitor_qmp_dispatcher_co(), but before
@ -103,7 +103,6 @@ static void monitor_qmp_cleanup_queue_and_resume(MonitorQMP *mon)
monitor_resume(&mon->common);
}
qemu_mutex_unlock(&mon->qmp_queue_lock);
}
void qmp_send_response(MonitorQMP *mon, const QDict *rsp)
@ -179,7 +178,7 @@ static QMPRequest *monitor_qmp_requests_pop_any_with_lock(void)
Monitor *mon;
MonitorQMP *qmp_mon;
qemu_mutex_lock(&monitor_lock);
QEMU_LOCK_GUARD(&monitor_lock);
QTAILQ_FOREACH(mon, &mon_list, entry) {
if (!monitor_is_qmp(mon)) {
@ -205,8 +204,6 @@ static QMPRequest *monitor_qmp_requests_pop_any_with_lock(void)
QTAILQ_INSERT_TAIL(&mon_list, mon, entry);
}
qemu_mutex_unlock(&monitor_lock);
return req_obj;
}
@ -376,31 +373,31 @@ static void handle_qmp_command(void *opaque, QObject *req, Error *err)
req_obj->err = err;
/* Protect qmp_requests and fetching its length. */
qemu_mutex_lock(&mon->qmp_queue_lock);
WITH_QEMU_LOCK_GUARD(&mon->qmp_queue_lock) {
/*
* Suspend the monitor when we can't queue more requests after
* this one. Dequeuing in monitor_qmp_dispatcher_co() or
* monitor_qmp_cleanup_queue_and_resume() will resume it.
* Note that when OOB is disabled, we queue at most one command,
* for backward compatibility.
*/
if (!qmp_oob_enabled(mon) ||
mon->qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1) {
monitor_suspend(&mon->common);
/*
* Suspend the monitor when we can't queue more requests after
* this one. Dequeuing in monitor_qmp_dispatcher_co() or
* monitor_qmp_cleanup_queue_and_resume() will resume it.
* Note that when OOB is disabled, we queue at most one command,
* for backward compatibility.
*/
if (!qmp_oob_enabled(mon) ||
mon->qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1) {
monitor_suspend(&mon->common);
}
/*
* Put the request to the end of queue so that requests will be
* handled in time order. Ownership for req_obj, req,
* etc. will be delivered to the handler side.
*/
trace_monitor_qmp_in_band_enqueue(req_obj, mon,
mon->qmp_requests->length);
assert(mon->qmp_requests->length < QMP_REQ_QUEUE_LEN_MAX);
g_queue_push_tail(mon->qmp_requests, req_obj);
}
/*
* Put the request to the end of queue so that requests will be
* handled in time order. Ownership for req_obj, req,
* etc. will be delivered to the handler side.
*/
trace_monitor_qmp_in_band_enqueue(req_obj, mon,
mon->qmp_requests->length);
assert(mon->qmp_requests->length < QMP_REQ_QUEUE_LEN_MAX);
g_queue_push_tail(mon->qmp_requests, req_obj);
qemu_mutex_unlock(&mon->qmp_queue_lock);
/* Kick the dispatcher routine */
if (!qatomic_xchg(&qmp_dispatcher_co_busy, true)) {
aio_co_wake(qmp_dispatcher_co);

View File

@ -792,7 +792,13 @@ static void fv_queue_set_started(VuDev *dev, int qidx, bool started)
assert(0);
}
} else {
/*
* Temporarily drop write-lock taken in virtio_loop() so that
* the queue thread doesn't block in virtio_send_msg().
*/
vu_dispatch_unlock(vud);
fv_queue_cleanup_thread(vud, qidx);
vu_dispatch_wrlock(vud);
}
}

View File

@ -37,6 +37,8 @@
#include "qemu/osdep.h"
#include "qemu/timer.h"
#include "qemu-version.h"
#include "qemu-common.h"
#include "fuse_virtio.h"
#include "fuse_log.h"
#include "fuse_lowlevel.h"
@ -221,22 +223,27 @@ static struct lo_inode *lo_find(struct lo_data *lo, struct stat *st,
static int xattr_map_client(const struct lo_data *lo, const char *client_name,
char **out_name);
static int is_dot_or_dotdot(const char *name)
static bool is_dot_or_dotdot(const char *name)
{
return name[0] == '.' &&
(name[1] == '\0' || (name[1] == '.' && name[2] == '\0'));
}
/* Is `path` a single path component that is not "." or ".."? */
static int is_safe_path_component(const char *path)
static bool is_safe_path_component(const char *path)
{
if (strchr(path, '/')) {
return 0;
return false;
}
return !is_dot_or_dotdot(path);
}
static bool is_empty(const char *name)
{
return name[0] == '\0';
}
static struct lo_data *lo_data(fuse_req_t req)
{
return (struct lo_data *)fuse_req_userdata(req);
@ -1083,6 +1090,11 @@ static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
fuse_log(FUSE_LOG_DEBUG, "lo_lookup(parent=%" PRIu64 ", name=%s)\n", parent,
name);
if (is_empty(name)) {
fuse_reply_err(req, ENOENT);
return;
}
/*
* Don't use is_safe_path_component(), allow "." and ".." for NFS export
* support.
@ -1174,6 +1186,11 @@ static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent,
struct fuse_entry_param e;
struct lo_cred old = {};
if (is_empty(name)) {
fuse_reply_err(req, ENOENT);
return;
}
if (!is_safe_path_component(name)) {
fuse_reply_err(req, EINVAL);
return;
@ -1246,6 +1263,11 @@ static void lo_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t parent,
char procname[64];
int saverr;
if (is_empty(name)) {
fuse_reply_err(req, ENOENT);
return;
}
if (!is_safe_path_component(name)) {
fuse_reply_err(req, EINVAL);
return;
@ -1308,8 +1330,7 @@ static struct lo_inode *lookup_name(fuse_req_t req, fuse_ino_t parent,
return NULL;
}
res = do_statx(lo, dir->fd, name, &attr,
AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW, &mnt_id);
res = do_statx(lo, dir->fd, name, &attr, AT_SYMLINK_NOFOLLOW, &mnt_id);
lo_inode_put(lo, &dir);
if (res == -1) {
return NULL;
@ -1324,6 +1345,11 @@ static void lo_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
struct lo_inode *inode;
struct lo_data *lo = lo_data(req);
if (is_empty(name)) {
fuse_reply_err(req, ENOENT);
return;
}
if (!is_safe_path_component(name)) {
fuse_reply_err(req, EINVAL);
return;
@ -1353,6 +1379,11 @@ static void lo_rename(fuse_req_t req, fuse_ino_t parent, const char *name,
struct lo_inode *newinode = NULL;
struct lo_data *lo = lo_data(req);
if (is_empty(name) || is_empty(newname)) {
fuse_reply_err(req, ENOENT);
return;
}
if (!is_safe_path_component(name) || !is_safe_path_component(newname)) {
fuse_reply_err(req, EINVAL);
return;
@ -1406,6 +1437,11 @@ static void lo_unlink(fuse_req_t req, fuse_ino_t parent, const char *name)
struct lo_inode *inode;
struct lo_data *lo = lo_data(req);
if (is_empty(name)) {
fuse_reply_err(req, ENOENT);
return;
}
if (!is_safe_path_component(name)) {
fuse_reply_err(req, EINVAL);
return;
@ -3666,6 +3702,11 @@ static void fuse_lo_data_cleanup(struct lo_data *lo)
free(lo->source);
}
static void qemu_version(void)
{
printf("virtiofsd version " QEMU_FULL_VERSION "\n" QEMU_COPYRIGHT "\n");
}
int main(int argc, char *argv[])
{
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
@ -3737,6 +3778,7 @@ int main(int argc, char *argv[])
ret = 0;
goto err_out1;
} else if (opts.show_version) {
qemu_version();
fuse_lowlevel_version();
ret = 0;
goto err_out1;