Commit 142b507f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from David Sterba:
 "First batch of various fixes, here's a list of notable ones:

   - fix unmountable seed device after fstrim

   - fix silent data loss in zoned mode due to ordered extent splitting

   - fix race leading to unpersisted data and metadata on fsync

   - fix deadlock when cloning inline extents and using qgroups"

* tag 'for-5.13-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: initialize return variable in cleanup_free_space_cache_v1
  btrfs: zoned: sanity check zone type
  btrfs: fix unmountable seed device after fstrim
  btrfs: fix deadlock when cloning inline extents and using qgroups
  btrfs: fix race leading to unpersisted data and metadata on fsync
  btrfs: do not consider send context as valid when trying to flush qgroups
  btrfs: zoned: fix silent data loss after failure splitting ordered extent
parents 0aa099a3 77364faf
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3127,7 +3127,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
			       struct btrfs_inode *inode, u64 new_size,
			       u32 min_type);

int btrfs_start_delalloc_snapshot(struct btrfs_root *root);
int btrfs_start_delalloc_snapshot(struct btrfs_root *root, bool in_reclaim_context);
int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, long nr,
			       bool in_reclaim_context);
int btrfs_set_extent_delalloc(struct btrfs_inode *inode, u64 start, u64 end,
+5 −1
Original line number Diff line number Diff line
@@ -1340,12 +1340,16 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr,
		stripe = bbio->stripes;
		for (i = 0; i < bbio->num_stripes; i++, stripe++) {
			u64 bytes;
			struct btrfs_device *device = stripe->dev;

			if (!stripe->dev->bdev) {
			if (!device->bdev) {
				ASSERT(btrfs_test_opt(fs_info, DEGRADED));
				continue;
			}

			if (!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state))
				continue;

			ret = do_discard_extent(stripe, &bytes);
			if (!ret) {
				discarded_bytes += bytes;
+25 −10
Original line number Diff line number Diff line
@@ -2067,6 +2067,30 @@ static int start_ordered_ops(struct inode *inode, loff_t start, loff_t end)
	return ret;
}

static inline bool skip_inode_logging(const struct btrfs_log_ctx *ctx)
{
	struct btrfs_inode *inode = BTRFS_I(ctx->inode);
	struct btrfs_fs_info *fs_info = inode->root->fs_info;

	if (btrfs_inode_in_log(inode, fs_info->generation) &&
	    list_empty(&ctx->ordered_extents))
		return true;

	/*
	 * If we are doing a fast fsync we can not bail out if the inode's
	 * last_trans is <= then the last committed transaction, because we only
	 * update the last_trans of the inode during ordered extent completion,
	 * and for a fast fsync we don't wait for that, we only wait for the
	 * writeback to complete.
	 */
	if (inode->last_trans <= fs_info->last_trans_committed &&
	    (test_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &inode->runtime_flags) ||
	     list_empty(&ctx->ordered_extents)))
		return true;

	return false;
}

/*
 * fsync call for both files and directories.  This logs the inode into
 * the tree log instead of forcing full commits whenever possible.
@@ -2185,17 +2209,8 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)

	atomic_inc(&root->log_batch);

	/*
	 * If we are doing a fast fsync we can not bail out if the inode's
	 * last_trans is <= then the last committed transaction, because we only
	 * update the last_trans of the inode during ordered extent completion,
	 * and for a fast fsync we don't wait for that, we only wait for the
	 * writeback to complete.
	 */
	smp_mb();
	if (btrfs_inode_in_log(BTRFS_I(inode), fs_info->generation) ||
	    (BTRFS_I(inode)->last_trans <= fs_info->last_trans_committed &&
	     (full_sync || list_empty(&ctx.ordered_extents)))) {
	if (skip_inode_logging(&ctx)) {
		/*
		 * We've had everything committed since the last time we were
		 * modified so clear this flag in case it was set for whatever
+1 −1
Original line number Diff line number Diff line
@@ -3949,7 +3949,7 @@ static int cleanup_free_space_cache_v1(struct btrfs_fs_info *fs_info,
{
	struct btrfs_block_group *block_group;
	struct rb_node *node;
	int ret;
	int ret = 0;

	btrfs_info(fs_info, "cleaning free space cache v1");

+2 −2
Original line number Diff line number Diff line
@@ -9678,7 +9678,7 @@ static int start_delalloc_inodes(struct btrfs_root *root,
	return ret;
}

int btrfs_start_delalloc_snapshot(struct btrfs_root *root)
int btrfs_start_delalloc_snapshot(struct btrfs_root *root, bool in_reclaim_context)
{
	struct writeback_control wbc = {
		.nr_to_write = LONG_MAX,
@@ -9691,7 +9691,7 @@ int btrfs_start_delalloc_snapshot(struct btrfs_root *root)
	if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state))
		return -EROFS;

	return start_delalloc_inodes(root, &wbc, true, false);
	return start_delalloc_inodes(root, &wbc, true, in_reclaim_context);
}

int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, long nr,
Loading