summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/dev.c29
-rw-r--r--fs/fuse/dev_uring.c20
-rw-r--r--fs/fuse/fuse_dev_i.h8
-rw-r--r--fs/fuse/fuse_i.h8
-rw-r--r--fs/fuse/req_timeout.c8
5 files changed, 44 insertions, 29 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 27357ee01fe5..52f46efd85ba 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -354,6 +354,7 @@ struct fuse_chan *fuse_chan_new(void)
if (!fch)
return NULL;
+ spin_lock_init(&fch->lock);
INIT_LIST_HEAD(&fch->devices);
spin_lock_init(&fch->bg_lock);
INIT_LIST_HEAD(&fch->bg_queue);
@@ -418,7 +419,7 @@ void fuse_dev_install(struct fuse_dev *fud, struct fuse_conn *fc)
{
struct fuse_conn *old_fc;
- spin_lock(&fc->lock);
+ spin_lock(&fc->chan->lock);
/*
* Pairs with:
* - xchg() in fuse_dev_release()
@@ -436,7 +437,7 @@ void fuse_dev_install(struct fuse_dev *fud, struct fuse_conn *fc)
list_add_tail(&fud->entry, &fc->chan->devices);
fuse_conn_get(fc);
}
- spin_unlock(&fc->lock);
+ spin_unlock(&fc->chan->lock);
}
EXPORT_SYMBOL_GPL(fuse_dev_install);
@@ -463,9 +464,9 @@ void fuse_dev_put(struct fuse_dev *fud)
fc = fuse_dev_fc_get(fud);
if (fc && fc != FUSE_DEV_FC_DISCONNECTED) {
/* This is the virtiofs case (fuse_dev_release() not called) */
- spin_lock(&fc->lock);
+ spin_lock(&fc->chan->lock);
list_del(&fud->entry);
- spin_unlock(&fc->lock);
+ spin_unlock(&fc->chan->lock);
fuse_conn_put(fc);
}
@@ -2060,9 +2061,9 @@ static void fuse_resend(struct fuse_conn *fc)
LIST_HEAD(to_queue);
unsigned int i;
- spin_lock(&fc->lock);
+ spin_lock(&fc->chan->lock);
if (!fc->chan->connected) {
- spin_unlock(&fc->lock);
+ spin_unlock(&fc->chan->lock);
return;
}
@@ -2074,7 +2075,7 @@ static void fuse_resend(struct fuse_conn *fc)
list_splice_tail_init(&fpq->processing[i], &to_queue);
spin_unlock(&fpq->lock);
}
- spin_unlock(&fc->lock);
+ spin_unlock(&fc->chan->lock);
list_for_each_entry_safe(req, next, &to_queue, list) {
set_bit(FR_PENDING, &req->flags);
@@ -2498,6 +2499,7 @@ static void end_polls(struct fuse_conn *fc)
{
struct rb_node *p;
+ spin_lock(&fc->lock);
p = rb_first(&fc->polled_files);
while (p) {
@@ -2507,6 +2509,7 @@ static void end_polls(struct fuse_conn *fc)
p = rb_next(p);
}
+ spin_unlock(&fc->lock);
}
/*
@@ -2531,7 +2534,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
{
struct fuse_iqueue *fiq = &fc->chan->iq;
- spin_lock(&fc->lock);
+ spin_lock(&fc->chan->lock);
if (fc->chan->connected) {
struct fuse_dev *fud;
struct fuse_req *req, *next;
@@ -2586,17 +2589,17 @@ void fuse_abort_conn(struct fuse_conn *fc)
kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
end_polls(fc);
wake_up_all(&fc->chan->blocked_waitq);
- spin_unlock(&fc->lock);
+ spin_unlock(&fc->chan->lock);
fuse_dev_end_requests(&to_end);
/*
- * fc->lock must not be taken to avoid conflicts with io-uring
+ * fc->chan->lock must not be taken to avoid conflicts with io-uring
* locks
*/
fuse_uring_abort(fc);
} else {
- spin_unlock(&fc->lock);
+ spin_unlock(&fc->chan->lock);
}
}
EXPORT_SYMBOL_GPL(fuse_abort_conn);
@@ -2630,11 +2633,11 @@ int fuse_dev_release(struct inode *inode, struct file *file)
fuse_dev_end_requests(&to_end);
- spin_lock(&fc->lock);
+ spin_lock(&fc->chan->lock);
list_del(&fud->entry);
/* Are we the last open device? */
last = list_empty(&fc->chan->devices);
- spin_unlock(&fc->lock);
+ spin_unlock(&fc->chan->lock);
if (last) {
WARN_ON(fc->chan->iq.fasync != NULL);
diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c
index eef7f7eac795..53bd5ae4b686 100644
--- a/fs/fuse/dev_uring.c
+++ b/fs/fuse/dev_uring.c
@@ -243,14 +243,14 @@ static struct fuse_ring *fuse_uring_create(struct fuse_conn *fc)
max_payload_size = max(FUSE_MIN_READ_BUFFER, fc->max_write);
max_payload_size = max(max_payload_size, fc->max_pages * PAGE_SIZE);
- spin_lock(&fc->lock);
+ spin_lock(&fc->chan->lock);
if (!fc->chan->connected) {
- spin_unlock(&fc->lock);
+ spin_unlock(&fc->chan->lock);
goto out_err;
}
if (fc->chan->ring) {
/* race, another thread created the ring in the meantime */
- spin_unlock(&fc->lock);
+ spin_unlock(&fc->chan->lock);
res = fc->chan->ring;
goto out_err;
}
@@ -262,7 +262,7 @@ static struct fuse_ring *fuse_uring_create(struct fuse_conn *fc)
ring->max_payload_sz = max_payload_size;
smp_store_release(&fc->chan->ring, ring);
- spin_unlock(&fc->lock);
+ spin_unlock(&fc->chan->lock);
return ring;
out_err:
@@ -302,9 +302,9 @@ static struct fuse_ring_queue *fuse_uring_create_queue(struct fuse_ring *ring,
queue->fpq.processing = pq;
fuse_pqueue_init(&queue->fpq);
- spin_lock(&fc->lock);
+ spin_lock(&fc->chan->lock);
if (ring->queues[qid]) {
- spin_unlock(&fc->lock);
+ spin_unlock(&fc->chan->lock);
kfree(queue->fpq.processing);
kfree(queue);
return ring->queues[qid];
@@ -314,7 +314,7 @@ static struct fuse_ring_queue *fuse_uring_create_queue(struct fuse_ring *ring,
* write_once and lock as the caller mostly doesn't take the lock at all
*/
WRITE_ONCE(ring->queues[qid], queue);
- spin_unlock(&fc->lock);
+ spin_unlock(&fc->chan->lock);
return queue;
}
@@ -1008,16 +1008,16 @@ static int fuse_uring_do_register(struct fuse_ring_ent *ent,
struct fuse_conn *fc = ring->fc;
struct fuse_iqueue *fiq = &fc->chan->iq;
- spin_lock(&fc->lock);
+ spin_lock(&fc->chan->lock);
/* abort teardown path is running or has run */
if (!fc->chan->connected) {
- spin_unlock(&fc->lock);
+ spin_unlock(&fc->chan->lock);
if (atomic_dec_and_test(&ring->queue_refs))
wake_up_all(&ring->stop_waitq);
kfree(ent);
return -ECONNABORTED;
}
- spin_unlock(&fc->lock);
+ spin_unlock(&fc->chan->lock);
fuse_uring_prepare_cancel(cmd, issue_flags, ent);
diff --git a/fs/fuse/fuse_dev_i.h b/fs/fuse/fuse_dev_i.h
index 5c31272a4902..22d9c9e795d9 100644
--- a/fs/fuse/fuse_dev_i.h
+++ b/fs/fuse/fuse_dev_i.h
@@ -88,6 +88,14 @@ struct fuse_iqueue {
};
struct fuse_chan {
+ /** Lock protecting:
+ - devices
+ - connected
+ - ring
+ - ring->queues[qid]
+ */
+ spinlock_t lock;
+
/** Input queue */
struct fuse_iqueue iq;
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 59bdabaf994b..6343218563b1 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -421,7 +421,7 @@ enum fuse_req_flag {
*
* .waitq.lock protects the following fields:
* - FR_ABORTED
- * - FR_LOCKED (may also be modified under fc->lock, tested under both)
+ * - FR_LOCKED (may also be modified under fpq->lock, tested under both)
*/
struct fuse_req {
/** This can be on either pending processing or io lists in
@@ -520,7 +520,11 @@ struct fuse_sync_bucket {
* fuse_mount is destroyed.
*/
struct fuse_conn {
- /** Lock protecting accessess to members of this structure */
+ /** Lock protecting:
+ - polled_files
+ - backing_files_map
+ - curr_bucket
+ */
spinlock_t lock;
/** Refcount */
diff --git a/fs/fuse/req_timeout.c b/fs/fuse/req_timeout.c
index ef2e39e4dcf4..401d3545b0a8 100644
--- a/fs/fuse/req_timeout.c
+++ b/fs/fuse/req_timeout.c
@@ -89,9 +89,9 @@ static void fuse_check_timeout(struct work_struct *work)
if (expired)
goto abort_conn;
- spin_lock(&fc->lock);
+ spin_lock(&fc->chan->lock);
if (!fc->chan->connected) {
- spin_unlock(&fc->lock);
+ spin_unlock(&fc->chan->lock);
return;
}
list_for_each_entry(fud, &fc->chan->devices, entry) {
@@ -100,13 +100,13 @@ static void fuse_check_timeout(struct work_struct *work)
if (fuse_request_expired(fc, &fpq->io) ||
fuse_fpq_processing_expired(fc, fpq->processing)) {
spin_unlock(&fpq->lock);
- spin_unlock(&fc->lock);
+ spin_unlock(&fc->chan->lock);
goto abort_conn;
}
spin_unlock(&fpq->lock);
}
- spin_unlock(&fc->lock);
+ spin_unlock(&fc->chan->lock);
if (fuse_uring_request_expired(fc))
goto abort_conn;