On Wed, Feb 06, 2019 at 09:36:26AM +0100, Miklos Szeredi wrote:
Yep. And is AIO doing anything in irq context? If so, why?
Because all waitqueues can be woken, and often are woken from irq context.
Would it make sense to just disable AIO on file descriptors where it makes zero sense?
using aio poll makes sense on every fd, just like you can use epoll or the upcoming io_uring poll on every fd.
Just use the waitqueue API properly in fuse and we are done:
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index a5e516a40e7a..1c693bb6339a 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -387,7 +387,7 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget, forget->forget_one.nodeid = nodeid; forget->forget_one.nlookup = nlookup;
- spin_lock(&fiq->waitq.lock); + spin_lock_irq(&fiq->waitq.lock); if (fiq->connected) { fiq->forget_list_tail->next = forget; fiq->forget_list_tail = forget; @@ -396,7 +396,7 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget, } else { kfree(forget); } - spin_unlock(&fiq->waitq.lock); + spin_unlock_irq(&fiq->waitq.lock); }
static void flush_bg_queue(struct fuse_conn *fc) @@ -410,10 +410,10 @@ static void flush_bg_queue(struct fuse_conn *fc) req = list_first_entry(&fc->bg_queue, struct fuse_req, list); list_del(&req->list); fc->active_background++; - spin_lock(&fiq->waitq.lock); + spin_lock_irq(&fiq->waitq.lock); req->in.h.unique = fuse_get_unique(fiq); queue_request(fiq, req); - spin_unlock(&fiq->waitq.lock); + spin_unlock_irq(&fiq->waitq.lock); } }
@@ -472,7 +472,7 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
static void queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req) { - spin_lock(&fiq->waitq.lock); + spin_lock_irq(&fiq->waitq.lock); if (test_bit(FR_FINISHED, &req->flags)) { spin_unlock(&fiq->waitq.lock); return; @@ -481,7 +481,7 @@ static void queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req) list_add_tail(&req->intr_entry, &fiq->interrupts); wake_up_locked(&fiq->waitq); } - spin_unlock(&fiq->waitq.lock); + spin_unlock_irq(&fiq->waitq.lock); kill_fasync(&fiq->fasync, SIGIO, POLL_IN); }
@@ -535,9 +535,9 @@ static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) struct fuse_iqueue *fiq = &fc->iq;
BUG_ON(test_bit(FR_BACKGROUND, &req->flags)); - spin_lock(&fiq->waitq.lock); + spin_lock_irq(&fiq->waitq.lock); if (!fiq->connected) { - spin_unlock(&fiq->waitq.lock); + spin_unlock_irq(&fiq->waitq.lock); req->out.h.error = -ENOTCONN; } else { req->in.h.unique = fuse_get_unique(fiq); @@ -545,7 +545,7 @@ static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) /* acquire extra reference, since request is still needed after request_end() */ __fuse_get_request(req); - spin_unlock(&fiq->waitq.lock); + spin_unlock_irq(&fiq->waitq.lock);
request_wait_answer(fc, req); /* Pairs with smp_wmb() in request_end() */ @@ -676,12 +676,12 @@ static int fuse_request_send_notify_reply(struct fuse_conn *fc,
__clear_bit(FR_ISREPLY, &req->flags); req->in.h.unique = unique; - spin_lock(&fiq->waitq.lock); + spin_lock_irq(&fiq->waitq.lock); if (fiq->connected) { queue_request(fiq, req); err = 0; } - spin_unlock(&fiq->waitq.lock); + spin_unlock_irq(&fiq->waitq.lock);
return err; }