@@ -168,6 +168,7 @@ xfs-y += $(addprefix scrub/, \
alloc_repair.o \
array.o \
bitmap.o \
+ blob.o \
bmap_repair.o \
ialloc_repair.o \
inode_repair.o \
new file mode 100644
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Oracle. All Rights Reserved.
+ * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ */
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_shared.h"
+#include "scrub/array.h"
+#include "scrub/blob.h"
+
+/*
+ * XFS Blob Storage
+ * ================
+ * Stores and retrieves blobs using a list. Objects are appended to
+ * the list and the pointer is returned as a magic cookie for retrieval.
+ */
+
+#define XB_KEY_MAGIC 0xABAADDAD
+struct xb_key {
+ struct list_head list;
+ uint32_t magic;
+ uint32_t size;
+ /* blob comes after here */
+} __attribute__((packed));
+
+#define XB_KEY_SIZE(sz) (sizeof(struct xb_key) + (sz))
+
+/* Initialize a blob storage object. */
+struct xblob *
+xblob_init(void)
+{
+ struct xblob *blob;
+ int error;
+
+ error = -ENOMEM;
+ blob = kmem_alloc(sizeof(struct xblob), KM_NOFS | KM_MAYFAIL);
+ if (!blob)
+ return ERR_PTR(error);
+
+ INIT_LIST_HEAD(&blob->list);
+ return blob;
+}
+
+/* Destroy a blob storage object. */
+void
+xblob_destroy(
+ struct xblob *blob)
+{
+ struct xb_key *key, *n;
+
+ list_for_each_entry_safe(key, n, &blob->list, list) {
+ list_del(&key->list);
+ kmem_free(key);
+ }
+ kmem_free(blob);
+}
+
+/* Retrieve a blob. */
+int
+xblob_get(
+ struct xblob *blob,
+ xblob_cookie cookie,
+ void *ptr,
+ uint32_t size)
+{
+ struct xb_key *key = (struct xb_key *)cookie;
+
+ if (key->magic != XB_KEY_MAGIC) {
+ ASSERT(0);
+ return -ENODATA;
+ }
+ if (size < key->size) {
+ ASSERT(0);
+ return -EFBIG;
+ }
+
+ memcpy(ptr, key + 1, key->size);
+ return 0;
+}
+
+/* Store a blob. */
+int
+xblob_put(
+ struct xblob *blob,
+ xblob_cookie *cookie,
+ void *ptr,
+ uint32_t size)
+{
+ struct xb_key *key;
+
+ key = kmem_alloc(XB_KEY_SIZE(size), KM_NOFS | KM_MAYFAIL);
+ if (!key)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&key->list);
+ list_add_tail(&key->list, &blob->list);
+ key->magic = XB_KEY_MAGIC;
+ key->size = size;
+ memcpy(key + 1, ptr, size);
+ *cookie = (xblob_cookie)key;
+ return 0;
+}
+
+/* Free a blob. */
+int
+xblob_free(
+ struct xblob *blob,
+ xblob_cookie cookie)
+{
+ struct xb_key *key = (struct xb_key *)cookie;
+
+ if (key->magic != XB_KEY_MAGIC) {
+ ASSERT(0);
+ return -ENODATA;
+ }
+ key->magic = 0;
+ list_del(&key->list);
+ kmem_free(key);
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Oracle. All Rights Reserved.
+ * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ */
+#ifndef __XFS_SCRUB_BLOB_H__
+#define __XFS_SCRUB_BLOB_H__
+
+struct xblob {
+ struct list_head list;
+};
+
+typedef void *xblob_cookie;
+
+struct xblob *xblob_init(void);
+void xblob_destroy(struct xblob *blob);
+int xblob_get(struct xblob *blob, xblob_cookie cookie, void *ptr,
+ uint32_t size);
+int xblob_put(struct xblob *blob, xblob_cookie *cookie, void *ptr,
+ uint32_t size);
+int xblob_free(struct xblob *blob, xblob_cookie cookie);
+
+#endif /* __XFS_SCRUB_BLOB_H__ */