And document which members they protect.
end_polls() is called with both, outer fch->lock is probably unnecessary,
but doesn't hurt for now.
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
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);
{
struct fuse_conn *old_fc;
- spin_lock(&fc->lock);
+ spin_lock(&fc->chan->lock);
/*
* Pairs with:
* - xchg() in fuse_dev_release()
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);
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);
}
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;
}
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);
{
struct rb_node *p;
+ spin_lock(&fc->lock);
p = rb_first(&fc->polled_files);
while (p) {
p = rb_next(p);
}
+ spin_unlock(&fc->lock);
}
/*
{
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;
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);
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);
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;
}
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:
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];
* 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;
}
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);
};
struct fuse_chan {
+ /** Lock protecting:
+ - devices
+ - connected
+ - ring
+ - ring->queues[qid]
+ */
+ spinlock_t lock;
+
/** Input queue */
struct fuse_iqueue iq;
*
* .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
* 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 */
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) {
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;