aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-01-16 11:44:43 -0500
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:59 -0400
commit2da98f003f4788b0a72c5f87bc55b061f65f30fa (patch)
treee94832937031f347168aaec4e50ab2ced8331ccb /fs/btrfs
parent9cce6c3bfca85bf92e8c9358542a18dfa6c232be (diff)
Btrfs: Run igrab on data=ordered inodes to prevent deadlocks during writeout
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/inode.c32
-rw-r--r--fs/btrfs/ordered-data.c10
-rw-r--r--fs/btrfs/super.c2
-rw-r--r--fs/btrfs/transaction.c1
5 files changed, 37 insertions, 10 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 1e19f2d86334..fa65fe027e45 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1145,7 +1145,7 @@ int btrfs_check_free_space(struct btrfs_root *root, u64 num_required,
1145int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page); 1145int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page);
1146int btrfs_readpage(struct file *file, struct page *page); 1146int btrfs_readpage(struct file *file, struct page *page);
1147void btrfs_delete_inode(struct inode *inode); 1147void btrfs_delete_inode(struct inode *inode);
1148void btrfs_drop_inode(struct inode *inode); 1148void btrfs_put_inode(struct inode *inode);
1149void btrfs_read_locked_inode(struct inode *inode); 1149void btrfs_read_locked_inode(struct inode *inode);
1150int btrfs_write_inode(struct inode *inode, int wait); 1150int btrfs_write_inode(struct inode *inode, int wait);
1151void btrfs_dirty_inode(struct inode *inode); 1151void btrfs_dirty_inode(struct inode *inode);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index f83f88ca8ac7..c1ac0bcbb462 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -601,6 +601,7 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
601{ 601{
602 struct btrfs_root *root; 602 struct btrfs_root *root;
603 struct btrfs_trans_handle *trans; 603 struct btrfs_trans_handle *trans;
604 struct inode *inode = dentry->d_inode;
604 int ret; 605 int ret;
605 unsigned long nr = 0; 606 unsigned long nr = 0;
606 607
@@ -617,6 +618,18 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
617 ret = btrfs_unlink_trans(trans, root, dir, dentry); 618 ret = btrfs_unlink_trans(trans, root, dir, dentry);
618 nr = trans->blocks_used; 619 nr = trans->blocks_used;
619 620
621 if (inode->i_nlink == 0) {
622 int found;
623 /* if the inode isn't linked anywhere,
624 * we don't need to worry about
625 * data=ordered
626 */
627 found = btrfs_del_ordered_inode(inode);
628 if (found == 1) {
629 atomic_dec(&inode->i_count);
630 }
631 }
632
620 btrfs_end_transaction(trans, root); 633 btrfs_end_transaction(trans, root);
621fail: 634fail:
622 mutex_unlock(&root->fs_info->fs_mutex); 635 mutex_unlock(&root->fs_info->fs_mutex);
@@ -993,15 +1006,22 @@ fail:
993 return err; 1006 return err;
994} 1007}
995 1008
996void btrfs_drop_inode(struct inode *inode) 1009void btrfs_put_inode(struct inode *inode)
997{ 1010{
998 if (!BTRFS_I(inode)->ordered_trans || inode->i_nlink) { 1011 int ret;
999 generic_drop_inode(inode); 1012
1013 if (!BTRFS_I(inode)->ordered_trans) {
1014 return;
1015 }
1016
1017 if (mapping_tagged(inode->i_mapping, PAGECACHE_TAG_DIRTY) ||
1018 mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK))
1000 return; 1019 return;
1020
1021 ret = btrfs_del_ordered_inode(inode);
1022 if (ret == 1) {
1023 atomic_dec(&inode->i_count);
1001 } 1024 }
1002 /* FIXME, make sure this delete actually ends up in the transaction */
1003 btrfs_del_ordered_inode(inode);
1004 generic_drop_inode(inode);
1005} 1025}
1006 1026
1007void btrfs_delete_inode(struct inode *inode) 1027void btrfs_delete_inode(struct inode *inode)
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
index b56011baa17c..cba2b623d02e 100644
--- a/fs/btrfs/ordered-data.c
+++ b/fs/btrfs/ordered-data.c
@@ -153,6 +153,8 @@ int btrfs_add_ordered_inode(struct inode *inode)
153 write_unlock(&tree->lock); 153 write_unlock(&tree->lock);
154 if (node) 154 if (node)
155 kfree(entry); 155 kfree(entry);
156 else
157 igrab(inode);
156 return 0; 158 return 0;
157} 159}
158 160
@@ -221,6 +223,7 @@ int btrfs_find_del_first_ordered_inode(struct btrfs_ordered_inode_tree *tree,
221} 223}
222 224
223static int __btrfs_del_ordered_inode(struct btrfs_ordered_inode_tree *tree, 225static int __btrfs_del_ordered_inode(struct btrfs_ordered_inode_tree *tree,
226 struct inode *inode,
224 u64 root_objectid, u64 objectid) 227 u64 root_objectid, u64 objectid)
225{ 228{
226 struct tree_entry *entry; 229 struct tree_entry *entry;
@@ -234,6 +237,7 @@ static int __btrfs_del_ordered_inode(struct btrfs_ordered_inode_tree *tree,
234 return 0; 237 return 0;
235 } 238 }
236 rb_erase(node, &tree->tree); 239 rb_erase(node, &tree->tree);
240 BTRFS_I(inode)->ordered_trans = 0;
237 write_unlock(&tree->lock); 241 write_unlock(&tree->lock);
238 entry = rb_entry(node, struct tree_entry, rb_node); 242 entry = rb_entry(node, struct tree_entry, rb_node);
239 kfree(entry); 243 kfree(entry);
@@ -244,14 +248,16 @@ int btrfs_del_ordered_inode(struct inode *inode)
244{ 248{
245 struct btrfs_root *root = BTRFS_I(inode)->root; 249 struct btrfs_root *root = BTRFS_I(inode)->root;
246 u64 root_objectid = root->root_key.objectid; 250 u64 root_objectid = root->root_key.objectid;
251 int ret = 0;
247 252
248 spin_lock(&root->fs_info->new_trans_lock); 253 spin_lock(&root->fs_info->new_trans_lock);
249 if (root->fs_info->running_transaction) { 254 if (root->fs_info->running_transaction) {
250 struct btrfs_ordered_inode_tree *tree; 255 struct btrfs_ordered_inode_tree *tree;
251 tree = &root->fs_info->running_transaction->ordered_inode_tree; 256 tree = &root->fs_info->running_transaction->ordered_inode_tree;
252 __btrfs_del_ordered_inode(tree, root_objectid, inode->i_ino); 257 ret = __btrfs_del_ordered_inode(tree, inode, root_objectid,
258 inode->i_ino);
253 } 259 }
254 spin_unlock(&root->fs_info->new_trans_lock); 260 spin_unlock(&root->fs_info->new_trans_lock);
255 return 0; 261 return ret;
256} 262}
257 263
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 4deea393ca94..e506de3168bc 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -425,7 +425,7 @@ static struct file_system_type btrfs_fs_type = {
425 425
426static struct super_operations btrfs_super_ops = { 426static struct super_operations btrfs_super_ops = {
427 .delete_inode = btrfs_delete_inode, 427 .delete_inode = btrfs_delete_inode,
428 .drop_inode = btrfs_drop_inode, 428 .put_inode = btrfs_put_inode,
429 .put_super = btrfs_put_super, 429 .put_super = btrfs_put_super,
430 .read_inode = btrfs_read_locked_inode, 430 .read_inode = btrfs_read_locked_inode,
431 .write_super = btrfs_write_super, 431 .write_super = btrfs_write_super,
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index a3205808ab2b..08f7a188dc3e 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -521,6 +521,7 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans,
521 if (inode) { 521 if (inode) {
522 if (S_ISREG(inode->i_mode)) 522 if (S_ISREG(inode->i_mode))
523 filemap_write_and_wait(inode->i_mapping); 523 filemap_write_and_wait(inode->i_mapping);
524 atomic_dec(&inode->i_count);
524 iput(inode); 525 iput(inode);
525 } 526 }
526 mutex_lock(&root->fs_info->fs_mutex); 527 mutex_lock(&root->fs_info->fs_mutex);