fuse: Optimize request_end() by not taking fiq->waitq.lock
We take global fiq->waitq.lock every time, when we are in this function, but interrupted requests are just small subset of all requests. This patch optimizes request_end() and makes it to take the lock when it's really needed. queue_interrupt() needs small change for that. After req is linked to interrupt list, we do smp_mb() and check for FR_FINISHED again. In case of FR_FINISHED bit has appeared, we remove req and leave the function: Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
Родитель
8da6e91832
Коммит
217316a601
|
@ -431,10 +431,16 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
|
|||
|
||||
if (test_and_set_bit(FR_FINISHED, &req->flags))
|
||||
goto put_request;
|
||||
|
||||
spin_lock(&fiq->waitq.lock);
|
||||
list_del_init(&req->intr_entry);
|
||||
spin_unlock(&fiq->waitq.lock);
|
||||
/*
|
||||
* test_and_set_bit() implies smp_mb() between bit
|
||||
* changing and below intr_entry check. Pairs with
|
||||
* smp_mb() from queue_interrupt().
|
||||
*/
|
||||
if (!list_empty(&req->intr_entry)) {
|
||||
spin_lock(&fiq->waitq.lock);
|
||||
list_del_init(&req->intr_entry);
|
||||
spin_unlock(&fiq->waitq.lock);
|
||||
}
|
||||
WARN_ON(test_bit(FR_PENDING, &req->flags));
|
||||
WARN_ON(test_bit(FR_SENT, &req->flags));
|
||||
if (test_bit(FR_BACKGROUND, &req->flags)) {
|
||||
|
@ -473,12 +479,18 @@ put_request:
|
|||
static void queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req)
|
||||
{
|
||||
spin_lock(&fiq->waitq.lock);
|
||||
if (test_bit(FR_FINISHED, &req->flags)) {
|
||||
spin_unlock(&fiq->waitq.lock);
|
||||
return;
|
||||
}
|
||||
if (list_empty(&req->intr_entry)) {
|
||||
list_add_tail(&req->intr_entry, &fiq->interrupts);
|
||||
/*
|
||||
* Pairs with smp_mb() implied by test_and_set_bit()
|
||||
* from request_end().
|
||||
*/
|
||||
smp_mb();
|
||||
if (test_bit(FR_FINISHED, &req->flags)) {
|
||||
list_del_init(&req->intr_entry);
|
||||
spin_unlock(&fiq->waitq.lock);
|
||||
return;
|
||||
}
|
||||
wake_up_locked(&fiq->waitq);
|
||||
kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче