Btrfs: optimize how we account for space in truncate
authorJosef Bacik <josef@redhat.com>
Mon, 8 Aug 2011 17:46:15 +0000 (13:46 -0400)
committerJosef Bacik <josef@redhat.com>
Wed, 19 Oct 2011 19:12:35 +0000 (15:12 -0400)
Currently we're starting and stopping a transaction for no real reason, so kill
that and just reserve enough space as if we can truncate all in one transaction.
Also use btrfs_block_rsv_check() for our reserve to minimize the amount of space
we may have to allocate for our slack space.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
fs/btrfs/inode.c

index fe3891e..4d057c0 100644 (file)
@@ -6482,6 +6482,7 @@ static int btrfs_truncate(struct inode *inode)
        struct btrfs_trans_handle *trans;
        unsigned long nr;
        u64 mask = root->sectorsize - 1;
+       u64 min_size = btrfs_calc_trans_metadata_size(root, 2);
 
        ret = btrfs_truncate_page(inode->i_mapping, inode->i_size);
        if (ret)
@@ -6530,17 +6531,21 @@ static int btrfs_truncate(struct inode *inode)
        if (!rsv)
                return -ENOMEM;
 
-       trans = btrfs_start_transaction(root, 4);
+       /*
+        * 2 for the truncate slack space
+        * 1 for the orphan item we're going to add
+        * 1 for the orphan item deletion
+        * 1 for updating the inode.
+        */
+       trans = btrfs_start_transaction(root, 5);
        if (IS_ERR(trans)) {
                err = PTR_ERR(trans);
                goto out;
        }
 
-       /*
-        * Reserve space for the truncate process.  Truncate should be adding
-        * space, but if there are snapshots it may end up using space.
-        */
-       ret = btrfs_truncate_reserve_metadata(trans, root, rsv);
+       /* Migrate the slack space for the truncate to our reserve */
+       ret = btrfs_block_rsv_migrate(&root->fs_info->trans_block_rsv, rsv,
+                                     min_size);
        BUG_ON(ret);
 
        ret = btrfs_orphan_add(trans, inode);
@@ -6549,21 +6554,6 @@ static int btrfs_truncate(struct inode *inode)
                goto out;
        }
 
-       nr = trans->blocks_used;
-       btrfs_end_transaction(trans, root);
-       btrfs_btree_balance_dirty(root, nr);
-
-       /*
-        * Ok so we've already migrated our bytes over for the truncate, so here
-        * just reserve the one slot we need for updating the inode.
-        */
-       trans = btrfs_start_transaction(root, 1);
-       if (IS_ERR(trans)) {
-               err = PTR_ERR(trans);
-               goto out;
-       }
-       trans->block_rsv = rsv;
-
        /*
         * setattr is responsible for setting the ordered_data_close flag,
         * but that is only tested during the last file release.  That
@@ -6585,20 +6575,30 @@ static int btrfs_truncate(struct inode *inode)
                btrfs_add_ordered_operation(trans, root, inode);
 
        while (1) {
+               ret = btrfs_block_rsv_check(trans, root, rsv, min_size, 0);
+               if (ret) {
+                       /*
+                        * This can only happen with the original transaction we
+                        * started above, every other time we shouldn't have a
+                        * transaction started yet.
+                        */
+                       if (ret == -EAGAIN)
+                               goto end_trans;
+                       err = ret;
+                       break;
+               }
+
                if (!trans) {
-                       trans = btrfs_start_transaction(root, 3);
+                       /* Just need the 1 for updating the inode */
+                       trans = btrfs_start_transaction(root, 1);
                        if (IS_ERR(trans)) {
                                err = PTR_ERR(trans);
                                goto out;
                        }
-
-                       ret = btrfs_truncate_reserve_metadata(trans, root,
-                                                             rsv);
-                       BUG_ON(ret);
-
-                       trans->block_rsv = rsv;
                }
 
+               trans->block_rsv = rsv;
+
                ret = btrfs_truncate_inode_items(trans, root, inode,
                                                 inode->i_size,
                                                 BTRFS_EXTENT_DATA_KEY);
@@ -6613,7 +6613,7 @@ static int btrfs_truncate(struct inode *inode)
                        err = ret;
                        break;
                }
-
+end_trans:
                nr = trans->blocks_used;
                btrfs_end_transaction(trans, root);
                trans = NULL;