socsvn commit: r236882 - soc2012/gpf/pefs_kmod/sbin/pefs

gpf at FreeBSD.org gpf at FreeBSD.org
Fri Jun 1 16:30:53 UTC 2012


Author: gpf
Date: Fri Jun  1 16:30:51 2012
New Revision: 236882
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=236882

Log:
  replace simple separate hashing with cuckoo hashing for .pefs.checksum.
  

Modified:
  soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c
  soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h

Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c
==============================================================================
--- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c	Fri Jun  1 16:29:59 2012	(r236881)
+++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c	Fri Jun  1 16:30:51 2012	(r236882)
@@ -38,6 +38,7 @@
 #include <ctype.h>
 #include <dirent.h>
 #include <inttypes.h>
+#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -61,13 +62,12 @@
 
 #define PEFS_CHECKSUM_FILE_VERSION 0xDD
 #define PEFS_HASH_BYTE_ALIGNMENT 512
+#define PEFS_EXTRA_TABLE_SIZE 0.15
 
-LIST_HEAD(file_header_head, file_header);
 TAILQ_HEAD(checksum_head, checksum);
 
 #define PEFS_CFH_SIZE 16
 #define PEFS_FH_SIZE 16
-#define PEFS_BUCKET_SIZE 8
 
 /* XXXgpf: unions for on disk structs and move to a different header? */
 struct checksum_file_header {
@@ -95,18 +95,49 @@
 };
 
 struct bucket {
-	struct file_header_head file_headers;
-	uint32_t offset_to_chain;
-	uint32_t nelements;
+	struct file_header * fhp;
 };
 
-struct hash_table {
-	struct bucket *buckets;
-	uint32_t size; /* how many buckets */
+/*
+ * This cuckoo hashing implementation requires 2 tables, each
+ * with his one hash function: pefs_hash1() & pefs_hash2()
+ */
+struct cuckoo_hash_table {
+	struct bucket *buckets1;
+	struct bucket *buckets2;
+	uint32_t size; /* how many buckets in each table */
 	uint32_t nelements;
 };
 
 static int
+pefs_is_prime(uint32_t num)
+{
+	int i;
+
+	if (num == 0)
+		return 1;
+
+	/* XXXgpf: [TODO] Take a look at arithmetics, comparisons between signed/unsigned etc */
+	for (i = 2; i <= sqrt(num); i++)  {
+		if (num % i == 0)
+			return 0;
+	}
+
+	return 1;
+}
+
+static int
+pefs_next_prime(uint32_t num)
+{
+	uint32_t i;
+
+	for (i = num;; i++)  {
+		if (pefs_is_prime(i))
+			return i;
+	}
+}
+
+static int
 pefs_compute_file_checksums(struct file_header *fhp, const EVP_MD *md,
 	uint8_t hash_len)
 {
@@ -127,6 +158,7 @@
 		return (PEFS_ERR_SYS);
 	}
 
+	/* XXXgpf: shouldn't we also check for empty files? */
 	resid = sb.st_size;
 
 	fd = open(fhp->path, O_RDONLY);
@@ -158,9 +190,9 @@
 		EVP_DigestUpdate(&mdctx, xsct.pxsct_ctext, xsct.pxsct_ctext_len);
 
 		dprintf(("read %d bytes from kernel\n\n", bytes_to_read));
-		dprintf(("printing contents of buffer:"));
-		for (i=0; i < (int)bytes_to_read; i++) dprintf(("%c", xsct.pxsct_ctext[i]));
-		dprintf(("!\n"));
+		//dprintf(("printing contents of buffer:"));
+		//for (i=0; i < (int)bytes_to_read; i++) dprintf(("%c", xsct.pxsct_ctext[i]));
+		//dprintf(("!\n"));
 
 		csp = malloc(sizeof(struct checksum));
 		if (csp == NULL) {
@@ -201,6 +233,7 @@
 	nfiles = 0;
 
 	while (fgets(buf, sizeof(buf), fpin) != NULL) {
+		/* XXXgpf: [TODO] check for numeric overflow */
 		nfiles++;
 	}
 
@@ -216,127 +249,205 @@
 }
 
 static void
-pefs_init_hash_table(struct hash_table *checksum_hash_tablep)
+pefs_init_hash_table(struct cuckoo_hash_table *chtp)
 {
-	checksum_hash_tablep->size = 0;
-	checksum_hash_tablep->nelements = 0;
-	checksum_hash_tablep->buckets = NULL;
+	chtp->size = 0;
+	chtp->nelements = 0;
+	chtp->buckets1 = NULL;
+	chtp->buckets2 = NULL;
 }
 
 static int
-pefs_allocate_hash_table(struct hash_table *checksum_hash_tablep, uint32_t nelements)
+pefs_allocate_hash_table(struct cuckoo_hash_table *chtp, uint32_t nelements)
 {
 	uint32_t i;
 
-	/*
-	 * XXXgpf: needs optimization
+	/* 
+	 * spending 15% more space for each table lowers the chance to fall into an 
+	 * infinite loop during cuckoo insertion to about 1.5%.
 	 */
-	checksum_hash_tablep->size = nelements;
-	checksum_hash_tablep->nelements = nelements;
-	checksum_hash_tablep->buckets = malloc (nelements * sizeof(struct bucket));
+	chtp->size = pefs_next_prime(nelements + (nelements * PEFS_EXTRA_TABLE_SIZE));
+	chtp->nelements = nelements;
+	if (chtp->size < chtp->nelements) {
+		pefs_warn("numeric overflow while computing hash table size");
+		return (PEFS_ERR_GENERIC);
+	}
+	dprintf(("hash table elem:%u\tsize: %u\n", chtp->nelements, chtp->size));
 
-	if (checksum_hash_tablep->buckets == NULL) {
+	chtp->buckets1 = malloc (chtp->size * sizeof(struct bucket));
+	if (chtp->buckets1 == NULL) {
 		pefs_warn("memory allocation error");
 		return (PEFS_ERR_SYS);
 	}
 
-	for (i = 0; i < checksum_hash_tablep->size; i++) {
-		checksum_hash_tablep->buckets[i].nelements = 0;
-		LIST_INIT(&(checksum_hash_tablep->buckets[i].file_headers));
+	for (i = 0; i < chtp->size; i++)
+		chtp->buckets1[i].fhp = NULL;
+
+	chtp->buckets2 = malloc (chtp->size * sizeof(struct bucket));
+	if (chtp->buckets2 == NULL) {
+		pefs_warn("memory allocation error");
+		return (PEFS_ERR_SYS);
 	}
 
+	for (i = 0; i < chtp->size; i++)
+		chtp->buckets2[i].fhp = NULL;
+
 	return (0);
 }
 
 static void
-pefs_free_hash_table(struct hash_table *checksum_hash_tablep)
+pefs_free_hash_table(struct cuckoo_hash_table *chtp)
 {
 	struct bucket *bp;
-	struct file_header *fhp, *tfhp;
+	struct file_header *fhp;
 	struct checksum *csp, *tcsp;
 	uint32_t i;
 
-	if (checksum_hash_tablep->buckets != NULL) {
-		for (i = 0; i < checksum_hash_tablep->size; i++) {
-			bp = &checksum_hash_tablep->buckets[i];
-			LIST_FOREACH_SAFE(fhp, &(bp->file_headers), bucket_entries, tfhp) {
+	if (chtp->buckets1 != NULL) {
+		for (i = 0; i < chtp->size; i++) {
+			bp = &chtp->buckets1[i];
+			fhp = bp->fhp;
+			if (fhp != NULL) {
+				TAILQ_FOREACH_SAFE(csp, &(fhp->checksums), checksum_entries, tcsp) {
+					TAILQ_REMOVE(&(fhp->checksums), csp, checksum_entries);
+					if (csp->hash != NULL)
+						free(csp->hash);
+					free(csp);
+				}
+				free(fhp);
+			}
+		}
+		free(chtp->buckets1);
+	}
+
+	if (chtp->buckets2 != NULL) {
+		for (i = 0; i < chtp->size; i++) {
+			bp = &chtp->buckets2[i];
+			fhp = bp->fhp;
+			if (fhp != NULL) {
 				TAILQ_FOREACH_SAFE(csp, &(fhp->checksums), checksum_entries, tcsp) {
 					TAILQ_REMOVE(&(fhp->checksums), csp, checksum_entries);
 					if (csp->hash != NULL)
 						free(csp->hash);
 					free(csp);
 				}
-				LIST_REMOVE(fhp, bucket_entries);
 				free(fhp);
 			}
 		}
-		free(checksum_hash_tablep->buckets);
+		free(chtp->buckets2);
 	}
 }
 
-static int
-pefs_add_to_bucket(struct bucket *bucketp, struct file_header *fhp)
+static uint32_t
+pefs_hash1(struct cuckoo_hash_table *chtp, struct file_header *fhp)
 {
-	struct file_header *elementp;
-	uint32_t i;
-
-	i = 1;
+	uint32_t nbucket;
 
-	if (bucketp->nelements == 0)
-		LIST_INSERT_HEAD(&(bucketp->file_headers), fhp, bucket_entries);
-	else
-		LIST_FOREACH(elementp, &(bucketp->file_headers), bucket_entries) {
-			if (elementp->file_id == fhp->file_id) {
-				warn("file identifier collision detected between files: %s & %s",
-						fhp->path, elementp->path);
-				return (PEFS_ERR_EXIST);
-			}
+	nbucket = fhp->file_id % chtp->size;
+	dprintf(("hash1: goto bucket %d\n", nbucket));
+	return (nbucket);
+}
 
-			if (fhp->file_id < elementp->file_id) {
-				LIST_INSERT_BEFORE(elementp, fhp, bucket_entries);
-				break;
-			}
-			else if (i++ == bucketp->nelements) {
-				LIST_INSERT_AFTER(elementp, fhp, bucket_entries);
-				break;
-			}
-		}
+static uint32_t
+pefs_hash2(struct cuckoo_hash_table *chtp, struct file_header *fhp)
+{
+	uint32_t nbucket;
 
-	bucketp->nelements++;
-	return (0);
+	nbucket = (fhp->file_id / chtp->size) % chtp->size;
+	dprintf(("hash2: goto bucket %d\n", nbucket));
+	return (nbucket);
 }
 
-static struct bucket *
-pefs_find_bucket(struct hash_table *checksum_hash_tablep, struct file_header *fhp)
+static int
+pefs_cuckoo_insert(struct cuckoo_hash_table *chtp,
+	struct file_header *fhp)
 {
-	uint32_t nbucket;
+	struct file_header *elem, *elem1, *elem2;
+	uint32_t i, max_tries, pos1, pos2;
+
+	max_tries = chtp->size;
+	elem = fhp;
 
-	nbucket = fhp->file_id % checksum_hash_tablep->size;
-	dprintf(("goto bucket %d\n", nbucket));
-	return (&(checksum_hash_tablep->buckets[nbucket]));
+	/* file_id collision check */
+	pos1 = pefs_hash1(chtp, elem);
+	elem1 = chtp->buckets1[pos1].fhp;
+	pos2 = pefs_hash2(chtp, elem);
+	elem2 = chtp->buckets2[pos2].fhp;
+	if (elem1 != NULL) {
+		if (elem1->file_id == fhp->file_id) {
+			pefs_warn("file identifier collision detected between files: %s & %s",
+					fhp->path, elem1->path);
+			return (PEFS_ERR_EXIST);
+		}
+	}
+
+	if (elem2 != NULL) {
+		if (elem2->file_id == fhp->file_id) {
+			pefs_warn("file identifier collision detected between files: %s & %s",
+					fhp->path, elem2->path);
+			return (PEFS_ERR_EXIST);
+		}
+	}
+
+	for (i = 0; i < max_tries; i++) {
+		pos1 = pefs_hash1(chtp, elem);
+		elem1 = chtp->buckets1[pos1].fhp;
+		/* do the cuckoo! */
+		chtp->buckets1[pos1].fhp = elem;
+		if (elem1 == NULL)
+			return 0;
+		pos2 = pefs_hash2(chtp, elem1);
+		elem2 = chtp->buckets2[pos2].fhp;
+		/* do the cuckoo! */
+		chtp->buckets2[pos2].fhp = elem1;
+		if (elem2 == NULL)
+			return 0;
+		else
+			elem = elem2;
+	}
+
+	pefs_warn("cuckoo_insert resulted in infinite loop!");
+	return (PEFS_ERR_CUCKOO_LOOP);
 }
 
 static int
-pefs_add_to_hash_table(struct hash_table *checksum_hash_tablep,
+pefs_add_to_hash_table(struct cuckoo_hash_table *chtp,
 	struct file_header *fhp)
 {
-	return (pefs_add_to_bucket(pefs_find_bucket(checksum_hash_tablep, fhp), fhp));
+	return (pefs_cuckoo_insert(chtp, fhp));
 }
 
 /* for debugging purposes */
 static void
-pefs_print_hash_table(struct hash_table *checksum_hash_tablep, uint8_t hash_len)
+pefs_print_hash_table(struct cuckoo_hash_table *chtp, uint8_t hash_len)
 {
 	struct file_header *fhp;
 	struct checksum *csp;
 	uint32_t i,j;
 
-	dprintf(("\n+++Printing Hash Table+++\n\n"));
-	for (i = 0; i < checksum_hash_tablep->size; i++) {
-		dprintf(("\nbucket %d with elements: %u\n", i, checksum_hash_tablep->buckets[i].nelements));
-		LIST_FOREACH(fhp, &(checksum_hash_tablep->buckets[i].file_headers), bucket_entries) {
-			//printf(("\tpath=%s!\t id = %d!\tnhashes = %d\n", fhp->path, (int)fhp->file_id, fhp->nhashes));
-			dprintf(("\tid = %llu!\tnhashes = %d\n", fhp->file_id, fhp->nhashes));
+	dprintf(("\n+++Printing Hash Table 1+++\n\n"));
+	for (i = 0; i < chtp->size; i++) {
+		fhp = chtp->buckets1[i].fhp;
+		dprintf(("\nbucket %d with element: %d\n", i, fhp == NULL ? 0 : 1));
+		if (fhp != NULL) {
+			//dprintf(("\tpath=%s\tid = %llu\tnhashes = %d\n", fhp->path, fhp->file_id, fhp->nhashes));
+			dprintf(("\tid = %llu\tnhashes = %d\n", fhp->file_id, fhp->nhashes));
+			TAILQ_FOREACH(csp, &(fhp->checksums), checksum_entries) {
+				dprintf(("\t\tdigest="));
+				for (j = 0; j < hash_len; j++)
+					dprintf(("%02x", csp->hash[j]));
+				dprintf(("\n"));
+			}
+		}
+	}
+
+	dprintf(("\n+++Printing Hash Table 2+++\n\n"));
+	for (i = 0; i < chtp->size; i++) {
+		fhp = chtp->buckets2[i].fhp;
+		dprintf(("\nbucket %d with element: %d\n", i, fhp == NULL ? 0 : 1));
+		if (fhp != NULL) {
+			//dprintf(("\tpath=%s\tid = %llu\tnhashes = %d\n", fhp->path, fhp->file_id, fhp->nhashes));
+			dprintf(("\tid = %llu\tnhashes = %d\n", fhp->file_id, fhp->nhashes));
 			TAILQ_FOREACH(csp, &(fhp->checksums), checksum_entries) {
 				dprintf(("\t\tdigest="));
 				for (j = 0; j < hash_len; j++)
@@ -477,7 +588,7 @@
  */
 static int
 pefs_create_in_memory_db(FILE *fpin, const EVP_MD *md, uint8_t hash_len,
-	struct hash_table *checksum_hash_tablep, char *fsroot)
+	struct cuckoo_hash_table *chtp, char *fsroot)
 {
 	struct statfs fs;
 	struct file_header *fhp;
@@ -493,7 +604,7 @@
 	if (error != 0)
 		return (error);
 
-	error = pefs_allocate_hash_table(checksum_hash_tablep, nfiles);
+	error = pefs_allocate_hash_table(chtp, nfiles);
 	if (error != 0)
 		return (error);
 
@@ -510,12 +621,12 @@
 		if (error != 0)
 			return (error);
 
-		error = pefs_add_to_hash_table(checksum_hash_tablep, fhp);
+		error = pefs_add_to_hash_table(chtp, fhp);
 		if (error != 0)
 			return (error);
 	}
 
-	pefs_print_hash_table(checksum_hash_tablep, hash_len);
+	pefs_print_hash_table(chtp, hash_len);
 
 	return (error);
 }
@@ -568,69 +679,65 @@
 	return (0);
 }
 
-static int
-pefs_write_bucket(int fdout, struct bucket *bp, uint32_t *buckets_offset)
-{
-	uint32_t offset_to_chain, nelements;
-	int bytes;
-
-	offset_to_chain = htole32(bp->offset_to_chain);
-	bytes = pwrite(fdout, &offset_to_chain, sizeof(offset_to_chain), *buckets_offset);
-	if (bytes != sizeof(offset_to_chain)) {
-		warn("error writing to .pefs.checksum");
-		return (PEFS_ERR_IO);
-	}
-	(*buckets_offset)+= sizeof(offset_to_chain);
-
-	nelements = htole32(bp->nelements);
-	bytes = pwrite(fdout, &nelements, sizeof(nelements), *buckets_offset);
-	if (bytes != sizeof(nelements)) {
-		warn("error writing to .pefs.checksum");
-		return (PEFS_ERR_IO);
-	}
-	(*buckets_offset)+= sizeof(nelements);
-
-	return (0);
-}
-
 /*
  * XXXgpf: [TODO] take a look at chained offsets
  */
 static int
-pefs_write_file_header(int fdout, struct file_header *fhp, uint32_t *fh_offset)
+pefs_write_file_header(int fdout, struct file_header *fhp, uint32_t *buckets_offset)
 {
 	uint64_t file_id;
 	uint32_t nhashes, offset_to_checksums;
 	int bytes;
 
 	nhashes = htole32(fhp->nhashes);
-	bytes = pwrite(fdout, &nhashes, sizeof(nhashes), *fh_offset);
+	bytes = pwrite(fdout, &nhashes, sizeof(nhashes), *buckets_offset);
 	if (bytes != sizeof(nhashes)) {
 		warn("error writing to .pefs.checksum");
 		return (PEFS_ERR_IO);
 	}
-	(*fh_offset)+= sizeof(nhashes);
+	(*buckets_offset)+= sizeof(nhashes);
 
 	offset_to_checksums = htole32(fhp->offset_to_checksums);
-	bytes = pwrite(fdout, &offset_to_checksums, sizeof(offset_to_checksums), *fh_offset);
+	bytes = pwrite(fdout, &offset_to_checksums, sizeof(offset_to_checksums), *buckets_offset);
 	if (bytes != sizeof(offset_to_checksums)) {
 		warn("error writing to .pefs.checksum");
 		return (PEFS_ERR_IO);
 	}
-	(*fh_offset)+= sizeof(offset_to_checksums);
+	(*buckets_offset)+= sizeof(offset_to_checksums);
 
 	file_id = htole64(fhp->file_id);
-	bytes = pwrite(fdout, &file_id, sizeof(file_id), *fh_offset);
+	bytes = pwrite(fdout, &file_id, sizeof(file_id), *buckets_offset);
 	if (bytes != sizeof(file_id)) {
 		warn("error writing to .pefs.checksum");
 		return (PEFS_ERR_IO);
 	}
-	(*fh_offset)+= sizeof(file_id);
+	(*buckets_offset)+= sizeof(file_id);
 
 	return (0);
 }
 
 static int
+pefs_write_bucket(int fdout, struct bucket *bp, uint32_t *buckets_offset)
+{
+	struct file_header emptyfh;
+	struct file_header *fhp;
+
+	fhp = bp->fhp;
+	if (fhp == NULL) {
+		/*
+		 * XXXgpf: empty files are not allowed so nhashes == 0 symbolizes an empty bucket.
+		 * perhaps a bitmap would be better? or we could steal a bit from some data member?
+		 */
+		emptyfh.nhashes = 0;
+		emptyfh.file_id = 0;
+		emptyfh.offset_to_checksums = 0;
+		fhp = &emptyfh;
+	}
+
+	return (pefs_write_file_header(fdout, fhp, buckets_offset));
+}
+
+static int
 pefs_write_hash(int fdout, struct checksum *csp, uint32_t *hashes_offset, uint8_t hash_len)
 {
 	int bytes;
@@ -649,16 +756,32 @@
  * All data member writes are done separately so as to avoid alignment problems.
  * Writes are always in little endian byte order.
  *
- * XXXgpf: [TODO] more comments about internal structure of file. This should probably
- * be done after design crystalizes (cuckoo hashing? embed? etc).
+ * First 16 bytes of .pefs.checksum are filled with .pefs.checksum's file header.
+ * Right after this header lies the 'index' part of our database. This index is later 
+ * kept in kernel memory.
+ *
+ * Index: 
+ * Both hash tables of cuckoo algorithm are written to the file sequentially. The 
+ * first hash table corresponds to hash1() and the second hash table to hash2().
+ * Each bucket (cell) of a hash table contains at most one entry(=file_header).
+ * The size of an entry is 16 bytes.
+ * 
+ * hash table entries end at the following offset: 
+ * 16 + hash_table_size * 2 * 16
+ *
+ * Checksums:
+ * The last part of .pefs.checksum is filled with the actual checksums.
+ * The offset where the first checksum starts is a 512 aligned address.
+ * Each hash table file header entry contains an offset that points to the beginning 
+ * of a chain of checksums for that particular file's 4k blocks.
  */
 static int
-pefs_write_checksum_file(int fdout, struct checksum_file_header *cfhp, struct hash_table *chtp)
+pefs_write_checksum_file(int fdout, struct checksum_file_header *cfhp, struct cuckoo_hash_table *chtp)
 {
 	struct bucket *bp;
 	struct checksum *csp;
 	struct file_header *fhp;
-	uint32_t i, buckets_offset, fh_offset, hashes_offset;
+	uint32_t i, buckets_offset, hashes_offset;
 	int error;
 
 	error = pefs_write_checksum_file_header(fdout, cfhp);
@@ -668,29 +791,40 @@
 	/* this points to where the buckets start */
 	buckets_offset = cfhp->offset_to_hash_table;
 
-	/* this points to where the buckets stop and the file headers start */
-	fh_offset = buckets_offset;
-	fh_offset+= chtp->size * PEFS_BUCKET_SIZE;
-
-	/* this points to where the file headers stop and the checksums start */
-	hashes_offset = fh_offset;
-	hashes_offset+= chtp->nelements * PEFS_FH_SIZE;
+	/* this points to where the buckets stop and the checksums start */
+	hashes_offset = buckets_offset;
+	hashes_offset+= chtp->size * PEFS_FH_SIZE * 2;
 	if (hashes_offset % PEFS_HASH_BYTE_ALIGNMENT != 0)
 		hashes_offset+= PEFS_HASH_BYTE_ALIGNMENT - (hashes_offset % PEFS_HASH_BYTE_ALIGNMENT);
 
 	for (i = 0; i < chtp->size; i++) {
-		bp = &chtp->buckets[i];
-		bp->offset_to_chain = fh_offset;
+		bp = &chtp->buckets1[i];
+		if (bp->fhp != NULL)
+			bp->fhp->offset_to_checksums = hashes_offset;
 		error = pefs_write_bucket(fdout, bp, &buckets_offset);
 		if (error != 0)
 			return (error);
 
-		LIST_FOREACH(fhp, &(chtp->buckets[i].file_headers), bucket_entries) {
-			fhp->offset_to_checksums = hashes_offset;
-			error = pefs_write_file_header(fdout, fhp, &fh_offset);
-			if (error != 0)
-				return (error);
+		fhp = bp->fhp;
+		if (fhp != NULL) {
+			TAILQ_FOREACH(csp, &(fhp->checksums), checksum_entries) {
+				error = pefs_write_hash(fdout, csp, &hashes_offset, cfhp->hash_len);
+				if (error != 0)
+					return (error);
+			}
+		}
+	}
 
+	for (i = 0; i < chtp->size; i++) {
+		bp = &chtp->buckets2[i];
+		if (bp->fhp != NULL)
+			bp->fhp->offset_to_checksums = hashes_offset;
+		error = pefs_write_bucket(fdout, bp, &buckets_offset);
+		if (error != 0)
+			return (error);
+
+		fhp = bp->fhp;
+		if (fhp != NULL) {
 			TAILQ_FOREACH(csp, &(fhp->checksums), checksum_entries) {
 				error = pefs_write_hash(fdout, csp, &hashes_offset, cfhp->hash_len);
 				if (error != 0)
@@ -704,7 +838,7 @@
 
 static void
 pefs_init_checksum_file_header(struct checksum_file_header *cfhp, const char *algo,
-		uint8_t hash_len, struct hash_table *chtp)
+		uint8_t hash_len, struct cuckoo_hash_table *chtp)
 {
 	cfhp->hash_len = hash_len;
 	cfhp->hash_table_size = chtp->size;
@@ -761,7 +895,7 @@
 int
 pefs_create_checksum_file(FILE *fpin, char *fsroot, char *csm_path, const char *algo)
 {
-	struct hash_table checksum_hash_table;
+	struct cuckoo_hash_table checksum_hash_table;
 	struct checksum_file_header cfh;
 	const EVP_MD *md;
 	int error, fdout;
@@ -784,6 +918,11 @@
 
 	error = pefs_create_in_memory_db(fpin, md, hash_len,
 		&checksum_hash_table, fsroot);
+	/*
+	 * XXXgpf: [TODO] Properly handle PEFS_ERR_CUCKOO_LOOP by retrying with
+	 * larger tables (next prime number?). We shouldn't have to reread all
+	 * file entries btw.
+	 */
 	if (error != 0)
 		goto out;
 

Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h
==============================================================================
--- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h	Fri Jun  1 16:29:59 2012	(r236881)
+++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h	Fri Jun  1 16:30:51 2012	(r236882)
@@ -61,6 +61,7 @@
 #define	PEFS_ERR_NOENT			5
 #define	PEFS_ERR_EXIST			6
 #define	PEFS_ERR_INVALID		7
+#define PEFS_ERR_CUCKOO_LOOP	8
 
 #define	PEFS_FS_IGNORE_TYPE		0x0001
 


More information about the svn-soc-all mailing list