|
@@ -1483,16 +1483,27 @@ EXPORT_SYMBOL(set_bh_page);
|
|
|
/*
|
|
|
* Called when truncating a buffer on a page completely.
|
|
|
*/
|
|
|
+
|
|
|
+/* Bits that are cleared during an invalidate */
|
|
|
+#define BUFFER_FLAGS_DISCARD \
|
|
|
+ (1 << BH_Mapped | 1 << BH_New | 1 << BH_Req | \
|
|
|
+ 1 << BH_Delay | 1 << BH_Unwritten)
|
|
|
+
|
|
|
static void discard_buffer(struct buffer_head * bh)
|
|
|
{
|
|
|
+ unsigned long b_state, b_state_old;
|
|
|
+
|
|
|
lock_buffer(bh);
|
|
|
clear_buffer_dirty(bh);
|
|
|
bh->b_bdev = NULL;
|
|
|
- clear_buffer_mapped(bh);
|
|
|
- clear_buffer_req(bh);
|
|
|
- clear_buffer_new(bh);
|
|
|
- clear_buffer_delay(bh);
|
|
|
- clear_buffer_unwritten(bh);
|
|
|
+ b_state = bh->b_state;
|
|
|
+ for (;;) {
|
|
|
+ b_state_old = cmpxchg(&bh->b_state, b_state,
|
|
|
+ (b_state & ~BUFFER_FLAGS_DISCARD));
|
|
|
+ if (b_state_old == b_state)
|
|
|
+ break;
|
|
|
+ b_state = b_state_old;
|
|
|
+ }
|
|
|
unlock_buffer(bh);
|
|
|
}
|
|
|
|