From 098ef98d5bff461c66c3798fbebca7b1c06fdf79 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 18 Sep 2022 17:10:33 -0400 Subject: [PATCH] bcachefs: Add private error codes for ENOSPC 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 --- fs/bcachefs/alloc_foreground.c | 4 +++- fs/bcachefs/btree_update_leaf.c | 8 +++++--- fs/bcachefs/buckets.c | 2 +- fs/bcachefs/disk_groups.c | 2 +- fs/bcachefs/ec.c | 4 ++-- fs/bcachefs/errcode.h | 16 +++++++++++++++- fs/bcachefs/fs-io.c | 4 ++-- fs/bcachefs/inode.c | 2 +- fs/bcachefs/journal.c | 13 ++++++++----- fs/bcachefs/journal_sb.c | 2 +- fs/bcachefs/quota.c | 2 +- fs/bcachefs/replicas.c | 16 +++++++--------- fs/bcachefs/str_hash.h | 4 ++-- fs/bcachefs/subvolume.c | 4 ++-- fs/bcachefs/super-io.c | 2 +- fs/bcachefs/super.c | 6 +++--- 16 files changed, 55 insertions(+), 36 deletions(-) diff --git a/fs/bcachefs/alloc_foreground.c b/fs/bcachefs/alloc_foreground.c index f60fe159916e1..e890b09f80c61 100644 --- a/fs/bcachefs/alloc_foreground.c +++ b/fs/bcachefs/alloc_foreground.c @@ -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; diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index d262a9e16b951..bf3177a3a4204 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -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; } diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c index 136e116981d70..f01b8171cb925 100644 --- a/fs/bcachefs/buckets.c +++ b/fs/bcachefs/buckets.c @@ -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); diff --git a/fs/bcachefs/disk_groups.c b/fs/bcachefs/disk_groups.c index 5f405d38b3deb..6b81f35861aca 100644 --- a/fs/bcachefs/disk_groups.c +++ b/fs/bcachefs/disk_groups.c @@ -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); } diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c index f33acf1af1109..aa83011463828 100644 --- a/fs/bcachefs/ec.c +++ b/fs/bcachefs/ec.c @@ -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; diff --git a/fs/bcachefs/errcode.h b/fs/bcachefs/errcode.h index 2088cc5a4f3c1..3dc477eb3600c 100644 --- a/fs/bcachefs/errcode.h +++ b/fs/bcachefs/errcode.h @@ -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) \ diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c index c83e1de9a39a2..73f5677cadcec 100644 --- a/fs/bcachefs/fs-io.c +++ b/fs/bcachefs/fs-io.c @@ -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) diff --git a/fs/bcachefs/inode.c b/fs/bcachefs/inode.c index fc0f98074dab3..99987db87ab62 100644 --- a/fs/bcachefs/inode.c +++ b/fs/bcachefs/inode.c @@ -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); diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c index 9961cc674ad73..97c1ecb65dbd3 100644 --- a/fs/bcachefs/journal.c +++ b/fs/bcachefs/journal.c @@ -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); diff --git a/fs/bcachefs/journal_sb.c b/fs/bcachefs/journal_sb.c index 001cecec1291b..cfdbd92d2164f 100644 --- a/fs/bcachefs/journal_sb.c +++ b/fs/bcachefs/journal_sb.c @@ -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); diff --git a/fs/bcachefs/quota.c b/fs/bcachefs/quota.c index 454c76e03be90..c12d715fb7581 100644 --- a/fs/bcachefs/quota.c +++ b/fs/bcachefs/quota.c @@ -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) diff --git a/fs/bcachefs/replicas.c b/fs/bcachefs/replicas.c index 4ede807e2fb75..e540c1aa91ba8 100644 --- a/fs/bcachefs/replicas.c +++ b/fs/bcachefs/replicas.c @@ -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); diff --git a/fs/bcachefs/str_hash.h b/fs/bcachefs/str_hash.h index 560983df13f09..6178ae620ff1f 100644 --- a/fs/bcachefs/str_hash.h +++ b/fs/bcachefs/str_hash.h @@ -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); diff --git a/fs/bcachefs/subvolume.c b/fs/bcachefs/subvolume.c index fb3f8e4074c7a..8c98bacca290b 100644 --- a/fs/bcachefs/subvolume.c +++ b/fs/bcachefs/subvolume.c @@ -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; diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c index 220fda28c8653..12edd4b9a44b3 100644 --- a/fs/bcachefs/super-io.c +++ b/fs/bcachefs/super-io.c @@ -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; } } diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index 1c8fac6036445..8dc87c1032167 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -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; } -- 2.30.2