[PATCH v2 3/5] refs/reftable: add fsck check for number of tables
- From
Karthik Nayak <karthik.188@gmail.com>
- Date
- Sep 2, 2025, 07:05 UTC
- Message-ID
- <20250902-228-reftable-introduce-consistency-checks-v2-3-4f96b3834779@gmail.com>
- In-Reply-To
- <20250902-228-reftable-introduce-consistency-checks-v2-0-4f96b3834779@gmail.com>
Introduce a reftable fsck check to check that the number of files in the reftable directory matches the number of files listed in 'tables.list'. We do this by iterating over the files in the reftable directory and counting all the files present excluding the 'tables.list'. This is also exposed over Git's fsck checks as a 'badReftableStackCount' error.
Signed-off-by: Karthik Nayak <karthik.188@gmail.com> --- Documentation/fsck-msgids.adoc | 3 +++ fsck.h | 1 + refs/reftable-backend.c | 3 +++ reftable/fsck.c | 34 ++++++++++++++++++++++++++++++++++ reftable/reftable-fsck.h | 2 ++ t/t0614-reftable-fsck.sh | 20 ++++++++++++++++++++ 6 files changed, 63 insertions(+)
diff --git a/Documentation/fsck-msgids.adoc b/Documentation/fsck-msgids.adoc index 784ddc0df5..707e2fc50a 100644 --- a/Documentation/fsck-msgids.adoc +++ b/Documentation/fsck-msgids.adoc @@ -38,6 +38,9 @@ `badReferentName`:: (ERROR) The referent name of a symref is invalid. +`badReftableStackCount`:: + (ERROR) Mismatch in number of tables. + `badReftableTableName`:: (ERROR) A reftable table has an invalid name. diff --git a/fsck.h b/fsck.h index 5901f944a1..256effc4f8 100644 --- a/fsck.h +++ b/fsck.h @@ -34,6 +34,7 @@ enum fsck_msg_type { FUNC(BAD_PACKED_REF_HEADER, ERROR) \ FUNC(BAD_PARENT_SHA1, ERROR) \ FUNC(BAD_REFERENT_NAME, ERROR) \ + FUNC(BAD_REFTABLE_STACK_COUNT, ERROR) \ FUNC(BAD_REFTABLE_TABLE_NAME, ERROR) \ FUNC(BAD_REF_CONTENT, ERROR) \ FUNC(BAD_REF_FILETYPE, ERROR) \ diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c index c38c6422f8..59c39f9b52 100644 --- a/refs/reftable-backend.c +++ b/refs/reftable-backend.c @@ -2695,6 +2695,9 @@ static int reftable_fsck_error_handler(struct reftable_fsck_info *info, case REFTABLE_FSCK_ERROR_TABLE_NAME: msg_id = FSCK_MSG_BAD_REFTABLE_TABLE_NAME; break; + case REFTABLE_FSCK_ERROR_STACK_COUNT: + msg_id = FSCK_MSG_BAD_REFTABLE_STACK_COUNT; + break; default: BUG("unknown fsck error: %d", info->error); } diff --git a/reftable/fsck.c b/reftable/fsck.c index 4282b1413e..20e6bfb0f1 100644 --- a/reftable/fsck.c +++ b/reftable/fsck.c @@ -2,6 +2,28 @@ #include "reftable-fsck.h" #include "stack.h" +static int reftable_fsck_valid_stack_count(struct reftable_stack *st) +{ + DIR *dir = opendir(st->reftable_dir); + struct dirent *d = NULL; + unsigned int count = 0; + + if (!dir) + return 0; + + while ((d = readdir(dir))) { + if (!strcmp(d->d_name, "tables.list")) + continue; + + if (d->d_type == DT_REG) + count++; + } + + closedir(dir); + + return count == st->tables_len; +} + int reftable_fsck_check(struct reftable_stack *stack, reftable_fsck_report_fn report_fn, reftable_fsck_verbose_fn verbose_fn, @@ -47,6 +69,18 @@ int reftable_fsck_check(struct reftable_stack *stack, } } + verbose_fn("Checking reftable tables count", cb_data); + + if (!reftable_fsck_valid_stack_count(stack)) { + struct reftable_fsck_info info = { + .error = REFTABLE_FSCK_ERROR_STACK_COUNT, + .path = "reftable/tables.list", + .msg = "mismatch in number of tables" + }; + + err = report_fn(&info, cb_data); + } + out: free_names(names); return err; diff --git a/reftable/reftable-fsck.h b/reftable/reftable-fsck.h index 4cf0053234..beba1bdd1a 100644 --- a/reftable/reftable-fsck.h +++ b/reftable/reftable-fsck.h @@ -6,6 +6,8 @@ enum reftable_fsck_error { /* Invalid table name */ REFTABLE_FSCK_ERROR_TABLE_NAME = -1, + /* Incorrect number of tables present */ + REFTABLE_FSCK_ERROR_STACK_COUNT = -2, }; /* Represents an individual error encountered during the FSCK checks. */ diff --git a/t/t0614-reftable-fsck.sh b/t/t0614-reftable-fsck.sh index 81d30df2d7..3a34a31890 100755 --- a/t/t0614-reftable-fsck.sh +++ b/t/t0614-reftable-fsck.sh @@ -55,4 +55,24 @@ test_expect_success 'table name should be checked' ' ) ' +test_expect_success 'table count should be checked' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + git commit --allow-empty -m initial && + + git refs verify 2>err && + test_must_be_empty err && + + touch .git/reftable/0x000000002812-0x000000002813-c830a596.ref && + + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: reftable/tables.list: badReftableStackCount: mismatch in number of tables + EOF + test_cmp expect err + ) +' + test_done
-- 2.50.1