diff options
| -rw-r--r-- | fs/btrfs/file.c | 22 | ||||
| -rw-r--r-- | fs/btrfs/scrub.c | 25 |
2 files changed, 38 insertions, 9 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index a902faab7161..b06d289f998f 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -293,15 +293,24 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info, | |||
| 293 | struct btrfs_key key; | 293 | struct btrfs_key key; |
| 294 | struct btrfs_ioctl_defrag_range_args range; | 294 | struct btrfs_ioctl_defrag_range_args range; |
| 295 | int num_defrag; | 295 | int num_defrag; |
| 296 | int index; | ||
| 297 | int ret; | ||
| 296 | 298 | ||
| 297 | /* get the inode */ | 299 | /* get the inode */ |
| 298 | key.objectid = defrag->root; | 300 | key.objectid = defrag->root; |
| 299 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); | 301 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); |
| 300 | key.offset = (u64)-1; | 302 | key.offset = (u64)-1; |
| 303 | |||
| 304 | index = srcu_read_lock(&fs_info->subvol_srcu); | ||
| 305 | |||
| 301 | inode_root = btrfs_read_fs_root_no_name(fs_info, &key); | 306 | inode_root = btrfs_read_fs_root_no_name(fs_info, &key); |
| 302 | if (IS_ERR(inode_root)) { | 307 | if (IS_ERR(inode_root)) { |
| 303 | kmem_cache_free(btrfs_inode_defrag_cachep, defrag); | 308 | ret = PTR_ERR(inode_root); |
| 304 | return PTR_ERR(inode_root); | 309 | goto cleanup; |
| 310 | } | ||
| 311 | if (btrfs_root_refs(&inode_root->root_item) == 0) { | ||
| 312 | ret = -ENOENT; | ||
| 313 | goto cleanup; | ||
| 305 | } | 314 | } |
| 306 | 315 | ||
| 307 | key.objectid = defrag->ino; | 316 | key.objectid = defrag->ino; |
| @@ -309,9 +318,10 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info, | |||
| 309 | key.offset = 0; | 318 | key.offset = 0; |
| 310 | inode = btrfs_iget(fs_info->sb, &key, inode_root, NULL); | 319 | inode = btrfs_iget(fs_info->sb, &key, inode_root, NULL); |
| 311 | if (IS_ERR(inode)) { | 320 | if (IS_ERR(inode)) { |
| 312 | kmem_cache_free(btrfs_inode_defrag_cachep, defrag); | 321 | ret = PTR_ERR(inode); |
| 313 | return PTR_ERR(inode); | 322 | goto cleanup; |
| 314 | } | 323 | } |
| 324 | srcu_read_unlock(&fs_info->subvol_srcu, index); | ||
| 315 | 325 | ||
| 316 | /* do a chunk of defrag */ | 326 | /* do a chunk of defrag */ |
| 317 | clear_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags); | 327 | clear_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags); |
| @@ -346,6 +356,10 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info, | |||
| 346 | 356 | ||
| 347 | iput(inode); | 357 | iput(inode); |
| 348 | return 0; | 358 | return 0; |
| 359 | cleanup: | ||
| 360 | srcu_read_unlock(&fs_info->subvol_srcu, index); | ||
| 361 | kmem_cache_free(btrfs_inode_defrag_cachep, defrag); | ||
| 362 | return ret; | ||
| 349 | } | 363 | } |
| 350 | 364 | ||
| 351 | /* | 365 | /* |
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index bdbb94f245c9..67783e03d121 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
| @@ -580,20 +580,29 @@ static int scrub_fixup_readpage(u64 inum, u64 offset, u64 root, void *fixup_ctx) | |||
| 580 | int corrected = 0; | 580 | int corrected = 0; |
| 581 | struct btrfs_key key; | 581 | struct btrfs_key key; |
| 582 | struct inode *inode = NULL; | 582 | struct inode *inode = NULL; |
| 583 | struct btrfs_fs_info *fs_info; | ||
| 583 | u64 end = offset + PAGE_SIZE - 1; | 584 | u64 end = offset + PAGE_SIZE - 1; |
| 584 | struct btrfs_root *local_root; | 585 | struct btrfs_root *local_root; |
| 586 | int srcu_index; | ||
| 585 | 587 | ||
| 586 | key.objectid = root; | 588 | key.objectid = root; |
| 587 | key.type = BTRFS_ROOT_ITEM_KEY; | 589 | key.type = BTRFS_ROOT_ITEM_KEY; |
| 588 | key.offset = (u64)-1; | 590 | key.offset = (u64)-1; |
| 589 | local_root = btrfs_read_fs_root_no_name(fixup->root->fs_info, &key); | 591 | |
| 590 | if (IS_ERR(local_root)) | 592 | fs_info = fixup->root->fs_info; |
| 593 | srcu_index = srcu_read_lock(&fs_info->subvol_srcu); | ||
| 594 | |||
| 595 | local_root = btrfs_read_fs_root_no_name(fs_info, &key); | ||
| 596 | if (IS_ERR(local_root)) { | ||
| 597 | srcu_read_unlock(&fs_info->subvol_srcu, srcu_index); | ||
| 591 | return PTR_ERR(local_root); | 598 | return PTR_ERR(local_root); |
| 599 | } | ||
| 592 | 600 | ||
| 593 | key.type = BTRFS_INODE_ITEM_KEY; | 601 | key.type = BTRFS_INODE_ITEM_KEY; |
| 594 | key.objectid = inum; | 602 | key.objectid = inum; |
| 595 | key.offset = 0; | 603 | key.offset = 0; |
| 596 | inode = btrfs_iget(fixup->root->fs_info->sb, &key, local_root, NULL); | 604 | inode = btrfs_iget(fs_info->sb, &key, local_root, NULL); |
| 605 | srcu_read_unlock(&fs_info->subvol_srcu, srcu_index); | ||
| 597 | if (IS_ERR(inode)) | 606 | if (IS_ERR(inode)) |
| 598 | return PTR_ERR(inode); | 607 | return PTR_ERR(inode); |
| 599 | 608 | ||
| @@ -606,7 +615,6 @@ static int scrub_fixup_readpage(u64 inum, u64 offset, u64 root, void *fixup_ctx) | |||
| 606 | } | 615 | } |
| 607 | 616 | ||
| 608 | if (PageUptodate(page)) { | 617 | if (PageUptodate(page)) { |
| 609 | struct btrfs_fs_info *fs_info; | ||
| 610 | if (PageDirty(page)) { | 618 | if (PageDirty(page)) { |
| 611 | /* | 619 | /* |
| 612 | * we need to write the data to the defect sector. the | 620 | * we need to write the data to the defect sector. the |
| @@ -3180,18 +3188,25 @@ static int copy_nocow_pages_for_inode(u64 inum, u64 offset, u64 root, void *ctx) | |||
| 3180 | u64 physical_for_dev_replace; | 3188 | u64 physical_for_dev_replace; |
| 3181 | u64 len; | 3189 | u64 len; |
| 3182 | struct btrfs_fs_info *fs_info = nocow_ctx->sctx->dev_root->fs_info; | 3190 | struct btrfs_fs_info *fs_info = nocow_ctx->sctx->dev_root->fs_info; |
| 3191 | int srcu_index; | ||
| 3183 | 3192 | ||
| 3184 | key.objectid = root; | 3193 | key.objectid = root; |
| 3185 | key.type = BTRFS_ROOT_ITEM_KEY; | 3194 | key.type = BTRFS_ROOT_ITEM_KEY; |
| 3186 | key.offset = (u64)-1; | 3195 | key.offset = (u64)-1; |
| 3196 | |||
| 3197 | srcu_index = srcu_read_lock(&fs_info->subvol_srcu); | ||
| 3198 | |||
| 3187 | local_root = btrfs_read_fs_root_no_name(fs_info, &key); | 3199 | local_root = btrfs_read_fs_root_no_name(fs_info, &key); |
| 3188 | if (IS_ERR(local_root)) | 3200 | if (IS_ERR(local_root)) { |
| 3201 | srcu_read_unlock(&fs_info->subvol_srcu, srcu_index); | ||
| 3189 | return PTR_ERR(local_root); | 3202 | return PTR_ERR(local_root); |
| 3203 | } | ||
| 3190 | 3204 | ||
| 3191 | key.type = BTRFS_INODE_ITEM_KEY; | 3205 | key.type = BTRFS_INODE_ITEM_KEY; |
| 3192 | key.objectid = inum; | 3206 | key.objectid = inum; |
| 3193 | key.offset = 0; | 3207 | key.offset = 0; |
| 3194 | inode = btrfs_iget(fs_info->sb, &key, local_root, NULL); | 3208 | inode = btrfs_iget(fs_info->sb, &key, local_root, NULL); |
| 3209 | srcu_read_unlock(&fs_info->subvol_srcu, srcu_index); | ||
| 3195 | if (IS_ERR(inode)) | 3210 | if (IS_ERR(inode)) |
| 3196 | return PTR_ERR(inode); | 3211 | return PTR_ERR(inode); |
| 3197 | 3212 | ||
