nfsv4: fix multithreading for nfsv4

Some multi-stage operations in nfs v4 can not be interleaved
so add mutex to prevent them from running concurrently.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
master
Ronnie Sahlberg 2022-01-05 11:48:16 +10:00
parent 4ca1e05f4e
commit 61e5863e46
4 changed files with 32 additions and 3 deletions

View File

@ -318,6 +318,7 @@ struct nfs_context {
int multithreading_enabled;
libnfs_mutex_t nfs_mutex;
libnfs_thread_t service_thread;
libnfs_mutex_t nfs4_open_mutex;
#endif /* HAVE_MULTITHREADING */
};

View File

@ -517,7 +517,7 @@ nfs_open(struct nfs_context *nfs, const char *path, int flags,
return -1;
}
if (nfs_open_async(nfs, path, flags, open_cb, &cb_data) != 0) {
if (nfs_open_async(nfs, path, flags, open_cb, &cb_data) != 0) {
nfs_set_error(nfs, "nfs_open_async failed. %s",
nfs_get_error(nfs));
nfs_destroy_cb_sem(&cb_data);

View File

@ -549,6 +549,7 @@ nfs_init_context(void)
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_init(&nfs->nfs_mutex);
nfs_mt_mutex_init(&nfs->nfs4_open_mutex);
#endif /* HAVE_MULTITHREADING */
return nfs;
}
@ -603,6 +604,7 @@ nfs_destroy_context(struct nfs_context *nfs)
}
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_destroy(&nfs->nfs4_open_mutex);
nfs_mt_mutex_destroy(&nfs->nfs_mutex);
#endif /* HAVE_MULTITHREADING */
free(nfs);

View File

@ -152,6 +152,7 @@ struct nfs4_cb_data {
*/
#define LOOKUP_FLAG_NO_FOLLOW 0x0001
#define LOOKUP_FLAG_IS_STATVFS64 0x0002
#define MUTEX_HELD 0x0004
int flags;
/* Internal callback for open-with-continuation use */
@ -243,6 +244,11 @@ nfs4_resolve_path(struct nfs_context *nfs, const char *path)
static void
free_nfs4_cb_data(struct nfs4_cb_data *data)
{
#ifdef HAVE_MULTITHREADING
if (data->flags & MUTEX_HELD) {
nfs_mt_mutex_unlock(&data->nfs->nfs4_open_mutex);
}
#endif
free(data->path);
free(data->filler.data);
if (data->filler.blob0.val && data->filler.blob0.free) {
@ -2456,7 +2462,8 @@ nfs4_open_async(struct nfs_context *nfs, const char *path, int flags,
{
struct nfs4_cb_data *data;
uint32_t m;
int ret;
data = init_cb_data_split_path(nfs, path);
if (data == NULL) {
return -1;
@ -2502,7 +2509,14 @@ nfs4_open_async(struct nfs_context *nfs, const char *path, int flags,
memcpy(data->filler.blob3.val, &m, sizeof(uint32_t));
}
return nfs4_open_async_internal(nfs, data, flags, mode);
#ifdef HAVE_MULTITHREADING
if (nfs->multithreading_enabled) {
nfs_mt_mutex_lock(&nfs->nfs4_open_mutex);
data->flags |= MUTEX_HELD;
}
#endif
ret = nfs4_open_async_internal(nfs, data, flags, mode);
return ret;
}
int
@ -2661,6 +2675,12 @@ nfs4_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb,
}
memset(data, 0, sizeof(*data));
#ifdef HAVE_MULTITHREADING
if (nfs->multithreading_enabled) {
nfs_mt_mutex_lock(&nfs->nfs4_open_mutex);
data->flags |= MUTEX_HELD;
}
#endif
data->nfs = nfs;
data->cb = cb;
data->private_data = private_data;
@ -3855,6 +3875,12 @@ nfs4_truncate_async(struct nfs_context *nfs, const char *path, uint64_t length,
length = nfs_hton64(length);
memcpy(data->filler.blob3.val, &length, sizeof(uint64_t));
#ifdef HAVE_MULTITHREADING
if (nfs->multithreading_enabled) {
nfs_mt_mutex_lock(&nfs->nfs4_open_mutex);
data->flags |= MUTEX_HELD;
}
#endif
if (nfs4_open_async_internal(nfs, data, O_WRONLY, 0) < 0) {
return -1;
}