All of lore.kernel.org
 help / color / mirror / Atom feed
* master - [device/bcache] some more work on bcache
@ 2018-04-23 13:46 David Teigland
  0 siblings, 0 replies; 2+ messages in thread
From: David Teigland @ 2018-04-23 13:46 UTC (permalink / raw)
  To: lvm-devel

Gitweb:        https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=0f0eb04edb00cb5e95c47cb9ca2e70574e6e49ce
Commit:        0f0eb04edb00cb5e95c47cb9ca2e70574e6e49ce
Parent:        46867a45d28ecb667d08df8d8cb497fffc10814d
Author:        Joe Thornber <ejt@redhat.com>
AuthorDate:    Thu Feb 1 14:52:43 2018 +0000
Committer:     David Teigland <teigland@redhat.com>
CommitterDate: Fri Apr 20 11:12:50 2018 -0500

[device/bcache] some more work on bcache

---
 lib/device/bcache.c   |   99 ++++++++++++++++++++++-----------
 lib/device/bcache.h   |    2 +-
 test/unit/Makefile.in |    2 +-
 test/unit/bcache_t.c  |  147 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 216 insertions(+), 34 deletions(-)

diff --git a/lib/device/bcache.c b/lib/device/bcache.c
index 3b8cf78..5a7b2f9 100644
--- a/lib/device/bcache.c
+++ b/lib/device/bcache.c
@@ -167,12 +167,19 @@ static struct io_engine *_engine_create(unsigned max_io)
 
 static void _engine_destroy(struct io_engine *e)
 {
+	int r;
+
 	_cb_set_destroy(e->cbs);
-	io_destroy(e->aio_context);
+
+	// io_destroy is really slow
+	r = io_destroy(e->aio_context);
+	if (r)
+		log_sys_warn("io_destroy");
+
 	dm_free(e);
 }
 
-static bool _engine_issue(struct io_engine *e, int fd, enum dir d,
+static bool _engine_issue(struct io_engine *e, enum dir d, int fd,
 			  sector_t sb, sector_t se, void *data, void *context)
 {
 	int r;
@@ -290,7 +297,6 @@ enum block_flags {
 };
 
 struct bcache {
-	int fd;
 	sector_t block_sectors;
 	uint64_t nr_data_blocks;
 	uint64_t nr_cache_blocks;
@@ -488,6 +494,30 @@ static void _relink(struct block *b)
  *
  *--------------------------------------------------------------*/
 
+static void _complete_io(void *context, int err)
+{
+	struct block *b = context;
+	struct bcache *cache = b->cache;
+
+	b->error = err;
+	_clear_flags(b, BF_IO_PENDING);
+	cache->nr_io_pending--;
+
+	/*
+	 * b is on the io_pending list, so we don't want to use unlink_block.
+	 * Which would incorrectly adjust nr_dirty.
+	 */
+	dm_list_del(&b->list);
+
+	if (b->error)
+		dm_list_add(&cache->errored, &b->list);
+
+	else {
+		_clear_flags(b, BF_DIRTY);
+		_link_block(b);
+	}
+}
+
 /*
  * |b->list| should be valid (either pointing to itself, on one of the other
  * lists.
@@ -502,7 +532,13 @@ static bool _issue_low_level(struct block *b, enum dir d)
 		return false;
 
 	_set_flags(b, BF_IO_PENDING);
-	return _engine_issue(cache->engine, cache->fd, d, sb, se, b->data, b);
+	if (!_engine_issue(cache->engine, d, b->fd, sb, se, b->data, b)) {
+		_complete_io(b, -EIO);
+		return false;
+	}
+
+	return true;
+
 }
 
 static inline bool _issue_read(struct block *b)
@@ -515,30 +551,6 @@ static inline bool _issue_write(struct block *b)
 	return _issue_low_level(b, DIR_WRITE);
 }
 
-static void _complete_io(void *context, int err)
-{
-	struct block *b = context;
-	struct bcache *cache = b->cache;
-
-	b->error = err;
-	_clear_flags(b, BF_IO_PENDING);
-	cache->nr_io_pending--;
-
-	/*
-	 * b is on the io_pending list, so we don't want to use unlink_block.
-	 * Which would incorrectly adjust nr_dirty.
-	 */
-	dm_list_del(&b->list);
-
-	if (b->error)
-		dm_list_add(&cache->errored, &b->list);
-
-	else {
-		_clear_flags(b, BF_DIRTY);
-		_link_block(b);
-	}
-}
-
 static bool _wait_io(struct bcache *cache)
 {
 	return _engine_wait(cache->engine, _complete_io);
@@ -598,7 +610,7 @@ static struct block *_find_unused_clean_block(struct bcache *cache)
 	return NULL;
 }
 
-static struct block *_new_block(struct bcache *cache, block_address index)
+static struct block *_new_block(struct bcache *cache, int fd, block_address index)
 {
 	struct block *b;
 
@@ -616,6 +628,7 @@ static struct block *_new_block(struct bcache *cache, block_address index)
 		dm_list_init(&b->list);
 		dm_list_init(&b->hash);
 		b->flags = 0;
+		b->fd = fd;
 		b->index = index;
 		b->ref_count = 0;
 		b->error = 0;
@@ -685,7 +698,7 @@ static struct block *_lookup_or_read_block(struct bcache *cache,
 	} else {
 		_miss(cache, flags);
 
-		b = _new_block(cache, index);
+		b = _new_block(cache, fd, index);
 		if (b) {
 			if (flags & GF_ZERO)
 				_zero_block(b);
@@ -728,6 +741,21 @@ struct bcache *bcache_create(sector_t block_sectors, unsigned nr_cache_blocks)
 {
 	struct bcache *cache;
 
+	if (!nr_cache_blocks) {
+		log_warn("bcache must have at least one cache block");
+		return NULL;
+	}
+
+	if (!block_sectors) {
+		log_warn("bcache must have a non zero block size");
+		return NULL;
+	}
+
+	if (block_sectors & ((PAGE_SIZE >> SECTOR_SHIFT) - 1)) {
+		log_warn("bcache block size must be a multiple of page size");
+		return NULL;
+	}
+
 	cache = dm_malloc(sizeof(*cache));
 	if (!cache)
 		return NULL;
@@ -787,6 +815,11 @@ void bcache_destroy(struct bcache *cache)
 	dm_free(cache);
 }
 
+unsigned bcache_nr_cache_blocks(struct bcache *cache)
+{
+	return cache->nr_cache_blocks;
+}
+
 void bcache_prefetch(struct bcache *cache, int fd, block_address index)
 {
 	struct block *b = _hash_lookup(cache, fd, index);
@@ -794,7 +827,7 @@ void bcache_prefetch(struct bcache *cache, int fd, block_address index)
 	if (!b) {
 		cache->prefetches++;
 
-		b = _new_block(cache, index);
+		b = _new_block(cache, fd, index);
 		if (b)
 			_issue_read(b);
 	}
@@ -803,7 +836,9 @@ void bcache_prefetch(struct bcache *cache, int fd, block_address index)
 bool bcache_get(struct bcache *cache, int fd, block_address index,
 	        unsigned flags, struct block **result)
 {
-	struct block *b = _lookup_or_read_block(cache, fd, index, flags);
+	struct block *b;
+
+	b = _lookup_or_read_block(cache, fd, index, flags);
 	if (b) {
 		if (!b->ref_count)
 			cache->nr_locked++;
diff --git a/lib/device/bcache.h b/lib/device/bcache.h
index 0747b5a..2730347 100644
--- a/lib/device/bcache.h
+++ b/lib/device/bcache.h
@@ -61,7 +61,7 @@ enum bcache_get_flags {
 
 typedef uint64_t block_address;
 
-unsigned bcache_get_max_prefetches(struct bcache *cache);
+unsigned bcache_nr_cache_blocks(struct bcache *cache);
 
 /*
  * Use the prefetch method to take advantage of asynchronous IO.  For example,
diff --git a/test/unit/Makefile.in b/test/unit/Makefile.in
index 8127ec0..5cf92ba 100644
--- a/test/unit/Makefile.in
+++ b/test/unit/Makefile.in
@@ -47,7 +47,7 @@ $(TARGETS): $(OBJECTS) $(top_builddir)/libdm/libdevmapper.$(LIB_SUFFIX)
 	$(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) -L$(top_builddir)/libdm \
 	      -o $@ $(OBJECTS) $(LDLIBS)
 
-unit: $(TARGETS)
+unit: $(TARGETS) $(top_builddir)/lib/liblvm-internal.a
 	@echo Running unit tests
 	LD_LIBRARY_PATH=$(top_builddir)/libdm ./$(TARGETS)
 endif
diff --git a/test/unit/bcache_t.c b/test/unit/bcache_t.c
index da274a9..ef92721 100644
--- a/test/unit/bcache_t.c
+++ b/test/unit/bcache_t.c
@@ -12,9 +12,21 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#define _GNU_SOURCE
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
 #include "units.h"
 #include "bcache.h"
 
+#define MEG 2048
+#define SECTOR_SHIFT 9
+
+static const char *_test_path = "test.bin";
+
 int bcache_init(void)
 {
 	return 0;
@@ -25,6 +37,42 @@ int bcache_fini(void)
 	return 0;
 }
 
+static int open_file(const char *path)
+{
+	return open(path, O_EXCL | O_RDWR | O_DIRECT, 0666);
+}
+
+static int _prep_file(const char *path)
+{
+	int fd, r;
+
+	fd = open(path, O_CREAT | O_TRUNC | O_EXCL | O_RDWR | O_DIRECT, 0666);
+	if (fd < 0)
+		return -1;
+
+	r = fallocate(fd, FALLOC_FL_ZERO_RANGE, 0, (16 * MEG) << SECTOR_SHIFT);
+	if (r) {
+		close(fd);
+		return -1;
+	}
+
+	close(fd);
+	return 0;
+}
+
+
+static int test_init(void)
+{
+	unlink(_test_path);
+	return _prep_file(_test_path);
+}
+
+static int test_exit(void)
+{
+	unlink(_test_path);
+	return 0;
+}
+
 static void test_create(void)
 {
 	struct bcache *cache = bcache_create(8, 16);
@@ -32,7 +80,106 @@ static void test_create(void)
 	bcache_destroy(cache);
 }
 
+static void test_nr_cache_blocks_must_be_positive(void)
+{
+	struct bcache *cache = bcache_create(8, 0);
+	CU_ASSERT_PTR_NULL(cache);
+}
+
+static void test_block_size_must_be_positive(void)
+{
+	struct bcache *cache = bcache_create(0, 16);
+	CU_ASSERT_PTR_NULL(cache);
+}
+
+static void test_block_size_must_be_multiple_of_page_size(void)
+{
+	unsigned i;
+	struct bcache *cache;
+
+	{
+		static unsigned _bad_examples[] = {3, 9, 13, 1025};
+
+		for (i = 0; i < DM_ARRAY_SIZE(_bad_examples); i++) {
+			cache = bcache_create(_bad_examples[i], 16);
+			CU_ASSERT_PTR_NULL(cache);
+		}
+	}
+
+	{
+		// Only testing a few sizes because io_destroy is seriously
+		// slow.
+		for (i = 1; i < 25; i++) {
+			cache = bcache_create(8 * i, 16);
+			CU_ASSERT_PTR_NOT_NULL(cache);
+			bcache_destroy(cache);
+		}
+	}
+}
+
+static void test_reads_work(void)
+{
+	int fd;
+
+	// FIXME: add fixtures.
+	test_init();
+	fd = open_file("./test.bin");
+	CU_ASSERT(fd >= 0);
+
+	{
+		int i;
+		struct block *b;
+		struct bcache *cache = bcache_create(8, 16);
+
+		CU_ASSERT(bcache_get(cache, fd, 0, 0, &b));
+		for (i = 0; i < 8 << SECTOR_SHIFT; i++)
+			CU_ASSERT(((unsigned char *) b->data)[i] == 0);
+		bcache_put(b);
+
+		bcache_destroy(cache);
+	}
+
+	close(fd);
+
+	test_exit();
+}
+
+static void test_prefetch_works(void)
+{
+	int fd;
+
+	// FIXME: add fixtures.
+	test_init();
+	fd = open_file("./test.bin");
+	CU_ASSERT(fd >= 0);
+
+	{
+		int i;
+		struct block *b;
+		struct bcache *cache = bcache_create(8, 16);
+
+		for (i = 0; i < 16; i++)
+			bcache_prefetch(cache, fd, i);
+
+		for (i = 0; i < 16; i++) {
+			CU_ASSERT(bcache_get(cache, fd, i, 0, &b));
+			bcache_put(b);
+		}
+
+		bcache_destroy(cache);
+	}
+
+	close(fd);
+
+	test_exit();
+}
+
 CU_TestInfo bcache_list[] = {
 	{ (char*)"create", test_create },
+	{ (char*)"nr cache block must be positive", test_nr_cache_blocks_must_be_positive },
+	{ (char*)"block size must be positive", test_block_size_must_be_positive },
+	{ (char*)"block size must be multiple of page size", test_block_size_must_be_multiple_of_page_size },
+	{ (char*)"reads work", test_reads_work },
+	{ (char*)"prefetch works", test_prefetch_works },
 	CU_TEST_INFO_NULL
 };



^ permalink raw reply related	[flat|nested] 2+ messages in thread

* master - [device/bcache] some more work on bcache
@ 2018-04-23 13:51 David Teigland
  0 siblings, 0 replies; 2+ messages in thread
From: David Teigland @ 2018-04-23 13:51 UTC (permalink / raw)
  To: lvm-devel

Gitweb:        https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=0f0eb04edb00cb5e95c47cb9ca2e70574e6e49ce
Commit:        0f0eb04edb00cb5e95c47cb9ca2e70574e6e49ce
Parent:        46867a45d28ecb667d08df8d8cb497fffc10814d
Author:        Joe Thornber <ejt@redhat.com>
AuthorDate:    Thu Feb 1 14:52:43 2018 +0000
Committer:     David Teigland <teigland@redhat.com>
CommitterDate: Fri Apr 20 11:12:50 2018 -0500

[device/bcache] some more work on bcache

---
 lib/device/bcache.c   |   99 ++++++++++++++++++++++-----------
 lib/device/bcache.h   |    2 +-
 test/unit/Makefile.in |    2 +-
 test/unit/bcache_t.c  |  147 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 216 insertions(+), 34 deletions(-)

diff --git a/lib/device/bcache.c b/lib/device/bcache.c
index 3b8cf78..5a7b2f9 100644
--- a/lib/device/bcache.c
+++ b/lib/device/bcache.c
@@ -167,12 +167,19 @@ static struct io_engine *_engine_create(unsigned max_io)
 
 static void _engine_destroy(struct io_engine *e)
 {
+	int r;
+
 	_cb_set_destroy(e->cbs);
-	io_destroy(e->aio_context);
+
+	// io_destroy is really slow
+	r = io_destroy(e->aio_context);
+	if (r)
+		log_sys_warn("io_destroy");
+
 	dm_free(e);
 }
 
-static bool _engine_issue(struct io_engine *e, int fd, enum dir d,
+static bool _engine_issue(struct io_engine *e, enum dir d, int fd,
 			  sector_t sb, sector_t se, void *data, void *context)
 {
 	int r;
@@ -290,7 +297,6 @@ enum block_flags {
 };
 
 struct bcache {
-	int fd;
 	sector_t block_sectors;
 	uint64_t nr_data_blocks;
 	uint64_t nr_cache_blocks;
@@ -488,6 +494,30 @@ static void _relink(struct block *b)
  *
  *--------------------------------------------------------------*/
 
+static void _complete_io(void *context, int err)
+{
+	struct block *b = context;
+	struct bcache *cache = b->cache;
+
+	b->error = err;
+	_clear_flags(b, BF_IO_PENDING);
+	cache->nr_io_pending--;
+
+	/*
+	 * b is on the io_pending list, so we don't want to use unlink_block.
+	 * Which would incorrectly adjust nr_dirty.
+	 */
+	dm_list_del(&b->list);
+
+	if (b->error)
+		dm_list_add(&cache->errored, &b->list);
+
+	else {
+		_clear_flags(b, BF_DIRTY);
+		_link_block(b);
+	}
+}
+
 /*
  * |b->list| should be valid (either pointing to itself, on one of the other
  * lists.
@@ -502,7 +532,13 @@ static bool _issue_low_level(struct block *b, enum dir d)
 		return false;
 
 	_set_flags(b, BF_IO_PENDING);
-	return _engine_issue(cache->engine, cache->fd, d, sb, se, b->data, b);
+	if (!_engine_issue(cache->engine, d, b->fd, sb, se, b->data, b)) {
+		_complete_io(b, -EIO);
+		return false;
+	}
+
+	return true;
+
 }
 
 static inline bool _issue_read(struct block *b)
@@ -515,30 +551,6 @@ static inline bool _issue_write(struct block *b)
 	return _issue_low_level(b, DIR_WRITE);
 }
 
-static void _complete_io(void *context, int err)
-{
-	struct block *b = context;
-	struct bcache *cache = b->cache;
-
-	b->error = err;
-	_clear_flags(b, BF_IO_PENDING);
-	cache->nr_io_pending--;
-
-	/*
-	 * b is on the io_pending list, so we don't want to use unlink_block.
-	 * Which would incorrectly adjust nr_dirty.
-	 */
-	dm_list_del(&b->list);
-
-	if (b->error)
-		dm_list_add(&cache->errored, &b->list);
-
-	else {
-		_clear_flags(b, BF_DIRTY);
-		_link_block(b);
-	}
-}
-
 static bool _wait_io(struct bcache *cache)
 {
 	return _engine_wait(cache->engine, _complete_io);
@@ -598,7 +610,7 @@ static struct block *_find_unused_clean_block(struct bcache *cache)
 	return NULL;
 }
 
-static struct block *_new_block(struct bcache *cache, block_address index)
+static struct block *_new_block(struct bcache *cache, int fd, block_address index)
 {
 	struct block *b;
 
@@ -616,6 +628,7 @@ static struct block *_new_block(struct bcache *cache, block_address index)
 		dm_list_init(&b->list);
 		dm_list_init(&b->hash);
 		b->flags = 0;
+		b->fd = fd;
 		b->index = index;
 		b->ref_count = 0;
 		b->error = 0;
@@ -685,7 +698,7 @@ static struct block *_lookup_or_read_block(struct bcache *cache,
 	} else {
 		_miss(cache, flags);
 
-		b = _new_block(cache, index);
+		b = _new_block(cache, fd, index);
 		if (b) {
 			if (flags & GF_ZERO)
 				_zero_block(b);
@@ -728,6 +741,21 @@ struct bcache *bcache_create(sector_t block_sectors, unsigned nr_cache_blocks)
 {
 	struct bcache *cache;
 
+	if (!nr_cache_blocks) {
+		log_warn("bcache must have at least one cache block");
+		return NULL;
+	}
+
+	if (!block_sectors) {
+		log_warn("bcache must have a non zero block size");
+		return NULL;
+	}
+
+	if (block_sectors & ((PAGE_SIZE >> SECTOR_SHIFT) - 1)) {
+		log_warn("bcache block size must be a multiple of page size");
+		return NULL;
+	}
+
 	cache = dm_malloc(sizeof(*cache));
 	if (!cache)
 		return NULL;
@@ -787,6 +815,11 @@ void bcache_destroy(struct bcache *cache)
 	dm_free(cache);
 }
 
+unsigned bcache_nr_cache_blocks(struct bcache *cache)
+{
+	return cache->nr_cache_blocks;
+}
+
 void bcache_prefetch(struct bcache *cache, int fd, block_address index)
 {
 	struct block *b = _hash_lookup(cache, fd, index);
@@ -794,7 +827,7 @@ void bcache_prefetch(struct bcache *cache, int fd, block_address index)
 	if (!b) {
 		cache->prefetches++;
 
-		b = _new_block(cache, index);
+		b = _new_block(cache, fd, index);
 		if (b)
 			_issue_read(b);
 	}
@@ -803,7 +836,9 @@ void bcache_prefetch(struct bcache *cache, int fd, block_address index)
 bool bcache_get(struct bcache *cache, int fd, block_address index,
 	        unsigned flags, struct block **result)
 {
-	struct block *b = _lookup_or_read_block(cache, fd, index, flags);
+	struct block *b;
+
+	b = _lookup_or_read_block(cache, fd, index, flags);
 	if (b) {
 		if (!b->ref_count)
 			cache->nr_locked++;
diff --git a/lib/device/bcache.h b/lib/device/bcache.h
index 0747b5a..2730347 100644
--- a/lib/device/bcache.h
+++ b/lib/device/bcache.h
@@ -61,7 +61,7 @@ enum bcache_get_flags {
 
 typedef uint64_t block_address;
 
-unsigned bcache_get_max_prefetches(struct bcache *cache);
+unsigned bcache_nr_cache_blocks(struct bcache *cache);
 
 /*
  * Use the prefetch method to take advantage of asynchronous IO.  For example,
diff --git a/test/unit/Makefile.in b/test/unit/Makefile.in
index 8127ec0..5cf92ba 100644
--- a/test/unit/Makefile.in
+++ b/test/unit/Makefile.in
@@ -47,7 +47,7 @@ $(TARGETS): $(OBJECTS) $(top_builddir)/libdm/libdevmapper.$(LIB_SUFFIX)
 	$(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) -L$(top_builddir)/libdm \
 	      -o $@ $(OBJECTS) $(LDLIBS)
 
-unit: $(TARGETS)
+unit: $(TARGETS) $(top_builddir)/lib/liblvm-internal.a
 	@echo Running unit tests
 	LD_LIBRARY_PATH=$(top_builddir)/libdm ./$(TARGETS)
 endif
diff --git a/test/unit/bcache_t.c b/test/unit/bcache_t.c
index da274a9..ef92721 100644
--- a/test/unit/bcache_t.c
+++ b/test/unit/bcache_t.c
@@ -12,9 +12,21 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#define _GNU_SOURCE
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
 #include "units.h"
 #include "bcache.h"
 
+#define MEG 2048
+#define SECTOR_SHIFT 9
+
+static const char *_test_path = "test.bin";
+
 int bcache_init(void)
 {
 	return 0;
@@ -25,6 +37,42 @@ int bcache_fini(void)
 	return 0;
 }
 
+static int open_file(const char *path)
+{
+	return open(path, O_EXCL | O_RDWR | O_DIRECT, 0666);
+}
+
+static int _prep_file(const char *path)
+{
+	int fd, r;
+
+	fd = open(path, O_CREAT | O_TRUNC | O_EXCL | O_RDWR | O_DIRECT, 0666);
+	if (fd < 0)
+		return -1;
+
+	r = fallocate(fd, FALLOC_FL_ZERO_RANGE, 0, (16 * MEG) << SECTOR_SHIFT);
+	if (r) {
+		close(fd);
+		return -1;
+	}
+
+	close(fd);
+	return 0;
+}
+
+
+static int test_init(void)
+{
+	unlink(_test_path);
+	return _prep_file(_test_path);
+}
+
+static int test_exit(void)
+{
+	unlink(_test_path);
+	return 0;
+}
+
 static void test_create(void)
 {
 	struct bcache *cache = bcache_create(8, 16);
@@ -32,7 +80,106 @@ static void test_create(void)
 	bcache_destroy(cache);
 }
 
+static void test_nr_cache_blocks_must_be_positive(void)
+{
+	struct bcache *cache = bcache_create(8, 0);
+	CU_ASSERT_PTR_NULL(cache);
+}
+
+static void test_block_size_must_be_positive(void)
+{
+	struct bcache *cache = bcache_create(0, 16);
+	CU_ASSERT_PTR_NULL(cache);
+}
+
+static void test_block_size_must_be_multiple_of_page_size(void)
+{
+	unsigned i;
+	struct bcache *cache;
+
+	{
+		static unsigned _bad_examples[] = {3, 9, 13, 1025};
+
+		for (i = 0; i < DM_ARRAY_SIZE(_bad_examples); i++) {
+			cache = bcache_create(_bad_examples[i], 16);
+			CU_ASSERT_PTR_NULL(cache);
+		}
+	}
+
+	{
+		// Only testing a few sizes because io_destroy is seriously
+		// slow.
+		for (i = 1; i < 25; i++) {
+			cache = bcache_create(8 * i, 16);
+			CU_ASSERT_PTR_NOT_NULL(cache);
+			bcache_destroy(cache);
+		}
+	}
+}
+
+static void test_reads_work(void)
+{
+	int fd;
+
+	// FIXME: add fixtures.
+	test_init();
+	fd = open_file("./test.bin");
+	CU_ASSERT(fd >= 0);
+
+	{
+		int i;
+		struct block *b;
+		struct bcache *cache = bcache_create(8, 16);
+
+		CU_ASSERT(bcache_get(cache, fd, 0, 0, &b));
+		for (i = 0; i < 8 << SECTOR_SHIFT; i++)
+			CU_ASSERT(((unsigned char *) b->data)[i] == 0);
+		bcache_put(b);
+
+		bcache_destroy(cache);
+	}
+
+	close(fd);
+
+	test_exit();
+}
+
+static void test_prefetch_works(void)
+{
+	int fd;
+
+	// FIXME: add fixtures.
+	test_init();
+	fd = open_file("./test.bin");
+	CU_ASSERT(fd >= 0);
+
+	{
+		int i;
+		struct block *b;
+		struct bcache *cache = bcache_create(8, 16);
+
+		for (i = 0; i < 16; i++)
+			bcache_prefetch(cache, fd, i);
+
+		for (i = 0; i < 16; i++) {
+			CU_ASSERT(bcache_get(cache, fd, i, 0, &b));
+			bcache_put(b);
+		}
+
+		bcache_destroy(cache);
+	}
+
+	close(fd);
+
+	test_exit();
+}
+
 CU_TestInfo bcache_list[] = {
 	{ (char*)"create", test_create },
+	{ (char*)"nr cache block must be positive", test_nr_cache_blocks_must_be_positive },
+	{ (char*)"block size must be positive", test_block_size_must_be_positive },
+	{ (char*)"block size must be multiple of page size", test_block_size_must_be_multiple_of_page_size },
+	{ (char*)"reads work", test_reads_work },
+	{ (char*)"prefetch works", test_prefetch_works },
 	CU_TEST_INFO_NULL
 };



^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2018-04-23 13:51 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-23 13:46 master - [device/bcache] some more work on bcache David Teigland
2018-04-23 13:51 David Teigland

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.