aboutsummaryrefslogtreecommitdiff
path: root/ks_index.c
diff options
context:
space:
mode:
Diffstat (limited to 'ks_index.c')
-rw-r--r--ks_index.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/ks_index.c b/ks_index.c
index 23ba8c1..4f08e5e 100644
--- a/ks_index.c
+++ b/ks_index.c
@@ -145,6 +145,43 @@ static inline void ks_heapsort(hal_ks_index_t *ksi)
}
}
+#define fsck(_ksi) \
+ do { hal_error_t _err = hal_ks_index_fsck(_ksi); if (_err != HAL_OK) return _err; } while (0)
+
+
+hal_error_t hal_ks_index_fsck(hal_ks_index_t *ksi)
+{
+ if (ksi == NULL || ksi->index == NULL || ksi->names == NULL ||
+ ksi->size == 0 || ksi->used > ksi->size)
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ int cur, prev = -1;
+
+ for (cur = 0; cur < ksi->used; cur++) {
+
+ const int cmp = (prev < 0 ? -1 : hal_uuid_cmp(&ksi->names[ksi->index[prev]].name,
+ &ksi->names[ksi->index[cur]].name));
+
+ const uint8_t cur_chunk = ksi->names[ksi->index[cur]].chunk;
+
+ const uint8_t prev_chunk = (prev < 0 ? 0 : ksi->names[ksi->index[prev]].chunk);
+
+ if (cmp > 0)
+ return HAL_ERROR_KSI_INDEX_UUID_MISORDERED;
+
+ if (cur_chunk > 0 && cmp != 0)
+ return HAL_ERROR_KSI_INDEX_CHUNK_ORPHANED;
+
+ if (cur_chunk > 0 && prev_chunk + 1 < cur_chunk)
+ return HAL_ERROR_KSI_INDEX_CHUNK_MISSING;
+
+ if (cur_chunk > 0 && prev_chunk + 1 > cur_chunk)
+ return HAL_ERROR_KSI_INDEX_CHUNK_OVERLAPS;
+ }
+
+ return HAL_OK;
+}
+
hal_error_t hal_ks_index_setup(hal_ks_index_t *ksi)
{
if (ksi == NULL || ksi->index == NULL || ksi->names == NULL ||
@@ -156,6 +193,13 @@ hal_error_t hal_ks_index_setup(hal_ks_index_t *ksi)
*/
ks_heapsort(ksi);
+
+ /*
+ * One might think we should fsck here, but errors in the index
+ * at this point probably relate to errors in the supplied data,
+ * which only the driver knows how to clean up.
+ */
+
return HAL_OK;
}
@@ -171,6 +215,8 @@ hal_error_t hal_ks_index_find(hal_ks_index_t *ksi,
int where;
+ fsck(ksi);
+
int ok = ks_find(ksi, name, chunk, hint, &where);
if (blockno != NULL)
@@ -195,6 +241,8 @@ hal_error_t hal_ks_index_find_range(hal_ks_index_t *ksi,
int where;
+ fsck(ksi);
+
if (!ks_find(ksi, name, 0, hint, &where))
return HAL_ERROR_KEY_NOT_FOUND;
@@ -235,6 +283,8 @@ hal_error_t hal_ks_index_add(hal_ks_index_t *ksi,
int where;
+ fsck(ksi);
+
if (ks_find(ksi, name, chunk, hint, &where))
return HAL_ERROR_KEY_NAME_IN_USE;
@@ -256,6 +306,8 @@ hal_error_t hal_ks_index_add(hal_ks_index_t *ksi,
if (hint != NULL)
*hint = where;
+ fsck(ksi);
+
return HAL_OK;
}
@@ -271,6 +323,8 @@ hal_error_t hal_ks_index_delete(hal_ks_index_t *ksi,
int where;
+ fsck(ksi);
+
if (ksi->used == 0 || !ks_find(ksi, name, chunk, hint, &where))
return HAL_ERROR_KEY_NOT_FOUND;
@@ -291,6 +345,8 @@ hal_error_t hal_ks_index_delete(hal_ks_index_t *ksi,
if (hint != NULL)
*hint = where;
+ fsck(ksi);
+
return HAL_OK;
}
@@ -307,6 +363,8 @@ hal_error_t hal_ks_index_delete_range(hal_ks_index_t *ksi,
int where;
+ fsck(ksi);
+
if (ksi->used == 0 || !ks_find(ksi, name, 0, hint, &where))
return HAL_ERROR_KEY_NOT_FOUND;
@@ -343,6 +401,8 @@ hal_error_t hal_ks_index_delete_range(hal_ks_index_t *ksi,
if (hint != NULL)
*hint = where;
+ fsck(ksi);
+
return HAL_OK;
}
@@ -361,6 +421,8 @@ hal_error_t hal_ks_index_replace(hal_ks_index_t *ksi,
int where;
+ fsck(ksi);
+
if (ksi->used == 0 || !ks_find(ksi, name, chunk, hint, &where))
return HAL_ERROR_KEY_NOT_FOUND;
@@ -385,6 +447,8 @@ hal_error_t hal_ks_index_replace(hal_ks_index_t *ksi,
if (hint != NULL)
*hint = where;
+ fsck(ksi);
+
return HAL_OK;
}