Commit c44db6c8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from David Sterba:
 "One-liner or short fixes for minor/moderate problems reported recently:

   - fixes or level adjustments of error messages

   - fix leaked transaction handles after aborted transactions, when
     using the remap tree feature

   - fix a few leaked chunk maps after errors

   - fix leaked page array in io_uring encoded read if an error occurs
     and the 'finished' is not called

   - fix double release of reserved extents when doing a range COW

   - don't commit super block when the filesystem is in shutdown state

   - fix squota accounting condition when checking members vs parent
     usage

   - other error handling fixes"

* tag 'for-7.0-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: check block group lookup in remove_range_from_remap_tree()
  btrfs: fix transaction handle leaks in btrfs_last_identity_remap_gone()
  btrfs: fix chunk map leak in btrfs_map_block() after btrfs_translate_remap()
  btrfs: fix chunk map leak in btrfs_map_block() after btrfs_chunk_map_num_copies()
  btrfs: fix compat mask in error messages in btrfs_check_features()
  btrfs: print correct subvol num if active swapfile prevents deletion
  btrfs: fix warning in scrub_verify_one_metadata()
  btrfs: fix objectid value in error message in check_extent_data_ref()
  btrfs: fix incorrect key offset in error message in check_dev_extent_item()
  btrfs: fix error message order of parameters in btrfs_delete_delayed_dir_index()
  btrfs: don't commit the super block when unmounting a shutdown filesystem
  btrfs: free pages on error in btrfs_uring_read_extent()
  btrfs: fix referenced/exclusive check in squota_check_parent_usage()
  btrfs: remove pointless WARN_ON() in cache_save_setup()
  btrfs: convert log messages to error level in btrfs_replay_log()
  btrfs: remove btrfs_handle_fs_error() after failure to recover log trees
  btrfs: remove redundant warning message in btrfs_check_uuid_tree()
  btrfs: change warning messages to error level in open_ctree()
  btrfs: fix a double release on reserved extents in cow_one_range()
  btrfs: handle discard errors in in btrfs_finish_extent_commit()
parents af4e9ef3 f8db8009
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -3340,7 +3340,6 @@ static int cache_save_setup(struct btrfs_block_group *block_group,
		btrfs_abort_transaction(trans, ret);
		goto out_put;
	}
	WARN_ON(ret);

	/* We've already setup this transaction, go ahead and exit */
	if (block_group->cache_generation == trans->transid &&
+1 −1
Original line number Diff line number Diff line
@@ -1657,7 +1657,7 @@ int btrfs_delete_delayed_dir_index(struct btrfs_trans_handle *trans,
	if (unlikely(ret)) {
		btrfs_err(trans->fs_info,
"failed to add delayed dir index item, root: %llu, inode: %llu, index: %llu, error: %d",
			  index, btrfs_root_id(node->root), node->inode_id, ret);
			  btrfs_root_id(node->root), node->inode_id, index, ret);
		btrfs_delayed_item_release_metadata(dir->root, item);
		btrfs_release_delayed_item(item);
	}
+21 −15
Original line number Diff line number Diff line
@@ -1994,7 +1994,7 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
	int level = btrfs_super_log_root_level(disk_super);

	if (unlikely(fs_devices->rw_devices == 0)) {
		btrfs_warn(fs_info, "log replay required on RO media");
		btrfs_err(fs_info, "log replay required on RO media");
		return -EIO;
	}

@@ -2008,9 +2008,9 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
	check.owner_root = BTRFS_TREE_LOG_OBJECTID;
	log_tree_root->node = read_tree_block(fs_info, bytenr, &check);
	if (IS_ERR(log_tree_root->node)) {
		btrfs_warn(fs_info, "failed to read log tree");
		ret = PTR_ERR(log_tree_root->node);
		log_tree_root->node = NULL;
		btrfs_err(fs_info, "failed to read log tree with error: %d", ret);
		btrfs_put_root(log_tree_root);
		return ret;
	}
@@ -2023,9 +2023,9 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
	/* returns with log_tree_root freed on success */
	ret = btrfs_recover_log_trees(log_tree_root);
	btrfs_put_root(log_tree_root);
	if (ret) {
		btrfs_handle_fs_error(fs_info, ret,
				      "Failed to recover log tree");
	if (unlikely(ret)) {
		ASSERT(BTRFS_FS_ERROR(fs_info) != 0);
		btrfs_err(fs_info, "failed to recover log trees with error: %d", ret);
		return ret;
	}

@@ -2972,7 +2972,6 @@ static int btrfs_check_uuid_tree(struct btrfs_fs_info *fs_info)
	task = kthread_run(btrfs_uuid_rescan_kthread, fs_info, "btrfs-uuid");
	if (IS_ERR(task)) {
		/* fs_info->update_uuid_tree_gen remains 0 in all error case */
		btrfs_warn(fs_info, "failed to start uuid_rescan task");
		up(&fs_info->uuid_tree_rescan_sem);
		return PTR_ERR(task);
	}
@@ -3188,7 +3187,7 @@ int btrfs_check_features(struct btrfs_fs_info *fs_info, bool is_rw_mount)
	if (incompat & ~BTRFS_FEATURE_INCOMPAT_SUPP) {
		btrfs_err(fs_info,
		"cannot mount because of unknown incompat features (0x%llx)",
		    incompat);
		    incompat & ~BTRFS_FEATURE_INCOMPAT_SUPP);
		return -EINVAL;
	}

@@ -3220,7 +3219,7 @@ int btrfs_check_features(struct btrfs_fs_info *fs_info, bool is_rw_mount)
	if (compat_ro_unsupp && is_rw_mount) {
		btrfs_err(fs_info,
	"cannot mount read-write because of unknown compat_ro features (0x%llx)",
		       compat_ro);
		       compat_ro_unsupp);
		return -EINVAL;
	}

@@ -3233,7 +3232,7 @@ int btrfs_check_features(struct btrfs_fs_info *fs_info, bool is_rw_mount)
	    !btrfs_test_opt(fs_info, NOLOGREPLAY)) {
		btrfs_err(fs_info,
"cannot replay dirty log with unsupported compat_ro features (0x%llx), try rescue=nologreplay",
			  compat_ro);
			  compat_ro_unsupp);
		return -EINVAL;
	}

@@ -3642,7 +3641,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
	fs_info->fs_root = btrfs_get_fs_root(fs_info, BTRFS_FS_TREE_OBJECTID, true);
	if (IS_ERR(fs_info->fs_root)) {
		ret = PTR_ERR(fs_info->fs_root);
		btrfs_warn(fs_info, "failed to read fs tree: %d", ret);
		btrfs_err(fs_info, "failed to read fs tree: %d", ret);
		fs_info->fs_root = NULL;
		goto fail_qgroup;
	}
@@ -3663,8 +3662,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
		btrfs_info(fs_info, "checking UUID tree");
		ret = btrfs_check_uuid_tree(fs_info);
		if (ret) {
			btrfs_warn(fs_info,
				"failed to check the UUID tree: %d", ret);
			btrfs_err(fs_info, "failed to check the UUID tree: %d", ret);
			close_ctree(fs_info);
			return ret;
		}
@@ -4399,9 +4397,17 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
		 */
		btrfs_flush_workqueue(fs_info->delayed_workers);

		/*
		 * If the filesystem is shutdown, then an attempt to commit the
		 * super block (or any write) will just fail. Since we freeze
		 * the filesystem before shutting it down, the filesystem is in
		 * a consistent state and we don't need to commit super blocks.
		 */
		if (!btrfs_is_shutdown(fs_info)) {
			ret = btrfs_commit_super(fs_info);
			if (ret)
			btrfs_err(fs_info, "commit super ret %d", ret);
				btrfs_err(fs_info, "commit super block returned %d", ret);
		}
	}

	kthread_stop(fs_info->transaction_kthread);
+7 −1
Original line number Diff line number Diff line
@@ -2933,9 +2933,15 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans)
	while (!TRANS_ABORTED(trans) && cached_state) {
		struct extent_state *next_state;

		if (btrfs_test_opt(fs_info, DISCARD_SYNC))
		if (btrfs_test_opt(fs_info, DISCARD_SYNC)) {
			ret = btrfs_discard_extent(fs_info, start,
						   end + 1 - start, NULL, true);
			if (ret) {
				btrfs_warn(fs_info,
				"discard failed for extent [%llu, %llu]: errno=%d %s",
					   start, end, ret, btrfs_decode_error(ret));
			}
		}

		next_state = btrfs_next_extent_state(unpin, cached_state);
		btrfs_clear_extent_dirty(unpin, start, end, &cached_state);
+17 −2
Original line number Diff line number Diff line
@@ -1392,10 +1392,25 @@ static int cow_one_range(struct btrfs_inode *inode, struct folio *locked_folio,
	return ret;

free_reserved:
	/*
	 * If we have reserved an extent for the current range and failed to
	 * create the respective extent map or ordered extent, it means that
	 * when we reserved the extent we decremented the extent's size from
	 * the data space_info's bytes_may_use counter and
	 * incremented the space_info's bytes_reserved counter by the same
	 * amount.
	 *
	 * We must make sure extent_clear_unlock_delalloc() does not try
	 * to decrement again the data space_info's bytes_may_use counter, which
	 * will be handled by btrfs_free_reserved_extent().
	 *
	 * Therefore we do not pass it the flag EXTENT_CLEAR_DATA_RESV, but only
	 * EXTENT_CLEAR_META_RESV.
	 */
	extent_clear_unlock_delalloc(inode, file_offset, cur_end, locked_folio, cached,
				     EXTENT_LOCKED | EXTENT_DELALLOC |
				     EXTENT_DELALLOC_NEW |
				     EXTENT_DEFRAG | EXTENT_DO_ACCOUNTING,
				     EXTENT_DEFRAG | EXTENT_CLEAR_META_RESV,
				     PAGE_UNLOCK | PAGE_START_WRITEBACK |
				     PAGE_END_WRITEBACK);
	btrfs_qgroup_free_data(inode, NULL, file_offset, cur_len, NULL);
@@ -4764,7 +4779,7 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry)
		spin_unlock(&dest->root_item_lock);
		btrfs_warn(fs_info,
			   "attempt to delete subvolume %llu with active swapfile",
			   btrfs_root_id(root));
			   btrfs_root_id(dest));
		ret = -EPERM;
		goto out_up_write;
	}
Loading