diff options
Diffstat (limited to 'fs/btrfs/relocation.c')
| -rw-r--r-- | fs/btrfs/relocation.c | 13 | 
1 files changed, 7 insertions, 6 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 8dd8de6b9fb8..0765e06d00b8 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -3780,6 +3780,7 @@ out:  /*   * Mark start of chunk relocation that is cancellable. Check if the cancellation   * has been requested meanwhile and don't start in that case. + * NOTE: if this returns an error, reloc_chunk_end() must not be called.   *   * Return:   *   0             success @@ -3796,10 +3797,8 @@ static int reloc_chunk_start(struct btrfs_fs_info *fs_info)  	if (atomic_read(&fs_info->reloc_cancel_req) > 0) {  		btrfs_info(fs_info, "chunk relocation canceled on start"); -		/* -		 * On cancel, clear all requests but let the caller mark -		 * the end after cleanup operations. -		 */ +		/* On cancel, clear all requests. */ +		clear_and_wake_up_bit(BTRFS_FS_RELOC_RUNNING, &fs_info->flags);  		atomic_set(&fs_info->reloc_cancel_req, 0);  		return -ECANCELED;  	} @@ -3808,9 +3807,11 @@ static int reloc_chunk_start(struct btrfs_fs_info *fs_info)  /*   * Mark end of chunk relocation that is cancellable and wake any waiters. + * NOTE: call only if a previous call to reloc_chunk_start() succeeded.   */  static void reloc_chunk_end(struct btrfs_fs_info *fs_info)  { +	ASSERT(test_bit(BTRFS_FS_RELOC_RUNNING, &fs_info->flags));  	/* Requested after start, clear bit first so any waiters can continue */  	if (atomic_read(&fs_info->reloc_cancel_req) > 0)  		btrfs_info(fs_info, "chunk relocation canceled during operation"); @@ -4023,9 +4024,9 @@ out:  	if (err && rw)  		btrfs_dec_block_group_ro(rc->block_group);  	iput(rc->data_inode); +	reloc_chunk_end(fs_info);  out_put_bg:  	btrfs_put_block_group(bg); -	reloc_chunk_end(fs_info);  	free_reloc_control(rc);  	return err;  } @@ -4208,8 +4209,8 @@ out_clean:  		ret = ret2;  out_unset:  	unset_reloc_control(rc); -out_end:  	reloc_chunk_end(fs_info); +out_end:  	free_reloc_control(rc);  out:  	free_reloc_roots(&reloc_roots);  | 
