diff options
Diffstat (limited to 'fs/buffer.c')
| -rw-r--r-- | fs/buffer.c | 93 | 
1 files changed, 53 insertions, 40 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 4d7433534f5..eba6e4f621c 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -77,7 +77,7 @@ EXPORT_SYMBOL(__lock_buffer);  void unlock_buffer(struct buffer_head *bh)  {  	clear_bit_unlock(BH_Lock, &bh->b_state); -	smp_mb__after_clear_bit(); +	smp_mb__after_atomic();  	wake_up_bit(&bh->b_state, BH_Lock);  }  EXPORT_SYMBOL(unlock_buffer); @@ -227,7 +227,7 @@ __find_get_block_slow(struct block_device *bdev, sector_t block)  	int all_mapped = 1;  	index = block >> (PAGE_CACHE_SHIFT - bd_inode->i_blkbits); -	page = find_get_page(bd_mapping, index); +	page = find_get_page_flags(bd_mapping, index, FGP_ACCESSED);  	if (!page)  		goto out; @@ -654,14 +654,16 @@ EXPORT_SYMBOL(mark_buffer_dirty_inode);  static void __set_page_dirty(struct page *page,  		struct address_space *mapping, int warn)  { -	spin_lock_irq(&mapping->tree_lock); +	unsigned long flags; + +	spin_lock_irqsave(&mapping->tree_lock, flags);  	if (page->mapping) {	/* Race with truncate? */  		WARN_ON_ONCE(warn && !PageUptodate(page));  		account_page_dirtied(page, mapping);  		radix_tree_tag_set(&mapping->page_tree,  				page_index(page), PAGECACHE_TAG_DIRTY);  	} -	spin_unlock_irq(&mapping->tree_lock); +	spin_unlock_irqrestore(&mapping->tree_lock, flags);  	__mark_inode_dirty(mapping->host, I_DIRTY_PAGES);  } @@ -1005,9 +1007,19 @@ grow_dev_page(struct block_device *bdev, sector_t block,  	struct buffer_head *bh;  	sector_t end_block;  	int ret = 0;		/* Will call free_more_memory() */ +	gfp_t gfp_mask; + +	gfp_mask = mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS; +	gfp_mask |= __GFP_MOVABLE; +	/* +	 * XXX: __getblk_slow() can not really deal with failure and +	 * will endlessly loop on improvised global reclaim.  Prefer +	 * looping in the allocator rather than here, at least that +	 * code knows what it's doing. +	 */ +	gfp_mask |= __GFP_NOFAIL; -	page = find_or_create_page(inode->i_mapping, index, -		(mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE); +	page = find_or_create_page(inode->i_mapping, index, gfp_mask);  	if (!page)  		return ret; @@ -1302,7 +1314,7 @@ static void bh_lru_install(struct buffer_head *bh)  		}  		while (out < BH_LRU_SIZE)  			bhs[out++] = NULL; -		memcpy(__this_cpu_ptr(&bh_lrus.bhs), bhs, sizeof(bhs)); +		memcpy(this_cpu_ptr(&bh_lrus.bhs), bhs, sizeof(bhs));  	}  	bh_lru_unlock(); @@ -1354,12 +1366,13 @@ __find_get_block(struct block_device *bdev, sector_t block, unsigned size)  	struct buffer_head *bh = lookup_bh_lru(bdev, block, size);  	if (bh == NULL) { +		/* __find_get_block_slow will mark the page accessed */  		bh = __find_get_block_slow(bdev, block);  		if (bh)  			bh_lru_install(bh); -	} -	if (bh) +	} else  		touch_buffer(bh); +  	return bh;  }  EXPORT_SYMBOL(__find_get_block); @@ -1471,16 +1484,27 @@ EXPORT_SYMBOL(set_bh_page);  /*   * Called when truncating a buffer on a page completely.   */ + +/* 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) +  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);  } @@ -2102,8 +2126,8 @@ EXPORT_SYMBOL(generic_write_end);   * Returns true if all buffers which correspond to a file portion   * we want to read are uptodate.   */ -int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc, -					unsigned long from) +int block_is_partially_uptodate(struct page *page, unsigned long from, +					unsigned long count)  {  	unsigned block_start, block_end, blocksize;  	unsigned to; @@ -2115,7 +2139,7 @@ int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc,  	head = page_buffers(page);  	blocksize = head->b_size; -	to = min_t(unsigned, PAGE_CACHE_SIZE - from, desc->count); +	to = min_t(unsigned, PAGE_CACHE_SIZE - from, count);  	to = from + to;  	if (from < blocksize && to > PAGE_CACHE_SIZE - blocksize)  		return 0; @@ -2867,10 +2891,9 @@ EXPORT_SYMBOL(block_truncate_page);  /*   * The generic ->writepage function for buffer-backed address_spaces - * this form passes in the end_io handler used to finish the IO.   */ -int block_write_full_page_endio(struct page *page, get_block_t *get_block, -			struct writeback_control *wbc, bh_end_io_t *handler) +int block_write_full_page(struct page *page, get_block_t *get_block, +			struct writeback_control *wbc)  {  	struct inode * const inode = page->mapping->host;  	loff_t i_size = i_size_read(inode); @@ -2880,7 +2903,7 @@ int block_write_full_page_endio(struct page *page, get_block_t *get_block,  	/* Is the page fully inside i_size? */  	if (page->index < end_index)  		return __block_write_full_page(inode, page, get_block, wbc, -					       handler); +					       end_buffer_async_write);  	/* Is the page fully outside i_size? (truncate in progress) */  	offset = i_size & (PAGE_CACHE_SIZE-1); @@ -2903,18 +2926,8 @@ int block_write_full_page_endio(struct page *page, get_block_t *get_block,  	 * writes to that region are not written out to the file."  	 */  	zero_user_segment(page, offset, PAGE_CACHE_SIZE); -	return __block_write_full_page(inode, page, get_block, wbc, handler); -} -EXPORT_SYMBOL(block_write_full_page_endio); - -/* - * The generic ->writepage function for buffer-backed address_spaces - */ -int block_write_full_page(struct page *page, get_block_t *get_block, -			struct writeback_control *wbc) -{ -	return block_write_full_page_endio(page, get_block, wbc, -					   end_buffer_async_write); +	return __block_write_full_page(inode, page, get_block, wbc, +							end_buffer_async_write);  }  EXPORT_SYMBOL(block_write_full_page); @@ -2972,11 +2985,11 @@ static void guard_bh_eod(int rw, struct bio *bio, struct buffer_head *bh)  	 * let it through, and the IO layer will turn it into  	 * an EIO.  	 */ -	if (unlikely(bio->bi_sector >= maxsector)) +	if (unlikely(bio->bi_iter.bi_sector >= maxsector))  		return; -	maxsector -= bio->bi_sector; -	bytes = bio->bi_size; +	maxsector -= bio->bi_iter.bi_sector; +	bytes = bio->bi_iter.bi_size;  	if (likely((bytes >> 9) <= maxsector))  		return; @@ -2984,7 +2997,7 @@ static void guard_bh_eod(int rw, struct bio *bio, struct buffer_head *bh)  	bytes = maxsector << 9;  	/* Truncate the bio.. */ -	bio->bi_size = bytes; +	bio->bi_iter.bi_size = bytes;  	bio->bi_io_vec[0].bv_len = bytes;  	/* ..and clear the end of the buffer for reads */ @@ -3019,14 +3032,14 @@ int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags)  	 */  	bio = bio_alloc(GFP_NOIO, 1); -	bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9); +	bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9);  	bio->bi_bdev = bh->b_bdev;  	bio->bi_io_vec[0].bv_page = bh->b_page;  	bio->bi_io_vec[0].bv_len = bh->b_size;  	bio->bi_io_vec[0].bv_offset = bh_offset(bh);  	bio->bi_vcnt = 1; -	bio->bi_size = bh->b_size; +	bio->bi_iter.bi_size = bh->b_size;  	bio->bi_end_io = end_bio_bh_io_sync;  	bio->bi_private = bh; @@ -3076,7 +3089,7 @@ EXPORT_SYMBOL(submit_bh);   * until the buffer gets unlocked).   *   * ll_rw_block sets b_end_io to simple completion handler that marks - * the buffer up-to-date (if approriate), unlocks the buffer and wakes + * the buffer up-to-date (if appropriate), unlocks the buffer and wakes   * any waiters.    *   * All of the buffers must be for the same device, and must also be a  | 
