Loading fs/buffer.c +45 −2 Original line number Original line Diff line number Diff line Loading @@ -1455,12 +1455,48 @@ static bool has_bh_in_lru(int cpu, void *dummy) return 0; return 0; } } static void __evict_bh_lru(void *arg) { struct bh_lru *b = &get_cpu_var(bh_lrus); struct buffer_head *bh = arg; int i; for (i = 0; i < BH_LRU_SIZE; i++) { if (b->bhs[i] == bh) { brelse(b->bhs[i]); b->bhs[i] = NULL; goto out; } } out: put_cpu_var(bh_lrus); } static bool bh_exists_in_lru(int cpu, void *arg) { struct bh_lru *b = per_cpu_ptr(&bh_lrus, cpu); struct buffer_head *bh = arg; int i; for (i = 0; i < BH_LRU_SIZE; i++) { if (b->bhs[i] == bh) return 1; } return 0; } void invalidate_bh_lrus(void) void invalidate_bh_lrus(void) { { on_each_cpu_cond(has_bh_in_lru, invalidate_bh_lru, NULL, 1, GFP_KERNEL); on_each_cpu_cond(has_bh_in_lru, invalidate_bh_lru, NULL, 1, GFP_KERNEL); } } EXPORT_SYMBOL_GPL(invalidate_bh_lrus); EXPORT_SYMBOL_GPL(invalidate_bh_lrus); static void evict_bh_lrus(struct buffer_head *bh) { on_each_cpu_cond(bh_exists_in_lru, __evict_bh_lru, bh, 1, GFP_ATOMIC); } void set_bh_page(struct buffer_head *bh, void set_bh_page(struct buffer_head *bh, struct page *page, unsigned long offset) struct page *page, unsigned long offset) { { Loading Loading @@ -3205,8 +3241,15 @@ drop_buffers(struct page *page, struct buffer_head **buffers_to_free) do { do { if (buffer_write_io_error(bh) && page->mapping) if (buffer_write_io_error(bh) && page->mapping) set_bit(AS_EIO, &page->mapping->flags); set_bit(AS_EIO, &page->mapping->flags); if (buffer_busy(bh)) { /* * Check if the busy failure was due to an * outstanding LRU reference */ evict_bh_lrus(bh); if (buffer_busy(bh)) if (buffer_busy(bh)) goto failed; goto failed; } bh = bh->b_this_page; bh = bh->b_this_page; } while (bh != head); } while (bh != head); Loading Loading
fs/buffer.c +45 −2 Original line number Original line Diff line number Diff line Loading @@ -1455,12 +1455,48 @@ static bool has_bh_in_lru(int cpu, void *dummy) return 0; return 0; } } static void __evict_bh_lru(void *arg) { struct bh_lru *b = &get_cpu_var(bh_lrus); struct buffer_head *bh = arg; int i; for (i = 0; i < BH_LRU_SIZE; i++) { if (b->bhs[i] == bh) { brelse(b->bhs[i]); b->bhs[i] = NULL; goto out; } } out: put_cpu_var(bh_lrus); } static bool bh_exists_in_lru(int cpu, void *arg) { struct bh_lru *b = per_cpu_ptr(&bh_lrus, cpu); struct buffer_head *bh = arg; int i; for (i = 0; i < BH_LRU_SIZE; i++) { if (b->bhs[i] == bh) return 1; } return 0; } void invalidate_bh_lrus(void) void invalidate_bh_lrus(void) { { on_each_cpu_cond(has_bh_in_lru, invalidate_bh_lru, NULL, 1, GFP_KERNEL); on_each_cpu_cond(has_bh_in_lru, invalidate_bh_lru, NULL, 1, GFP_KERNEL); } } EXPORT_SYMBOL_GPL(invalidate_bh_lrus); EXPORT_SYMBOL_GPL(invalidate_bh_lrus); static void evict_bh_lrus(struct buffer_head *bh) { on_each_cpu_cond(bh_exists_in_lru, __evict_bh_lru, bh, 1, GFP_ATOMIC); } void set_bh_page(struct buffer_head *bh, void set_bh_page(struct buffer_head *bh, struct page *page, unsigned long offset) struct page *page, unsigned long offset) { { Loading Loading @@ -3205,8 +3241,15 @@ drop_buffers(struct page *page, struct buffer_head **buffers_to_free) do { do { if (buffer_write_io_error(bh) && page->mapping) if (buffer_write_io_error(bh) && page->mapping) set_bit(AS_EIO, &page->mapping->flags); set_bit(AS_EIO, &page->mapping->flags); if (buffer_busy(bh)) { /* * Check if the busy failure was due to an * outstanding LRU reference */ evict_bh_lrus(bh); if (buffer_busy(bh)) if (buffer_busy(bh)) goto failed; goto failed; } bh = bh->b_this_page; bh = bh->b_this_page; } while (bh != head); } while (bh != head); Loading