/* write back the superblocks */
trans = btrfs_start_transaction(root, 0);
- if (!IS_ERR(trans))
+ if (!IS_ERR(trans)) {
+ /*
+ * Ignore any error here, if we failed to remove the DEV_STATS
+ * item for devid 0, it's not a big deal. We have other ways
+ * to address it.
+ */
+ btrfs_remove_dev_stat_item(trans, BTRFS_DEV_REPLACE_DEVID);
btrfs_commit_transaction(trans);
+ }
mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
update_dev_time(rcu_dereference_raw(device->name));
}
+int btrfs_remove_dev_stat_item(struct btrfs_trans_handle *trans, u64 devid)
+{
+ BTRFS_PATH_AUTO_RELEASE(path);
+ struct btrfs_fs_info *fs_info = trans->fs_info;
+ struct btrfs_root *dev_root = fs_info->dev_root;
+ struct btrfs_key key;
+ int ret;
+
+ key.objectid = BTRFS_DEV_STATS_OBJECTID;
+ key.type = BTRFS_PERSISTENT_ITEM_KEY;
+ key.offset = devid;
+
+ ret = btrfs_search_slot(trans, dev_root, &key, &path, -1, 1);
+ if (ret < 0) {
+ btrfs_warn(fs_info,
+ "error %d while searching for dev_stats item for devid %llu",
+ ret, devid);
+ return ret;
+ }
+ /* The dev stats item does not exist, nothing to bother. */
+ if (ret > 0)
+ return 0;
+ ret = btrfs_del_item(trans, dev_root, &path);
+ if (ret < 0) {
+ btrfs_warn(fs_info,
+ "error %d while deleting dev_stats item for devid %llu",
+ ret, devid);
+ return ret;
+ }
+ return 0;
+}
+
int btrfs_rm_device(struct btrfs_fs_info *fs_info,
struct btrfs_dev_lookup_args *args,
struct file **bdev_file)
u64 *pending_start, u64 *pending_end);
bool btrfs_find_hole_in_pending_extents(struct btrfs_device *device,
u64 *start, u64 *len, u64 min_hole_size);
+int btrfs_remove_dev_stat_item(struct btrfs_trans_handle *trans, u64 devid);
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
struct btrfs_io_context *alloc_btrfs_io_context(struct btrfs_fs_info *fs_info,