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

Commit 89ce8a63 authored by Chris Mason's avatar Chris Mason
Browse files

Add btrfs_end_transaction_throttle to force writers to wait for pending commits



The existing throttle mechanism was often not sufficient to prevent
new writers from coming in and making a given transaction run forever.
This adds an explicit wait at the end of most operations so they will
allow the current transaction to close.

There is no wait inside file_write, inode updates, or cow filling, all which
have different deadlock possibilities.

This is a temporary measure until better asynchronous commit support is
added.  This code leads to stalls as it waits for data=ordered
writeback, and it really needs to be fixed.

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 333db94c
Loading
Loading
Loading
Loading
+0 −18
Original line number Diff line number Diff line
@@ -1672,24 +1672,6 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
	set_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, buf);
}

void btrfs_throttle(struct btrfs_root *root)
{
#if 0
	struct backing_dev_info *bdi;

	bdi = &root->fs_info->bdi;
	if (atomic_read(&root->fs_info->throttles) &&
	    bdi_write_congested(bdi)) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
		congestion_wait(WRITE, HZ/20);
#else
		blk_congestion_wait(WRITE, HZ/20);
#endif

	}
#endif
}

void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr)
{
	/*
+0 −1
Original line number Diff line number Diff line
@@ -70,7 +70,6 @@ int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf);
int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid);
u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len);
void btrfs_csum_final(u32 crc, char *result);
void btrfs_throttle(struct btrfs_root *root);
int btrfs_open_device(struct btrfs_device *dev);
int btrfs_verify_block_csum(struct btrfs_root *root,
			    struct extent_buffer *buf);
+0 −1
Original line number Diff line number Diff line
@@ -934,7 +934,6 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
		balance_dirty_pages_ratelimited_nr(inode->i_mapping, num_pages);
		if (num_pages < (root->leafsize >> PAGE_CACHE_SHIFT) + 1)
			btrfs_btree_balance_dirty(root, 1);
		btrfs_throttle(root);
		cond_resched();
	}
out:
+8 −16
Original line number Diff line number Diff line
@@ -855,10 +855,9 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
		btrfs_del_ordered_inode(inode, 1);
	}

	btrfs_end_transaction(trans, root);
	btrfs_end_transaction_throttle(trans, root);
fail:
	btrfs_btree_balance_dirty(root, nr);
	btrfs_throttle(root);
	return ret;
}

@@ -889,10 +888,9 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
	}

	nr = trans->blocks_used;
	ret = btrfs_end_transaction(trans, root);
	ret = btrfs_end_transaction_throttle(trans, root);
fail:
	btrfs_btree_balance_dirty(root, nr);
	btrfs_throttle(root);

	if (ret && !err)
		err = ret;
@@ -1871,14 +1869,13 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
	btrfs_update_inode_block_group(trans, dir);
out_unlock:
	nr = trans->blocks_used;
	btrfs_end_transaction(trans, root);
	btrfs_end_transaction_throttle(trans, root);
fail:
	if (drop_inode) {
		inode_dec_link_count(inode);
		iput(inode);
	}
	btrfs_btree_balance_dirty(root, nr);
	btrfs_throttle(root);
	return err;
}

@@ -1936,14 +1933,13 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
	btrfs_update_inode_block_group(trans, dir);
out_unlock:
	nr = trans->blocks_used;
	btrfs_end_transaction(trans, root);
	btrfs_end_transaction_throttle(trans, root);
fail:
	if (drop_inode) {
		inode_dec_link_count(inode);
		iput(inode);
	}
	btrfs_btree_balance_dirty(root, nr);
	btrfs_throttle(root);
	return err;
}

@@ -1985,14 +1981,13 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
		drop_inode = 1;

	nr = trans->blocks_used;
	btrfs_end_transaction(trans, root);
	btrfs_end_transaction_throttle(trans, root);
fail:
	if (drop_inode) {
		inode_dec_link_count(inode);
		iput(inode);
	}
	btrfs_btree_balance_dirty(root, nr);
	btrfs_throttle(root);
	return err;
}

@@ -2055,13 +2050,12 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)

out_fail:
	nr = trans->blocks_used;
	btrfs_end_transaction(trans, root);
	btrfs_end_transaction_throttle(trans, root);

out_unlock:
	if (drop_on_err)
		iput(inode);
	btrfs_btree_balance_dirty(root, nr);
	btrfs_throttle(root);
	return err;
}

@@ -2587,10 +2581,9 @@ static void btrfs_truncate(struct inode *inode)
	btrfs_update_inode(trans, root, inode);
	nr = trans->blocks_used;

	ret = btrfs_end_transaction(trans, root);
	ret = btrfs_end_transaction_throttle(trans, root);
	BUG_ON(ret);
	btrfs_btree_balance_dirty(root, nr);
	btrfs_throttle(root);
}

/*
@@ -2912,14 +2905,13 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,

out_unlock:
	nr = trans->blocks_used;
	btrfs_end_transaction(trans, root);
	btrfs_end_transaction_throttle(trans, root);
out_fail:
	if (drop_inode) {
		inode_dec_link_count(inode);
		iput(inode);
	}
	btrfs_btree_balance_dirty(root, nr);
	btrfs_throttle(root);
	return err;
}

+0 −2
Original line number Diff line number Diff line
@@ -164,7 +164,6 @@ static noinline int create_subvol(struct btrfs_root *root, char *name,
		ret = err;
fail_commit:
	btrfs_btree_balance_dirty(root, nr);
	btrfs_throttle(root);
	return ret;
}

@@ -206,7 +205,6 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen)

fail_unlock:
	btrfs_btree_balance_dirty(root, nr);
	btrfs_throttle(root);
	return ret;
}

Loading