On Tue, May 13, 2014 at 03:29:00PM -0700, Andrew Morton wrote: > On Tue, 13 May 2014 10:45:48 +0100 Mel Gorman <mgorman@xxxxxxx> wrote: > > > Discarding buffers uses a bunch of atomic operations when discarding buffers > > because ...... I can't think of a reason. Use a cmpxchg loop to clear all the > > necessary flags. In most (all?) cases this will be a single atomic operations. > > > > --- a/fs/buffer.c > > +++ b/fs/buffer.c > > @@ -1485,14 +1485,18 @@ EXPORT_SYMBOL(set_bh_page); > > */ > > 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); > > } > > > > --- a/include/linux/buffer_head.h > > +++ b/include/linux/buffer_head.h > > @@ -77,6 +77,11 @@ struct buffer_head { > > atomic_t b_count; /* users using this buffer_head */ > > }; > > > > +/* 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) > > + > > There isn't much point in having this in the header file is there? > No, it's not necessary. I was just keeping it with the definition of the flags. Your fix on top looks fine. -- Mel Gorman SUSE Labs -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html