iSome more comments in bstorage.c - dedup - deduplicating backup program Err bitreich.org 70 hgit clone git://bitreich.org/dedup/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/dedup/ URL:git://bitreich.org/dedup/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/dedup/ bitreich.org 70 1Log /scm/dedup/log.gph bitreich.org 70 1Files /scm/dedup/files.gph bitreich.org 70 1Refs /scm/dedup/refs.gph bitreich.org 70 1Tags /scm/dedup/tag bitreich.org 70 1README /scm/dedup/file/README.gph bitreich.org 70 1LICENSE /scm/dedup/file/LICENSE.gph bitreich.org 70 i--- Err bitreich.org 70 1commit 891041b03c66d2c37f4aef65de717e0f3740d1d1 /scm/dedup/commit/891041b03c66d2c37f4aef65de717e0f3740d1d1.gph bitreich.org 70 1parent bb81bcb6bd4b4bf7dbe36d2a47087dec0c58f812 /scm/dedup/commit/bb81bcb6bd4b4bf7dbe36d2a47087dec0c58f812.gph bitreich.org 70 hAuthor: sin URL:mailto:sin@2f30.org bitreich.org 70 iDate: Wed, 1 May 2019 20:54:49 +0100 Err bitreich.org 70 i Err bitreich.org 70 iSome more comments in bstorage.c Err bitreich.org 70 i Err bitreich.org 70 iDiffstat: Err bitreich.org 70 i M bstorage.c | 111 +++++++++++++++++++++---------- Err bitreich.org 70 i Err bitreich.org 70 i1 file changed, 75 insertions(+), 36 deletions(-) Err bitreich.org 70 i--- Err bitreich.org 70 1diff --git a/bstorage.c b/bstorage.c /scm/dedup/file/bstorage.c.gph bitreich.org 70 i@@ -2,10 +2,10 @@ Err bitreich.org 70 i * Storage layer implementation using a single backing file. Err bitreich.org 70 i * The file format is as follows: Err bitreich.org 70 i * Err bitreich.org 70 i- * [storage header] Err bitreich.org 70 i- * [storage descriptor 0] Err bitreich.org 70 i+ * [block header] Err bitreich.org 70 i+ * [block descriptor 0] Err bitreich.org 70 i * [data] Err bitreich.org 70 i- * [storage descriptor 1] Err bitreich.org 70 i+ * [block descriptor 1] Err bitreich.org 70 i * [data] Err bitreich.org 70 i * ... Err bitreich.org 70 i */ Err bitreich.org 70 i@@ -26,31 +26,30 @@ Err bitreich.org 70 i #include "queue.h" Err bitreich.org 70 i #include "tree.h" Err bitreich.org 70 i Err bitreich.org 70 i+/* block header flags */ Err bitreich.org 70 i+#define BHDRMAGIC "DEDUPDIDUPDIDUP" Err bitreich.org 70 i+#define NBHDRMAGIC sizeof(BHDRMAGIC) Err bitreich.org 70 i #define VMIN 0 Err bitreich.org 70 i #define VMAJ 1 Err bitreich.org 70 i- Err bitreich.org 70 i #define VMINMASK 0xff Err bitreich.org 70 i #define VMAJSHIFT 8 Err bitreich.org 70 i #define VMAJMASK 0xff Err bitreich.org 70 i- Err bitreich.org 70 i #define HALGOSHIFT 19 Err bitreich.org 70 i #define HALGOMASK 0x7 Err bitreich.org 70 i #define CALGOSHIFT 16 Err bitreich.org 70 i #define CALGOMASK 0x7 Err bitreich.org 70 i- Err bitreich.org 70 i-#define BHDRMAGIC "DEDUPDIDUPDIDUP" Err bitreich.org 70 i-#define NBHDRMAGIC sizeof(BHDRMAGIC) Err bitreich.org 70 i-#define BD2BTYPE 0x100 Err bitreich.org 70 i-#define BD2STYPE 0x101 Err bitreich.org 70 i- Err bitreich.org 70 i-#define BHDRSIZE (NBHDRMAGIC + 8 + 8) Err bitreich.org 70 i-#define BDSIZE (8 + 8 + 8 + 8 + (MDSIZE)) Err bitreich.org 70 i- Err bitreich.org 70 i #define CNONETYPE 0 Err bitreich.org 70 i #define CSNAPPYTYPE 1 Err bitreich.org 70 i #define HBLAKE2BTYPE 0 Err bitreich.org 70 i #define HBLAKE2STYPE 1 Err bitreich.org 70 i+#define BHDRSIZE (NBHDRMAGIC + 8 + 8) Err bitreich.org 70 i+ Err bitreich.org 70 i+/* block descriptor flags */ Err bitreich.org 70 i+#define BD2BTYPE 0x100 Err bitreich.org 70 i+#define BD2STYPE 0x101 Err bitreich.org 70 i+#define BDSIZE (8 + 8 + 8 + 8 + (MDSIZE)) Err bitreich.org 70 i Err bitreich.org 70 i+/* misc helpers */ Err bitreich.org 70 i extern ssize_t xread(int, void *, size_t); Err bitreich.org 70 i extern ssize_t xwrite(int, void *, size_t); Err bitreich.org 70 i extern int pack(unsigned char *, char *, ...); Err bitreich.org 70 i@@ -80,30 +79,30 @@ static struct bops bops = { Err bitreich.org 70 i Err bitreich.org 70 i /* Block header structure */ Err bitreich.org 70 i struct bhdr { Err bitreich.org 70 i- char magic[NBHDRMAGIC]; Err bitreich.org 70 i- uint64_t flags; Err bitreich.org 70 i- uint64_t nbd; Err bitreich.org 70 i+ char magic[NBHDRMAGIC]; /* magic number for file(1) */ Err bitreich.org 70 i+ uint64_t flags; /* version number, compression/hashing configuration */ Err bitreich.org 70 i+ uint64_t nbd; /* number of block descriptors */ Err bitreich.org 70 i }; Err bitreich.org 70 i Err bitreich.org 70 i /* Block descriptor */ Err bitreich.org 70 i struct bd { Err bitreich.org 70 i- uint16_t type; Err bitreich.org 70 i- uint8_t reserved[6]; Err bitreich.org 70 i- uint64_t offset; /* offset of block */ Err bitreich.org 70 i- uint64_t size; /* size of block */ Err bitreich.org 70 i- uint64_t refcnt; Err bitreich.org 70 i- unsigned char md[MDSIZE]; Err bitreich.org 70 i- RB_ENTRY(bd) rbe; Err bitreich.org 70 i- SLIST_ENTRY(bd) sle; Err bitreich.org 70 i+ uint16_t type; /* type of hashing algorithm used */ Err bitreich.org 70 i+ uint8_t reserved[6]; /* should be set to 0 when writing */ Err bitreich.org 70 i+ uint64_t offset; /* block offset */ Err bitreich.org 70 i+ uint64_t size; /* block size */ Err bitreich.org 70 i+ uint64_t refcnt; /* reference count of block, 0 if block is removed */ Err bitreich.org 70 i+ unsigned char md[MDSIZE]; /* hash of block */ Err bitreich.org 70 i+ RB_ENTRY(bd) rbe; /* bdcache link node */ Err bitreich.org 70 i+ SLIST_ENTRY(bd) sle; /* gchead link node */ Err bitreich.org 70 i }; Err bitreich.org 70 i RB_HEAD(bdcache, bd); Err bitreich.org 70 i Err bitreich.org 70 i /* Storage layer context */ Err bitreich.org 70 i struct sctx { Err bitreich.org 70 i- struct bdcache bdcache; Err bitreich.org 70 i- SLIST_HEAD(gchead, bd) gchead; Err bitreich.org 70 i- struct bhdr bhdr; Err bitreich.org 70 i- int fd; Err bitreich.org 70 i+ struct bdcache bdcache; /* cache of block descriptors */ Err bitreich.org 70 i+ SLIST_HEAD(gchead, bd) gchead; /* list of all blocks with a zero refcount */ Err bitreich.org 70 i+ struct bhdr bhdr; /* block header entry */ Err bitreich.org 70 i+ int fd; /* underlying storage file descriptor */ Err bitreich.org 70 i int rdonly; /* when set to 1, the bssync() operation is a no-op */ Err bitreich.org 70 i int type; /* hash algorithm for new blocks */ Err bitreich.org 70 i }; Err bitreich.org 70 i@@ -231,7 +230,7 @@ packbd(int fd, struct bd *bd) Err bitreich.org 70 i return n; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i-/* Insert block descriptor to cache */ Err bitreich.org 70 i+/* Load block descriptor from file */ Err bitreich.org 70 i static int Err bitreich.org 70 i loadbd(struct sctx *sctx) Err bitreich.org 70 i { Err bitreich.org 70 i@@ -257,6 +256,16 @@ loadbd(struct sctx *sctx) Err bitreich.org 70 i return -1; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i+ /* Err bitreich.org 70 i+ * When refcount is 0 the block has been removed. Err bitreich.org 70 i+ * In that case, the block descriptor is still present Err bitreich.org 70 i+ * in the file as it is used to locate the next block Err bitreich.org 70 i+ * descriptor which could be live. Err bitreich.org 70 i+ * Err bitreich.org 70 i+ * The garbage collection list links together all block Err bitreich.org 70 i+ * descriptors that have a reference count of 0. Err bitreich.org 70 i+ * This is needed to implement the gc operation. Err bitreich.org 70 i+ */ Err bitreich.org 70 i if (bd->refcnt > 0) Err bitreich.org 70 i RB_INSERT(bdcache, &sctx->bdcache, bd); Err bitreich.org 70 i else Err bitreich.org 70 i@@ -295,7 +304,7 @@ initbdcache(struct sctx *sctx) Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i-/* Create storage */ Err bitreich.org 70 i+/* Create storage file */ Err bitreich.org 70 i static int Err bitreich.org 70 i bscreat(struct bctx *bctx, char *path, int mode, struct bparam *bpar) Err bitreich.org 70 i { Err bitreich.org 70 i@@ -346,6 +355,7 @@ bscreat(struct bctx *bctx, char *path, int mode, struct bparam *bpar) Err bitreich.org 70 i bhdr->nbd = 0; Err bitreich.org 70 i sctx->fd = fd; Err bitreich.org 70 i Err bitreich.org 70 i+ /* Write the block header entry to the file */ Err bitreich.org 70 i if (packbhdr(fd, bhdr) < 0) { Err bitreich.org 70 i free(sctx); Err bitreich.org 70 i close(fd); Err bitreich.org 70 i@@ -354,7 +364,7 @@ bscreat(struct bctx *bctx, char *path, int mode, struct bparam *bpar) Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i-/* Open storage */ Err bitreich.org 70 i+/* Open storage file */ Err bitreich.org 70 i static int Err bitreich.org 70 i bsopen(struct bctx *bctx, char *path, int flags, int mode, struct bparam *bpar) Err bitreich.org 70 i { Err bitreich.org 70 i@@ -387,6 +397,8 @@ bsopen(struct bctx *bctx, char *path, int flags, int mode, struct bparam *bpar) Err bitreich.org 70 i RB_INIT(&sctx->bdcache); Err bitreich.org 70 i SLIST_INIT(&sctx->gchead); Err bitreich.org 70 i bhdr = &sctx->bhdr; Err bitreich.org 70 i+ Err bitreich.org 70 i+ /* Read block header entry from file */ Err bitreich.org 70 i if (unpackbhdr(fd, bhdr) < 0) { Err bitreich.org 70 i free(sctx); Err bitreich.org 70 i close(fd); Err bitreich.org 70 i@@ -442,6 +454,10 @@ bsopen(struct bctx *bctx, char *path, int flags, int mode, struct bparam *bpar) Err bitreich.org 70 i sctx->fd = fd; Err bitreich.org 70 i sctx->rdonly = flags == O_RDONLY; Err bitreich.org 70 i Err bitreich.org 70 i+ /* Err bitreich.org 70 i+ * Initialize block descriptor cache Err bitreich.org 70 i+ * and garbage collection list. Err bitreich.org 70 i+ */ Err bitreich.org 70 i if (initbdcache(sctx) < 0) { Err bitreich.org 70 i free(sctx); Err bitreich.org 70 i close(fd); Err bitreich.org 70 i@@ -450,7 +466,7 @@ bsopen(struct bctx *bctx, char *path, int flags, int mode, struct bparam *bpar) Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i-/* Write a block */ Err bitreich.org 70 i+/* Write a block to the storage file */ Err bitreich.org 70 i static int Err bitreich.org 70 i bsput(struct bctx *bctx, void *buf, size_t n, unsigned char *md) Err bitreich.org 70 i { Err bitreich.org 70 i@@ -460,7 +476,6 @@ bsput(struct bctx *bctx, void *buf, size_t n, unsigned char *md) Err bitreich.org 70 i off_t offs; Err bitreich.org 70 i Err bitreich.org 70 i sctx = bctx->sctx; Err bitreich.org 70 i- Err bitreich.org 70 i switch (sctx->type) { Err bitreich.org 70 i case BD2BTYPE: Err bitreich.org 70 i if (b2bhash(buf, n, key.md) < 0) Err bitreich.org 70 i@@ -474,6 +489,11 @@ bsput(struct bctx *bctx, void *buf, size_t n, unsigned char *md) Err bitreich.org 70 i return -1; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i+ /* Err bitreich.org 70 i+ * If the block is already present in the cache Err bitreich.org 70 i+ * just increment the reference count and write back Err bitreich.org 70 i+ * the block descriptor associated for that block. Err bitreich.org 70 i+ */ Err bitreich.org 70 i bd = RB_FIND(bdcache, &sctx->bdcache, &key); Err bitreich.org 70 i if (bd != NULL) { Err bitreich.org 70 i off_t bdoffs; Err bitreich.org 70 i@@ -482,7 +502,6 @@ bsput(struct bctx *bctx, void *buf, size_t n, unsigned char *md) Err bitreich.org 70 i if (lseek(sctx->fd, bdoffs, SEEK_SET) < 0) Err bitreich.org 70 i return -1; Err bitreich.org 70 i Err bitreich.org 70 i- /* Block already present, increment the reference count */ Err bitreich.org 70 i bd->refcnt++; Err bitreich.org 70 i if (packbd(sctx->fd, bd) < 0) { Err bitreich.org 70 i bd->refcnt--; Err bitreich.org 70 i@@ -493,10 +512,12 @@ bsput(struct bctx *bctx, void *buf, size_t n, unsigned char *md) Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i+ /* New blocks are always appended to the storage file */ Err bitreich.org 70 i offs = lseek(sctx->fd, 0, SEEK_END); Err bitreich.org 70 i if (offs < 0) Err bitreich.org 70 i return -1; Err bitreich.org 70 i Err bitreich.org 70 i+ /* Allocate a new block descriptor */ Err bitreich.org 70 i bd = calloc(1, sizeof(*bd)); Err bitreich.org 70 i if (bd == NULL) Err bitreich.org 70 i return -1; Err bitreich.org 70 i@@ -506,25 +527,34 @@ bsput(struct bctx *bctx, void *buf, size_t n, unsigned char *md) Err bitreich.org 70 i bd->refcnt = 1; Err bitreich.org 70 i memcpy(bd->md, key.md, MDSIZE); Err bitreich.org 70 i Err bitreich.org 70 i+ /* Write block descriptor to storage file */ Err bitreich.org 70 i if (packbd(sctx->fd, bd) < 0) { Err bitreich.org 70 i free(bd); Err bitreich.org 70 i return -1; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i+ /* Append block payload to block descriptor */ Err bitreich.org 70 i if (xwrite(sctx->fd, buf, n) != n) { Err bitreich.org 70 i+ /* Shouldn't fail but if it does rewind storage file state */ Err bitreich.org 70 i ftruncate(sctx->fd, offs); Err bitreich.org 70 i free(bd); Err bitreich.org 70 i return -1; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i+ /* Err bitreich.org 70 i+ * Update block entry header. Err bitreich.org 70 i+ * The header will be written to the storage file Err bitreich.org 70 i+ * when bsclose() or bssync() is called. Err bitreich.org 70 i+ */ Err bitreich.org 70 i bhdr = &sctx->bhdr; Err bitreich.org 70 i bhdr->nbd++; Err bitreich.org 70 i+ Err bitreich.org 70 i RB_INSERT(bdcache, &sctx->bdcache, bd); Err bitreich.org 70 i memcpy(md, bd->md, MDSIZE); Err bitreich.org 70 i return bd->size; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i-/* Read a block */ Err bitreich.org 70 i+/* Read a block from the storage file */ Err bitreich.org 70 i static int Err bitreich.org 70 i bsget(struct bctx *bctx, unsigned char *md, void *buf, size_t *n) Err bitreich.org 70 i { Err bitreich.org 70 i@@ -576,6 +606,7 @@ bsrm(struct bctx *bctx, unsigned char *md) Err bitreich.org 70 i return -1; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i+ /* This block is still referenced so just return */ Err bitreich.org 70 i if (bd->refcnt > 0) Err bitreich.org 70 i return 0; Err bitreich.org 70 i Err bitreich.org 70 i@@ -600,6 +631,14 @@ bsrm(struct bctx *bctx, unsigned char *md) Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i+/* Err bitreich.org 70 i+ * Re-punch all holes in the storage file. Err bitreich.org 70 i+ * This is needed when the storage file is copied from Err bitreich.org 70 i+ * one system to another and back. The target system Err bitreich.org 70 i+ * may not support hole punching so the holes will be Err bitreich.org 70 i+ * filled with literal zeroes, negating the space saving Err bitreich.org 70 i+ * effects. Err bitreich.org 70 i+ */ Err bitreich.org 70 i static int Err bitreich.org 70 i bsgc(struct bctx *bctx) Err bitreich.org 70 i { Err bitreich.org 70 .