Re: [RFC] set_blocksize() oddity.

MOLNAR Ingo (mingo@valerie.inf.elte.hu)
Fri, 9 Apr 1999 17:23:00 +0200 (MET DST)


On Fri, 9 Apr 1999, Alexander Viro wrote:

> set_blocksize() seems to do really odd thing:
> suppose you have clean buffer (b_count==0, all nice and dandy) with
> b_size==foo.
> set_blocksize(dev, bar) will leave it on a clean list and will call
> remove_from_hash_queue() on it.
> set_blocksize(dev,foo) now. Nothing happens with our buffer.
> set_blocksize(dev,bar) again and there we go -
> remove_from_hash_queue() is called again.
>
> Repeat until the complete satisfaction (nr_hashed_buffers going negative ;-/)
>
> Wouldn't remove_from_queues() be the right thing here?

yep, the RAID patch has been doing this for some time:

--- linux/fs/buffer.c.orig Tue Apr 6 16:35:10 1999
+++ linux/fs/buffer.c Wed Apr 7 16:08:12 1999
@@ -663,9 +663,16 @@
continue;
if (bh->b_size == size)
continue;
- bhnext->b_count++;
+ /*
+ * We try to completely drop alien-size
+ * buffers. subtle: we have to protect
+ * bhnext across the wait and across the
+ * try_to_free... call because we have
+ * to keep the 'way forward' on the list.
+ */
+ if (bhnext)
+ bhnext->b_count++;
wait_on_buffer(bh);
- bhnext->b_count--;
if (bh->b_dev == dev && bh->b_size != size) {
clear_bit(BH_Dirty, &bh->b_state);
clear_bit(BH_Uptodate, &bh->b_state);
@@ -673,11 +680,57 @@
bh->b_flushtime = 0;
}
remove_from_hash_queue(bh);
+
+ /*
+ * lets be mega-conservative about what to free:
+ */
+ if ( (bh->b_dev != dev) ||
+ (bh->b_size == size) ||
+ bh->b_count ||
+ buffer_protected(bh) ||
+ buffer_dirty(bh) ||
+ buffer_locked(bh) ||
+ waitqueue_active(&bh->b_wait)) {
+ if (bhnext)
+ bhnext->b_count--;
+ continue;
+ }
+ try_to_free_buffers(buffer_page(bh));
+ if (bhnext)
+ bhnext->b_count--;
}
}
}

-- mingo

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/