- alloc_buffer_head() should take the allocation mode as an arg, and not assume. - Use __GFP_NOFAIL in JBD's call to alloc_buffer_head(). - Remove all the retry code from jbd_kmalloc() - do it via page allocator controls. 25-akpm/fs/buffer.c | 8 ++++---- 25-akpm/fs/jbd/journal.c | 33 +++------------------------------ 25-akpm/include/linux/buffer_head.h | 2 +- 3 files changed, 8 insertions(+), 35 deletions(-) diff -puN fs/buffer.c~alloc_buffer_head-take-gfp fs/buffer.c --- 25/fs/buffer.c~alloc_buffer_head-take-gfp Thu Apr 17 15:24:38 2003 +++ 25-akpm/fs/buffer.c Thu Apr 17 15:24:38 2003 @@ -998,7 +998,7 @@ try_again: head = NULL; offset = PAGE_SIZE; while ((offset -= size) >= 0) { - bh = alloc_buffer_head(); + bh = alloc_buffer_head(GFP_NOFS); if (!bh) goto no_grow; @@ -2349,7 +2349,7 @@ int nobh_prepare_write(struct page *page if (buffer_uptodate(&map_bh)) continue; /* reiserfs does this */ if (block_start < from || block_end > to) { - struct buffer_head *bh = alloc_buffer_head(); + struct buffer_head *bh = alloc_buffer_head(GFP_NOFS); if (!bh) { ret = -ENOMEM; @@ -2908,9 +2908,9 @@ static void recalc_bh_state(void) buffer_heads_over_limit = (tot > max_buffer_heads); } -struct buffer_head *alloc_buffer_head(void) +struct buffer_head *alloc_buffer_head(int gfp_flags) { - struct buffer_head *ret = kmem_cache_alloc(bh_cachep, GFP_NOFS); + struct buffer_head *ret = kmem_cache_alloc(bh_cachep, gfp_flags); if (ret) { preempt_disable(); __get_cpu_var(bh_accounting).nr++; diff -puN fs/jbd/journal.c~alloc_buffer_head-take-gfp fs/jbd/journal.c --- 25/fs/jbd/journal.c~alloc_buffer_head-take-gfp Thu Apr 17 15:24:38 2003 +++ 25-akpm/fs/jbd/journal.c Thu Apr 17 15:26:51 2003 @@ -457,14 +457,8 @@ int journal_write_metadata_buffer(transa /* * Right, time to make up the new buffer_head. */ - do { - new_bh = alloc_buffer_head(); - if (!new_bh) { - printk (KERN_NOTICE "%s: ENOMEM at alloc_buffer_head, " - "trying again.\n", __FUNCTION__); - yield(); - } - } while (!new_bh); + new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL); + /* keep subsequent assertions sane */ new_bh->b_state = 0; init_buffer(new_bh, NULL, NULL); @@ -1613,28 +1607,7 @@ void shrink_journal_memory(void) */ void * __jbd_kmalloc (const char *where, size_t size, int flags, int retry) { - void *p; - static unsigned long last_warning; - - while (1) { - p = kmalloc(size, flags); - if (p) - return p; - if (!retry) - return NULL; - /* Log every retry for debugging. Also log them to the - * syslog, but do rate-limiting on the non-debugging - * messages. */ - jbd_debug(1, "ENOMEM in %s, retrying.\n", where); - - if (time_after(jiffies, last_warning + 5*HZ)) { - printk(KERN_NOTICE - "ENOMEM in %s, retrying.\n", where); - last_warning = jiffies; - } - - yield(); - } + return kmalloc(size, flags | (retry ? __GFP_NOFAIL : 0)); } /* diff -puN include/linux/buffer_head.h~alloc_buffer_head-take-gfp include/linux/buffer_head.h --- 25/include/linux/buffer_head.h~alloc_buffer_head-take-gfp Thu Apr 17 15:24:38 2003 +++ 25-akpm/include/linux/buffer_head.h Thu Apr 17 15:24:38 2003 @@ -172,7 +172,7 @@ struct buffer_head * __getblk(struct blo void __brelse(struct buffer_head *); void __bforget(struct buffer_head *); struct buffer_head *__bread(struct block_device *, sector_t block, int size); -struct buffer_head *alloc_buffer_head(void); +struct buffer_head *alloc_buffer_head(int gfp_flags); void free_buffer_head(struct buffer_head * bh); void FASTCALL(unlock_buffer(struct buffer_head *bh)); void ll_rw_block(int, int, struct buffer_head * bh[]); _