Blame view

fs/btrfs/dev-replace.c 34.2 KB
c1d7c514f   David Sterba   btrfs: replace GP...
1
  // SPDX-License-Identifier: GPL-2.0
e93c89c1a   Stefan Behrens   Btrfs: add new so...
2
3
  /*
   * Copyright (C) STRATO AG 2012.  All rights reserved.
e93c89c1a   Stefan Behrens   Btrfs: add new so...
4
   */
c1d7c514f   David Sterba   btrfs: replace GP...
5

e93c89c1a   Stefan Behrens   Btrfs: add new so...
6
7
8
  #include <linux/sched.h>
  #include <linux/bio.h>
  #include <linux/slab.h>
e93c89c1a   Stefan Behrens   Btrfs: add new so...
9
  #include <linux/blkdev.h>
e93c89c1a   Stefan Behrens   Btrfs: add new so...
10
11
  #include <linux/kthread.h>
  #include <linux/math64.h>
602cbe91f   David Sterba   btrfs: move cond_...
12
  #include "misc.h"
e93c89c1a   Stefan Behrens   Btrfs: add new so...
13
14
15
16
17
18
19
20
21
22
  #include "ctree.h"
  #include "extent_map.h"
  #include "disk-io.h"
  #include "transaction.h"
  #include "print-tree.h"
  #include "volumes.h"
  #include "async-thread.h"
  #include "check-integrity.h"
  #include "rcu-string.h"
  #include "dev-replace.h"
49c6f736f   Anand Jain   btrfs: dev replac...
23
  #include "sysfs.h"
e93c89c1a   Stefan Behrens   Btrfs: add new so...
24

30b3688e1   Qu Wenruo   btrfs: Add overvi...
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
  /*
   * Device replace overview
   *
   * [Objective]
   * To copy all extents (both new and on-disk) from source device to target
   * device, while still keeping the filesystem read-write.
   *
   * [Method]
   * There are two main methods involved:
   *
   * - Write duplication
   *
   *   All new writes will be written to both target and source devices, so even
   *   if replace gets canceled, sources device still contans up-to-date data.
   *
   *   Location:		handle_ops_on_dev_replace() from __btrfs_map_block()
   *   Start:		btrfs_dev_replace_start()
   *   End:		btrfs_dev_replace_finishing()
   *   Content:		Latest data/metadata
   *
   * - Copy existing extents
   *
   *   This happens by re-using scrub facility, as scrub also iterates through
   *   existing extents from commit root.
   *
   *   Location:		scrub_write_block_to_dev_replace() from
   *   			scrub_block_complete()
   *   Content:		Data/meta from commit root.
   *
   * Due to the content difference, we need to avoid nocow write when dev-replace
   * is happening.  This is done by marking the block group read-only and waiting
   * for NOCOW writes.
   *
   * After replace is done, the finishing part is done by swapping the target and
   * source devices.
   *
   *   Location:		btrfs_dev_replace_update_device_in_mapping_tree() from
   *   			btrfs_dev_replace_finishing()
   */
e93c89c1a   Stefan Behrens   Btrfs: add new so...
64
65
  static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
  				       int scrub_ret);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
66
  static int btrfs_dev_replace_kthread(void *data);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
  
  int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
  {
  	struct btrfs_key key;
  	struct btrfs_root *dev_root = fs_info->dev_root;
  	struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
  	struct extent_buffer *eb;
  	int slot;
  	int ret = 0;
  	struct btrfs_path *path = NULL;
  	int item_size;
  	struct btrfs_dev_replace_item *ptr;
  	u64 src_devid;
  
  	path = btrfs_alloc_path();
  	if (!path) {
  		ret = -ENOMEM;
  		goto out;
  	}
  
  	key.objectid = 0;
  	key.type = BTRFS_DEV_REPLACE_KEY;
  	key.offset = 0;
  	ret = btrfs_search_slot(NULL, dev_root, &key, path, 0, 0);
  	if (ret) {
  no_valid_dev_replace_entry_found:
cf89af146   Anand Jain   btrfs: dev-replac...
93
94
95
96
97
98
99
100
101
102
103
  		/*
  		 * We don't have a replace item or it's corrupted.  If there is
  		 * a replace target, fail the mount.
  		 */
  		if (btrfs_find_device(fs_info->fs_devices,
  				      BTRFS_DEV_REPLACE_DEVID, NULL, NULL, false)) {
  			btrfs_err(fs_info,
  			"found replace target device without a valid replace item");
  			ret = -EUCLEAN;
  			goto out;
  		}
e93c89c1a   Stefan Behrens   Btrfs: add new so...
104
105
  		ret = 0;
  		dev_replace->replace_state =
27e022a9c   Anand Jain   btrfs: replace: B...
106
  			BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
107
108
  		dev_replace->cont_reading_from_srcdev_mode =
  		    BTRFS_DEV_REPLACE_ITEM_CONT_READING_FROM_SRCDEV_MODE_ALWAYS;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
  		dev_replace->time_started = 0;
  		dev_replace->time_stopped = 0;
  		atomic64_set(&dev_replace->num_write_errors, 0);
  		atomic64_set(&dev_replace->num_uncorrectable_read_errors, 0);
  		dev_replace->cursor_left = 0;
  		dev_replace->committed_cursor_left = 0;
  		dev_replace->cursor_left_last_write_of_item = 0;
  		dev_replace->cursor_right = 0;
  		dev_replace->srcdev = NULL;
  		dev_replace->tgtdev = NULL;
  		dev_replace->is_valid = 0;
  		dev_replace->item_needs_writeback = 0;
  		goto out;
  	}
  	slot = path->slots[0];
  	eb = path->nodes[0];
  	item_size = btrfs_item_size_nr(eb, slot);
  	ptr = btrfs_item_ptr(eb, slot, struct btrfs_dev_replace_item);
  
  	if (item_size != sizeof(struct btrfs_dev_replace_item)) {
efe120a06   Frank Holton   Btrfs: convert pr...
129
130
  		btrfs_warn(fs_info,
  			"dev_replace entry found has unexpected size, ignore entry");
e93c89c1a   Stefan Behrens   Btrfs: add new so...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
  		goto no_valid_dev_replace_entry_found;
  	}
  
  	src_devid = btrfs_dev_replace_src_devid(eb, ptr);
  	dev_replace->cont_reading_from_srcdev_mode =
  		btrfs_dev_replace_cont_reading_from_srcdev_mode(eb, ptr);
  	dev_replace->replace_state = btrfs_dev_replace_replace_state(eb, ptr);
  	dev_replace->time_started = btrfs_dev_replace_time_started(eb, ptr);
  	dev_replace->time_stopped =
  		btrfs_dev_replace_time_stopped(eb, ptr);
  	atomic64_set(&dev_replace->num_write_errors,
  		     btrfs_dev_replace_num_write_errors(eb, ptr));
  	atomic64_set(&dev_replace->num_uncorrectable_read_errors,
  		     btrfs_dev_replace_num_uncorrectable_read_errors(eb, ptr));
  	dev_replace->cursor_left = btrfs_dev_replace_cursor_left(eb, ptr);
  	dev_replace->committed_cursor_left = dev_replace->cursor_left;
  	dev_replace->cursor_left_last_write_of_item = dev_replace->cursor_left;
  	dev_replace->cursor_right = btrfs_dev_replace_cursor_right(eb, ptr);
  	dev_replace->is_valid = 1;
  
  	dev_replace->item_needs_writeback = 0;
  	switch (dev_replace->replace_state) {
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
cf89af146   Anand Jain   btrfs: dev-replac...
156
157
158
159
160
161
162
163
164
165
166
167
168
  		/*
  		 * We don't have an active replace item but if there is a
  		 * replace target, fail the mount.
  		 */
  		if (btrfs_find_device(fs_info->fs_devices,
  				      BTRFS_DEV_REPLACE_DEVID, NULL, NULL, false)) {
  			btrfs_err(fs_info,
  			"replace devid present without an active replace item");
  			ret = -EUCLEAN;
  		} else {
  			dev_replace->srcdev = NULL;
  			dev_replace->tgtdev = NULL;
  		}
e93c89c1a   Stefan Behrens   Btrfs: add new so...
169
170
171
  		break;
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
e4319cd9c   Anand Jain   btrfs: refactor b...
172
  		dev_replace->srcdev = btrfs_find_device(fs_info->fs_devices,
09ba3bc9d   Anand Jain   btrfs: merge btrf...
173
  						src_devid, NULL, NULL, true);
e4319cd9c   Anand Jain   btrfs: refactor b...
174
  		dev_replace->tgtdev = btrfs_find_device(fs_info->fs_devices,
e93c89c1a   Stefan Behrens   Btrfs: add new so...
175
  							BTRFS_DEV_REPLACE_DEVID,
09ba3bc9d   Anand Jain   btrfs: merge btrf...
176
  							NULL, NULL, true);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
177
178
179
180
181
  		/*
  		 * allow 'btrfs dev replace_cancel' if src/tgt device is
  		 * missing
  		 */
  		if (!dev_replace->srcdev &&
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
182
  		    !btrfs_test_opt(fs_info, DEGRADED)) {
e93c89c1a   Stefan Behrens   Btrfs: add new so...
183
  			ret = -EIO;
efe120a06   Frank Holton   Btrfs: convert pr...
184
185
186
187
188
  			btrfs_warn(fs_info,
  			   "cannot mount because device replace operation is ongoing and");
  			btrfs_warn(fs_info,
  			   "srcdev (devid %llu) is missing, need to run 'btrfs dev scan'?",
  			   src_devid);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
189
190
  		}
  		if (!dev_replace->tgtdev &&
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
191
  		    !btrfs_test_opt(fs_info, DEGRADED)) {
e93c89c1a   Stefan Behrens   Btrfs: add new so...
192
  			ret = -EIO;
efe120a06   Frank Holton   Btrfs: convert pr...
193
194
195
196
  			btrfs_warn(fs_info,
  			   "cannot mount because device replace operation is ongoing and");
  			btrfs_warn(fs_info,
  			   "tgtdev (devid %llu) is missing, need to run 'btrfs dev scan'?",
6e71c47af   Geert Uytterhoeven   Btrfs: Make BTRFS...
197
  				BTRFS_DEV_REPLACE_DEVID);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
198
199
200
201
202
203
204
  		}
  		if (dev_replace->tgtdev) {
  			if (dev_replace->srcdev) {
  				dev_replace->tgtdev->total_bytes =
  					dev_replace->srcdev->total_bytes;
  				dev_replace->tgtdev->disk_total_bytes =
  					dev_replace->srcdev->disk_total_bytes;
935e5cc93   Miao Xie   Btrfs: fix wrong ...
205
206
  				dev_replace->tgtdev->commit_total_bytes =
  					dev_replace->srcdev->commit_total_bytes;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
207
208
  				dev_replace->tgtdev->bytes_used =
  					dev_replace->srcdev->bytes_used;
ce7213c70   Miao Xie   Btrfs: fix wrong ...
209
210
  				dev_replace->tgtdev->commit_bytes_used =
  					dev_replace->srcdev->commit_bytes_used;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
211
  			}
401e29c12   Anand Jain   btrfs: cleanup de...
212
213
  			set_bit(BTRFS_DEV_STATE_REPLACE_TGT,
  				&dev_replace->tgtdev->dev_state);
15fc1283f   Anand Jain   btrfs: open code ...
214
215
216
217
218
219
220
221
  
  			WARN_ON(fs_info->fs_devices->rw_devices == 0);
  			dev_replace->tgtdev->io_width = fs_info->sectorsize;
  			dev_replace->tgtdev->io_align = fs_info->sectorsize;
  			dev_replace->tgtdev->sector_size = fs_info->sectorsize;
  			dev_replace->tgtdev->fs_info = fs_info;
  			set_bit(BTRFS_DEV_STATE_IN_FS_METADATA,
  				&dev_replace->tgtdev->dev_state);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
222
223
224
225
226
  		}
  		break;
  	}
  
  out:
527afb449   Tsutomu Itoh   Btrfs: cleanup: r...
227
  	btrfs_free_path(path);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
228
229
230
231
  	return ret;
  }
  
  /*
d48f39d5a   David Sterba   btrfs: move btrfs...
232
233
234
235
236
237
238
239
240
241
242
243
   * Initialize a new device for device replace target from a given source dev
   * and path.
   *
   * Return 0 and new device in @device_out, otherwise return < 0
   */
  static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
  				  const char *device_path,
  				  struct btrfs_device *srcdev,
  				  struct btrfs_device **device_out)
  {
  	struct btrfs_device *device;
  	struct block_device *bdev;
d48f39d5a   David Sterba   btrfs: move btrfs...
244
245
246
247
248
  	struct rcu_string *name;
  	u64 devid = BTRFS_DEV_REPLACE_DEVID;
  	int ret = 0;
  
  	*device_out = NULL;
c6a5d9549   Anand Jain   btrfs: fix replac...
249
  	if (srcdev->fs_devices->seeding) {
d48f39d5a   David Sterba   btrfs: move btrfs...
250
251
252
253
254
255
256
257
258
259
  		btrfs_err(fs_info, "the filesystem is a seed filesystem!");
  		return -EINVAL;
  	}
  
  	bdev = blkdev_get_by_path(device_path, FMODE_WRITE | FMODE_EXCL,
  				  fs_info->bdev_holder);
  	if (IS_ERR(bdev)) {
  		btrfs_err(fs_info, "target device %s is invalid!", device_path);
  		return PTR_ERR(bdev);
  	}
ddb937846   Nikolay Borisov   btrfs: Don't open...
260
  	sync_blockdev(bdev);
d48f39d5a   David Sterba   btrfs: move btrfs...
261

1888709d7   Anand Jain   btrfs: remove tmp...
262
  	list_for_each_entry(device, &fs_info->fs_devices->devices, dev_list) {
d48f39d5a   David Sterba   btrfs: move btrfs...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
  		if (device->bdev == bdev) {
  			btrfs_err(fs_info,
  				  "target device is in the filesystem!");
  			ret = -EEXIST;
  			goto error;
  		}
  	}
  
  
  	if (i_size_read(bdev->bd_inode) <
  	    btrfs_device_get_total_bytes(srcdev)) {
  		btrfs_err(fs_info,
  			  "target device is smaller than source device!");
  		ret = -EINVAL;
  		goto error;
  	}
  
  
  	device = btrfs_alloc_device(NULL, &devid, NULL);
  	if (IS_ERR(device)) {
  		ret = PTR_ERR(device);
  		goto error;
  	}
  
  	name = rcu_string_strdup(device_path, GFP_KERNEL);
  	if (!name) {
  		btrfs_free_device(device);
  		ret = -ENOMEM;
  		goto error;
  	}
  	rcu_assign_pointer(device->name, name);
d48f39d5a   David Sterba   btrfs: move btrfs...
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
  	set_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state);
  	device->generation = 0;
  	device->io_width = fs_info->sectorsize;
  	device->io_align = fs_info->sectorsize;
  	device->sector_size = fs_info->sectorsize;
  	device->total_bytes = btrfs_device_get_total_bytes(srcdev);
  	device->disk_total_bytes = btrfs_device_get_disk_total_bytes(srcdev);
  	device->bytes_used = btrfs_device_get_bytes_used(srcdev);
  	device->commit_total_bytes = srcdev->commit_total_bytes;
  	device->commit_bytes_used = device->bytes_used;
  	device->fs_info = fs_info;
  	device->bdev = bdev;
  	set_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state);
  	set_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state);
  	device->mode = FMODE_EXCL;
  	device->dev_stats_valid = 1;
  	set_blocksize(device->bdev, BTRFS_BDEV_BLOCKSIZE);
  	device->fs_devices = fs_info->fs_devices;
b0d9e1ea1   Nikolay Borisov   btrfs: Reduce cri...
312
313
  
  	mutex_lock(&fs_info->fs_devices->device_list_mutex);
d48f39d5a   David Sterba   btrfs: move btrfs...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
  	list_add(&device->dev_list, &fs_info->fs_devices->devices);
  	fs_info->fs_devices->num_devices++;
  	fs_info->fs_devices->open_devices++;
  	mutex_unlock(&fs_info->fs_devices->device_list_mutex);
  
  	*device_out = device;
  	return 0;
  
  error:
  	blkdev_put(bdev, FMODE_EXCL);
  	return ret;
  }
  
  /*
e93c89c1a   Stefan Behrens   Btrfs: add new so...
328
329
330
   * called from commit_transaction. Writes changed device replace state to
   * disk.
   */
2b584c688   David Sterba   btrfs: get fs_inf...
331
  int btrfs_run_dev_replace(struct btrfs_trans_handle *trans)
e93c89c1a   Stefan Behrens   Btrfs: add new so...
332
  {
2b584c688   David Sterba   btrfs: get fs_inf...
333
  	struct btrfs_fs_info *fs_info = trans->fs_info;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
334
335
336
337
338
339
340
  	int ret;
  	struct btrfs_root *dev_root = fs_info->dev_root;
  	struct btrfs_path *path;
  	struct btrfs_key key;
  	struct extent_buffer *eb;
  	struct btrfs_dev_replace_item *ptr;
  	struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
cb5583dd5   David Sterba   btrfs: dev-replac...
341
  	down_read(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
342
343
  	if (!dev_replace->is_valid ||
  	    !dev_replace->item_needs_writeback) {
cb5583dd5   David Sterba   btrfs: dev-replac...
344
  		up_read(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
345
346
  		return 0;
  	}
cb5583dd5   David Sterba   btrfs: dev-replac...
347
  	up_read(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
348
349
350
351
352
353
354
355
356
357
358
359
  
  	key.objectid = 0;
  	key.type = BTRFS_DEV_REPLACE_KEY;
  	key.offset = 0;
  
  	path = btrfs_alloc_path();
  	if (!path) {
  		ret = -ENOMEM;
  		goto out;
  	}
  	ret = btrfs_search_slot(trans, dev_root, &key, path, -1, 1);
  	if (ret < 0) {
5d163e0e6   Jeff Mahoney   btrfs: unsplit pr...
360
361
362
  		btrfs_warn(fs_info,
  			   "error %d while searching for dev_replace item!",
  			   ret);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
  		goto out;
  	}
  
  	if (ret == 0 &&
  	    btrfs_item_size_nr(path->nodes[0], path->slots[0]) < sizeof(*ptr)) {
  		/*
  		 * need to delete old one and insert a new one.
  		 * Since no attempt is made to recover any old state, if the
  		 * dev_replace state is 'running', the data on the target
  		 * drive is lost.
  		 * It would be possible to recover the state: just make sure
  		 * that the beginning of the item is never changed and always
  		 * contains all the essential information. Then read this
  		 * minimal set of information and use it as a base for the
  		 * new state.
  		 */
  		ret = btrfs_del_item(trans, dev_root, path);
  		if (ret != 0) {
5d163e0e6   Jeff Mahoney   btrfs: unsplit pr...
381
382
383
  			btrfs_warn(fs_info,
  				   "delete too small dev_replace item failed %d!",
  				   ret);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
384
385
386
387
388
389
390
391
392
393
394
  			goto out;
  		}
  		ret = 1;
  	}
  
  	if (ret == 1) {
  		/* need to insert a new item */
  		btrfs_release_path(path);
  		ret = btrfs_insert_empty_item(trans, dev_root, path,
  					      &key, sizeof(*ptr));
  		if (ret < 0) {
5d163e0e6   Jeff Mahoney   btrfs: unsplit pr...
395
396
  			btrfs_warn(fs_info,
  				   "insert dev_replace item failed %d!", ret);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
397
398
399
400
401
402
403
  			goto out;
  		}
  	}
  
  	eb = path->nodes[0];
  	ptr = btrfs_item_ptr(eb, path->slots[0],
  			     struct btrfs_dev_replace_item);
cb5583dd5   David Sterba   btrfs: dev-replac...
404
  	down_write(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
  	if (dev_replace->srcdev)
  		btrfs_set_dev_replace_src_devid(eb, ptr,
  			dev_replace->srcdev->devid);
  	else
  		btrfs_set_dev_replace_src_devid(eb, ptr, (u64)-1);
  	btrfs_set_dev_replace_cont_reading_from_srcdev_mode(eb, ptr,
  		dev_replace->cont_reading_from_srcdev_mode);
  	btrfs_set_dev_replace_replace_state(eb, ptr,
  		dev_replace->replace_state);
  	btrfs_set_dev_replace_time_started(eb, ptr, dev_replace->time_started);
  	btrfs_set_dev_replace_time_stopped(eb, ptr, dev_replace->time_stopped);
  	btrfs_set_dev_replace_num_write_errors(eb, ptr,
  		atomic64_read(&dev_replace->num_write_errors));
  	btrfs_set_dev_replace_num_uncorrectable_read_errors(eb, ptr,
  		atomic64_read(&dev_replace->num_uncorrectable_read_errors));
  	dev_replace->cursor_left_last_write_of_item =
  		dev_replace->cursor_left;
  	btrfs_set_dev_replace_cursor_left(eb, ptr,
  		dev_replace->cursor_left_last_write_of_item);
  	btrfs_set_dev_replace_cursor_right(eb, ptr,
  		dev_replace->cursor_right);
  	dev_replace->item_needs_writeback = 0;
cb5583dd5   David Sterba   btrfs: dev-replac...
427
  	up_write(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
428
429
430
431
432
433
434
435
  
  	btrfs_mark_buffer_dirty(eb);
  
  out:
  	btrfs_free_path(path);
  
  	return ret;
  }
3c958bd23   Anand Jain   btrfs: add helper...
436
437
  static char* btrfs_dev_name(struct btrfs_device *device)
  {
acf18c56f   Anand Jain   btrfs: fix null p...
438
  	if (!device || test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state))
3c958bd23   Anand Jain   btrfs: add helper...
439
440
441
442
  		return "<missing disk>";
  	else
  		return rcu_str_deref(device->name);
  }
54862d6d2   Anand Jain   btrfs: mark btrfs...
443
  static int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
da353f6b3   David Sterba   btrfs: constify d...
444
445
  		const char *tgtdev_name, u64 srcdevid, const char *srcdev_name,
  		int read_src)
e93c89c1a   Stefan Behrens   Btrfs: add new so...
446
  {
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
447
  	struct btrfs_root *root = fs_info->dev_root;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
448
  	struct btrfs_trans_handle *trans;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
449
450
451
452
  	struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
  	int ret;
  	struct btrfs_device *tgt_device = NULL;
  	struct btrfs_device *src_device = NULL;
a27a94c2b   Nikolay Borisov   btrfs: Make btrfs...
453
454
455
456
  	src_device = btrfs_find_device_by_devspec(fs_info, srcdevid,
  						  srcdev_name);
  	if (IS_ERR(src_device))
  		return PTR_ERR(src_device);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
457

eede2bf34   Omar Sandoval   Btrfs: prevent io...
458
459
460
461
462
463
  	if (btrfs_pinned_by_swapfile(fs_info, src_device)) {
  		btrfs_warn_in_rcu(fs_info,
  	  "cannot replace device %s (devid %llu) due to active swapfile",
  			btrfs_dev_name(src_device), src_device->devid);
  		return -ETXTBSY;
  	}
9e271ae27   Anand Jain   Btrfs: kernel ope...
464
465
466
467
468
469
  	/*
  	 * Here we commit the transaction to make sure commit_total_bytes
  	 * of all the devices are updated.
  	 */
  	trans = btrfs_attach_transaction(root);
  	if (!IS_ERR(trans)) {
3a45bb207   Jeff Mahoney   btrfs: remove roo...
470
  		ret = btrfs_commit_transaction(trans);
9e271ae27   Anand Jain   Btrfs: kernel ope...
471
472
473
474
475
  		if (ret)
  			return ret;
  	} else if (PTR_ERR(trans) != -ENOENT) {
  		return PTR_ERR(trans);
  	}
e1e0eb43c   Nikolay Borisov   btrfs: Ensure btr...
476
477
478
479
  	ret = btrfs_init_dev_replace_tgtdev(fs_info, tgtdev_name,
  					    src_device, &tgt_device);
  	if (ret)
  		return ret;
cb5583dd5   David Sterba   btrfs: dev-replac...
480
  	down_write(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
481
482
483
484
485
486
487
  	switch (dev_replace->replace_state) {
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
  		break;
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
5c0614712   Jeff Mahoney   btrfs: fix error ...
488
  		ASSERT(0);
b5255456c   Anand Jain   btrfs: refactor b...
489
  		ret = BTRFS_IOCTL_DEV_REPLACE_RESULT_ALREADY_STARTED;
fa19452a4   Nikolay Borisov   btrfs: Streamline...
490
  		up_write(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
491
492
  		goto leave;
  	}
b5255456c   Anand Jain   btrfs: refactor b...
493
  	dev_replace->cont_reading_from_srcdev_mode = read_src;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
494
  	dev_replace->srcdev = src_device;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
495
  	dev_replace->tgtdev = tgt_device;
fc23c246d   Anand Jain   btrfs: use fs_inf...
496
  	btrfs_info_in_rcu(fs_info,
ecaeb14b9   David Sterba   btrfs: switch mes...
497
  		      "dev_replace from %s (devid %llu) to %s started",
3c958bd23   Anand Jain   btrfs: add helper...
498
  		      btrfs_dev_name(src_device),
e93c89c1a   Stefan Behrens   Btrfs: add new so...
499
500
  		      src_device->devid,
  		      rcu_str_deref(tgt_device->name));
e93c89c1a   Stefan Behrens   Btrfs: add new so...
501
502
503
504
505
  	/*
  	 * from now on, the writes to the srcdev are all duplicated to
  	 * go to the tgtdev as well (refer to btrfs_map_block()).
  	 */
  	dev_replace->replace_state = BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED;
a944442c2   Allen Pais   btrfs: replace ge...
506
  	dev_replace->time_started = ktime_get_real_seconds();
e93c89c1a   Stefan Behrens   Btrfs: add new so...
507
508
509
510
511
512
  	dev_replace->cursor_left = 0;
  	dev_replace->committed_cursor_left = 0;
  	dev_replace->cursor_left_last_write_of_item = 0;
  	dev_replace->cursor_right = 0;
  	dev_replace->is_valid = 1;
  	dev_replace->item_needs_writeback = 1;
7ccefb98c   Yauhen Kharuzhy   btrfs: Reset IO e...
513
514
  	atomic64_set(&dev_replace->num_write_errors, 0);
  	atomic64_set(&dev_replace->num_uncorrectable_read_errors, 0);
cb5583dd5   David Sterba   btrfs: dev-replac...
515
  	up_write(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
516

cd36da2e7   Anand Jain   btrfs: simplify p...
517
  	ret = btrfs_sysfs_add_device(tgt_device);
73416dab2   Liu Bo   Btrfs: move kobj ...
518
  	if (ret)
ab8d0fc48   Jeff Mahoney   btrfs: convert pr...
519
  		btrfs_err(fs_info, "kobj add dev failed %d", ret);
73416dab2   Liu Bo   Btrfs: move kobj ...
520

6374e57ad   Chris Mason   btrfs: fix intege...
521
  	btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
522

f232ab04f   Nikolay Borisov   btrfs: Explicitly...
523
524
  	/* Commit dev_replace state and reserve 1 item for it. */
  	trans = btrfs_start_transaction(root, 1);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
525
526
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
cb5583dd5   David Sterba   btrfs: dev-replac...
527
  		down_write(&dev_replace->rwsem);
5c0614712   Jeff Mahoney   btrfs: fix error ...
528
529
530
531
  		dev_replace->replace_state =
  			BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED;
  		dev_replace->srcdev = NULL;
  		dev_replace->tgtdev = NULL;
fa19452a4   Nikolay Borisov   btrfs: Streamline...
532
  		up_write(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
533
534
  		goto leave;
  	}
3a45bb207   Jeff Mahoney   btrfs: remove roo...
535
  	ret = btrfs_commit_transaction(trans);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
536
537
538
539
  	WARN_ON(ret);
  
  	/* the disk copy procedure reuses the scrub code */
  	ret = btrfs_scrub_dev(fs_info, src_device->devid, 0,
7cc8e58d5   Miao Xie   Btrfs: fix unprot...
540
  			      btrfs_device_get_total_bytes(src_device),
e93c89c1a   Stefan Behrens   Btrfs: add new so...
541
  			      &dev_replace->scrub_progress, 0, 1);
fc23c246d   Anand Jain   btrfs: use fs_inf...
542
  	ret = btrfs_dev_replace_finishing(fs_info, ret);
4cea9037f   David Sterba   btrfs: dev-replac...
543
  	if (ret == -EINPROGRESS)
b5255456c   Anand Jain   btrfs: refactor b...
544
  		ret = BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
545

2fc9f6baa   Eryu Guan   Btrfs: return fai...
546
  	return ret;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
547
548
  
  leave:
4f5ad7bd6   Nikolay Borisov   btrfs: Remove fs_...
549
  	btrfs_destroy_dev_replace_tgtdev(tgt_device);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
550
551
  	return ret;
  }
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
552
  int btrfs_dev_replace_by_ioctl(struct btrfs_fs_info *fs_info,
b5255456c   Anand Jain   btrfs: refactor b...
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
  			    struct btrfs_ioctl_dev_replace_args *args)
  {
  	int ret;
  
  	switch (args->start.cont_reading_from_srcdev_mode) {
  	case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS:
  	case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID:
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	if ((args->start.srcdevid == 0 && args->start.srcdev_name[0] == '\0') ||
  	    args->start.tgtdev_name[0] == '\0')
  		return -EINVAL;
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
568
  	ret = btrfs_dev_replace_start(fs_info, args->start.tgtdev_name,
b5255456c   Anand Jain   btrfs: refactor b...
569
570
571
572
573
  					args->start.srcdevid,
  					args->start.srcdev_name,
  					args->start.cont_reading_from_srcdev_mode);
  	args->result = ret;
  	/* don't warn if EINPROGRESS, someone else might be running scrub */
53e62fb5a   Anand Jain   btrfs: dev-replac...
574
575
576
  	if (ret == BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS ||
  	    ret == BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR)
  		return 0;
b5255456c   Anand Jain   btrfs: refactor b...
577
578
579
  
  	return ret;
  }
c404e0dc2   Miao Xie   Btrfs: fix use-af...
580
  /*
013276101   Nicholas D Steeves   btrfs: fix string...
581
   * blocked until all in-flight bios operations are finished.
c404e0dc2   Miao Xie   Btrfs: fix use-af...
582
583
584
   */
  static void btrfs_rm_dev_replace_blocked(struct btrfs_fs_info *fs_info)
  {
c404e0dc2   Miao Xie   Btrfs: fix use-af...
585
  	set_bit(BTRFS_FS_STATE_DEV_REPLACING, &fs_info->fs_state);
7f8d236ae   David Sterba   btrfs: dev-replac...
586
587
  	wait_event(fs_info->dev_replace.replace_wait, !percpu_counter_sum(
  		   &fs_info->dev_replace.bio_counter));
c404e0dc2   Miao Xie   Btrfs: fix use-af...
588
589
590
591
592
593
594
595
  }
  
  /*
   * we have removed target device, it is safe to allow new bios request.
   */
  static void btrfs_rm_dev_replace_unblocked(struct btrfs_fs_info *fs_info)
  {
  	clear_bit(BTRFS_FS_STATE_DEV_REPLACING, &fs_info->fs_state);
7f8d236ae   David Sterba   btrfs: dev-replac...
596
  	wake_up(&fs_info->dev_replace.replace_wait);
c404e0dc2   Miao Xie   Btrfs: fix use-af...
597
  }
4c8f35327   Filipe Manana   btrfs: fix filesy...
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
  /*
   * When finishing the device replace, before swapping the source device with the
   * target device we must update the chunk allocation state in the target device,
   * as it is empty because replace works by directly copying the chunks and not
   * through the normal chunk allocation path.
   */
  static int btrfs_set_target_alloc_state(struct btrfs_device *srcdev,
  					struct btrfs_device *tgtdev)
  {
  	struct extent_state *cached_state = NULL;
  	u64 start = 0;
  	u64 found_start;
  	u64 found_end;
  	int ret = 0;
  
  	lockdep_assert_held(&srcdev->fs_info->chunk_mutex);
  
  	while (!find_first_extent_bit(&srcdev->alloc_state, start,
  				      &found_start, &found_end,
  				      CHUNK_ALLOCATED, &cached_state)) {
  		ret = set_extent_bits(&tgtdev->alloc_state, found_start,
  				      found_end, CHUNK_ALLOCATED);
  		if (ret)
  			break;
  		start = found_end + 1;
  	}
  
  	free_extent_state(cached_state);
  	return ret;
  }
0725c0c93   Anand Jain   btrfs: move btrfs...
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
  static void btrfs_dev_replace_update_device_in_mapping_tree(
  						struct btrfs_fs_info *fs_info,
  						struct btrfs_device *srcdev,
  						struct btrfs_device *tgtdev)
  {
  	struct extent_map_tree *em_tree = &fs_info->mapping_tree;
  	struct extent_map *em;
  	struct map_lookup *map;
  	u64 start = 0;
  	int i;
  
  	write_lock(&em_tree->lock);
  	do {
  		em = lookup_extent_mapping(em_tree, start, (u64)-1);
  		if (!em)
  			break;
  		map = em->map_lookup;
  		for (i = 0; i < map->num_stripes; i++)
  			if (srcdev == map->stripes[i].dev)
  				map->stripes[i].dev = tgtdev;
  		start = em->start + em->len;
  		free_extent_map(em);
  	} while (start);
  	write_unlock(&em_tree->lock);
  }
e93c89c1a   Stefan Behrens   Btrfs: add new so...
653
654
655
656
657
658
659
660
661
662
663
664
665
  static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
  				       int scrub_ret)
  {
  	struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
  	struct btrfs_device *tgt_device;
  	struct btrfs_device *src_device;
  	struct btrfs_root *root = fs_info->tree_root;
  	u8 uuid_tmp[BTRFS_UUID_SIZE];
  	struct btrfs_trans_handle *trans;
  	int ret = 0;
  
  	/* don't allow cancel or unmount to disturb the finishing procedure */
  	mutex_lock(&dev_replace->lock_finishing_cancel_unmount);
cb5583dd5   David Sterba   btrfs: dev-replac...
666
  	down_read(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
667
668
669
  	/* was the operation canceled, or is it finished? */
  	if (dev_replace->replace_state !=
  	    BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED) {
cb5583dd5   David Sterba   btrfs: dev-replac...
670
  		up_read(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
671
672
673
674
675
676
  		mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
  		return 0;
  	}
  
  	tgt_device = dev_replace->tgtdev;
  	src_device = dev_replace->srcdev;
cb5583dd5   David Sterba   btrfs: dev-replac...
677
  	up_read(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
678

e93c89c1a   Stefan Behrens   Btrfs: add new so...
679
680
681
682
  	/*
  	 * flush all outstanding I/O and inode extent mappings before the
  	 * copy operation is declared as being finished
  	 */
17243f73a   Filipe Manana   btrfs: fix deadlo...
683
  	ret = btrfs_start_delalloc_roots(fs_info, U64_MAX, false);
3edb2a68c   Miao Xie   Btrfs: check the ...
684
685
686
687
  	if (ret) {
  		mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
  		return ret;
  	}
6374e57ad   Chris Mason   btrfs: fix intege...
688
  	btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
689

66d204a16   Filipe Manana   btrfs: fix readah...
690
691
  	if (!scrub_ret)
  		btrfs_reada_remove_dev(src_device);
debd1c065   Nikolay Borisov   btrfs: Ensure rep...
692
693
694
695
696
697
698
699
  	/*
  	 * We have to use this loop approach because at this point src_device
  	 * has to be available for transaction commit to complete, yet new
  	 * chunks shouldn't be allocated on the device.
  	 */
  	while (1) {
  		trans = btrfs_start_transaction(root, 0);
  		if (IS_ERR(trans)) {
66d204a16   Filipe Manana   btrfs: fix readah...
700
  			btrfs_reada_undo_remove_dev(src_device);
debd1c065   Nikolay Borisov   btrfs: Ensure rep...
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
  			mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
  			return PTR_ERR(trans);
  		}
  		ret = btrfs_commit_transaction(trans);
  		WARN_ON(ret);
  
  		/* Prevent write_all_supers() during the finishing procedure */
  		mutex_lock(&fs_info->fs_devices->device_list_mutex);
  		/* Prevent new chunks being allocated on the source device */
  		mutex_lock(&fs_info->chunk_mutex);
  
  		if (!list_empty(&src_device->post_commit_list)) {
  			mutex_unlock(&fs_info->fs_devices->device_list_mutex);
  			mutex_unlock(&fs_info->chunk_mutex);
  		} else {
  			break;
  		}
e93c89c1a   Stefan Behrens   Btrfs: add new so...
718
  	}
e93c89c1a   Stefan Behrens   Btrfs: add new so...
719

cb5583dd5   David Sterba   btrfs: dev-replac...
720
  	down_write(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
721
722
723
724
725
  	dev_replace->replace_state =
  		scrub_ret ? BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED
  			  : BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED;
  	dev_replace->tgtdev = NULL;
  	dev_replace->srcdev = NULL;
a944442c2   Allen Pais   btrfs: replace ge...
726
  	dev_replace->time_stopped = ktime_get_real_seconds();
e93c89c1a   Stefan Behrens   Btrfs: add new so...
727
  	dev_replace->item_needs_writeback = 1;
4c8f35327   Filipe Manana   btrfs: fix filesy...
728
729
730
731
  	/*
  	 * Update allocation state in the new device and replace the old device
  	 * with the new one in the mapping tree.
  	 */
c404e0dc2   Miao Xie   Btrfs: fix use-af...
732
  	if (!scrub_ret) {
4c8f35327   Filipe Manana   btrfs: fix filesy...
733
734
735
  		scrub_ret = btrfs_set_target_alloc_state(src_device, tgt_device);
  		if (scrub_ret)
  			goto error;
c404e0dc2   Miao Xie   Btrfs: fix use-af...
736
737
738
739
  		btrfs_dev_replace_update_device_in_mapping_tree(fs_info,
  								src_device,
  								tgt_device);
  	} else {
f9085abfa   Anand Jain   btrfs: don't repo...
740
741
  		if (scrub_ret != -ECANCELED)
  			btrfs_err_in_rcu(fs_info,
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
742
  				 "btrfs_scrub_dev(%s, %llu, %s) failed %d",
3c958bd23   Anand Jain   btrfs: add helper...
743
  				 btrfs_dev_name(src_device),
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
744
745
  				 src_device->devid,
  				 rcu_str_deref(tgt_device->name), scrub_ret);
4c8f35327   Filipe Manana   btrfs: fix filesy...
746
  error:
cb5583dd5   David Sterba   btrfs: dev-replac...
747
  		up_write(&dev_replace->rwsem);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
748
749
  		mutex_unlock(&fs_info->chunk_mutex);
  		mutex_unlock(&fs_info->fs_devices->device_list_mutex);
66d204a16   Filipe Manana   btrfs: fix readah...
750
  		btrfs_reada_undo_remove_dev(src_device);
ae6529c35   Qu Wenruo   btrfs: Wait for i...
751
  		btrfs_rm_dev_replace_blocked(fs_info);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
752
  		if (tgt_device)
4f5ad7bd6   Nikolay Borisov   btrfs: Remove fs_...
753
  			btrfs_destroy_dev_replace_tgtdev(tgt_device);
ae6529c35   Qu Wenruo   btrfs: Wait for i...
754
  		btrfs_rm_dev_replace_unblocked(fs_info);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
755
  		mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
2fc9f6baa   Eryu Guan   Btrfs: return fai...
756
  		return scrub_ret;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
757
  	}
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
758
759
  	btrfs_info_in_rcu(fs_info,
  			  "dev_replace from %s (devid %llu) to %s finished",
3c958bd23   Anand Jain   btrfs: add helper...
760
  			  btrfs_dev_name(src_device),
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
761
762
  			  src_device->devid,
  			  rcu_str_deref(tgt_device->name));
401e29c12   Anand Jain   btrfs: cleanup de...
763
  	clear_bit(BTRFS_DEV_STATE_REPLACE_TGT, &tgt_device->dev_state);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
764
765
  	tgt_device->devid = src_device->devid;
  	src_device->devid = BTRFS_DEV_REPLACE_DEVID;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
766
767
768
  	memcpy(uuid_tmp, tgt_device->uuid, sizeof(uuid_tmp));
  	memcpy(tgt_device->uuid, src_device->uuid, sizeof(tgt_device->uuid));
  	memcpy(src_device->uuid, uuid_tmp, sizeof(src_device->uuid));
7cc8e58d5   Miao Xie   Btrfs: fix unprot...
769
770
771
772
  	btrfs_device_set_total_bytes(tgt_device, src_device->total_bytes);
  	btrfs_device_set_disk_total_bytes(tgt_device,
  					  src_device->disk_total_bytes);
  	btrfs_device_set_bytes_used(tgt_device, src_device->bytes_used);
ce7213c70   Miao Xie   Btrfs: fix wrong ...
773
  	tgt_device->commit_bytes_used = src_device->bytes_used;
88acff64c   Anand Jain   btrfs: cleanup as...
774

d6507cf1e   Nikolay Borisov   btrfs: Remove fs_...
775
  	btrfs_assign_next_active_device(src_device, tgt_device);
88acff64c   Anand Jain   btrfs: cleanup as...
776

e93c89c1a   Stefan Behrens   Btrfs: add new so...
777
  	list_add(&tgt_device->dev_alloc_list, &fs_info->fs_devices->alloc_list);
82372bc81   Miao Xie   Btrfs: make the l...
778
  	fs_info->fs_devices->rw_devices++;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
779

cb5583dd5   David Sterba   btrfs: dev-replac...
780
  	up_write(&dev_replace->rwsem);
c404e0dc2   Miao Xie   Btrfs: fix use-af...
781
  	btrfs_rm_dev_replace_blocked(fs_info);
68a9db5f2   Nikolay Borisov   btrfs: Remove fs_...
782
  	btrfs_rm_dev_replace_remove_srcdev(src_device);
1357272fc   Ilya Dryomov   Btrfs: fix a use-...
783

c404e0dc2   Miao Xie   Btrfs: fix use-af...
784
  	btrfs_rm_dev_replace_unblocked(fs_info);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
785
  	/*
1e7e1f9e3   Misono Tomohiro   btrfs: replace: R...
786
787
788
789
790
791
  	 * Increment dev_stats_ccnt so that btrfs_run_dev_stats() will
  	 * update on-disk dev stats value during commit transaction
  	 */
  	atomic_inc(&tgt_device->dev_stats_ccnt);
  
  	/*
e93c89c1a   Stefan Behrens   Btrfs: add new so...
792
793
794
795
796
797
  	 * this is again a consistent state where no dev_replace procedure
  	 * is running, the target device is part of the filesystem, the
  	 * source device is not part of the filesystem anymore and its 1st
  	 * superblock is scratched out so that it is no longer marked to
  	 * belong to this filesystem.
  	 */
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
798
799
  	mutex_unlock(&fs_info->chunk_mutex);
  	mutex_unlock(&fs_info->fs_devices->device_list_mutex);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
800

084b6e7c7   Qu Wenruo   btrfs: Fix a lock...
801
  	/* replace the sysfs entry */
53f8a74cb   Anand Jain   btrfs: split and ...
802
  	btrfs_sysfs_remove_device(src_device);
668e48af7   Anand Jain   btrfs: sysfs, add...
803
  	btrfs_sysfs_update_devid(tgt_device);
313b08585   Josef Bacik   btrfs: move btrfs...
804
805
806
  	if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &src_device->dev_state))
  		btrfs_scratch_superblocks(fs_info, src_device->bdev,
  					  src_device->name->str);
084b6e7c7   Qu Wenruo   btrfs: Fix a lock...
807

e93c89c1a   Stefan Behrens   Btrfs: add new so...
808
809
810
  	/* write back the superblocks */
  	trans = btrfs_start_transaction(root, 0);
  	if (!IS_ERR(trans))
3a45bb207   Jeff Mahoney   btrfs: remove roo...
811
  		btrfs_commit_transaction(trans);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
812
813
  
  	mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
a466c85ed   Josef Bacik   btrfs: move btrfs...
814
  	btrfs_rm_dev_replace_free_srcdev(src_device);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
815
816
  	return 0;
  }
74b595fe6   David Sterba   btrfs: factor rea...
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
  /*
   * Read progress of device replace status according to the state and last
   * stored position. The value format is the same as for
   * btrfs_dev_replace::progress_1000
   */
  static u64 btrfs_dev_replace_progress(struct btrfs_fs_info *fs_info)
  {
  	struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
  	u64 ret = 0;
  
  	switch (dev_replace->replace_state) {
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
  		ret = 0;
  		break;
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED:
  		ret = 1000;
  		break;
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
  		ret = div64_u64(dev_replace->cursor_left,
  				div_u64(btrfs_device_get_total_bytes(
  						dev_replace->srcdev), 1000));
  		break;
  	}
  
  	return ret;
  }
e93c89c1a   Stefan Behrens   Btrfs: add new so...
845
846
847
848
  void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info,
  			      struct btrfs_ioctl_dev_replace_args *args)
  {
  	struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
cb5583dd5   David Sterba   btrfs: dev-replac...
849
  	down_read(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
850
851
852
853
854
855
856
857
858
859
  	/* even if !dev_replace_is_valid, the values are good enough for
  	 * the replace_status ioctl */
  	args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR;
  	args->status.replace_state = dev_replace->replace_state;
  	args->status.time_started = dev_replace->time_started;
  	args->status.time_stopped = dev_replace->time_stopped;
  	args->status.num_write_errors =
  		atomic64_read(&dev_replace->num_write_errors);
  	args->status.num_uncorrectable_read_errors =
  		atomic64_read(&dev_replace->num_uncorrectable_read_errors);
74b595fe6   David Sterba   btrfs: factor rea...
860
  	args->status.progress_1000 = btrfs_dev_replace_progress(fs_info);
cb5583dd5   David Sterba   btrfs: dev-replac...
861
  	up_read(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
862
  }
18e67c73d   Anand Jain   btrfs: btrfs_dev_...
863
  int btrfs_dev_replace_cancel(struct btrfs_fs_info *fs_info)
e93c89c1a   Stefan Behrens   Btrfs: add new so...
864
865
866
  {
  	struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
  	struct btrfs_device *tgt_device = NULL;
8f2ceaa7b   Anand Jain   btrfs: log, when ...
867
  	struct btrfs_device *src_device = NULL;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
868
869
  	struct btrfs_trans_handle *trans;
  	struct btrfs_root *root = fs_info->tree_root;
18e67c73d   Anand Jain   btrfs: btrfs_dev_...
870
  	int result;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
871
  	int ret;
bc98a42c1   David Howells   VFS: Convert sb->...
872
  	if (sb_rdonly(fs_info->sb))
e649e587c   Ilya Dryomov   Btrfs: disallow '...
873
  		return -EROFS;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
874
  	mutex_lock(&dev_replace->lock_finishing_cancel_unmount);
cb5583dd5   David Sterba   btrfs: dev-replac...
875
  	down_write(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
876
877
878
879
880
  	switch (dev_replace->replace_state) {
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
  		result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NOT_STARTED;
cb5583dd5   David Sterba   btrfs: dev-replac...
881
  		up_write(&dev_replace->rwsem);
d189dd70e   Anand Jain   btrfs: fix use-af...
882
  		break;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
883
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
d189dd70e   Anand Jain   btrfs: fix use-af...
884
885
  		tgt_device = dev_replace->tgtdev;
  		src_device = dev_replace->srcdev;
cb5583dd5   David Sterba   btrfs: dev-replac...
886
  		up_write(&dev_replace->rwsem);
b47dda2ef   Anand Jain   btrfs: dev-replac...
887
888
889
890
891
892
893
894
895
896
897
898
899
900
  		ret = btrfs_scrub_cancel(fs_info);
  		if (ret < 0) {
  			result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NOT_STARTED;
  		} else {
  			result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR;
  			/*
  			 * btrfs_dev_replace_finishing() will handle the
  			 * cleanup part
  			 */
  			btrfs_info_in_rcu(fs_info,
  				"dev_replace from %s (devid %llu) to %s canceled",
  				btrfs_dev_name(src_device), src_device->devid,
  				btrfs_dev_name(tgt_device));
  		}
d189dd70e   Anand Jain   btrfs: fix use-af...
901
  		break;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
902
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
d189dd70e   Anand Jain   btrfs: fix use-af...
903
904
905
906
  		/*
  		 * Scrub doing the replace isn't running so we need to do the
  		 * cleanup step of btrfs_dev_replace_finishing() here
  		 */
e93c89c1a   Stefan Behrens   Btrfs: add new so...
907
908
  		result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR;
  		tgt_device = dev_replace->tgtdev;
8f2ceaa7b   Anand Jain   btrfs: log, when ...
909
  		src_device = dev_replace->srcdev;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
910
911
  		dev_replace->tgtdev = NULL;
  		dev_replace->srcdev = NULL;
d189dd70e   Anand Jain   btrfs: fix use-af...
912
913
914
915
  		dev_replace->replace_state =
  				BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED;
  		dev_replace->time_stopped = ktime_get_real_seconds();
  		dev_replace->item_needs_writeback = 1;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
916

cb5583dd5   David Sterba   btrfs: dev-replac...
917
  		up_write(&dev_replace->rwsem);
8f2ceaa7b   Anand Jain   btrfs: log, when ...
918

fe97e2e17   Anand Jain   btrfs: dev-replac...
919
920
921
  		/* Scrub for replace must not be running in suspended state */
  		ret = btrfs_scrub_cancel(fs_info);
  		ASSERT(ret != -ENOTCONN);
d189dd70e   Anand Jain   btrfs: fix use-af...
922
923
924
925
926
927
928
929
  
  		trans = btrfs_start_transaction(root, 0);
  		if (IS_ERR(trans)) {
  			mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
  			return PTR_ERR(trans);
  		}
  		ret = btrfs_commit_transaction(trans);
  		WARN_ON(ret);
8f2ceaa7b   Anand Jain   btrfs: log, when ...
930

d189dd70e   Anand Jain   btrfs: fix use-af...
931
932
933
934
935
936
937
938
939
  		btrfs_info_in_rcu(fs_info,
  		"suspended dev_replace from %s (devid %llu) to %s canceled",
  			btrfs_dev_name(src_device), src_device->devid,
  			btrfs_dev_name(tgt_device));
  
  		if (tgt_device)
  			btrfs_destroy_dev_replace_tgtdev(tgt_device);
  		break;
  	default:
669e859b5   Dan Carpenter   btrfs: drop the l...
940
  		up_write(&dev_replace->rwsem);
d189dd70e   Anand Jain   btrfs: fix use-af...
941
942
  		result = -EINVAL;
  	}
e93c89c1a   Stefan Behrens   Btrfs: add new so...
943

e93c89c1a   Stefan Behrens   Btrfs: add new so...
944
945
946
947
948
949
950
951
952
  	mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
  	return result;
  }
  
  void btrfs_dev_replace_suspend_for_unmount(struct btrfs_fs_info *fs_info)
  {
  	struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
  
  	mutex_lock(&dev_replace->lock_finishing_cancel_unmount);
cb5583dd5   David Sterba   btrfs: dev-replac...
953
  	down_write(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
954
955
956
957
958
959
960
961
962
  	switch (dev_replace->replace_state) {
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
  		break;
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
  		dev_replace->replace_state =
  			BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED;
a944442c2   Allen Pais   btrfs: replace ge...
963
  		dev_replace->time_stopped = ktime_get_real_seconds();
e93c89c1a   Stefan Behrens   Btrfs: add new so...
964
  		dev_replace->item_needs_writeback = 1;
efe120a06   Frank Holton   Btrfs: convert pr...
965
  		btrfs_info(fs_info, "suspending dev_replace for unmount");
e93c89c1a   Stefan Behrens   Btrfs: add new so...
966
967
  		break;
  	}
cb5583dd5   David Sterba   btrfs: dev-replac...
968
  	up_write(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
969
970
971
972
973
974
975
976
  	mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
  }
  
  /* resume dev_replace procedure that was interrupted by unmount */
  int btrfs_resume_dev_replace_async(struct btrfs_fs_info *fs_info)
  {
  	struct task_struct *task;
  	struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
cb5583dd5   David Sterba   btrfs: dev-replac...
977
  	down_write(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
978
979
980
981
  	switch (dev_replace->replace_state) {
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
cb5583dd5   David Sterba   btrfs: dev-replac...
982
  		up_write(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
983
984
985
986
987
988
989
990
991
  		return 0;
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
  		break;
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
  		dev_replace->replace_state =
  			BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED;
  		break;
  	}
  	if (!dev_replace->tgtdev || !dev_replace->tgtdev->bdev) {
efe120a06   Frank Holton   Btrfs: convert pr...
992
  		btrfs_info(fs_info,
5d163e0e6   Jeff Mahoney   btrfs: unsplit pr...
993
994
995
  			   "cannot continue dev_replace, tgtdev is missing");
  		btrfs_info(fs_info,
  			   "you may cancel the operation after 'mount -o degraded'");
0d228ece5   Anand Jain   btrfs: dev-replac...
996
997
  		dev_replace->replace_state =
  					BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED;
cb5583dd5   David Sterba   btrfs: dev-replac...
998
  		up_write(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
999
1000
  		return 0;
  	}
cb5583dd5   David Sterba   btrfs: dev-replac...
1001
  	up_write(&dev_replace->rwsem);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
1002

010a47bde   David Sterba   btrfs: add proper...
1003
1004
1005
1006
1007
  	/*
  	 * This could collide with a paused balance, but the exclusive op logic
  	 * should never allow both to start and pause. We don't want to allow
  	 * dev-replace to start anyway.
  	 */
c3e1f96c3   Goldwyn Rodrigues   btrfs: enumerate ...
1008
  	if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_DEV_REPLACE)) {
cb5583dd5   David Sterba   btrfs: dev-replac...
1009
  		down_write(&dev_replace->rwsem);
05c49e6bc   Anand Jain   btrfs: dev-replac...
1010
1011
  		dev_replace->replace_state =
  					BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED;
cb5583dd5   David Sterba   btrfs: dev-replac...
1012
  		up_write(&dev_replace->rwsem);
010a47bde   David Sterba   btrfs: add proper...
1013
1014
1015
1016
  		btrfs_info(fs_info,
  		"cannot resume dev-replace, other exclusive operation running");
  		return 0;
  	}
e93c89c1a   Stefan Behrens   Btrfs: add new so...
1017
  	task = kthread_run(btrfs_dev_replace_kthread, fs_info, "btrfs-devrepl");
8c6ffba0e   Rusty Russell   PTR_RET is now PT...
1018
  	return PTR_ERR_OR_ZERO(task);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
1019
1020
1021
1022
1023
1024
  }
  
  static int btrfs_dev_replace_kthread(void *data)
  {
  	struct btrfs_fs_info *fs_info = data;
  	struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
1025
  	u64 progress;
00251a527   David Sterba   btrfs: squeeze bt...
1026
  	int ret;
e93c89c1a   Stefan Behrens   Btrfs: add new so...
1027

f1b8a1e8c   David Sterba   btrfs: simplify b...
1028
1029
1030
  	progress = btrfs_dev_replace_progress(fs_info);
  	progress = div_u64(progress, 10);
  	btrfs_info_in_rcu(fs_info,
3c958bd23   Anand Jain   btrfs: add helper...
1031
1032
  		"continuing dev_replace from %s (devid %llu) to target %s @%u%%",
  		btrfs_dev_name(dev_replace->srcdev),
f1b8a1e8c   David Sterba   btrfs: simplify b...
1033
  		dev_replace->srcdev->devid,
3c958bd23   Anand Jain   btrfs: add helper...
1034
  		btrfs_dev_name(dev_replace->tgtdev),
f1b8a1e8c   David Sterba   btrfs: simplify b...
1035
  		(unsigned int)progress);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
1036
1037
  	ret = btrfs_scrub_dev(fs_info, dev_replace->srcdev->devid,
  			      dev_replace->committed_cursor_left,
7cc8e58d5   Miao Xie   Btrfs: fix unprot...
1038
  			      btrfs_device_get_total_bytes(dev_replace->srcdev),
e93c89c1a   Stefan Behrens   Btrfs: add new so...
1039
1040
  			      &dev_replace->scrub_progress, 0, 1);
  	ret = btrfs_dev_replace_finishing(fs_info, ret);
49365e697   Anand Jain   btrfs: silence wa...
1041
  	WARN_ON(ret && ret != -ECANCELED);
00251a527   David Sterba   btrfs: squeeze bt...
1042

c3e1f96c3   Goldwyn Rodrigues   btrfs: enumerate ...
1043
  	btrfs_exclop_finish(fs_info);
e93c89c1a   Stefan Behrens   Btrfs: add new so...
1044
1045
  	return 0;
  }
e1f60a658   David Sterba   btrfs: add __pure...
1046
  int __pure btrfs_dev_replace_is_ongoing(struct btrfs_dev_replace *dev_replace)
e93c89c1a   Stefan Behrens   Btrfs: add new so...
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
  {
  	if (!dev_replace->is_valid)
  		return 0;
  
  	switch (dev_replace->replace_state) {
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
  		return 0;
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
  	case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
  		/*
  		 * return true even if tgtdev is missing (this is
  		 * something that can happen if the dev_replace
  		 * procedure is suspended by an umount and then
  		 * the tgtdev is missing (or "btrfs dev scan") was
52042d8e8   Andrea Gelmini   btrfs: Fix typos ...
1063
  		 * not called and the filesystem is remounted
e93c89c1a   Stefan Behrens   Btrfs: add new so...
1064
1065
  		 * in degraded state. This does not stop the
  		 * dev_replace procedure. It needs to be canceled
bb7ab3b92   Adam Buchbinder   btrfs: Fix misspe...
1066
  		 * manually if the cancellation is wanted.
e93c89c1a   Stefan Behrens   Btrfs: add new so...
1067
1068
1069
1070
1071
  		 */
  		break;
  	}
  	return 1;
  }
c404e0dc2   Miao Xie   Btrfs: fix use-af...
1072
1073
  void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info)
  {
7f8d236ae   David Sterba   btrfs: dev-replac...
1074
  	percpu_counter_inc(&fs_info->dev_replace.bio_counter);
c404e0dc2   Miao Xie   Btrfs: fix use-af...
1075
  }
4245215d6   Miao Xie   Btrfs, raid56: fi...
1076
  void btrfs_bio_counter_sub(struct btrfs_fs_info *fs_info, s64 amount)
c404e0dc2   Miao Xie   Btrfs: fix use-af...
1077
  {
7f8d236ae   David Sterba   btrfs: dev-replac...
1078
1079
  	percpu_counter_sub(&fs_info->dev_replace.bio_counter, amount);
  	cond_wake_up_nomb(&fs_info->dev_replace.replace_wait);
c404e0dc2   Miao Xie   Btrfs: fix use-af...
1080
1081
1082
1083
  }
  
  void btrfs_bio_counter_inc_blocked(struct btrfs_fs_info *fs_info)
  {
09dd7a01c   Zhao Lei   Btrfs: Cleanup bt...
1084
  	while (1) {
7f8d236ae   David Sterba   btrfs: dev-replac...
1085
  		percpu_counter_inc(&fs_info->dev_replace.bio_counter);
09dd7a01c   Zhao Lei   Btrfs: Cleanup bt...
1086
1087
1088
  		if (likely(!test_bit(BTRFS_FS_STATE_DEV_REPLACING,
  				     &fs_info->fs_state)))
  			break;
c404e0dc2   Miao Xie   Btrfs: fix use-af...
1089
  		btrfs_bio_counter_dec(fs_info);
7f8d236ae   David Sterba   btrfs: dev-replac...
1090
  		wait_event(fs_info->dev_replace.replace_wait,
c404e0dc2   Miao Xie   Btrfs: fix use-af...
1091
1092
  			   !test_bit(BTRFS_FS_STATE_DEV_REPLACING,
  				     &fs_info->fs_state));
c404e0dc2   Miao Xie   Btrfs: fix use-af...
1093
  	}
c404e0dc2   Miao Xie   Btrfs: fix use-af...
1094
  }