Fix btrfs_del_ordered_inode to allow forcing the drop during unlinks
This allows us to delete an unlinked inode with dirty pages from the list
instead of forcing commit to write these out before deleting the inode.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 1b756fa..9601241 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1245,7 +1245,10 @@
int level;
int should_reada = p->reada;
int lowest_unlock = 1;
+ int blocksize;
u8 lowest_level = 0;
+ u64 blocknr;
+ u64 gen;
lowest_level = p->lowest_level;
WARN_ON(lowest_level && ins_len);
@@ -1320,11 +1323,12 @@
reada_for_search(root, p, level, slot,
key->objectid);
- tmp = btrfs_find_tree_block(root,
- btrfs_node_blockptr(b, slot),
- btrfs_level_size(root, level - 1));
- if (tmp && btrfs_buffer_uptodate(tmp,
- btrfs_node_ptr_generation(b, slot))) {
+ blocknr = btrfs_node_blockptr(b, slot);
+ gen = btrfs_node_ptr_generation(b, slot);
+ blocksize = btrfs_level_size(root, level - 1);
+
+ tmp = btrfs_find_tree_block(root, blocknr, blocksize);
+ if (tmp && btrfs_buffer_uptodate(tmp, gen)) {
b = tmp;
} else {
/*
@@ -1336,6 +1340,10 @@
btrfs_release_path(NULL, p);
if (tmp)
free_extent_buffer(tmp);
+ tmp = read_tree_block(root, blocknr,
+ blocksize, gen);
+ if (tmp)
+ free_extent_buffer(tmp);
goto again;
} else {
b = read_node_slot(root, b, slot);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 18bbe10..b7f8f92 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -976,7 +976,7 @@
int btrfs_release_file(struct inode * inode, struct file * filp)
{
- btrfs_del_ordered_inode(inode);
+ btrfs_del_ordered_inode(inode, 0);
if (filp->private_data)
btrfs_ioctl_trans_end(filp);
return 0;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index b2251e2..cf27b59 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -852,7 +852,7 @@
* we don't need to worry about
* data=ordered
*/
- btrfs_del_ordered_inode(inode);
+ btrfs_del_ordered_inode(inode, 1);
}
btrfs_end_transaction(trans, root);
@@ -1276,14 +1276,12 @@
btrfs_end_transaction(trans, root);
btrfs_btree_balance_dirty(root, nr);
- btrfs_throttle(root);
return;
no_delete_lock:
nr = trans->blocks_used;
btrfs_end_transaction(trans, root);
btrfs_btree_balance_dirty(root, nr);
- btrfs_throttle(root);
no_delete:
clear_inode(inode);
}
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
index 8dd8180..5e4c0d95 100644
--- a/fs/btrfs/ordered-data.c
+++ b/fs/btrfs/ordered-data.c
@@ -254,7 +254,7 @@
return;
}
-void btrfs_del_ordered_inode(struct inode *inode)
+void btrfs_del_ordered_inode(struct inode *inode, int force)
{
struct btrfs_root *root = BTRFS_I(inode)->root;
u64 root_objectid = root->root_key.objectid;
@@ -263,8 +263,8 @@
return;
}
- if (mapping_tagged(inode->i_mapping, PAGECACHE_TAG_DIRTY) ||
- mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK))
+ if (!force && (mapping_tagged(inode->i_mapping, PAGECACHE_TAG_DIRTY) ||
+ mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK)))
return;
spin_lock(&root->fs_info->new_trans_lock);
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h
index c515c4b..4fa7873 100644
--- a/fs/btrfs/ordered-data.h
+++ b/fs/btrfs/ordered-data.h
@@ -38,6 +38,6 @@
int btrfs_find_first_ordered_inode(struct btrfs_ordered_inode_tree *tree,
u64 *root_objectid, u64 *objectid,
struct inode **inode);
-void btrfs_del_ordered_inode(struct inode *inode);
+void btrfs_del_ordered_inode(struct inode *inode, int force);
int btrfs_ordered_throttle(struct btrfs_root *root, struct inode *inode);
#endif