Re: [PATCH] exclusive wakeup for lock_buffer

From: Marcelo Tosatti (marcelo@conectiva.com.br)
Date: Mon Feb 19 2001 - 19:51:36 EST


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/



This archive was generated by hypermail 2b29 : Fri Feb 23 2001 - 21:00:21 EST