bcachefs: Add private error codes for ENOSPC
authorKent Overstreet <kent.overstreet@linux.dev>
Sun, 18 Sep 2022 21:10:33 +0000 (17:10 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:40 +0000 (17:09 -0400)
Continuing the saga of introducing private dedicated error codes for
each error path, this patch converts ENOSPC to error codes that are
subtypes of ENOSPC. We've recently had a test failure where we got
-ENOSPC where we shouldn't have, and didn't have enough information to
tell where it came from, so this patch will solve that problem.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
16 files changed:
fs/bcachefs/alloc_foreground.c
fs/bcachefs/btree_update_leaf.c
fs/bcachefs/buckets.c
fs/bcachefs/disk_groups.c
fs/bcachefs/ec.c
fs/bcachefs/errcode.h
fs/bcachefs/fs-io.c
fs/bcachefs/inode.c
fs/bcachefs/journal.c
fs/bcachefs/journal_sb.c
fs/bcachefs/quota.c
fs/bcachefs/replicas.c
fs/bcachefs/str_hash.h
fs/bcachefs/subvolume.c
fs/bcachefs/super-io.c
fs/bcachefs/super.c

index f60fe159916e19bfd22761621507e645b44cd0d3..e890b09f80c619707939b4bf6db0ccc0c4f63312 100644 (file)
@@ -1246,7 +1246,9 @@ err:
 
        if (bch2_err_matches(ret, BCH_ERR_open_buckets_empty) ||
            bch2_err_matches(ret, BCH_ERR_freelist_empty))
-               return cl ? -EAGAIN : -ENOSPC;
+               return cl
+                       ? -EAGAIN
+                       : -BCH_ERR_ENOSPC_bucket_alloc;
 
        if (bch2_err_matches(ret, BCH_ERR_insufficient_devices))
                return -EROFS;
index d262a9e16b951092701a3d8c5950192094b9d95e..bf3177a3a4204f80db94e4422c0a1da848f2b88a 100644 (file)
@@ -1037,9 +1037,11 @@ int bch2_trans_commit_error(struct btree_trans *trans,
        }
 
        BUG_ON(bch2_err_matches(ret, BCH_ERR_transaction_restart) != !!trans->restarted);
-       BUG_ON(ret == -ENOSPC &&
-              !(trans->flags & BTREE_INSERT_NOWAIT) &&
-              (trans->flags & BTREE_INSERT_NOFAIL));
+
+       bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOSPC) &&
+                               !(trans->flags & BTREE_INSERT_NOWAIT) &&
+                               (trans->flags & BTREE_INSERT_NOFAIL), c,
+               "%s: incorrectly got %s\n", __func__, bch2_err_str(ret));
 
        return ret;
 }
index 136e116981d703935d86f42760650a60ceb7cadb..f01b8171cb9255d401932a7e5cc3d7c9f797521c 100644 (file)
@@ -1991,7 +1991,7 @@ recalculate:
                ret = 0;
        } else {
                atomic64_set(&c->sectors_available, sectors_available);
-               ret = -ENOSPC;
+               ret = -BCH_ERR_ENOSPC_disk_reservation;
        }
 
        mutex_unlock(&c->sectors_available_lock);
index 5f405d38b3debd189bd9fc28d23cae54cf4dcfc4..6b81f35861aca327dd6b50e42b2194edf8fc7cec 100644 (file)
@@ -276,7 +276,7 @@ static int __bch2_disk_group_add(struct bch_sb_handle *sb, unsigned parent,
 
                groups = bch2_sb_resize_disk_groups(sb, u64s);
                if (!groups)
-                       return -ENOSPC;
+                       return -BCH_ERR_ENOSPC_disk_label_add;
 
                nr_groups = disk_groups_nr(groups);
        }
index f33acf1af1109ea091bbd171ce9fca51421a12f6..aa83011463828c871a5149e2ba6ddc9aeabd829d 100644 (file)
@@ -731,7 +731,7 @@ static int ec_stripe_bkey_insert(struct btree_trans *trans,
                                continue;
                        }
 
-                       ret = -ENOSPC;
+                       ret = -BCH_ERR_ENOSPC_stripe_create;
                        break;
                }
 
@@ -1388,7 +1388,7 @@ static int __bch2_ec_stripe_head_reuse(struct bch_fs *c,
        idx = get_existing_stripe(c, h);
        if (idx < 0) {
                bch_err(c, "failed to find an existing stripe");
-               return -ENOSPC;
+               return -BCH_ERR_ENOSPC_stripe_reuse;
        }
 
        h->s->have_existing_stripe = true;
index 2088cc5a4f3c1d23f9343eec43ff4d06a3f7ca76..3dc477eb3600c800564fd4fc4484d30711b07e65 100644 (file)
@@ -2,7 +2,21 @@
 #ifndef _BCACHEFS_ERRCODE_H
 #define _BCACHEFS_ERRCODE_H
 
-#define BCH_ERRCODES()                                                 \
+#define BCH_ERRCODES()                                                         \
+       x(ENOSPC,                       ENOSPC_disk_reservation)                \
+       x(ENOSPC,                       ENOSPC_bucket_alloc)                    \
+       x(ENOSPC,                       ENOSPC_disk_label_add)                  \
+       x(ENOSPC,                       ENOSPC_stripe_create)                   \
+       x(ENOSPC,                       ENOSPC_stripe_reuse)                    \
+       x(ENOSPC,                       ENOSPC_inode_create)                    \
+       x(ENOSPC,                       ENOSPC_str_hash_create)                 \
+       x(ENOSPC,                       ENOSPC_snapshot_create)                 \
+       x(ENOSPC,                       ENOSPC_subvolume_create)                \
+       x(ENOSPC,                       ENOSPC_sb)                              \
+       x(ENOSPC,                       ENOSPC_sb_journal)                      \
+       x(ENOSPC,                       ENOSPC_sb_quota)                        \
+       x(ENOSPC,                       ENOSPC_sb_replicas)                     \
+       x(ENOSPC,                       ENOSPC_sb_members)                      \
        x(0,                            open_buckets_empty)                     \
        x(0,                            freelist_empty)                         \
        x(BCH_ERR_freelist_empty,       no_buckets_found)                       \
index c83e1de9a39a275040ed546debf25f2943bd7822..73f5677cadcec47d8d22391bdc24088770999387 100644 (file)
@@ -3031,7 +3031,7 @@ bkey_err:
        bch2_trans_unlock(&trans); /* lock ordering, before taking pagecache locks: */
        mark_pagecache_reserved(inode, start_sector, iter.pos.offset);
 
-       if (ret == -ENOSPC && (mode & FALLOC_FL_ZERO_RANGE)) {
+       if (bch2_err_matches(ret, ENOSPC) && (mode & FALLOC_FL_ZERO_RANGE)) {
                struct quota_res quota_res = { 0 };
                s64 i_sectors_delta = 0;
 
@@ -3082,7 +3082,7 @@ static long bchfs_fallocate(struct bch_inode_info *inode, int mode,
         * so that the VFS cache i_size is consistent with the btree i_size:
         */
        if (ret &&
-           !(ret == -ENOSPC && (mode & FALLOC_FL_ZERO_RANGE)))
+           !(bch2_err_matches(ret, ENOSPC) && (mode & FALLOC_FL_ZERO_RANGE)))
                return ret;
 
        if (mode & FALLOC_FL_KEEP_SIZE && end > inode->v.i_size)
index fc0f98074dab3889b89fd81e4fcb0922ae219fb2..99987db87ab629971131eea6726c8d287421307f 100644 (file)
@@ -552,7 +552,7 @@ again:
                goto found_slot;
 
        if (!ret && start == min)
-               ret = -ENOSPC;
+               ret = -BCH_ERR_ENOSPC_inode_create;
 
        if (ret) {
                bch2_trans_iter_exit(trans, iter);
index 9961cc674ad7383c57cf2ecad1825b712858c386..97c1ecb65dbd3654207dd52a0b0469e7040173dc 100644 (file)
@@ -808,14 +808,16 @@ static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr,
                if (new_fs) {
                        bu[nr_got] = bch2_bucket_alloc_new_fs(ca);
                        if (bu[nr_got] < 0) {
-                               ret = -ENOSPC;
+                               ret = -BCH_ERR_ENOSPC_bucket_alloc;
                                break;
                        }
                } else {
                        ob[nr_got] = bch2_bucket_alloc(c, ca, RESERVE_none,
                                               false, cl);
                        if (IS_ERR(ob[nr_got])) {
-                               ret = cl ? -EAGAIN : -ENOSPC;
+                               ret = cl
+                                       ? -EAGAIN
+                                       : -BCH_ERR_ENOSPC_bucket_alloc;
                                break;
                        }
 
@@ -942,10 +944,11 @@ int bch2_set_nr_journal_buckets(struct bch_fs *c, struct bch_dev *ca,
                 * reservation to ensure we'll actually be able to allocate:
                 */
 
-               if (bch2_disk_reservation_get(c, &disk_res,
-                                             bucket_to_sector(ca, nr - ja->nr), 1, 0)) {
+               ret = bch2_disk_reservation_get(c, &disk_res,
+                                               bucket_to_sector(ca, nr - ja->nr), 1, 0);
+               if (ret) {
                        mutex_unlock(&c->sb_lock);
-                       return -ENOSPC;
+                       return ret;
                }
 
                ret = __bch2_set_nr_journal_buckets(ca, nr, false, &cl);
index 001cecec1291b291a95eba65274a1a6dba782ff2..cfdbd92d2164f4360983c2ed47773e0e8272bfb5 100644 (file)
@@ -197,7 +197,7 @@ int bch2_journal_buckets_to_sb(struct bch_fs *c, struct bch_dev *ca)
        j = bch2_sb_resize_journal_v2(&ca->disk_sb,
                                 (sizeof(*j) + sizeof(j->d[0]) * nr) / sizeof(u64));
        if (!j)
-               return -ENOSPC;
+               return -BCH_ERR_ENOSPC_sb_journal;
 
        bch2_sb_field_delete(&ca->disk_sb, BCH_SB_FIELD_journal);
 
index 454c76e03be90484ebb68c5cbb55b2537ae1429f..c12d715fb75813cefad722dcb9005daccd3c3e5b 100644 (file)
@@ -665,7 +665,7 @@ static int bch2_quota_set_info(struct super_block *sb, int type,
                sb_quota = bch2_sb_resize_quota(&c->disk_sb,
                                        sizeof(*sb_quota) / sizeof(u64));
                if (!sb_quota)
-                       return -ENOSPC;
+                       return -BCH_ERR_ENOSPC_sb_quota;
        }
 
        if (info->i_fieldmask & QC_SPC_TIMER)
index 4ede807e2fb758c45ec73d4fd178376897a21dfb..e540c1aa91ba8a5f9804667a2401c70c4effe13f 100644 (file)
@@ -485,7 +485,7 @@ int bch2_replicas_gc_end(struct bch_fs *c, int ret)
                    bch2_fs_usage_read_one(c, &c->usage_base->replicas[i])) {
                        n = cpu_replicas_add_entry(&c->replicas_gc, e);
                        if (!n.entries) {
-                               ret = -ENOSPC;
+                               ret = -ENOMEM;
                                goto err;
                        }
 
@@ -494,10 +494,9 @@ int bch2_replicas_gc_end(struct bch_fs *c, int ret)
                }
        }
 
-       if (bch2_cpu_replicas_to_sb_replicas(c, &c->replicas_gc)) {
-               ret = -ENOSPC;
+       ret = bch2_cpu_replicas_to_sb_replicas(c, &c->replicas_gc);
+       if (ret)
                goto err;
-       }
 
        ret = replicas_table_update(c, &c->replicas_gc);
 err:
@@ -600,10 +599,9 @@ retry:
 
        bch2_cpu_replicas_sort(&new);
 
-       if (bch2_cpu_replicas_to_sb_replicas(c, &new)) {
-               ret = -ENOSPC;
+       ret = bch2_cpu_replicas_to_sb_replicas(c, &new);
+       if (ret)
                goto err;
-       }
 
        ret = replicas_table_update(c, &new);
 err:
@@ -758,7 +756,7 @@ static int bch2_cpu_replicas_to_sb_replicas_v0(struct bch_fs *c,
        sb_r = bch2_sb_resize_replicas_v0(&c->disk_sb,
                        DIV_ROUND_UP(bytes, sizeof(u64)));
        if (!sb_r)
-               return -ENOSPC;
+               return -BCH_ERR_ENOSPC_sb_replicas;
 
        bch2_sb_field_delete(&c->disk_sb, BCH_SB_FIELD_replicas);
        sb_r = bch2_sb_get_replicas_v0(c->disk_sb.sb);
@@ -803,7 +801,7 @@ static int bch2_cpu_replicas_to_sb_replicas(struct bch_fs *c,
        sb_r = bch2_sb_resize_replicas(&c->disk_sb,
                        DIV_ROUND_UP(bytes, sizeof(u64)));
        if (!sb_r)
-               return -ENOSPC;
+               return -BCH_ERR_ENOSPC_sb_replicas;
 
        bch2_sb_field_delete(&c->disk_sb, BCH_SB_FIELD_replicas_v0);
        sb_r = bch2_sb_get_replicas(c->disk_sb.sb);
index 560983df13f09645b7739aed855a65bb7f5a3e96..6178ae620ff1fdb8c1999cdbd5664538fc9a7578 100644 (file)
@@ -207,7 +207,7 @@ bch2_hash_hole(struct btree_trans *trans,
                        return 0;
        bch2_trans_iter_exit(trans, iter);
 
-       return ret ?: -ENOSPC;
+       return ret ?: -BCH_ERR_ENOSPC_str_hash_create;
 }
 
 static __always_inline
@@ -277,7 +277,7 @@ int bch2_hash_set_snapshot(struct btree_trans *trans,
        }
 
        if (!ret)
-               ret = -ENOSPC;
+               ret = -BCH_ERR_ENOSPC_str_hash_create;
 out:
        bch2_trans_iter_exit(trans, &slot);
        bch2_trans_iter_exit(trans, &iter);
index fb3f8e4074c7a65d38939402a80a91af6db18ba4..8c98bacca290b8301f421a16707eebf811e32126 100644 (file)
@@ -517,7 +517,7 @@ int bch2_snapshot_node_create(struct btree_trans *trans, u32 parent,
                        goto err;
 
                if (!k.k || !k.k->p.offset) {
-                       ret = -ENOSPC;
+                       ret = -BCH_ERR_ENOSPC_snapshot_create;
                        goto err;
                }
 
@@ -1031,7 +1031,7 @@ int bch2_subvolume_create(struct btree_trans *trans, u64 inode,
        }
 
        if (!ret)
-               ret = -ENOSPC;
+               ret = -BCH_ERR_ENOSPC_subvolume_create;
        goto err;
 found_slot:
        snapshot_subvols[0] = dst_iter.pos.offset;
index 220fda28c865334f4f53f6d2e5ab2ab7709903f6..12edd4b9a44b323f0ad83d9788e2a2a87fda27b8 100644 (file)
@@ -132,7 +132,7 @@ int bch2_sb_realloc(struct bch_sb_handle *sb, unsigned u64s)
                if (new_bytes > max_bytes) {
                        pr_err("%pg: superblock too big: want %zu but have %llu",
                               sb->bdev, new_bytes, max_bytes);
-                       return -ENOSPC;
+                       return -BCH_ERR_ENOSPC_sb;
                }
        }
 
index 1c8fac60364458d58f3f89d5aa7481b0bbb260df..8dc87c1032167a01dc0fb70dcdcf5fc2e425d634 100644 (file)
@@ -1584,7 +1584,7 @@ int bch2_dev_add(struct bch_fs *c, const char *path)
                                le32_to_cpu(mi->field.u64s) +
                                sizeof(dev_mi) / sizeof(u64))) {
                bch_err(c, "device add error: new device superblock too small");
-               ret = -ENOSPC;
+               ret = -BCH_ERR_ENOSPC_sb_members;
                goto err_unlock;
        }
 
@@ -1597,7 +1597,7 @@ int bch2_dev_add(struct bch_fs *c, const char *path)
                        goto have_slot;
 no_slot:
        bch_err(c, "device add error: already have maximum number of devices");
-       ret = -ENOSPC;
+       ret = -BCH_ERR_ENOSPC_sb_members;
        goto err_unlock;
 
 have_slot:
@@ -1608,7 +1608,7 @@ have_slot:
        mi = bch2_sb_resize_members(&c->disk_sb, u64s);
        if (!mi) {
                bch_err(c, "device add error: no room in superblock for member info");
-               ret = -ENOSPC;
+               ret = -BCH_ERR_ENOSPC_sb_members;
                goto err_unlock;
        }