|
@@ -3582,6 +3582,46 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
|
|
*/
|
|
*/
|
|
scrub_pause_on(fs_info);
|
|
scrub_pause_on(fs_info);
|
|
ret = btrfs_inc_block_group_ro(root, cache);
|
|
ret = btrfs_inc_block_group_ro(root, cache);
|
|
|
|
+ if (!ret && is_dev_replace) {
|
|
|
|
+ /*
|
|
|
|
+ * If we are doing a device replace wait for any tasks
|
|
|
|
+ * that started dellaloc right before we set the block
|
|
|
|
+ * group to RO mode, as they might have just allocated
|
|
|
|
+ * an extent from it or decided they could do a nocow
|
|
|
|
+ * write. And if any such tasks did that, wait for their
|
|
|
|
+ * ordered extents to complete and then commit the
|
|
|
|
+ * current transaction, so that we can later see the new
|
|
|
|
+ * extent items in the extent tree - the ordered extents
|
|
|
|
+ * create delayed data references (for cow writes) when
|
|
|
|
+ * they complete, which will be run and insert the
|
|
|
|
+ * corresponding extent items into the extent tree when
|
|
|
|
+ * we commit the transaction they used when running
|
|
|
|
+ * inode.c:btrfs_finish_ordered_io(). We later use
|
|
|
|
+ * the commit root of the extent tree to find extents
|
|
|
|
+ * to copy from the srcdev into the tgtdev, and we don't
|
|
|
|
+ * want to miss any new extents.
|
|
|
|
+ */
|
|
|
|
+ btrfs_wait_block_group_reservations(cache);
|
|
|
|
+ btrfs_wait_nocow_writers(cache);
|
|
|
|
+ ret = btrfs_wait_ordered_roots(fs_info, -1,
|
|
|
|
+ cache->key.objectid,
|
|
|
|
+ cache->key.offset);
|
|
|
|
+ if (ret > 0) {
|
|
|
|
+ struct btrfs_trans_handle *trans;
|
|
|
|
+
|
|
|
|
+ trans = btrfs_join_transaction(root);
|
|
|
|
+ if (IS_ERR(trans))
|
|
|
|
+ ret = PTR_ERR(trans);
|
|
|
|
+ else
|
|
|
|
+ ret = btrfs_commit_transaction(trans,
|
|
|
|
+ root);
|
|
|
|
+ if (ret) {
|
|
|
|
+ scrub_pause_off(fs_info);
|
|
|
|
+ btrfs_put_block_group(cache);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
scrub_pause_off(fs_info);
|
|
scrub_pause_off(fs_info);
|
|
|
|
|
|
if (ret == 0) {
|
|
if (ret == 0) {
|