mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	btrfs: teach __process_pages_contig about PAGE_LOCK operation
Signed-off-by: Liu Bo <bo.li.liu@oracle.com> Reviewed-by: David Sterba <dsterba@suse.com> [ changes to the helper separated from the following patch ] Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
		
							parent
							
								
									873695b301
								
							
						
					
					
						commit
						da2c7009f6
					
				
					 2 changed files with 44 additions and 7 deletions
				
			
		| 
						 | 
				
			
			@ -1554,6 +1554,11 @@ static noinline u64 find_delalloc_range(struct extent_io_tree *tree,
 | 
			
		|||
	return found;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int __process_pages_contig(struct address_space *mapping,
 | 
			
		||||
				  struct page *locked_page,
 | 
			
		||||
				  pgoff_t start_index, pgoff_t end_index,
 | 
			
		||||
				  unsigned long page_ops, pgoff_t *index_ret);
 | 
			
		||||
 | 
			
		||||
static noinline void __unlock_for_delalloc(struct inode *inode,
 | 
			
		||||
					   struct page *locked_page,
 | 
			
		||||
					   u64 start, u64 end)
 | 
			
		||||
| 
						 | 
				
			
			@ -1731,17 +1736,24 @@ STATIC u64 find_lock_delalloc_range(struct inode *inode,
 | 
			
		|||
	return found;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __process_pages_contig(struct address_space *mapping,
 | 
			
		||||
				   struct page *locked_page,
 | 
			
		||||
				   pgoff_t start_index, pgoff_t end_index,
 | 
			
		||||
				   unsigned long page_ops)
 | 
			
		||||
static int __process_pages_contig(struct address_space *mapping,
 | 
			
		||||
				  struct page *locked_page,
 | 
			
		||||
				  pgoff_t start_index, pgoff_t end_index,
 | 
			
		||||
				  unsigned long page_ops, pgoff_t *index_ret)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long nr_pages = end_index - start_index + 1;
 | 
			
		||||
	unsigned long pages_locked = 0;
 | 
			
		||||
	pgoff_t index = start_index;
 | 
			
		||||
	struct page *pages[16];
 | 
			
		||||
	unsigned ret;
 | 
			
		||||
	int err = 0;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	if (page_ops & PAGE_LOCK) {
 | 
			
		||||
		ASSERT(page_ops == PAGE_LOCK);
 | 
			
		||||
		ASSERT(index_ret && *index_ret == start_index);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((page_ops & PAGE_SET_ERROR) && nr_pages > 0)
 | 
			
		||||
		mapping_set_error(mapping, -EIO);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1749,13 +1761,22 @@ static void __process_pages_contig(struct address_space *mapping,
 | 
			
		|||
		ret = find_get_pages_contig(mapping, index,
 | 
			
		||||
				     min_t(unsigned long,
 | 
			
		||||
				     nr_pages, ARRAY_SIZE(pages)), pages);
 | 
			
		||||
		for (i = 0; i < ret; i++) {
 | 
			
		||||
		if (ret == 0) {
 | 
			
		||||
			/*
 | 
			
		||||
			 * Only if we're going to lock these pages,
 | 
			
		||||
			 * can we find nothing at @index.
 | 
			
		||||
			 */
 | 
			
		||||
			ASSERT(page_ops & PAGE_LOCK);
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (i = 0; i < ret; i++) {
 | 
			
		||||
			if (page_ops & PAGE_SET_PRIVATE2)
 | 
			
		||||
				SetPagePrivate2(pages[i]);
 | 
			
		||||
 | 
			
		||||
			if (pages[i] == locked_page) {
 | 
			
		||||
				put_page(pages[i]);
 | 
			
		||||
				pages_locked++;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (page_ops & PAGE_CLEAR_DIRTY)
 | 
			
		||||
| 
						 | 
				
			
			@ -1768,12 +1789,27 @@ static void __process_pages_contig(struct address_space *mapping,
 | 
			
		|||
				end_page_writeback(pages[i]);
 | 
			
		||||
			if (page_ops & PAGE_UNLOCK)
 | 
			
		||||
				unlock_page(pages[i]);
 | 
			
		||||
			if (page_ops & PAGE_LOCK) {
 | 
			
		||||
				lock_page(pages[i]);
 | 
			
		||||
				if (!PageDirty(pages[i]) ||
 | 
			
		||||
				    pages[i]->mapping != mapping) {
 | 
			
		||||
					unlock_page(pages[i]);
 | 
			
		||||
					put_page(pages[i]);
 | 
			
		||||
					err = -EAGAIN;
 | 
			
		||||
					goto out;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			put_page(pages[i]);
 | 
			
		||||
			pages_locked++;
 | 
			
		||||
		}
 | 
			
		||||
		nr_pages -= ret;
 | 
			
		||||
		index += ret;
 | 
			
		||||
		cond_resched();
 | 
			
		||||
	}
 | 
			
		||||
out:
 | 
			
		||||
	if (err && index_ret)
 | 
			
		||||
		*index_ret = start_index + pages_locked - 1;
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end,
 | 
			
		||||
| 
						 | 
				
			
			@ -1786,7 +1822,7 @@ void extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end,
 | 
			
		|||
 | 
			
		||||
	__process_pages_contig(inode->i_mapping, locked_page,
 | 
			
		||||
			       start >> PAGE_SHIFT, end >> PAGE_SHIFT,
 | 
			
		||||
			       page_ops);
 | 
			
		||||
			       page_ops, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,13 +45,14 @@
 | 
			
		|||
#define EXTENT_BUFFER_IN_TREE 10
 | 
			
		||||
#define EXTENT_BUFFER_WRITE_ERR 11    /* write IO error */
 | 
			
		||||
 | 
			
		||||
/* these are flags for extent_clear_unlock_delalloc */
 | 
			
		||||
/* these are flags for __process_pages_contig */
 | 
			
		||||
#define PAGE_UNLOCK		(1 << 0)
 | 
			
		||||
#define PAGE_CLEAR_DIRTY	(1 << 1)
 | 
			
		||||
#define PAGE_SET_WRITEBACK	(1 << 2)
 | 
			
		||||
#define PAGE_END_WRITEBACK	(1 << 3)
 | 
			
		||||
#define PAGE_SET_PRIVATE2	(1 << 4)
 | 
			
		||||
#define PAGE_SET_ERROR		(1 << 5)
 | 
			
		||||
#define PAGE_LOCK		(1 << 6)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * page->private values.  Every page that is controlled by the extent
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue