Fix btrfs_del_ordered_inode to allow forcing the drop during unlinks
authorChris Mason <chris.mason@oracle.com>
Wed, 25 Jun 2008 20:01:30 +0000 (16:01 -0400)
committerChris Mason <chris.mason@oracle.com>
Thu, 25 Sep 2008 15:04:03 +0000 (11:04 -0400)
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>
fs/btrfs/ctree.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ordered-data.c
fs/btrfs/ordered-data.h

index 1b756fae279932f79946972d368c3bde5c8a3421..9601241e552b038bc1778057a329cd18bb6eea0d 100644 (file)
@@ -1245,7 +1245,10 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
        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 @@ again:
                                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 {
                                /*
@@ -1334,6 +1338,10 @@ again:
                                 */
                                if (level > 1) {
                                        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;
index 18bbe108a0e60e22f3f90414d1fa65adc68b3ded..b7f8f92daf8a55e5f953ae1ac67d773bbd8e482e 100644 (file)
@@ -976,7 +976,7 @@ out_nolock:
 
 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;
index b2251e27ac84c018c0278343c0042a2c4a472393..cf27b5984627fc7b92fe2f41c5d32fe62e94e62b 100644 (file)
@@ -852,7 +852,7 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
                 * 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 @@ void btrfs_delete_inode(struct inode *inode)
 
        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);
 }
index 8dd8180183ff0b6931e435c518aa556f5ec81cb8..5e4c0d95ce43224bad1f9c94655986f571f7c089 100644 (file)
@@ -254,7 +254,7 @@ static void __btrfs_del_ordered_inode(struct btrfs_ordered_inode_tree *tree,
        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 @@ void btrfs_del_ordered_inode(struct inode *inode)
                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);
index c515c4b39996096d508c4feda8229b3cdf4dd5ac..4fa78736423e2e5a37a51b3ce1f4c0891f1b1136 100644 (file)
@@ -38,6 +38,6 @@ int btrfs_find_del_first_ordered_inode(struct btrfs_ordered_inode_tree *tree,
 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