mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
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>
This commit is contained in:
parent
6beeb66c9b
commit
f5237919c5
6 changed files with 1304 additions and 2 deletions
39
Documentation/block/test-iosched.txt
Normal file
39
Documentation/block/test-iosched.txt
Normal file
|
@ -0,0 +1,39 @@
|
|||
Test IO 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.
|
||||
|
||||
The test IO scheduler implements the no-op scheduler operations, and uses
|
||||
them in order to dispatch the non-test requests when no test is running.
|
||||
This will allow to keep a normal FS operation in parallel to the test
|
||||
capability.
|
||||
The test IO scheduler keeps two different queues, one for real-world requests
|
||||
(inserted by the FS) and the other for the test requests.
|
||||
The test IO scheduler chooses the queue for dispatch requests according to the
|
||||
test state (IDLE/RUNNING).
|
||||
|
||||
the test IO scheduler is compiled by default as a dynamic module and enabled
|
||||
only if CONFIG_DEBUG_FS is defined.
|
||||
|
||||
Each block device test utility that would like to use the test-iosched test
|
||||
services, should register as a blk_dev_test_type and supply an init and exit
|
||||
callbacks. Those callback are called upon selection (or removal) of the
|
||||
test-iosched as the active scheduler. From that point the block device test
|
||||
can start a test and supply its own callbacks for preparing, running, result
|
||||
checking and cleanup of the test.
|
||||
|
||||
Each test is exposed via debugfs and can be triggered by writing to
|
||||
the debugfs file. In order to add a new test one should expose a new debugfs
|
||||
file for the new test.
|
||||
|
||||
Selecting IO schedulers
|
||||
-----------------------
|
||||
Refer to Documentation/block/switching-sched.txt for information on
|
||||
selecting an io scheduler on a per-device basis.
|
||||
|
||||
|
||||
May 10 2012, maya Erez <merez@codeaurora.org>
|
||||
|
||||
|
|
@ -12,6 +12,17 @@ config IOSCHED_NOOP
|
|||
that do their own scheduling and require only minimal assistance from
|
||||
the kernel.
|
||||
|
||||
config IOSCHED_TEST
|
||||
tristate "Test I/O scheduler"
|
||||
depends on DEBUG_FS
|
||||
default m
|
||||
---help---
|
||||
The test I/O scheduler is a duplicate of the noop scheduler with
|
||||
addition of test utlity.
|
||||
It 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.
|
||||
|
||||
config IOSCHED_DEADLINE
|
||||
tristate "Deadline I/O scheduler"
|
||||
default y
|
||||
|
|
|
@ -15,6 +15,7 @@ obj-$(CONFIG_BLK_DEV_THROTTLING) += blk-throttle.o
|
|||
obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o
|
||||
obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o
|
||||
obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o
|
||||
obj-$(CONFIG_IOSCHED_TEST) += test-iosched.o
|
||||
|
||||
obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o
|
||||
obj-$(CONFIG_BLK_DEV_INTEGRITY) += blk-integrity.o
|
||||
|
|
|
@ -977,8 +977,6 @@ struct request *blk_get_request(struct request_queue *q, int rw, gfp_t gfp_mask)
|
|||
{
|
||||
struct request *rq;
|
||||
|
||||
BUG_ON(rw != READ && rw != WRITE);
|
||||
|
||||
spin_lock_irq(q->queue_lock);
|
||||
if (gfp_mask & __GFP_WAIT)
|
||||
rq = get_request_wait(q, rw, NULL);
|
||||
|
@ -1311,6 +1309,7 @@ void init_request_from_bio(struct request *req, struct bio *bio)
|
|||
req->ioprio = bio_prio(bio);
|
||||
blk_rq_bio_prep(req->q, req, bio);
|
||||
}
|
||||
EXPORT_SYMBOL(init_request_from_bio);
|
||||
|
||||
void blk_queue_bio(struct request_queue *q, struct bio *bio)
|
||||
{
|
||||
|
|
1019
block/test-iosched.c
Normal file
1019
block/test-iosched.c
Normal file
File diff suppressed because it is too large
Load diff
233
include/linux/test-iosched.h
Normal file
233
include/linux/test-iosched.h
Normal file
|
@ -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 */
|
Loading…
Reference in a new issue