diff options
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 69 |
1 files changed, 59 insertions, 10 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index a6d35b0054ca..3ab80e9cd767 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -161,8 +161,10 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) | |||
161 | int again = 0; | 161 | int again = 0; |
162 | unsigned long num_run; | 162 | unsigned long num_run; |
163 | unsigned long num_sync_run; | 163 | unsigned long num_sync_run; |
164 | unsigned long batch_run = 0; | ||
164 | unsigned long limit; | 165 | unsigned long limit; |
165 | unsigned long last_waited = 0; | 166 | unsigned long last_waited = 0; |
167 | int force_reg = 0; | ||
166 | 168 | ||
167 | bdi = blk_get_backing_dev_info(device->bdev); | 169 | bdi = blk_get_backing_dev_info(device->bdev); |
168 | fs_info = device->dev_root->fs_info; | 170 | fs_info = device->dev_root->fs_info; |
@@ -176,19 +178,22 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) | |||
176 | 178 | ||
177 | loop: | 179 | loop: |
178 | spin_lock(&device->io_lock); | 180 | spin_lock(&device->io_lock); |
179 | num_run = 0; | ||
180 | 181 | ||
181 | loop_lock: | 182 | loop_lock: |
183 | num_run = 0; | ||
182 | 184 | ||
183 | /* take all the bios off the list at once and process them | 185 | /* take all the bios off the list at once and process them |
184 | * later on (without the lock held). But, remember the | 186 | * later on (without the lock held). But, remember the |
185 | * tail and other pointers so the bios can be properly reinserted | 187 | * tail and other pointers so the bios can be properly reinserted |
186 | * into the list if we hit congestion | 188 | * into the list if we hit congestion |
187 | */ | 189 | */ |
188 | if (device->pending_sync_bios.head) | 190 | if (!force_reg && device->pending_sync_bios.head) { |
189 | pending_bios = &device->pending_sync_bios; | 191 | pending_bios = &device->pending_sync_bios; |
190 | else | 192 | force_reg = 1; |
193 | } else { | ||
191 | pending_bios = &device->pending_bios; | 194 | pending_bios = &device->pending_bios; |
195 | force_reg = 0; | ||
196 | } | ||
192 | 197 | ||
193 | pending = pending_bios->head; | 198 | pending = pending_bios->head; |
194 | tail = pending_bios->tail; | 199 | tail = pending_bios->tail; |
@@ -228,10 +233,14 @@ loop_lock: | |||
228 | while (pending) { | 233 | while (pending) { |
229 | 234 | ||
230 | rmb(); | 235 | rmb(); |
231 | if (pending_bios != &device->pending_sync_bios && | 236 | /* we want to work on both lists, but do more bios on the |
232 | device->pending_sync_bios.head && | 237 | * sync list than the regular list |
233 | num_run > 16) { | 238 | */ |
234 | cond_resched(); | 239 | if ((num_run > 32 && |
240 | pending_bios != &device->pending_sync_bios && | ||
241 | device->pending_sync_bios.head) || | ||
242 | (num_run > 64 && pending_bios == &device->pending_sync_bios && | ||
243 | device->pending_bios.head)) { | ||
235 | spin_lock(&device->io_lock); | 244 | spin_lock(&device->io_lock); |
236 | requeue_list(pending_bios, pending, tail); | 245 | requeue_list(pending_bios, pending, tail); |
237 | goto loop_lock; | 246 | goto loop_lock; |
@@ -249,6 +258,8 @@ loop_lock: | |||
249 | BUG_ON(atomic_read(&cur->bi_cnt) == 0); | 258 | BUG_ON(atomic_read(&cur->bi_cnt) == 0); |
250 | submit_bio(cur->bi_rw, cur); | 259 | submit_bio(cur->bi_rw, cur); |
251 | num_run++; | 260 | num_run++; |
261 | batch_run++; | ||
262 | |||
252 | if (bio_sync(cur)) | 263 | if (bio_sync(cur)) |
253 | num_sync_run++; | 264 | num_sync_run++; |
254 | 265 | ||
@@ -265,7 +276,7 @@ loop_lock: | |||
265 | * is now congested. Back off and let other work structs | 276 | * is now congested. Back off and let other work structs |
266 | * run instead | 277 | * run instead |
267 | */ | 278 | */ |
268 | if (pending && bdi_write_congested(bdi) && num_run > 16 && | 279 | if (pending && bdi_write_congested(bdi) && batch_run > 32 && |
269 | fs_info->fs_devices->open_devices > 1) { | 280 | fs_info->fs_devices->open_devices > 1) { |
270 | struct io_context *ioc; | 281 | struct io_context *ioc; |
271 | 282 | ||
@@ -366,6 +377,7 @@ static noinline int device_list_add(const char *path, | |||
366 | memcpy(fs_devices->fsid, disk_super->fsid, BTRFS_FSID_SIZE); | 377 | memcpy(fs_devices->fsid, disk_super->fsid, BTRFS_FSID_SIZE); |
367 | fs_devices->latest_devid = devid; | 378 | fs_devices->latest_devid = devid; |
368 | fs_devices->latest_trans = found_transid; | 379 | fs_devices->latest_trans = found_transid; |
380 | mutex_init(&fs_devices->device_list_mutex); | ||
369 | device = NULL; | 381 | device = NULL; |
370 | } else { | 382 | } else { |
371 | device = __find_device(&fs_devices->devices, devid, | 383 | device = __find_device(&fs_devices->devices, devid, |
@@ -392,7 +404,11 @@ static noinline int device_list_add(const char *path, | |||
392 | return -ENOMEM; | 404 | return -ENOMEM; |
393 | } | 405 | } |
394 | INIT_LIST_HEAD(&device->dev_alloc_list); | 406 | INIT_LIST_HEAD(&device->dev_alloc_list); |
407 | |||
408 | mutex_lock(&fs_devices->device_list_mutex); | ||
395 | list_add(&device->dev_list, &fs_devices->devices); | 409 | list_add(&device->dev_list, &fs_devices->devices); |
410 | mutex_unlock(&fs_devices->device_list_mutex); | ||
411 | |||
396 | device->fs_devices = fs_devices; | 412 | device->fs_devices = fs_devices; |
397 | fs_devices->num_devices++; | 413 | fs_devices->num_devices++; |
398 | } | 414 | } |
@@ -418,10 +434,12 @@ static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig) | |||
418 | INIT_LIST_HEAD(&fs_devices->devices); | 434 | INIT_LIST_HEAD(&fs_devices->devices); |
419 | INIT_LIST_HEAD(&fs_devices->alloc_list); | 435 | INIT_LIST_HEAD(&fs_devices->alloc_list); |
420 | INIT_LIST_HEAD(&fs_devices->list); | 436 | INIT_LIST_HEAD(&fs_devices->list); |
437 | mutex_init(&fs_devices->device_list_mutex); | ||
421 | fs_devices->latest_devid = orig->latest_devid; | 438 | fs_devices->latest_devid = orig->latest_devid; |
422 | fs_devices->latest_trans = orig->latest_trans; | 439 | fs_devices->latest_trans = orig->latest_trans; |
423 | memcpy(fs_devices->fsid, orig->fsid, sizeof(fs_devices->fsid)); | 440 | memcpy(fs_devices->fsid, orig->fsid, sizeof(fs_devices->fsid)); |
424 | 441 | ||
442 | mutex_lock(&orig->device_list_mutex); | ||
425 | list_for_each_entry(orig_dev, &orig->devices, dev_list) { | 443 | list_for_each_entry(orig_dev, &orig->devices, dev_list) { |
426 | device = kzalloc(sizeof(*device), GFP_NOFS); | 444 | device = kzalloc(sizeof(*device), GFP_NOFS); |
427 | if (!device) | 445 | if (!device) |
@@ -443,8 +461,10 @@ static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig) | |||
443 | device->fs_devices = fs_devices; | 461 | device->fs_devices = fs_devices; |
444 | fs_devices->num_devices++; | 462 | fs_devices->num_devices++; |
445 | } | 463 | } |
464 | mutex_unlock(&orig->device_list_mutex); | ||
446 | return fs_devices; | 465 | return fs_devices; |
447 | error: | 466 | error: |
467 | mutex_unlock(&orig->device_list_mutex); | ||
448 | free_fs_devices(fs_devices); | 468 | free_fs_devices(fs_devices); |
449 | return ERR_PTR(-ENOMEM); | 469 | return ERR_PTR(-ENOMEM); |
450 | } | 470 | } |
@@ -455,6 +475,7 @@ int btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices) | |||
455 | 475 | ||
456 | mutex_lock(&uuid_mutex); | 476 | mutex_lock(&uuid_mutex); |
457 | again: | 477 | again: |
478 | mutex_lock(&fs_devices->device_list_mutex); | ||
458 | list_for_each_entry_safe(device, next, &fs_devices->devices, dev_list) { | 479 | list_for_each_entry_safe(device, next, &fs_devices->devices, dev_list) { |
459 | if (device->in_fs_metadata) | 480 | if (device->in_fs_metadata) |
460 | continue; | 481 | continue; |
@@ -474,6 +495,7 @@ again: | |||
474 | kfree(device->name); | 495 | kfree(device->name); |
475 | kfree(device); | 496 | kfree(device); |
476 | } | 497 | } |
498 | mutex_unlock(&fs_devices->device_list_mutex); | ||
477 | 499 | ||
478 | if (fs_devices->seed) { | 500 | if (fs_devices->seed) { |
479 | fs_devices = fs_devices->seed; | 501 | fs_devices = fs_devices->seed; |
@@ -594,6 +616,9 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, | |||
594 | device->in_fs_metadata = 0; | 616 | device->in_fs_metadata = 0; |
595 | device->mode = flags; | 617 | device->mode = flags; |
596 | 618 | ||
619 | if (!blk_queue_nonrot(bdev_get_queue(bdev))) | ||
620 | fs_devices->rotating = 1; | ||
621 | |||
597 | fs_devices->open_devices++; | 622 | fs_devices->open_devices++; |
598 | if (device->writeable) { | 623 | if (device->writeable) { |
599 | fs_devices->rw_devices++; | 624 | fs_devices->rw_devices++; |
@@ -1121,12 +1146,14 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1121 | 1146 | ||
1122 | device = NULL; | 1147 | device = NULL; |
1123 | devices = &root->fs_info->fs_devices->devices; | 1148 | devices = &root->fs_info->fs_devices->devices; |
1149 | mutex_lock(&root->fs_info->fs_devices->device_list_mutex); | ||
1124 | list_for_each_entry(tmp, devices, dev_list) { | 1150 | list_for_each_entry(tmp, devices, dev_list) { |
1125 | if (tmp->in_fs_metadata && !tmp->bdev) { | 1151 | if (tmp->in_fs_metadata && !tmp->bdev) { |
1126 | device = tmp; | 1152 | device = tmp; |
1127 | break; | 1153 | break; |
1128 | } | 1154 | } |
1129 | } | 1155 | } |
1156 | mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); | ||
1130 | bdev = NULL; | 1157 | bdev = NULL; |
1131 | bh = NULL; | 1158 | bh = NULL; |
1132 | disk_super = NULL; | 1159 | disk_super = NULL; |
@@ -1181,7 +1208,16 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1181 | goto error_brelse; | 1208 | goto error_brelse; |
1182 | 1209 | ||
1183 | device->in_fs_metadata = 0; | 1210 | device->in_fs_metadata = 0; |
1211 | |||
1212 | /* | ||
1213 | * the device list mutex makes sure that we don't change | ||
1214 | * the device list while someone else is writing out all | ||
1215 | * the device supers. | ||
1216 | */ | ||
1217 | mutex_lock(&root->fs_info->fs_devices->device_list_mutex); | ||
1184 | list_del_init(&device->dev_list); | 1218 | list_del_init(&device->dev_list); |
1219 | mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); | ||
1220 | |||
1185 | device->fs_devices->num_devices--; | 1221 | device->fs_devices->num_devices--; |
1186 | 1222 | ||
1187 | next_device = list_entry(root->fs_info->fs_devices->devices.next, | 1223 | next_device = list_entry(root->fs_info->fs_devices->devices.next, |
@@ -1275,6 +1311,7 @@ static int btrfs_prepare_sprout(struct btrfs_trans_handle *trans, | |||
1275 | seed_devices->opened = 1; | 1311 | seed_devices->opened = 1; |
1276 | INIT_LIST_HEAD(&seed_devices->devices); | 1312 | INIT_LIST_HEAD(&seed_devices->devices); |
1277 | INIT_LIST_HEAD(&seed_devices->alloc_list); | 1313 | INIT_LIST_HEAD(&seed_devices->alloc_list); |
1314 | mutex_init(&seed_devices->device_list_mutex); | ||
1278 | list_splice_init(&fs_devices->devices, &seed_devices->devices); | 1315 | list_splice_init(&fs_devices->devices, &seed_devices->devices); |
1279 | list_splice_init(&fs_devices->alloc_list, &seed_devices->alloc_list); | 1316 | list_splice_init(&fs_devices->alloc_list, &seed_devices->alloc_list); |
1280 | list_for_each_entry(device, &seed_devices->devices, dev_list) { | 1317 | list_for_each_entry(device, &seed_devices->devices, dev_list) { |
@@ -1400,6 +1437,10 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
1400 | mutex_lock(&root->fs_info->volume_mutex); | 1437 | mutex_lock(&root->fs_info->volume_mutex); |
1401 | 1438 | ||
1402 | devices = &root->fs_info->fs_devices->devices; | 1439 | devices = &root->fs_info->fs_devices->devices; |
1440 | /* | ||
1441 | * we have the volume lock, so we don't need the extra | ||
1442 | * device list mutex while reading the list here. | ||
1443 | */ | ||
1403 | list_for_each_entry(device, devices, dev_list) { | 1444 | list_for_each_entry(device, devices, dev_list) { |
1404 | if (device->bdev == bdev) { | 1445 | if (device->bdev == bdev) { |
1405 | ret = -EEXIST; | 1446 | ret = -EEXIST; |
@@ -1454,6 +1495,12 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
1454 | } | 1495 | } |
1455 | 1496 | ||
1456 | device->fs_devices = root->fs_info->fs_devices; | 1497 | device->fs_devices = root->fs_info->fs_devices; |
1498 | |||
1499 | /* | ||
1500 | * we don't want write_supers to jump in here with our device | ||
1501 | * half setup | ||
1502 | */ | ||
1503 | mutex_lock(&root->fs_info->fs_devices->device_list_mutex); | ||
1457 | list_add(&device->dev_list, &root->fs_info->fs_devices->devices); | 1504 | list_add(&device->dev_list, &root->fs_info->fs_devices->devices); |
1458 | list_add(&device->dev_alloc_list, | 1505 | list_add(&device->dev_alloc_list, |
1459 | &root->fs_info->fs_devices->alloc_list); | 1506 | &root->fs_info->fs_devices->alloc_list); |
@@ -1462,6 +1509,9 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
1462 | root->fs_info->fs_devices->rw_devices++; | 1509 | root->fs_info->fs_devices->rw_devices++; |
1463 | root->fs_info->fs_devices->total_rw_bytes += device->total_bytes; | 1510 | root->fs_info->fs_devices->total_rw_bytes += device->total_bytes; |
1464 | 1511 | ||
1512 | if (!blk_queue_nonrot(bdev_get_queue(bdev))) | ||
1513 | root->fs_info->fs_devices->rotating = 1; | ||
1514 | |||
1465 | total_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); | 1515 | total_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); |
1466 | btrfs_set_super_total_bytes(&root->fs_info->super_copy, | 1516 | btrfs_set_super_total_bytes(&root->fs_info->super_copy, |
1467 | total_bytes + device->total_bytes); | 1517 | total_bytes + device->total_bytes); |
@@ -1469,6 +1519,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
1469 | total_bytes = btrfs_super_num_devices(&root->fs_info->super_copy); | 1519 | total_bytes = btrfs_super_num_devices(&root->fs_info->super_copy); |
1470 | btrfs_set_super_num_devices(&root->fs_info->super_copy, | 1520 | btrfs_set_super_num_devices(&root->fs_info->super_copy, |
1471 | total_bytes + 1); | 1521 | total_bytes + 1); |
1522 | mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); | ||
1472 | 1523 | ||
1473 | if (seeding_dev) { | 1524 | if (seeding_dev) { |
1474 | ret = init_first_rw_device(trans, root, device); | 1525 | ret = init_first_rw_device(trans, root, device); |
@@ -1671,8 +1722,6 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, | |||
1671 | int ret; | 1722 | int ret; |
1672 | int i; | 1723 | int i; |
1673 | 1724 | ||
1674 | printk(KERN_INFO "btrfs relocating chunk %llu\n", | ||
1675 | (unsigned long long)chunk_offset); | ||
1676 | root = root->fs_info->chunk_root; | 1725 | root = root->fs_info->chunk_root; |
1677 | extent_root = root->fs_info->extent_root; | 1726 | extent_root = root->fs_info->extent_root; |
1678 | em_tree = &root->fs_info->mapping_tree.map_tree; | 1727 | em_tree = &root->fs_info->mapping_tree.map_tree; |