diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-01-16 16:09:22 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:59 -0400 |
commit | 4d5e74bc0aec3f54b7e429d77b7c35de042c507d (patch) | |
tree | bba22e2a9cfbe5663a2489c5404fff72639b5277 /fs/btrfs/transaction.c | |
parent | 2da98f003f4788b0a72c5f87bc55b061f65f30fa (diff) |
Btrfs: Fix data=ordered vs wait_on_inode deadlock on older kernels
Using ilookup5 during data=ordered writeback could deadlock on I_LOCK. This
saves a pointer to the inode instead.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 30 |
1 files changed, 13 insertions, 17 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 08f7a188dc3e..b6bbfc179c29 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -490,19 +490,17 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans, | |||
490 | while(1) { | 490 | while(1) { |
491 | ret = btrfs_find_first_ordered_inode( | 491 | ret = btrfs_find_first_ordered_inode( |
492 | &cur_trans->ordered_inode_tree, | 492 | &cur_trans->ordered_inode_tree, |
493 | &root_objectid, &objectid); | 493 | &root_objectid, &objectid, &inode); |
494 | if (!ret) | 494 | if (!ret) |
495 | break; | 495 | break; |
496 | 496 | ||
497 | mutex_unlock(&root->fs_info->trans_mutex); | 497 | mutex_unlock(&root->fs_info->trans_mutex); |
498 | mutex_unlock(&root->fs_info->fs_mutex); | 498 | mutex_unlock(&root->fs_info->fs_mutex); |
499 | inode = btrfs_ilookup(root->fs_info->sb, objectid, | 499 | |
500 | root_objectid); | 500 | if (S_ISREG(inode->i_mode)) |
501 | if (inode) { | 501 | filemap_fdatawrite(inode->i_mapping); |
502 | if (S_ISREG(inode->i_mode)) | 502 | iput(inode); |
503 | filemap_fdatawrite(inode->i_mapping); | 503 | |
504 | iput(inode); | ||
505 | } | ||
506 | mutex_lock(&root->fs_info->fs_mutex); | 504 | mutex_lock(&root->fs_info->fs_mutex); |
507 | mutex_lock(&root->fs_info->trans_mutex); | 505 | mutex_lock(&root->fs_info->trans_mutex); |
508 | } | 506 | } |
@@ -511,19 +509,17 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans, | |||
511 | objectid = 0; | 509 | objectid = 0; |
512 | ret = btrfs_find_del_first_ordered_inode( | 510 | ret = btrfs_find_del_first_ordered_inode( |
513 | &cur_trans->ordered_inode_tree, | 511 | &cur_trans->ordered_inode_tree, |
514 | &root_objectid, &objectid); | 512 | &root_objectid, &objectid, &inode); |
515 | if (!ret) | 513 | if (!ret) |
516 | break; | 514 | break; |
517 | mutex_unlock(&root->fs_info->trans_mutex); | 515 | mutex_unlock(&root->fs_info->trans_mutex); |
518 | mutex_unlock(&root->fs_info->fs_mutex); | 516 | mutex_unlock(&root->fs_info->fs_mutex); |
519 | inode = btrfs_ilookup(root->fs_info->sb, objectid, | 517 | |
520 | root_objectid); | 518 | if (S_ISREG(inode->i_mode)) |
521 | if (inode) { | 519 | filemap_write_and_wait(inode->i_mapping); |
522 | if (S_ISREG(inode->i_mode)) | 520 | atomic_dec(&inode->i_count); |
523 | filemap_write_and_wait(inode->i_mapping); | 521 | iput(inode); |
524 | atomic_dec(&inode->i_count); | 522 | |
525 | iput(inode); | ||
526 | } | ||
527 | mutex_lock(&root->fs_info->fs_mutex); | 523 | mutex_lock(&root->fs_info->fs_mutex); |
528 | mutex_lock(&root->fs_info->trans_mutex); | 524 | mutex_lock(&root->fs_info->trans_mutex); |
529 | } | 525 | } |