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

Commit 55c69072 authored by Chris Mason's avatar Chris Mason
Browse files

Btrfs: Fix extent_buffer usage when nodesize != leafsize

parent 21ad10cf
Loading
Loading
Loading
Loading
+23 −3
Original line number Original line Diff line number Diff line
@@ -197,9 +197,23 @@ int csum_dirty_buffer(struct btrfs_root *root, struct page *page)
	if (found_start != start) {
	if (found_start != start) {
		printk("warning: eb start incorrect %Lu buffer %Lu len %lu\n",
		printk("warning: eb start incorrect %Lu buffer %Lu len %lu\n",
		       start, found_start, len);
		       start, found_start, len);
		WARN_ON(1);
		goto err;
	}
	if (eb->first_page != page) {
		printk("bad first page %lu %lu\n", eb->first_page->index,
		       page->index);
		WARN_ON(1);
		goto err;
	}
	if (!PageUptodate(page)) {
		printk("csum not up to date page %lu\n", page->index);
		WARN_ON(1);
		goto err;
	}
	}
	found_level = btrfs_header_level(eb);
	found_level = btrfs_header_level(eb);
	csum_tree_block(root, eb, 0);
	csum_tree_block(root, eb, 0);
err:
	free_extent_buffer(eb);
	free_extent_buffer(eb);
out:
out:
	return 0;
	return 0;
@@ -368,7 +382,10 @@ int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		     struct extent_buffer *buf)
		     struct extent_buffer *buf)
{
{
	struct inode *btree_inode = root->fs_info->btree_inode;
	struct inode *btree_inode = root->fs_info->btree_inode;
	clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, buf);
	if (btrfs_header_generation(buf) ==
	    root->fs_info->running_transaction->transid)
		clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree,
					  buf);
	return 0;
	return 0;
}
}


@@ -897,8 +914,11 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)


void btrfs_throttle(struct btrfs_root *root)
void btrfs_throttle(struct btrfs_root *root)
{
{
	if (root->fs_info->throttles)
	struct backing_dev_info *bdi;
		congestion_wait(WRITE, HZ/10);

	bdi = root->fs_info->sb->s_bdev->bd_inode->i_mapping->backing_dev_info;
	if (root->fs_info->throttles && bdi_write_congested(bdi))
		congestion_wait(WRITE, HZ/20);
}
}


void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr)
void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr)
+10 −3
Original line number Original line Diff line number Diff line
@@ -1212,6 +1212,7 @@ static int pin_down_bytes(struct btrfs_root *root, u64 bytenr, u32 num_bytes,
				u64 header_transid =
				u64 header_transid =
					btrfs_header_generation(buf);
					btrfs_header_generation(buf);
				if (header_transid == transid) {
				if (header_transid == transid) {
					clean_tree_block(NULL, root, buf);
					free_extent_buffer(buf);
					free_extent_buffer(buf);
					return 1;
					return 1;
				}
				}
@@ -1249,7 +1250,6 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
	key.objectid = bytenr;
	key.objectid = bytenr;
	btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
	btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
	key.offset = num_bytes;
	key.offset = num_bytes;

	path = btrfs_alloc_path();
	path = btrfs_alloc_path();
	if (!path)
	if (!path)
		return -ENOMEM;
		return -ENOMEM;
@@ -1648,8 +1648,6 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
			       search_start, search_end, hint_byte, ins,
			       search_start, search_end, hint_byte, ins,
			       trans->alloc_exclude_start,
			       trans->alloc_exclude_start,
			       trans->alloc_exclude_nr, data);
			       trans->alloc_exclude_nr, data);
if (ret)
printk("find free extent returns %d\n", ret);
	BUG_ON(ret);
	BUG_ON(ret);
	if (ret)
	if (ret)
		return ret;
		return ret;
@@ -1764,7 +1762,16 @@ struct extent_buffer *__btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
				  0, 0, 0);
				  0, 0, 0);
		return ERR_PTR(-ENOMEM);
		return ERR_PTR(-ENOMEM);
	}
	}
	btrfs_set_header_generation(buf, trans->transid);
	clean_tree_block(trans, root, buf);
	wait_on_tree_block_writeback(root, buf);
	btrfs_set_buffer_uptodate(buf);
	btrfs_set_buffer_uptodate(buf);

	if (PageDirty(buf->first_page)) {
		printk("page %lu dirty\n", buf->first_page->index);
		WARN_ON(1);
	}

	set_extent_dirty(&trans->transaction->dirty_pages, buf->start,
	set_extent_dirty(&trans->transaction->dirty_pages, buf->start,
			 buf->start + buf->len - 1, GFP_NOFS);
			 buf->start + buf->len - 1, GFP_NOFS);
	set_extent_bits(&BTRFS_I(root->fs_info->btree_inode)->extent_tree,
	set_extent_bits(&BTRFS_I(root->fs_info->btree_inode)->extent_tree,
+21 −9
Original line number Original line Diff line number Diff line
@@ -1663,6 +1663,13 @@ void set_page_extent_mapped(struct page *page)
	}
	}
}
}


void set_page_extent_head(struct page *page, unsigned long len)
{
	WARN_ON(page->private && page->private == EXTENT_PAGE_PRIVATE &&
		PageDirty(page));
	set_page_private(page, EXTENT_PAGE_PRIVATE_FIRST_PAGE | len << 2);
}

/*
/*
 * basic readpage implementation.  Locked extent state structs are inserted
 * basic readpage implementation.  Locked extent state structs are inserted
 * into the tree that are removed when the IO is done (by the end_io
 * into the tree that are removed when the IO is done (by the end_io
@@ -2490,8 +2497,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
		mark_page_accessed(page0);
		mark_page_accessed(page0);
		set_page_extent_mapped(page0);
		set_page_extent_mapped(page0);
		WARN_ON(!PageUptodate(page0));
		WARN_ON(!PageUptodate(page0));
		set_page_private(page0, EXTENT_PAGE_PRIVATE_FIRST_PAGE |
		set_page_extent_head(page0, len);
				 len << 2);
	} else {
	} else {
		i = 0;
		i = 0;
	}
	}
@@ -2505,8 +2511,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
		mark_page_accessed(p);
		mark_page_accessed(p);
		if (i == 0) {
		if (i == 0) {
			eb->first_page = p;
			eb->first_page = p;
			set_page_private(p, EXTENT_PAGE_PRIVATE_FIRST_PAGE |
			set_page_extent_head(p, len);
					 len << 2);
		} else {
		} else {
			set_page_private(p, EXTENT_PAGE_PRIVATE);
			set_page_private(p, EXTENT_PAGE_PRIVATE);
		}
		}
@@ -2569,8 +2574,7 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,


		if (i == 0) {
		if (i == 0) {
			eb->first_page = p;
			eb->first_page = p;
			set_page_private(p, EXTENT_PAGE_PRIVATE_FIRST_PAGE |
			set_page_extent_head(p, len);
					 len << 2);
		} else {
		} else {
			set_page_private(p, EXTENT_PAGE_PRIVATE);
			set_page_private(p, EXTENT_PAGE_PRIVATE);
		}
		}
@@ -2643,6 +2647,11 @@ int clear_extent_buffer_dirty(struct extent_map_tree *tree,
	for (i = 0; i < num_pages; i++) {
	for (i = 0; i < num_pages; i++) {
		page = extent_buffer_page(eb, i);
		page = extent_buffer_page(eb, i);
		lock_page(page);
		lock_page(page);
		if (i == 0)
			set_page_extent_head(page, eb->len);
		else
			set_page_private(page, EXTENT_PAGE_PRIVATE);

		/*
		/*
		 * if we're on the last page or the first page and the
		 * if we're on the last page or the first page and the
		 * block isn't aligned on a page boundary, do extra checks
		 * block isn't aligned on a page boundary, do extra checks
@@ -2697,9 +2706,12 @@ int set_extent_buffer_dirty(struct extent_map_tree *tree,
		 */
		 */
		if (i == 0) {
		if (i == 0) {
			lock_page(page);
			lock_page(page);
			set_page_private(page,
			set_page_extent_head(page, eb->len);
					 EXTENT_PAGE_PRIVATE_FIRST_PAGE |
		} else if (PagePrivate(page) &&
					 eb->len << 2);
			   page->private != EXTENT_PAGE_PRIVATE) {
			lock_page(page);
			set_page_extent_mapped(page);
			unlock_page(page);
		}
		}
		__set_page_dirty_nobuffers(extent_buffer_page(eb, i));
		__set_page_dirty_nobuffers(extent_buffer_page(eb, i));
		if (i == 0)
		if (i == 0)