Btrfs: only retry transaction reservation once
authorJosef Bacik <josef@redhat.com>
Tue, 5 Apr 2011 15:57:27 +0000 (11:57 -0400)
committerJosef Bacik <josef@redhat.com>
Fri, 8 Apr 2011 17:00:32 +0000 (13:00 -0400)
I saw a lockup where we kept getting into this start transaction->commit
transaction loop because of enospce.  The fact is if we fail to make our
reservation, we've tried _everything_ several times, so we only need to try and
commit the transaction once, and if that doesn't work then we really are out of
space and need to just exit.  Thanks,

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

index 5b158da7e0bb7816710859ee47f7fad4007fb4a2..4583008217e61c7039658614e2641fd72ab2ce5f 100644 (file)
@@ -181,6 +181,7 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
 {
        struct btrfs_trans_handle *h;
        struct btrfs_transaction *cur_trans;
+       int retries = 0;
        int ret;
 
        if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)
@@ -224,10 +225,18 @@ again:
 
        if (num_items > 0) {
                ret = btrfs_trans_reserve_metadata(h, root, num_items);
-               if (ret == -EAGAIN) {
+               if (ret == -EAGAIN && !retries) {
+                       retries++;
                        btrfs_commit_transaction(h, root);
                        goto again;
+               } else if (ret == -EAGAIN) {
+                       /*
+                        * We have already retried and got EAGAIN, so really we
+                        * don't have space, so set ret to -ENOSPC.
+                        */
+                       ret = -ENOSPC;
                }
+
                if (ret < 0) {
                        btrfs_end_transaction(h, root);
                        return ERR_PTR(ret);