On 11/15/2018 11:31 PM, David Sterba wrote:
On Sun, Nov 11, 2018 at 10:22:23PM +0800, Anand Jain wrote:
As of now only user requested replace cancel can cancel the replace-scrub
so no need to log error for it.

This has probably some user visible effect or threre are steps to
reproduce the message even if it's not expected (ie. the case that this
patch fixes). Please update the changelog, thanks.




before the patch [1]
  [1]
    btrfs: fix use-after-free due to race between replace start and cancel

 We used to set the replace_state to CANCELED [2] and then call
 btrfs_scrub_cancel(), but the problem with this approach is
 if the scrub isn't running yet, then things get messier.

[2]
-       dev_replace->replace_state = BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED;

 So to fix, [1] shall set replace_state to CANCELED only after the
 replace cancel thread has successfully canceled the replace using
 btrfs_scrub_cancel().

 And about the cleanup process for the replace target..
 we call
   btrfs_dev_replace_finishing(.. ret)
 after
  ret= btrfs_scrub_dev()

 now ret is -ECANCELED due to replace cancel request by the user.
 (its not set to -ECANCELED for any other reason).

 btrfs_dev_replace_finishing() has the following code [3] which it
 earlier blocked processing of the cleanup process after the cancel,
 because the replace_state was already updated to
 BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED.


[3]
--------------
static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
                                       int scrub_ret)
{

::
        /* was the operation canceled, or is it finished? */
        if (dev_replace->replace_state !=
            BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED) {
                btrfs_dev_replace_read_unlock(dev_replace);
                mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
                return 0;
        }
-----------

 In fact before this patch [1] the code wasn't sync-ing the IO
 when replace was canceled. Which this patch also fixes by using
 the  btrfs_dev_replace_finishing()


-----------
btrfs_dev_replace_finishing
::
        /*
         * flush all outstanding I/O and inode extent mappings before the
         * copy operation is declared as being finished
         */
        ret = btrfs_start_delalloc_roots(fs_info, -1);
        if (ret) {
                mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
                return ret;
        }
        btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1);
-----------

 So to answer above question... these warn and error log wasn't
 reported before when replace was canceled and now since I am
 using the btrfs_dev_replace_finishing() to finish the job
 of cancel.. it shall be reported which is ok to quite.

 Do you think we still need to update the change log?

HTH.

Thanks, Anand

Reply via email to