block: Add test-iosched scheduler

The test scheduler allows testing a block device by dispatching
specific requests according to the test case and declare PASS/FAIL
according to the requests completion error code

Change-Id: Ief91f9fed6e3c3c75627d27264d5252ea14f10ad
Signed-off-by: Maya Erez <merez@codeaurora.org>
diff --git a/include/linux/test-iosched.h b/include/linux/test-iosched.h
new file mode 100644
index 0000000..8054409
--- /dev/null
+++ b/include/linux/test-iosched.h
@@ -0,0 +1,233 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * The test scheduler allows to test the block device by dispatching
+ * specific requests according to the test case and declare PASS/FAIL
+ * according to the requests completion error code.
+ * Each test is exposed via debugfs and can be triggered by writing to
+ * the debugfs file.
+ *
+ */
+
+#ifndef _LINUX_TEST_IOSCHED_H
+#define _LINUX_TEST_IOSCHED_H
+
+/*
+ * Patterns definitions for read/write requests data
+ */
+#define TEST_PATTERN_SEQUENTIAL	-1
+#define TEST_PATTERN_5A		0x5A5A5A5A
+#define TEST_PATTERN_FF		0xFFFFFFFF
+#define TEST_NO_PATTERN		0xDEADBEEF
+#define BIO_U32_SIZE 1024
+
+struct test_data;
+
+typedef int (prepare_test_fn) (struct test_data *);
+typedef int (run_test_fn) (struct test_data *);
+typedef int (check_test_result_fn) (struct test_data *);
+typedef int (post_test_fn) (struct test_data *);
+typedef char* (get_test_case_str_fn) (struct test_data *);
+typedef void (blk_dev_test_init_fn) (void);
+typedef void (blk_dev_test_exit_fn) (void);
+
+/**
+ * enum test_state - defines the state of the test
+ */
+enum test_state {
+	TEST_IDLE,
+	TEST_RUNNING,
+	TEST_COMPLETED,
+};
+
+/**
+ * enum test_results - defines the success orfailure of the test
+ */
+enum test_results {
+	TEST_NO_RESULT,
+	TEST_FAILED,
+	TEST_PASSED,
+	TEST_NOT_SUPPORTED,
+};
+
+/**
+ * enum req_unique_type - defines a unique request type
+ */
+enum req_unique_type {
+	REQ_UNIQUE_NONE,
+	REQ_UNIQUE_DISCARD,
+	REQ_UNIQUE_FLUSH,
+};
+
+/**
+ * struct test_debug - debugfs directories
+ * @debug_root:		The test-iosched debugfs root directory
+ * @debug_utils_root:	test-iosched debugfs utils root
+ *			directory
+ * @debug_tests_root:	test-iosched debugfs tests root
+ *			directory
+ * @debug_test_result:	Exposes the test result to the user
+ *			space
+ * @start_sector:	The start sector for read/write requests
+ */
+struct test_debug {
+	struct dentry *debug_root;
+	struct dentry *debug_utils_root;
+	struct dentry *debug_tests_root;
+	struct dentry *debug_test_result;
+	struct dentry *start_sector;
+};
+
+/**
+ * struct test_request - defines a test request
+ * @queuelist:		The test requests list
+ * @bios_buffer:	Write/read requests data buffer
+ * @buf_size:		Write/read requests data buffer size (in
+ *			bytes)
+ * @rq:			A block request, to be dispatched
+ * @req_completed:	A flag to indicate if the request was
+ *			completed
+ * @req_result:		Keeps the error code received in the
+ *			request completion callback
+ * @is_err_expected:	A flag to indicate if the request should
+ *			fail
+ * @wr_rd_data_pattern:	A pattern written to the write data
+ *			buffer. Can be used in read requests to
+ *			verify the data
+ * @req_id:		A unique ID to identify a test request
+ *			to ease the debugging of the test cases
+ */
+struct test_request {
+	struct list_head queuelist;
+	unsigned int *bios_buffer;
+	int buf_size;
+	struct request *rq;
+	bool req_completed;
+	int req_result;
+	int is_err_expected;
+	int wr_rd_data_pattern;
+	int req_id;
+};
+
+/**
+ * struct test_info - specific test information
+ * @testcase:		The current running test case
+ * @timeout_msec:	Test specific test timeout
+ * @buf_size:		Write/read requests data buffer size (in
+ *			bytes)
+ * @prepare_test_fn:	Test specific test preparation callback
+ * @run_test_fn:	Test specific test running callback
+ * @check_test_result_fn: Test specific test result checking
+ *			callback
+ * @get_test_case_str_fn: Test specific function to get the test name
+ * @data:		Test specific private data
+ */
+struct test_info {
+	int testcase;
+	unsigned timeout_msec;
+	prepare_test_fn *prepare_test_fn;
+	run_test_fn *run_test_fn;
+	check_test_result_fn *check_test_result_fn;
+	post_test_fn *post_test_fn;
+	get_test_case_str_fn *get_test_case_str_fn;
+	void *data;
+};
+
+/**
+ * struct blk_dev_test_type - identifies block device test
+ * @list:	list head pointer
+ * @init_fn:	block device test init callback
+ * @exit_fn:	block device test exit callback
+ */
+struct blk_dev_test_type {
+	struct list_head list;
+	blk_dev_test_init_fn *init_fn;
+	blk_dev_test_exit_fn *exit_fn;
+};
+
+/**
+ * struct test_data - global test iosched data
+ * @queue:		The test IO scheduler requests list
+ * @test_queue:		The test requests list
+ * @next_req:		Points to the next request to be
+ *			dispatched from the test requests list
+ * @wait_q:		A wait queue for waiting for the test
+ *			requests completion
+ * @test_state:		Indicates if there is a running test.
+ *			Used for dispatch function
+ * @test_result:	Indicates if the test passed or failed
+ * @debug:		The test debugfs entries
+ * @req_q:		The block layer request queue
+ * @num_of_write_bios:	The number of write BIOs added to the test requests.
+ *			Used to calcualte the sector number of
+ *			new BIOs.
+ * @start_sector:	The address of the first sector that can
+ *			be accessed by the test
+ * @timeout_timer:	A timer to verify test completion in
+ *			case of non-completed requests
+ * @wr_rd_next_req_id:	A unique ID to identify WRITE/READ
+ *			request to ease the debugging of the
+ *			test cases
+ * @unique_next_req_id:	A unique ID to identify
+ *			FLUSH/DISCARD/SANITIZE request to ease
+ *			the debugging of the test cases
+ * @lock:		A lock to verify running a single test
+ *			at a time
+ * @test_info:		A specific test data to be set by the
+ *			test invokation function
+ * @ignore_round:	A boolean variable indicating that a
+ *			test round was disturbed by an external
+ *			flush request, therefore disqualifying
+ *			the results
+ */
+struct test_data {
+	struct list_head queue;
+	struct list_head test_queue;
+	struct test_request *next_req;
+	wait_queue_head_t wait_q;
+	enum test_state test_state;
+	enum test_results test_result;
+	struct test_debug debug;
+	struct request_queue *req_q;
+	int num_of_write_bios;
+	u32 start_sector;
+	struct timer_list timeout_timer;
+	int wr_rd_next_req_id;
+	int unique_next_req_id;
+	spinlock_t lock;
+	struct test_info test_info;
+	bool fs_wr_reqs_during_test;
+	bool ignore_round;
+};
+
+extern int test_iosched_start_test(struct test_info *t_info);
+extern void test_iosched_mark_test_completion(void);
+extern int test_iosched_add_unique_test_req(int is_err_expcted,
+		enum req_unique_type req_unique,
+		int start_sec, int nr_sects, rq_end_io_fn *end_req_io);
+extern int test_iosched_add_wr_rd_test_req(int is_err_expcted,
+	      int direction, int start_sec,
+	      int num_bios, int pattern, rq_end_io_fn *end_req_io);
+
+extern struct dentry *test_iosched_get_debugfs_tests_root(void);
+extern struct dentry *test_iosched_get_debugfs_utils_root(void);
+
+extern struct request_queue *test_iosched_get_req_queue(void);
+
+extern void test_iosched_set_test_result(int);
+
+void test_iosched_set_ignore_round(bool ignore_round);
+
+void test_iosched_register(struct blk_dev_test_type *bdt);
+
+void test_iosched_unregister(struct blk_dev_test_type *bdt);
+
+#endif /* _LINUX_TEST_IOSCHED_H */