Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id ; Mon, 19 Feb 2001 21:40:45 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id ; Mon, 19 Feb 2001 21:40:36 -0500 Received: from perninha.conectiva.com.br ([200.250.58.156]:16901 "EHLO perninha.conectiva.com.br") by vger.kernel.org with ESMTP id ; Mon, 19 Feb 2001 21:40:19 -0500 Date: Mon, 19 Feb 2001 22:51:36 -0200 (BRST) From: Marcelo Tosatti To: Linus Torvalds cc: lkml Subject: Re: [PATCH] exclusive wakeup for lock_buffer In-Reply-To: Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org On Mon, 19 Feb 2001, Linus Torvalds wrote: > > > On Mon, 19 Feb 2001, Marcelo Tosatti wrote: > > > > The following patch makes lock_buffer() use the exclusive wakeup scheme > > added in 2.3. > > Ugh, This is horrible. > > You should NOT have one function that does two completely different things > depending on a flag. That way lies madness and bad coding habits. > > Just do two different functions - make one be "__wait_on_buffer()", and > the other be "__lock_buffer()". See how the page functions work. > > Linus Ok. --- linux/include/linux/locks.h.orig Mon Feb 19 23:16:50 2001 +++ linux/include/linux/locks.h Mon Feb 19 23:21:48 2001 @@ -13,6 +13,7 @@ * lock buffers. */ extern void __wait_on_buffer(struct buffer_head *); +extern void __lock_buffer(struct buffer_head *); extern inline void wait_on_buffer(struct buffer_head * bh) { @@ -22,8 +23,8 @@ extern inline void lock_buffer(struct buffer_head * bh) { - while (test_and_set_bit(BH_Lock, &bh->b_state)) - __wait_on_buffer(bh); + if (test_and_set_bit(BH_Lock, &bh->b_state)) + __lock_on_buffer(bh); } extern inline void unlock_buffer(struct buffer_head *bh) --- linux/fs/buffer.c.orig Mon Feb 19 23:09:31 2001 +++ linux/fs/buffer.c Mon Feb 19 23:31:25 2001 @@ -161,6 +161,30 @@ atomic_dec(&bh->b_count); } +void __lock_on_buffer(struct buffer_head * bh) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + + atomic_inc(&bh->b_count); + add_wait_queue_exclusive(&bh->b_wait, &wait); + for(;;) { + set_task_state(tsk, TASK_UNINTERRUPTIBLE); + if (test_bit(BH_Lock, &bh->b_state)) { + run_task_queue(&tq_disk); + schedule(); + continue; + } + + if (!test_and_set_bit(BH_Lock, &bh->b_state)) + break; + } + tsk->state = TASK_RUNNING; + remove_wait_queue(&bh->b_wait, &wait); + atomic_dec(&bh->b_count); +} + + /* Call sync_buffers with wait!=0 to ensure that the call does not * return until all buffer writes have completed. Sync() may return * before the writes have finished; fsync() may not. - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/