Re: [PATCH] exclusive wakeup for lock_buffer

Marcelo Tosatti (marcelo@conectiva.com.br)
Mon, 19 Feb 2001 22:51:36 -0200 (BRST)


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/