Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 217316a6 authored by Kirill Tkhai's avatar Kirill Tkhai Committed by Miklos Szeredi
Browse files

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: default avatarKirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 8da6e918
Loading
Loading
Loading
Loading
+20 −8
Original line number Diff line number Diff line
@@ -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;

	/*
	 * 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 @@ 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);
	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;
		}
	if (list_empty(&req->intr_entry)) {
		list_add_tail(&req->intr_entry, &fiq->interrupts);
		wake_up_locked(&fiq->waitq);
		kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
	}