[Cluster-devel] [PATCH 2/2] gfs2: Extended attribute readahead optimization
Andreas Gruenbacher
agruenba at redhat.com
Thu Nov 12 15:33:12 UTC 2015
On Thu, Nov 12, 2015 at 2:44 PM, Steven Whitehouse <swhiteho at redhat.com> wrote:
> Hi,
>
>
> On 01/11/15 19:02, Andreas Gruenbacher wrote:
>>
>> Instead of submitting separate bio for the inode and its extended
>> attributes, submit a single bio for both when possible. The entire
>> request becomes a normal read, not a readahead.
>>
>> To keep track of the buffer heads that make up the bio, we allocate
>> temporary buffer head arrays: in the endio handler, it would also be
>> possible to compute the buffer head block numbers from the bio and to
>> grab the buffer heads with gfs2_getbuf, but the code would become even
>> messier.
>> ---
>> fs/gfs2/meta_io.c | 94
>> ++++++++++++++++++++++++++++++++++++++++++++-----------
>> 1 file changed, 76 insertions(+), 18 deletions(-)
>>
>> diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
>> index 0f24828..e650127 100644
>> --- a/fs/gfs2/meta_io.c
>> +++ b/fs/gfs2/meta_io.c
>> @@ -187,19 +187,63 @@ struct buffer_head *gfs2_meta_new(struct gfs2_glock
>> *gl, u64 blkno)
>> return bh;
>> }
>> -static void gfs2_meta_readahead(struct gfs2_glock *gl, u64 blkno)
>> +struct gfs2_meta_read {
>> + int num;
>> + struct buffer_head *bhs[0];
>> +};
>> +
>> +static void gfs2_meta_read_endio(struct bio *bio) {
>> + struct gfs2_meta_read *r = bio->bi_private;
>> + int i;
>> +
>> + for (i = 0; i < r->num; i++) {
>> + struct buffer_head *bh = r->bhs[i];
>> +
>> + if (unlikely(bio_flagged(bio, BIO_QUIET)))
>> + set_bit(BH_Quiet, &bh->b_state);
>> +
>> + bh->b_end_io(bh, !bio->bi_error);
>> + }
>> + bio_put(bio);
>> + kfree(r);
>> +}
>> +
>> +/*
>> + * (See submit_bh_wbc.)
>> + */
>> +static void gfs2_submit_bhs(int rw, struct buffer_head *bhs[], int num)
>> {
>> - struct buffer_head *bh;
>> + struct gfs2_meta_read *r;
>> + struct buffer_head *bh = bhs[0];
>> + struct bio *bio;
>> + int i;
>> - bh = gfs2_getbuf(gl, blkno, 1);
>> - lock_buffer(bh);
>> - if (buffer_uptodate(bh)) {
>> - unlock_buffer(bh);
>> - brelse(bh);
>> + if (!num)
>> + return;
>> +
>> + if (num == 1) {
>> + bh->b_end_io = end_buffer_read_sync;
>> + submit_bh(rw, bh);
>> return;
>> }
>> - bh->b_end_io = end_buffer_read_sync;
>> - submit_bh(READA | REQ_META | REQ_PRIO, bh);
>> +
>> + r = kmalloc(sizeof(*r) + num * sizeof(r->bhs[0]),
>> + GFP_NOIO | __GFP_NOFAIL);
>
> Can we avoid doing this I wonder? I would like to avoid adding GFP_NOFAIL
> allocations, and I think it should be possible to figure out where the
> buffers are using the bio itself (i.e. iterating over it, similar to
> gfs2_end_log_write() in lops.c) so that we don't need to allocate this
> additional memory.
Yes, that's better than going through gfs2_getbuf() again. I'll change that.
Thanks,
Andreas
More information about the Cluster-devel
mailing list