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;
 | 
						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,
 | 
					static noinline void __unlock_for_delalloc(struct inode *inode,
 | 
				
			||||||
					   struct page *locked_page,
 | 
										   struct page *locked_page,
 | 
				
			||||||
					   u64 start, u64 end)
 | 
										   u64 start, u64 end)
 | 
				
			||||||
| 
						 | 
					@ -1731,17 +1736,24 @@ STATIC u64 find_lock_delalloc_range(struct inode *inode,
 | 
				
			||||||
	return found;
 | 
						return found;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void __process_pages_contig(struct address_space *mapping,
 | 
					static int __process_pages_contig(struct address_space *mapping,
 | 
				
			||||||
				   struct page *locked_page,
 | 
									  struct page *locked_page,
 | 
				
			||||||
				   pgoff_t start_index, pgoff_t end_index,
 | 
									  pgoff_t start_index, pgoff_t end_index,
 | 
				
			||||||
				   unsigned long page_ops)
 | 
									  unsigned long page_ops, pgoff_t *index_ret)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned long nr_pages = end_index - start_index + 1;
 | 
						unsigned long nr_pages = end_index - start_index + 1;
 | 
				
			||||||
 | 
						unsigned long pages_locked = 0;
 | 
				
			||||||
	pgoff_t index = start_index;
 | 
						pgoff_t index = start_index;
 | 
				
			||||||
	struct page *pages[16];
 | 
						struct page *pages[16];
 | 
				
			||||||
	unsigned ret;
 | 
						unsigned ret;
 | 
				
			||||||
 | 
						int err = 0;
 | 
				
			||||||
	int i;
 | 
						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)
 | 
						if ((page_ops & PAGE_SET_ERROR) && nr_pages > 0)
 | 
				
			||||||
		mapping_set_error(mapping, -EIO);
 | 
							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,
 | 
							ret = find_get_pages_contig(mapping, index,
 | 
				
			||||||
				     min_t(unsigned long,
 | 
									     min_t(unsigned long,
 | 
				
			||||||
				     nr_pages, ARRAY_SIZE(pages)), pages);
 | 
									     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)
 | 
								if (page_ops & PAGE_SET_PRIVATE2)
 | 
				
			||||||
				SetPagePrivate2(pages[i]);
 | 
									SetPagePrivate2(pages[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (pages[i] == locked_page) {
 | 
								if (pages[i] == locked_page) {
 | 
				
			||||||
				put_page(pages[i]);
 | 
									put_page(pages[i]);
 | 
				
			||||||
 | 
									pages_locked++;
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (page_ops & PAGE_CLEAR_DIRTY)
 | 
								if (page_ops & PAGE_CLEAR_DIRTY)
 | 
				
			||||||
| 
						 | 
					@ -1768,12 +1789,27 @@ static void __process_pages_contig(struct address_space *mapping,
 | 
				
			||||||
				end_page_writeback(pages[i]);
 | 
									end_page_writeback(pages[i]);
 | 
				
			||||||
			if (page_ops & PAGE_UNLOCK)
 | 
								if (page_ops & PAGE_UNLOCK)
 | 
				
			||||||
				unlock_page(pages[i]);
 | 
									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]);
 | 
								put_page(pages[i]);
 | 
				
			||||||
 | 
								pages_locked++;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		nr_pages -= ret;
 | 
							nr_pages -= ret;
 | 
				
			||||||
		index += ret;
 | 
							index += ret;
 | 
				
			||||||
		cond_resched();
 | 
							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,
 | 
					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,
 | 
						__process_pages_contig(inode->i_mapping, locked_page,
 | 
				
			||||||
			       start >> PAGE_SHIFT, end >> PAGE_SHIFT,
 | 
								       start >> PAGE_SHIFT, end >> PAGE_SHIFT,
 | 
				
			||||||
			       page_ops);
 | 
								       page_ops, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,13 +45,14 @@
 | 
				
			||||||
#define EXTENT_BUFFER_IN_TREE 10
 | 
					#define EXTENT_BUFFER_IN_TREE 10
 | 
				
			||||||
#define EXTENT_BUFFER_WRITE_ERR 11    /* write IO error */
 | 
					#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_UNLOCK		(1 << 0)
 | 
				
			||||||
#define PAGE_CLEAR_DIRTY	(1 << 1)
 | 
					#define PAGE_CLEAR_DIRTY	(1 << 1)
 | 
				
			||||||
#define PAGE_SET_WRITEBACK	(1 << 2)
 | 
					#define PAGE_SET_WRITEBACK	(1 << 2)
 | 
				
			||||||
#define PAGE_END_WRITEBACK	(1 << 3)
 | 
					#define PAGE_END_WRITEBACK	(1 << 3)
 | 
				
			||||||
#define PAGE_SET_PRIVATE2	(1 << 4)
 | 
					#define PAGE_SET_PRIVATE2	(1 << 4)
 | 
				
			||||||
#define PAGE_SET_ERROR		(1 << 5)
 | 
					#define PAGE_SET_ERROR		(1 << 5)
 | 
				
			||||||
 | 
					#define PAGE_LOCK		(1 << 6)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * page->private values.  Every page that is controlled by the extent
 | 
					 * page->private values.  Every page that is controlled by the extent
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue