ext4: fold __mpage_da_writepage() into write_cache_pages_da()
Fold the __mpage_da_writepage() function into write_cache_pages_da(). This will give us opportunities to clean up and simplify the resulting code. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
This commit is contained in:
		
					parent
					
						
							
								6fd7a46781
							
						
					
				
			
			
				commit
				
					
						8eb9e5ce21
					
				
			
		
					 1 changed files with 91 additions and 115 deletions
				
			
		
							
								
								
									
										206
									
								
								fs/ext4/inode.c
									
										
									
									
									
								
							
							
						
						
									
										206
									
								
								fs/ext4/inode.c
									
										
									
									
									
								
							| 
						 | 
					@ -2437,102 +2437,6 @@ static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh)
 | 
				
			||||||
	return (buffer_delay(bh) || buffer_unwritten(bh)) && buffer_dirty(bh);
 | 
						return (buffer_delay(bh) || buffer_unwritten(bh)) && buffer_dirty(bh);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * __mpage_da_writepage - finds extent of pages and blocks
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @page: page to consider
 | 
					 | 
				
			||||||
 * @wbc: not used, we just follow rules
 | 
					 | 
				
			||||||
 * @data: context
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * The function finds extents of pages and scan them for all blocks.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static int __mpage_da_writepage(struct page *page,
 | 
					 | 
				
			||||||
				struct writeback_control *wbc,
 | 
					 | 
				
			||||||
				struct mpage_da_data *mpd)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct inode *inode = mpd->inode;
 | 
					 | 
				
			||||||
	struct buffer_head *bh, *head;
 | 
					 | 
				
			||||||
	sector_t logical;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * Can we merge this page to current extent?
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	if (mpd->next_page != page->index) {
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * Nope, we can't. So, we map non-allocated blocks
 | 
					 | 
				
			||||||
		 * and start IO on them
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		if (mpd->next_page != mpd->first_page) {
 | 
					 | 
				
			||||||
			mpage_da_map_and_submit(mpd);
 | 
					 | 
				
			||||||
			/*
 | 
					 | 
				
			||||||
			 * skip rest of the page in the page_vec
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			redirty_page_for_writepage(wbc, page);
 | 
					 | 
				
			||||||
			unlock_page(page);
 | 
					 | 
				
			||||||
			return MPAGE_DA_EXTENT_TAIL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * Start next extent of pages ...
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		mpd->first_page = page->index;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * ... and blocks
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		mpd->b_size = 0;
 | 
					 | 
				
			||||||
		mpd->b_state = 0;
 | 
					 | 
				
			||||||
		mpd->b_blocknr = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mpd->next_page = page->index + 1;
 | 
					 | 
				
			||||||
	logical = (sector_t) page->index <<
 | 
					 | 
				
			||||||
		  (PAGE_CACHE_SHIFT - inode->i_blkbits);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!page_has_buffers(page)) {
 | 
					 | 
				
			||||||
		mpage_add_bh_to_extent(mpd, logical, PAGE_CACHE_SIZE,
 | 
					 | 
				
			||||||
				       (1 << BH_Dirty) | (1 << BH_Uptodate));
 | 
					 | 
				
			||||||
		if (mpd->io_done)
 | 
					 | 
				
			||||||
			return MPAGE_DA_EXTENT_TAIL;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * Page with regular buffer heads, just add all dirty ones
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		head = page_buffers(page);
 | 
					 | 
				
			||||||
		bh = head;
 | 
					 | 
				
			||||||
		do {
 | 
					 | 
				
			||||||
			BUG_ON(buffer_locked(bh));
 | 
					 | 
				
			||||||
			/*
 | 
					 | 
				
			||||||
			 * We need to try to allocate
 | 
					 | 
				
			||||||
			 * unmapped blocks in the same page.
 | 
					 | 
				
			||||||
			 * Otherwise we won't make progress
 | 
					 | 
				
			||||||
			 * with the page in ext4_writepage
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			if (ext4_bh_delay_or_unwritten(NULL, bh)) {
 | 
					 | 
				
			||||||
				mpage_add_bh_to_extent(mpd, logical,
 | 
					 | 
				
			||||||
						       bh->b_size,
 | 
					 | 
				
			||||||
						       bh->b_state);
 | 
					 | 
				
			||||||
				if (mpd->io_done)
 | 
					 | 
				
			||||||
					return MPAGE_DA_EXTENT_TAIL;
 | 
					 | 
				
			||||||
			} else if (buffer_dirty(bh) && (buffer_mapped(bh))) {
 | 
					 | 
				
			||||||
				/*
 | 
					 | 
				
			||||||
				 * mapped dirty buffer. We need to update
 | 
					 | 
				
			||||||
				 * the b_state because we look at
 | 
					 | 
				
			||||||
				 * b_state in mpage_da_map_blocks. We don't
 | 
					 | 
				
			||||||
				 * update b_size because if we find an
 | 
					 | 
				
			||||||
				 * unmapped buffer_head later we need to
 | 
					 | 
				
			||||||
				 * use the b_state flag of that buffer_head.
 | 
					 | 
				
			||||||
				 */
 | 
					 | 
				
			||||||
				if (mpd->b_size == 0)
 | 
					 | 
				
			||||||
					mpd->b_state = bh->b_state & BH_FLAGS;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			logical++;
 | 
					 | 
				
			||||||
		} while ((bh = bh->b_this_page) != head);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * This is a special get_blocks_t callback which is used by
 | 
					 * This is a special get_blocks_t callback which is used by
 | 
				
			||||||
 * ext4_da_write_begin().  It will either return mapped block or
 | 
					 * ext4_da_write_begin().  It will either return mapped block or
 | 
				
			||||||
| 
						 | 
					@ -2811,18 +2715,17 @@ static int ext4_da_writepages_trans_blocks(struct inode *inode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * write_cache_pages_da - walk the list of dirty pages of the given
 | 
					 * write_cache_pages_da - walk the list of dirty pages of the given
 | 
				
			||||||
 * address space and call the callback function (which usually writes
 | 
					 * address space and accumulate pages that need writing, and call
 | 
				
			||||||
 * the pages).
 | 
					 * mpage_da_map_and_submit to map the pages and then write them.
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This is a forked version of write_cache_pages().  Differences:
 | 
					 | 
				
			||||||
 *	Range cyclic is ignored.
 | 
					 | 
				
			||||||
 *	no_nrwrite_index_update is always presumed true
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int write_cache_pages_da(struct address_space *mapping,
 | 
					static int write_cache_pages_da(struct address_space *mapping,
 | 
				
			||||||
				struct writeback_control *wbc,
 | 
									struct writeback_control *wbc,
 | 
				
			||||||
				struct mpage_da_data *mpd,
 | 
									struct mpage_da_data *mpd,
 | 
				
			||||||
				pgoff_t *done_index)
 | 
									pgoff_t *done_index)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct inode *inode = mpd->inode;
 | 
				
			||||||
 | 
						struct buffer_head *bh, *head;
 | 
				
			||||||
 | 
						sector_t logical;
 | 
				
			||||||
	int ret = 0;
 | 
						int ret = 0;
 | 
				
			||||||
	int done = 0;
 | 
						int done = 0;
 | 
				
			||||||
	struct pagevec pvec;
 | 
						struct pagevec pvec;
 | 
				
			||||||
| 
						 | 
					@ -2899,17 +2802,90 @@ continue_unlock:
 | 
				
			||||||
			if (!clear_page_dirty_for_io(page))
 | 
								if (!clear_page_dirty_for_io(page))
 | 
				
			||||||
				goto continue_unlock;
 | 
									goto continue_unlock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ret = __mpage_da_writepage(page, wbc, mpd);
 | 
								/* BEGIN __mpage_da_writepage */
 | 
				
			||||||
			if (unlikely(ret)) {
 | 
					
 | 
				
			||||||
				if (ret == AOP_WRITEPAGE_ACTIVATE) {
 | 
								/*
 | 
				
			||||||
 | 
								 * Can we merge this page to current extent?
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								if (mpd->next_page != page->index) {
 | 
				
			||||||
 | 
									/*
 | 
				
			||||||
 | 
									 * Nope, we can't. So, we map
 | 
				
			||||||
 | 
									 * non-allocated blocks and start IO
 | 
				
			||||||
 | 
									 * on them
 | 
				
			||||||
 | 
									 */
 | 
				
			||||||
 | 
									if (mpd->next_page != mpd->first_page) {
 | 
				
			||||||
 | 
										mpage_da_map_and_submit(mpd);
 | 
				
			||||||
 | 
										/*
 | 
				
			||||||
 | 
										 * skip rest of the page in the page_vec
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
										redirty_page_for_writepage(wbc, page);
 | 
				
			||||||
					unlock_page(page);
 | 
										unlock_page(page);
 | 
				
			||||||
					ret = 0;
 | 
										ret = MPAGE_DA_EXTENT_TAIL;
 | 
				
			||||||
				} else {
 | 
										goto out;
 | 
				
			||||||
					done = 1;
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									/*
 | 
				
			||||||
 | 
									 * Start next extent of pages and blocks
 | 
				
			||||||
 | 
									 */
 | 
				
			||||||
 | 
									mpd->first_page = page->index;
 | 
				
			||||||
 | 
									mpd->b_size = 0;
 | 
				
			||||||
 | 
									mpd->b_state = 0;
 | 
				
			||||||
 | 
									mpd->b_blocknr = 0;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								mpd->next_page = page->index + 1;
 | 
				
			||||||
 | 
								logical = (sector_t) page->index <<
 | 
				
			||||||
 | 
									(PAGE_CACHE_SHIFT - inode->i_blkbits);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!page_has_buffers(page)) {
 | 
				
			||||||
 | 
									mpage_add_bh_to_extent(mpd, logical, PAGE_CACHE_SIZE,
 | 
				
			||||||
 | 
											       (1 << BH_Dirty) | (1 << BH_Uptodate));
 | 
				
			||||||
 | 
									if (mpd->io_done) {
 | 
				
			||||||
 | 
										ret = MPAGE_DA_EXTENT_TAIL;
 | 
				
			||||||
 | 
										goto out;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									/*
 | 
				
			||||||
 | 
									 * Page with regular buffer heads, just add all dirty ones
 | 
				
			||||||
 | 
									 */
 | 
				
			||||||
 | 
									head = page_buffers(page);
 | 
				
			||||||
 | 
									bh = head;
 | 
				
			||||||
 | 
									do {
 | 
				
			||||||
 | 
										BUG_ON(buffer_locked(bh));
 | 
				
			||||||
 | 
										/*
 | 
				
			||||||
 | 
										 * We need to try to allocate
 | 
				
			||||||
 | 
										 * unmapped blocks in the same page.
 | 
				
			||||||
 | 
										 * Otherwise we won't make progress
 | 
				
			||||||
 | 
										 * with the page in ext4_writepage
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
										if (ext4_bh_delay_or_unwritten(NULL, bh)) {
 | 
				
			||||||
 | 
											mpage_add_bh_to_extent(mpd, logical,
 | 
				
			||||||
 | 
													       bh->b_size,
 | 
				
			||||||
 | 
													       bh->b_state);
 | 
				
			||||||
 | 
											if (mpd->io_done) {
 | 
				
			||||||
 | 
												ret = MPAGE_DA_EXTENT_TAIL;
 | 
				
			||||||
 | 
												goto out;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										} else if (buffer_dirty(bh) && (buffer_mapped(bh))) {
 | 
				
			||||||
 | 
											/*
 | 
				
			||||||
 | 
											 * mapped dirty buffer. We need to update
 | 
				
			||||||
 | 
											 * the b_state because we look at
 | 
				
			||||||
 | 
											 * b_state in mpage_da_map_blocks. We don't
 | 
				
			||||||
 | 
											 * update b_size because if we find an
 | 
				
			||||||
 | 
											 * unmapped buffer_head later we need to
 | 
				
			||||||
 | 
											 * use the b_state flag of that buffer_head.
 | 
				
			||||||
 | 
											 */
 | 
				
			||||||
 | 
											if (mpd->b_size == 0)
 | 
				
			||||||
 | 
												mpd->b_state = bh->b_state & BH_FLAGS;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										logical++;
 | 
				
			||||||
 | 
									} while ((bh = bh->b_this_page) != head);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* END __mpage_da_writepage */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (nr_to_write > 0) {
 | 
								if (nr_to_write > 0) {
 | 
				
			||||||
				nr_to_write--;
 | 
									nr_to_write--;
 | 
				
			||||||
				if (nr_to_write == 0 &&
 | 
									if (nr_to_write == 0 &&
 | 
				
			||||||
| 
						 | 
					@ -2933,6 +2909,10 @@ continue_unlock:
 | 
				
			||||||
		cond_resched();
 | 
							cond_resched();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						pagevec_release(&pvec);
 | 
				
			||||||
 | 
						cond_resched();
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3059,13 +3039,9 @@ retry:
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Now call __mpage_da_writepage to find the next
 | 
							 * Now call write_cache_pages_da() to find the next
 | 
				
			||||||
		 * contiguous region of logical blocks that need
 | 
							 * contiguous region of logical blocks that need
 | 
				
			||||||
		 * blocks to be allocated by ext4.  We don't actually
 | 
							 * blocks to be allocated by ext4 and submit them.
 | 
				
			||||||
		 * submit the blocks for I/O here, even though
 | 
					 | 
				
			||||||
		 * write_cache_pages thinks it will, and will set the
 | 
					 | 
				
			||||||
		 * pages as clean for write before calling
 | 
					 | 
				
			||||||
		 * __mpage_da_writepage().
 | 
					 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		mpd.b_size = 0;
 | 
							mpd.b_size = 0;
 | 
				
			||||||
		mpd.b_state = 0;
 | 
							mpd.b_state = 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue