lkml.org 
[lkml]   [2010]   [Aug]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 3/5] fs: add nofail variant of alloc_buffer_head
    Add alloc_buffer_head_nofail().  This function is equivalent to
    alloc_buffer_head(), except that it will never return NULL and instead
    loop forever trying to allocate memory.

    If the first allocation attempt fails, a warning will be emitted,
    including a call trace. Subsequent failures will suppress this warning.

    This was added as a helper function for documentation and auditability.
    No future callers should be added.

    Signed-off-by: David Rientjes <rientjes@google.com>
    ---
    fs/buffer.c | 18 ++++++++++++++++++
    fs/gfs2/log.c | 2 +-
    fs/jbd/journal.c | 2 +-
    include/linux/buffer_head.h | 1 +
    4 files changed, 21 insertions(+), 2 deletions(-)

    diff --git a/fs/buffer.c b/fs/buffer.c
    --- a/fs/buffer.c
    +++ b/fs/buffer.c
    @@ -3238,6 +3238,24 @@ struct buffer_head *alloc_buffer_head(gfp_t gfp_flags)
    }
    EXPORT_SYMBOL(alloc_buffer_head);

    +/*
    + * NOTE: no new callers of this function should be implemented!
    + * All memory allocations should be failable whenever possible.
    + */
    +struct buffer_head *alloc_buffer_head_nofail(gfp_t gfp_flags)
    +{
    + struct buffer_head *ret;
    +
    + for (;;) {
    + ret = alloc_buffer_head(gfp_flags);
    + if (ret)
    + return ret;
    + WARN_ONCE(1, "Out of memory; no fallback implemented "
    + "(flags=0x%x)\n",
    + gfp_flags);
    + }
    +}
    +
    void free_buffer_head(struct buffer_head *bh)
    {
    BUG_ON(!list_empty(&bh->b_assoc_buffers));
    diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
    --- a/fs/gfs2/log.c
    +++ b/fs/gfs2/log.c
    @@ -523,7 +523,7 @@ struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp,
    u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head);
    struct buffer_head *bh;

    - bh = alloc_buffer_head(GFP_NOFS | __GFP_NOFAIL);
    + bh = alloc_buffer_head_nofail(GFP_NOFS);
    atomic_set(&bh->b_count, 1);
    bh->b_state = (1 << BH_Mapped) | (1 << BH_Uptodate) | (1 << BH_Lock);
    set_bh_page(bh, real->b_page, bh_offset(real));
    diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
    --- a/fs/jbd/journal.c
    +++ b/fs/jbd/journal.c
    @@ -301,7 +301,7 @@ int journal_write_metadata_buffer(transaction_t *transaction,
    */
    J_ASSERT_BH(bh_in, buffer_jbddirty(bh_in));

    - new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL);
    + new_bh = alloc_buffer_head_nofail(GFP_NOFS);
    /* keep subsequent assertions sane */
    new_bh->b_state = 0;
    init_buffer(new_bh, NULL, NULL);
    diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
    --- a/include/linux/buffer_head.h
    +++ b/include/linux/buffer_head.h
    @@ -176,6 +176,7 @@ void __breadahead(struct block_device *, sector_t block, unsigned int size);
    struct buffer_head *__bread(struct block_device *, sector_t block, unsigned size);
    void invalidate_bh_lrus(void);
    struct buffer_head *alloc_buffer_head(gfp_t gfp_flags);
    +struct buffer_head *alloc_buffer_head_nofail(gfp_t gfp_flags);
    void free_buffer_head(struct buffer_head * bh);
    void unlock_buffer(struct buffer_head *bh);
    void __lock_buffer(struct buffer_head *bh);

    \
     
     \ /
      Last update: 2010-08-24 12:53    [W:0.027 / U:29.720 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site