mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	btrfs: hooks for readahead
This adds the hooks needed for readahead. In the readpage_end_io_hook, the extent state is checked for the EXTENT_READAHEAD flag. Only in this case the readahead hook is called, to keep the impact on non-ra as low as possible. Additionally, a hook for a failed IO is added, otherwise readahead would wait indefinitely for the extent to finish. Changes for v2: - eliminate race condition Signed-off-by: Arne Jansen <sensille@gmx.net>
This commit is contained in:
		
							parent
							
								
									7414a03fbf
								
							
						
					
					
						commit
						4bb31e928d
					
				
					 2 changed files with 38 additions and 1 deletions
				
			
		| 
						 | 
					@ -609,11 +609,47 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
 | 
				
			||||||
	end = min_t(u64, eb->len, PAGE_CACHE_SIZE);
 | 
						end = min_t(u64, eb->len, PAGE_CACHE_SIZE);
 | 
				
			||||||
	end = eb->start + end - 1;
 | 
						end = eb->start + end - 1;
 | 
				
			||||||
err:
 | 
					err:
 | 
				
			||||||
 | 
						if (test_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) {
 | 
				
			||||||
 | 
							clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags);
 | 
				
			||||||
 | 
							btree_readahead_hook(root, eb, eb->start, ret);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free_extent_buffer(eb);
 | 
						free_extent_buffer(eb);
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int btree_io_failed_hook(struct bio *failed_bio,
 | 
				
			||||||
 | 
								 struct page *page, u64 start, u64 end,
 | 
				
			||||||
 | 
								 struct extent_state *state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct extent_io_tree *tree;
 | 
				
			||||||
 | 
						unsigned long len;
 | 
				
			||||||
 | 
						struct extent_buffer *eb;
 | 
				
			||||||
 | 
						struct btrfs_root *root = BTRFS_I(page->mapping->host)->root;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tree = &BTRFS_I(page->mapping->host)->io_tree;
 | 
				
			||||||
 | 
						if (page->private == EXTENT_PAGE_PRIVATE)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						if (!page->private)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						len = page->private >> 2;
 | 
				
			||||||
 | 
						WARN_ON(len == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						eb = alloc_extent_buffer(tree, start, len, page);
 | 
				
			||||||
 | 
						if (eb == NULL)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (test_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) {
 | 
				
			||||||
 | 
							clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags);
 | 
				
			||||||
 | 
							btree_readahead_hook(root, eb, eb->start, -EIO);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						return -EIO;	/* we fixed nothing */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void end_workqueue_bio(struct bio *bio, int err)
 | 
					static void end_workqueue_bio(struct bio *bio, int err)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct end_io_wq *end_io_wq = bio->bi_private;
 | 
						struct end_io_wq *end_io_wq = bio->bi_private;
 | 
				
			||||||
| 
						 | 
					@ -3166,6 +3202,7 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)
 | 
				
			||||||
static struct extent_io_ops btree_extent_io_ops = {
 | 
					static struct extent_io_ops btree_extent_io_ops = {
 | 
				
			||||||
	.write_cache_pages_lock_hook = btree_lock_page_hook,
 | 
						.write_cache_pages_lock_hook = btree_lock_page_hook,
 | 
				
			||||||
	.readpage_end_io_hook = btree_readpage_end_io_hook,
 | 
						.readpage_end_io_hook = btree_readpage_end_io_hook,
 | 
				
			||||||
 | 
						.readpage_io_failed_hook = btree_io_failed_hook,
 | 
				
			||||||
	.submit_bio_hook = btree_submit_bio_hook,
 | 
						.submit_bio_hook = btree_submit_bio_hook,
 | 
				
			||||||
	/* note we're sharing with inode.c for the merge bio hook */
 | 
						/* note we're sharing with inode.c for the merge bio hook */
 | 
				
			||||||
	.merge_bio_hook = btrfs_merge_bio_hook,
 | 
						.merge_bio_hook = btrfs_merge_bio_hook,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1731,7 +1731,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
 | 
				
			||||||
		if (!uptodate && tree->ops &&
 | 
							if (!uptodate && tree->ops &&
 | 
				
			||||||
		    tree->ops->readpage_io_failed_hook) {
 | 
							    tree->ops->readpage_io_failed_hook) {
 | 
				
			||||||
			ret = tree->ops->readpage_io_failed_hook(bio, page,
 | 
								ret = tree->ops->readpage_io_failed_hook(bio, page,
 | 
				
			||||||
							 start, end, NULL);
 | 
												 start, end, state);
 | 
				
			||||||
			if (ret == 0) {
 | 
								if (ret == 0) {
 | 
				
			||||||
				uptodate =
 | 
									uptodate =
 | 
				
			||||||
					test_bit(BIO_UPTODATE, &bio->bi_flags);
 | 
										test_bit(BIO_UPTODATE, &bio->bi_flags);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue