Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9e8a4a8b authored by Liu Bo's avatar Liu Bo Committed by Chris Mason
Browse files

Btrfs: use flag EXTENT_DEFRAG for snapshot-aware defrag



We're going to use this flag EXTENT_DEFRAG to indicate which range
belongs to defragment so that we can implement snapshow-aware defrag:

We set the EXTENT_DEFRAG flag when dirtying the extents that need
defragmented, so later on writeback thread can differentiate between
normal writeback and writeback started by defragmentation.

Original-Signed-off-by: default avatarLi Zefan <lizf@cn.fujitsu.com>
Signed-off-by: default avatarLiu Bo <bo.li.liu@oracle.com>
parent 3d6b5c3b
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -1144,6 +1144,14 @@ int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end,
			      NULL, cached_state, mask);
}

int set_extent_defrag(struct extent_io_tree *tree, u64 start, u64 end,
		      struct extent_state **cached_state, gfp_t mask)
{
	return set_extent_bit(tree, start, end,
			      EXTENT_DELALLOC | EXTENT_UPTODATE | EXTENT_DEFRAG,
			      NULL, cached_state, mask);
}

int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
		       gfp_t mask)
{
+2 −0
Original line number Diff line number Diff line
@@ -235,6 +235,8 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
		       int bits, int clear_bits, gfp_t mask);
int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end,
			struct extent_state **cached_state, gfp_t mask);
int set_extent_defrag(struct extent_io_tree *tree, u64 start, u64 end,
		      struct extent_state **cached_state, gfp_t mask);
int find_first_extent_bit(struct extent_io_tree *tree, u64 start,
			  u64 *start_ret, u64 *end_ret, int bits);
struct extent_state *find_first_extent_bit_state(struct extent_io_tree *tree,
+2 −2
Original line number Diff line number Diff line
@@ -1203,8 +1203,8 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file,

		clear_extent_bit(&BTRFS_I(inode)->io_tree, start_pos,
				  last_pos - 1, EXTENT_DIRTY | EXTENT_DELALLOC |
				  EXTENT_DO_ACCOUNTING, 0, 0, &cached_state,
				  GFP_NOFS);
				  EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
				  0, 0, &cached_state, GFP_NOFS);
		unlock_extent_cached(&BTRFS_I(inode)->io_tree,
				     start_pos, last_pos - 1, &cached_state,
				     GFP_NOFS);
+12 −8
Original line number Diff line number Diff line
@@ -3549,7 +3549,8 @@ int btrfs_truncate_page(struct inode *inode, loff_t from, loff_t len,
	}

	clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start, page_end,
			  EXTENT_DIRTY | EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING,
			  EXTENT_DIRTY | EXTENT_DELALLOC |
			  EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
			  0, 0, &cached_state, GFP_NOFS);

	ret = btrfs_set_extent_delalloc(inode, page_start, page_end,
@@ -6061,7 +6062,8 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
	if (lockstart < lockend) {
		if (create && len < lockend - lockstart) {
			clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
					 lockstart + len - 1, unlock_bits, 1, 0,
					 lockstart + len - 1,
					 unlock_bits | EXTENT_DEFRAG, 1, 0,
					 &cached_state, GFP_NOFS);
			/*
			 * Beside unlock, we also need to cleanup reserved space
@@ -6069,8 +6071,8 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
			 */
			clear_extent_bit(&BTRFS_I(inode)->io_tree,
					 lockstart + len, lockend,
					 unlock_bits | EXTENT_DO_ACCOUNTING,
					 1, 0, NULL, GFP_NOFS);
					 unlock_bits | EXTENT_DO_ACCOUNTING |
					 EXTENT_DEFRAG, 1, 0, NULL, GFP_NOFS);
		} else {
			clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
					 lockend, unlock_bits, 1, 0,
@@ -6635,8 +6637,8 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset)
		 */
		clear_extent_bit(tree, page_start, page_end,
				 EXTENT_DIRTY | EXTENT_DELALLOC |
				 EXTENT_LOCKED | EXTENT_DO_ACCOUNTING, 1, 0,
				 &cached_state, GFP_NOFS);
				 EXTENT_LOCKED | EXTENT_DO_ACCOUNTING |
				 EXTENT_DEFRAG, 1, 0, &cached_state, GFP_NOFS);
		/*
		 * whoever cleared the private bit is responsible
		 * for the finish_ordered_io
@@ -6652,7 +6654,8 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset)
	}
	clear_extent_bit(tree, page_start, page_end,
		 EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC |
		 EXTENT_DO_ACCOUNTING, 1, 1, &cached_state, GFP_NOFS);
		 EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, 1, 1,
		 &cached_state, GFP_NOFS);
	__btrfs_releasepage(page, GFP_NOFS);

	ClearPageChecked(page);
@@ -6749,7 +6752,8 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
	 * prepare_pages in the normal write path.
	 */
	clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start, page_end,
			  EXTENT_DIRTY | EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING,
			  EXTENT_DIRTY | EXTENT_DELALLOC |
			  EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
			  0, 0, &cached_state, GFP_NOFS);

	ret = btrfs_set_extent_delalloc(inode, page_start, page_end,
+4 −4
Original line number Diff line number Diff line
@@ -1023,8 +1023,8 @@ static int cluster_pages_for_defrag(struct inode *inode,
			 page_start, page_end - 1, 0, &cached_state);
	clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start,
			  page_end - 1, EXTENT_DIRTY | EXTENT_DELALLOC |
			  EXTENT_DO_ACCOUNTING, 0, 0, &cached_state,
			  GFP_NOFS);
			  EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, 0, 0,
			  &cached_state, GFP_NOFS);

	if (i_done != page_cnt) {
		spin_lock(&BTRFS_I(inode)->lock);
@@ -1035,8 +1035,8 @@ static int cluster_pages_for_defrag(struct inode *inode,
	}


	btrfs_set_extent_delalloc(inode, page_start, page_end - 1,
				  &cached_state);
	set_extent_defrag(&BTRFS_I(inode)->io_tree, page_start, page_end - 1,
			  &cached_state, GFP_NOFS);

	unlock_extent_cached(&BTRFS_I(inode)->io_tree,
			     page_start, page_end - 1, &cached_state,