summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2009-04-29 08:51:07 +0000
committerChris Johns <chrisj@rtems.org>2009-04-29 08:51:07 +0000
commit57aa979e4f8ef9fcace629b22f16faa1b5bf5e73 (patch)
tree0aa45f200cbc05f58c378c3e0e0b35466edb2269 /cpukit
parent2009-04-29 Chris Johns <chrisj@rtems.org> (diff)
downloadrtems-57aa979e4f8ef9fcace629b22f16faa1b5bf5e73.tar.bz2
2009-04-29 Sebastian Huber <sebastian.huber@embedded-brains.de>
* sapi/include/confdefs.h, libblock/include/rtems/bdbuf.h: Changed type of rtems_bdbuf_pool_configuration_size to size_t. * libblock/include/rtems/bdbuf.h, libblock/include/rtems/blkdev.h, libblock/include/rtems/diskdevs.h, libblock/src/bdbuf.c, libblock/src/blkdev.c, libblock/src/diskdevs.c: Buffer pool allocation is now cache aligned. The cache functions are currently not available on all platforms so the cache line size is fixed to 32 bytes for now. Changed various integer types which refer to block sizes, numbers and indexes. Fixed logical block indexes in buffer get and read function. It is now possible to delete logical disks. Modified documentation
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/ChangeLog15
-rw-r--r--cpukit/libblock/include/rtems/bdbuf.h230
-rw-r--r--cpukit/libblock/include/rtems/blkdev.h229
-rw-r--r--cpukit/libblock/include/rtems/diskdevs.h340
-rw-r--r--cpukit/libblock/src/bdbuf.c279
-rw-r--r--cpukit/libblock/src/blkdev.c6
-rw-r--r--cpukit/libblock/src/diskdevs.c318
-rw-r--r--cpukit/sapi/include/confdefs.h2
8 files changed, 680 insertions, 739 deletions
diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog
index 72d710303c..eaa3eae678 100644
--- a/cpukit/ChangeLog
+++ b/cpukit/ChangeLog
@@ -1,3 +1,18 @@
+2009-04-29 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * sapi/include/confdefs.h, libblock/include/rtems/bdbuf.h: Changed
+ type of rtems_bdbuf_pool_configuration_size to size_t.
+
+ * libblock/include/rtems/bdbuf.h, libblock/include/rtems/blkdev.h,
+ libblock/include/rtems/diskdevs.h, libblock/src/bdbuf.c,
+ libblock/src/blkdev.c, libblock/src/diskdevs.c: Buffer pool
+ allocation is now cache aligned. The cache functions are
+ currently not available on all platforms so the cache line size is
+ fixed to 32 bytes for now. Changed various integer types which
+ refer to block sizes, numbers and indexes. Fixed logical block
+ indexes in buffer get and read function. It is now possible to
+ delete logical disks. Modified documentation
+
2009-04-29 Chris Johns <chrisj@rtems.org>
* libcsupport/include/rtems/libio.h: Add rtems_off64_t for
diff --git a/cpukit/libblock/include/rtems/bdbuf.h b/cpukit/libblock/include/rtems/bdbuf.h
index 56dc9b44cb..52ee557054 100644
--- a/cpukit/libblock/include/rtems/bdbuf.h
+++ b/cpukit/libblock/include/rtems/bdbuf.h
@@ -1,7 +1,7 @@
/**
- * @file rtems/bdbuf.h
+ * @file
*
- * Block Device Buffer Management
+ * Block device buffer management.
*/
/*
@@ -28,21 +28,101 @@
#ifdef __cplusplus
extern "C" {
#endif
+
+/**
+ * @defgroup rtems_libblock Block Device Library
+ */
+/**
+ * @defgroup rtems_bdbuf Block Device Buffer Management
+ *
+ * @ingroup rtems_libblock
+ *
+ * The Block Device Buffer Management implements a cache between the disk
+ * devices and file systems. The code provides read ahead and write queuing to
+ * the drivers and fast cache look up using an AVL tree.
+ *
+ * The buffers are held in pools based on size. Each pool has buffers and the
+ * buffers follow this state machine:
+ *
+ * @dot
+ * digraph g {
+ * ready [label="Ready\nRead Ahead"];
+ * transfer [label="Transfer"];
+ * accessed [label="Accessed\nAccessed Modified"];
+ * modified [label="Modified\nSynchronized"];
+ * cached [label="Cached"];
+ * ready -> transfer [label="Read\nRead Ahead"];
+ * transfer -> ready [label="Read Ahead Complete"];
+ * ready -> accessed [label="Get"];
+ * transfer -> accessed [label="Read or Write\nComplete"];
+ * transfer -> cached [label="Read or Write\nComplete"];
+ * accessed -> cached [label="Release"];
+ * cached -> accessed [label="Get"];
+ * modified -> accessed [label="Get"];
+ * accessed -> modified [label="Modified"];
+ * accessed -> transfer [label="Swap"];
+ * }
+ * @enddot
+ *
+ * Empty buffers are added to the ready list and removed from this queue when a
+ * caller requests a buffer. This is referred to as getting a buffer in the
+ * code and the event get in the state diagram. The buffer is assigned to a
+ * block and inserted to the AVL based on the block/device key. If the block is
+ * to be read by the user and not in the cache (ready) it is transfered from
+ * the disk into memory. If no ready buffers exist the buffer is taken from the
+ * LRU list. If no buffers are on the LRU list the modified list is check. If
+ * no buffers are on the modified list the request blocks. If buffers are on
+ * the modified list the buffers hold timer is expired and the swap out task
+ * woken.
+ *
+ * A block being accessed is given to the file system layer and not accessable
+ * to another requester until released back to the cache. The same goes to a
+ * buffer in the transfer state. The transfer state means being read or
+ * written. If the file system has modifed the block and releases it as
+ * modified it placed on the pool's modified list and a hold timer
+ * initialised. The buffer is held for the hold time before being written to
+ * disk. Buffers are held for a configurable period of time on the modified
+ * list as a write sets the state to transfer and this locks the buffer out
+ * from the file system until the write complete. Buffers are often repeatable
+ * accessed and modified in a series of small updates so if sent to the disk
+ * when released as modified the user would have to block waiting until it had
+ * been written. This would be a performance problem.
+ *
+ * The code performs mulitple block reads and writes. Multiple block reads or
+ * read ahead increases performance with hardware that supports it. It also
+ * helps with a large cache as the disk head movement is reduced. It how-ever
+ * is a speculative operation so excessive use can remove valuable and needed
+ * blocks from the cache. The get call knows if a read is a for the file system
+ * or if it is a read ahead get. If the get is for a read ahead block and the
+ * block is already in the cache or no ready buffers are available the read
+ * ahead is stopped. The transfer occurs with the blocks so far. If a buffer is
+ * in the read ahead state and release it is placed on the ready list rather
+ * than the LRU list. This means these buffers are used before buffers used by
+ * the file system.
+ *
+ * The pool has the following lists of buffers:
+ * - @c ready: Empty buffers created when the pool is initialised.
+ * - @c modified: Buffers waiting to be written to disk.
+ * - @c sync: Buffers to be synced to disk.
+ * - @c lru: Accessed buffers released in least recently used order.
+ *
+ * @{
+ */
/**
* State of a buffer in the cache.
*/
typedef enum
{
- RTEMS_BDBUF_STATE_EMPTY = 0, /*< Not in use. */
- RTEMS_BDBUF_STATE_READ_AHEAD = 1, /*< Holds read ahead data only */
- RTEMS_BDBUF_STATE_CACHED = 2, /*< In the cache and available */
- RTEMS_BDBUF_STATE_ACCESS = 3, /*< The user has the buffer */
- RTEMS_BDBUF_STATE_MODIFIED = 4, /*< In the cache but modified */
- RTEMS_BDBUF_STATE_ACCESS_MODIFIED = 5, /*< With the user but modified */
- RTEMS_BDBUF_STATE_SYNC = 6, /*< Requested to be sync'ed */
- RTEMS_BDBUF_STATE_TRANSFER = 7 /*< Being transferred to or from disk */
+ RTEMS_BDBUF_STATE_EMPTY = 0, /**< Not in use. */
+ RTEMS_BDBUF_STATE_READ_AHEAD = 1, /**< Holds read ahead data only */
+ RTEMS_BDBUF_STATE_CACHED = 2, /**< In the cache and available */
+ RTEMS_BDBUF_STATE_ACCESS = 3, /**< The user has the buffer */
+ RTEMS_BDBUF_STATE_MODIFIED = 4, /**< In the cache but modified */
+ RTEMS_BDBUF_STATE_ACCESS_MODIFIED = 5, /**< With the user but modified */
+ RTEMS_BDBUF_STATE_SYNC = 6, /**< Requested to be sync'ed */
+ RTEMS_BDBUF_STATE_TRANSFER = 7 /**< Being transferred to or from disk */
} rtems_bdbuf_buf_state;
/**
@@ -57,27 +137,27 @@ typedef struct rtems_bdbuf_buffer
struct rtems_bdbuf_avl_node
{
- signed char cache; /*< Cache */
- struct rtems_bdbuf_buffer* left; /*< Left Child */
- struct rtems_bdbuf_buffer* right; /*< Right Child */
- signed char bal; /*< The balance of the sub-tree */
+ signed char cache; /**< Cache */
+ struct rtems_bdbuf_buffer* left; /**< Left Child */
+ struct rtems_bdbuf_buffer* right; /**< Right Child */
+ signed char bal; /**< The balance of the sub-tree */
} avl;
- dev_t dev; /*< device number */
- rtems_blkdev_bnum block; /*< block number on the device */
+ dev_t dev; /**< device number */
+ rtems_blkdev_bnum block; /**< block number on the device */
- unsigned char* buffer; /*< Pointer to the buffer memory area */
- int error; /*< If not 0 indicate an error value (errno)
+ unsigned char* buffer; /**< Pointer to the buffer memory area */
+ int error; /**< If not 0 indicate an error value (errno)
* which can be used by user later */
- volatile rtems_bdbuf_buf_state state; /*< State of the buffer. */
+ volatile rtems_bdbuf_buf_state state; /**< State of the buffer. */
- volatile uint32_t waiters; /*< The number of threads waiting on this
+ volatile uint32_t waiters; /**< The number of threads waiting on this
* buffer. */
- rtems_bdpool_id pool; /*< Identifier of buffer pool to which this buffer
+ rtems_bdpool_id pool; /**< Identifier of buffer pool to which this buffer
belongs */
- volatile uint32_t hold_timer; /*< Timer to indicate how long a buffer
+ volatile uint32_t hold_timer; /**< Timer to indicate how long a buffer
* has been held in the cache modified. */
} rtems_bdbuf_buffer;
@@ -87,38 +167,38 @@ typedef struct rtems_bdbuf_buffer
*/
typedef struct rtems_bdbuf_pool
{
- uint32_t blksize; /*< The size of the blocks (in bytes) */
- uint32_t nblks; /*< Number of blocks in this pool */
+ uint32_t blksize; /**< The size of the blocks (in bytes) */
+ uint32_t nblks; /**< Number of blocks in this pool */
- uint32_t flags; /*< Configuration flags */
+ uint32_t flags; /**< Configuration flags */
- rtems_id lock; /*< The pool lock. Lock this data and
+ rtems_id lock; /**< The pool lock. Lock this data and
* all BDs. */
- rtems_id sync_lock; /*< Sync calls lock writes. */
- bool sync_active; /*< True if a sync is active. */
- rtems_id sync_requester; /*< The sync requester. */
- dev_t sync_device; /*< The device to sync */
+ rtems_id sync_lock; /**< Sync calls lock writes. */
+ bool sync_active; /**< True if a sync is active. */
+ rtems_id sync_requester; /**< The sync requester. */
+ dev_t sync_device; /**< The device to sync */
- rtems_bdbuf_buffer* tree; /*< Buffer descriptor lookup AVL tree
+ rtems_bdbuf_buffer* tree; /**< Buffer descriptor lookup AVL tree
* root */
- rtems_chain_control ready; /*< Free buffers list (or read-ahead) */
- rtems_chain_control lru; /*< Last recently used list */
- rtems_chain_control modified; /*< Modified buffers list */
- rtems_chain_control sync; /*< Buffers to sync list */
+ rtems_chain_control ready; /**< Free buffers list (or read-ahead) */
+ rtems_chain_control lru; /**< Last recently used list */
+ rtems_chain_control modified; /**< Modified buffers list */
+ rtems_chain_control sync; /**< Buffers to sync list */
- rtems_id access; /*< Obtain if waiting for a buffer in the
+ rtems_id access; /**< Obtain if waiting for a buffer in the
* ACCESS state. */
- volatile uint32_t access_waiters; /*< Count of access blockers. */
- rtems_id transfer; /*< Obtain if waiting for a buffer in the
+ volatile uint32_t access_waiters; /**< Count of access blockers. */
+ rtems_id transfer; /**< Obtain if waiting for a buffer in the
* TRANSFER state. */
- volatile uint32_t transfer_waiters; /*< Count of transfer blockers. */
- rtems_id waiting; /*< Obtain if waiting for a buffer and the
+ volatile uint32_t transfer_waiters; /**< Count of transfer blockers. */
+ rtems_id waiting; /**< Obtain if waiting for a buffer and the
* none are available. */
- volatile uint32_t wait_waiters; /*< Count of waiting blockers. */
+ volatile uint32_t wait_waiters; /**< Count of waiting blockers. */
- rtems_bdbuf_buffer* bds; /*< Pointer to table of buffer descriptors
+ rtems_bdbuf_buffer* bds; /**< Pointer to table of buffer descriptors
* allocated for this buffer pool. */
- void* buffers; /*< The buffer's memory. */
+ void* buffers; /**< The buffer's memory. */
} rtems_bdbuf_pool;
/**
@@ -126,35 +206,46 @@ typedef struct rtems_bdbuf_pool
* location) for buffering layer pool.
*/
typedef struct rtems_bdbuf_pool_config {
- int size; /*< Size of block */
- int num; /*< Number of blocks of appropriate size */
- unsigned char* mem_area; /*< Pointer to the blocks location or NULL, in this
+ int size; /**< Size of block */
+ int num; /**< Number of blocks of appropriate size */
+ unsigned char* mem_area; /**< Pointer to the blocks location or NULL, in this
* case memory for blocks will be allocated by
* Buffering Layer with the help of RTEMS partition
* manager */
} rtems_bdbuf_pool_config;
/**
- * External references provided by the user for each pool in the system.
+ * External reference to the pool configuration table describing each pool in
+ * the system.
+ *
+ * The configuration table is provided by the application.
*/
extern rtems_bdbuf_pool_config rtems_bdbuf_pool_configuration[];
-extern int rtems_bdbuf_pool_configuration_size;
+
+/**
+ * External reference the size of the pool configuration table
+ * @ref rtems_bdbuf_pool_configuration.
+ *
+ * The configuration table size is provided by the application.
+ */
+extern size_t rtems_bdbuf_pool_configuration_size;
/**
* Buffering configuration definition. See confdefs.h for support on using this
* structure.
*/
typedef struct rtems_bdbuf_config {
- uint32_t max_read_ahead_blocks; /*< Number of blocks to read ahead. */
- uint32_t max_write_blocks; /*< Number of blocks to write at once. */
- rtems_task_priority swapout_priority; /*< Priority of the swap out task. */
- uint32_t swapout_period; /*< Period swapout checks buf timers. */
- uint32_t swap_block_hold; /*< Period a buffer is held. */
+ uint32_t max_read_ahead_blocks; /**< Number of blocks to read ahead. */
+ uint32_t max_write_blocks; /**< Number of blocks to write at once. */
+ rtems_task_priority swapout_priority; /**< Priority of the swap out task. */
+ uint32_t swapout_period; /**< Period swapout checks buf timers. */
+ uint32_t swap_block_hold; /**< Period a buffer is held. */
} rtems_bdbuf_config;
/**
- * External referernce to the configuration. The configuration is provided by
- * the user.
+ * External reference to the configuration.
+ *
+ * The configuration is provided by the application.
*/
extern rtems_bdbuf_config rtems_bdbuf_configuration;
@@ -163,10 +254,26 @@ extern rtems_bdbuf_config rtems_bdbuf_configuration;
* than this defined max. This stops thrashing in the cache.
*/
#define RTEMS_BDBUF_MAX_READ_AHEAD_BLOCKS_DEFAULT 32
+
+/**
+ * Default maximum number of blocks to write at once.
+ */
#define RTEMS_BDBUF_MAX_WRITE_BLOCKS_DEFAULT 16
+
+/**
+ * Default swap-out task priority.
+ */
#define RTEMS_BDBUF_SWAPOUT_TASK_PRIORITY_DEFAULT 15
-#define RTEMS_BDBUF_SWAPOUT_TASK_SWAP_PERIOD_DEFAULT 250 /* milli-seconds */
-#define RTEMS_BDBUF_SWAPOUT_TASK_BLOCK_HOLD_DEFAULT 1000 /* milli-seconds */
+
+/**
+ * Default swap-out task swap period in milli seconds.
+ */
+#define RTEMS_BDBUF_SWAPOUT_TASK_SWAP_PERIOD_DEFAULT 250
+
+/**
+ * Default swap-out task block hold time in milli seconds.
+ */
+#define RTEMS_BDBUF_SWAPOUT_TASK_BLOCK_HOLD_DEFAULT 1000
/**
* Prepare buffering layer to work - initialize buffer descritors and (if it is
@@ -335,8 +442,13 @@ rtems_bdbuf_find_pool (uint32_t block_size, rtems_bdpool_id *pool);
*
* @note Buffer pools enumerated continuously starting from 0.
*/
-rtems_status_code
-rtems_bdbuf_get_pool_info (rtems_bdpool_id pool, int *block_size, int *blocks);
+rtems_status_code rtems_bdbuf_get_pool_info(
+ rtems_bdpool_id pool,
+ uint32_t *block_size,
+ uint32_t *blocks
+);
+
+/** @} */
#ifdef __cplusplus
}
diff --git a/cpukit/libblock/include/rtems/blkdev.h b/cpukit/libblock/include/rtems/blkdev.h
index 57cbb6e47c..d5ec9f46cb 100644
--- a/cpukit/libblock/include/rtems/blkdev.h
+++ b/cpukit/libblock/include/rtems/blkdev.h
@@ -1,6 +1,7 @@
/**
- * @file rtems/blkdev.h
- * block device driver interface definitions
+ * @file
+ *
+ * Block device management.
*/
/*
@@ -20,109 +21,168 @@
extern "C" {
#endif
-/*
- * Interface with device drivers Block device looks, initialized and behaves
- * like traditional RTEMS device driver. Heart of the block device driver is in
- * BIOREQUEST ioctl. This call puts I/O request to the block device queue, in
- * priority order, for asynchronous processing. When driver executes request,
- * req_done function invoked, so callee knows about it. Look for details below.
+/**
+ * @defgroup rtems_blkdev Block Device Management
+ *
+ * @ingroup rtems_libblock
+ *
+ * Interface between device drivers and the block device library.
+ *
+ * The heart of the block device driver is the @ref RTEMS_BLKIO_REQUEST IO
+ * control. This call puts IO @ref rtems_blkdev_request "requests" to the block
+ * device for asynchronous processing. When a driver executes a request, it
+ * invokes the request done callback function to finish the request.
+ *
+ * @{
*/
-/*
- * Block device block number datatype
+/**
+ * Block device block index type.
*/
typedef uint32_t rtems_blkdev_bnum;
-/* Block device request type */
+/**
+ * Block device request type.
+ */
typedef enum rtems_blkdev_request_op {
- RTEMS_BLKDEV_REQ_READ, /* Read operation */
- RTEMS_BLKDEV_REQ_WRITE, /* Write operation */
- RTEMS_BLKDEV_CAPABILITIES /* Capabilities request */
+ RTEMS_BLKDEV_REQ_READ,
+ RTEMS_BLKDEV_REQ_WRITE,
+ RTEMS_BLKDEV_CAPABILITIES
} rtems_blkdev_request_op;
/**
- * ATA multi-sector buffer requests only supported. This option
- * means the cache will only supply multiple buffers that are
- * inorder so the ATA multi-sector command can be used. This is a
+ * Only consecutive multi-sector buffer requests are supported.
+ *
+ * This option means the cache will only supply multiple buffers that are
+ * inorder so the ATA multi-sector command for example can be used. This is a
* hack to work around the current ATA driver.
*/
#define RTEMS_BLKDEV_CAP_MULTISECTOR_CONT (1 << 0)
-/*
- * @typedef rtems_blkdev_request_cb
- *
+/**
* Type for block device request done callback function.
*
- * @param arg Argument supplied in blkdev_request
- * @param status RTEMS status code for this operation
- * @param errno errno value to be passed to the user when
- * status != RTEMS_SUCCESSFUL
+ * @param arg Argument supplied in @ref rtems_blkdev_request.
+ * @param status Status code for this operation.
+ * @param errno The @c errno value to be passed to the user when status is not
+ * equal to @c RTEMS_SUCCESSFUL.
*/
typedef void (* rtems_blkdev_request_cb)(void *arg,
rtems_status_code status,
int error);
/**
- * @struct rtems_blkdev_sg_buffer
- * Block device scatter/gather buffer structure
+ * Block device scatter or gather buffer structure.
*/
typedef struct rtems_blkdev_sg_buffer {
- uint32_t block; /* The block number */
- uint32_t length; /* Buffer length */
- void *buffer; /* Buffer pointer */
- void *user; /* User pointer */
+ /**
+ * Block index.
+ */
+ rtems_blkdev_bnum block;
+
+ /**
+ * Buffer length.
+ */
+ uint32_t length;
+
+ /**
+ * Buffer pointer.
+ */
+ void *buffer;
+
+ /**
+ * User pointer.
+ */
+ void *user;
} rtems_blkdev_sg_buffer;
-/* blkdev_request (Block Device Request) structure is
- * used to read/write a number of blocks from/to device.
+/**
+ * The block device dequest structure is used to read or write a number of
+ * blocks from or to the device.
*/
typedef struct rtems_blkdev_request {
- /* Block device operation (read or write) */
- rtems_blkdev_request_op req;
- /* Callback function */
- rtems_blkdev_request_cb req_done;
- /* Argument to be passed to callback function*/
- void *done_arg;
- /* Last I/O operation completion status */
- rtems_status_code status;
- /* If status != RTEMS_SUCCESSFUL, this field contains error code */
- int error;
- /* Number of blocks for this request. */
- uint32_t bufnum;
-
- /* The task requesting the IO operation. */
- rtems_id io_task;
-
- /* List of scatter/gather buffers */
- rtems_blkdev_sg_buffer bufs[0];
+ /**
+ * Block device operation (read or write).
+ */
+ rtems_blkdev_request_op req;
+
+ /**
+ * Request done callback function.
+ */
+ rtems_blkdev_request_cb req_done;
+
+ /**
+ * Argument to be passed to callback function.
+ */
+ void *done_arg;
+
+ /**
+ * Last IO operation completion status.
+ */
+ rtems_status_code status;
+
+ /**
+ * If @c status is not equal to @c RTEMS_SUCCESSFUL, this field contains the
+ * error number.
+ */
+ int error;
+
+ /**
+ * Number of blocks for this request.
+ */
+ uint32_t bufnum;
+
+ /**
+ * The task requesting the IO operation.
+ */
+ rtems_id io_task;
+
+ /**
+ * List of scatter or gather buffers.
+ */
+ rtems_blkdev_sg_buffer bufs[0];
} rtems_blkdev_request;
-/* The start block in a request. Only valid if the driver has returned the
- * RTEMS_BLKDEV_CAPABILITIES of RTEMS_BLKDEV_CAP_MULTISECTOR_CONT */
-#define RTEMS_BLKDEV_START_BLOCK(_r) (_r->bufs[0].block)
-
-/* Block device IOCTL request codes */
-#define RTEMS_BLKIO_REQUEST _IOWR('B', 1, rtems_blkdev_request)
-#define RTEMS_BLKIO_GETBLKSIZE _IO('B', 2)
-#define RTEMS_BLKIO_GETSIZE _IO('B', 3)
-#define RTEMS_BLKIO_SYNCDEV _IO('B', 4)
+/**
+ * The start block in a request.
+ *
+ * Only valid if the driver has returned the @ref RTEMS_BLKDEV_CAPABILITIES of
+ * @ref RTEMS_BLKDEV_CAP_MULTISECTOR_CONT.
+ */
+#define RTEMS_BLKDEV_START_BLOCK(req) (req->bufs[0].block)
-/* Device driver interface conventions suppose that driver may
- * contain initialize/open/close/read/write/ioctl entry points. These
- * primitives (except initialize) can be implemented in generic fashion,
- * based upon supplied block device driver ioctl handler. Every block
- * device driver should provide initialize entry point, which is register
- * all block devices and appropriate ioctl handlers.
+/**
+ * @name IO Control Request Codes
+ *
+ * @{
*/
+#define RTEMS_BLKIO_REQUEST _IOWR('B', 1, rtems_blkdev_request)
+#define RTEMS_BLKIO_GETBLKSIZE _IO('B', 2)
+#define RTEMS_BLKIO_GETSIZE _IO('B', 3)
+#define RTEMS_BLKIO_SYNCDEV _IO('B', 4)
+
+/** @} */
+
+/**
+ * The device driver interface conventions suppose that a driver may contain an
+ * initialize, open, close, read, write and IO control entry points. These
+ * primitives (except initialize) can be implemented in a generic fashion based
+ * upon the supplied block device driver IO control handler. Every block device
+ * driver should provide an initialize entry point, which registers the
+ * appropriate IO control handler.
+ */
#define RTEMS_GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES \
- rtems_blkdev_generic_open, rtems_blkdev_generic_close, \
- rtems_blkdev_generic_read, rtems_blkdev_generic_write, \
- rtems_blkdev_generic_ioctl
+ .open_entry = rtems_blkdev_generic_open, \
+ .close_entry = rtems_blkdev_generic_close, \
+ .read_entry = rtems_blkdev_generic_read, \
+ .write_entry = rtems_blkdev_generic_write, \
+ .control_entry = rtems_blkdev_generic_ioctl
-/* blkdev_generic_read --
- * Generic block device read primitive. Implemented using block device
- * buffer management primitives.
+/**
+ * Generic block device read primitive.
+ *
+ * Implemented using block device buffer management primitives.
*/
rtems_device_driver
rtems_blkdev_generic_read(
@@ -131,9 +191,10 @@ rtems_blkdev_generic_read(
void * arg
);
-/* blkdev_generic_write --
- * Generic block device driver write primitive. Implemented using block
- * device buffer management primitives.
+/**
+ * Generic block device write primitive.
+ *
+ * Implemented using block device buffer management primitives.
*/
rtems_device_driver
rtems_blkdev_generic_write(
@@ -142,8 +203,10 @@ rtems_blkdev_generic_write(
void * arg
);
-/* blkdev_generic_open --
- * Generic block device open primitive.
+/**
+ * Generic block device open primitive.
+ *
+ * Implemented using block device buffer management primitives.
*/
rtems_device_driver
rtems_blkdev_generic_open(
@@ -152,8 +215,10 @@ rtems_blkdev_generic_open(
void * arg
);
-/* blkdev_generic_close --
- * Generic block device close primitive.
+/**
+ * Generic block device close primitive.
+ *
+ * Implemented using block device buffer management primitives.
*/
rtems_device_driver
rtems_blkdev_generic_close(
@@ -162,8 +227,10 @@ rtems_blkdev_generic_close(
void * arg
);
-/* blkdev_generic_ioctl --
- * Generic block device ioctl primitive.
+/**
+ * Generic block device IO control primitive.
+ *
+ * Implemented using block device buffer management primitives.
*/
rtems_device_driver
rtems_blkdev_generic_ioctl(
@@ -172,6 +239,8 @@ rtems_blkdev_generic_ioctl(
void * arg
);
+/** @} */
+
#ifdef __cplusplus
}
#endif
diff --git a/cpukit/libblock/include/rtems/diskdevs.h b/cpukit/libblock/include/rtems/diskdevs.h
index af56f720a0..da5c32ec13 100644
--- a/cpukit/libblock/include/rtems/diskdevs.h
+++ b/cpukit/libblock/include/rtems/diskdevs.h
@@ -1,6 +1,7 @@
/**
- * @file rtems/diskdevs.h
- * Physical and logical block devices (disks) support
+ * @file
+ *
+ * Block device disk management.
*/
/*
@@ -13,197 +14,212 @@
#ifndef _RTEMS_DISKDEVS_H
#define _RTEMS_DISKDEVS_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include <rtems.h>
#include <rtems/libio.h>
#include <stdlib.h>
-/* Buffer pool identifier */
+/**
+ * @ingroup rtems_bdbuf
+ *
+ * Buffer pool identifier.
+ */
typedef int rtems_bdpool_id;
#include <rtems/blkdev.h>
-/* Driver capabilities. */
+#ifdef __cplusplus
+extern "C" {
+#endif
-/* Block device ioctl handler */
-typedef int (* rtems_block_device_ioctl) (dev_t dev, uint32_t req, void *argp);
+/**
+ * @defgroup rtems_disk Block Device Disk Management
+ *
+ * @ingroup rtems_libblock
+ *
+ * This module provides functions to manage disk devices. The disk devices are
+ * accessed via the RTEMS block device library. A disk is a set of blocks
+ * which are identified by a consecutive set of non-negative integers starting
+ * at zero. There are also logical disks which contain a subset of consecutive
+ * disk blocks. The logical disks are used to represent the partitions of a
+ * disk.
+ *
+ * @{
+ */
-/* rtems_disk_device: Entry of this type created for every disk device
- * (both for logical and physical disks).
- * Array of arrays of pointers to disk_device structures maintained. First
- * table indexed by major number and second table indexed by minor number.
- * Such data organization allow quick lookup using data structure of
- * moderated size.
+/**
+ * Block device IO control handler type.
+ */
+typedef int (*rtems_block_device_ioctl)( dev_t dev, uint32_t req, void *argp);
+
+/**
+ * Description of a disk device (logical and physical disks).
+ *
+ * An array of pointer tables to rtems_disk_device structures is maintained.
+ * The first table will be indexed by the major number and the second table
+ * will be indexed by the minor number. This allows quick lookup using a data
+ * structure of moderated size.
*/
typedef struct rtems_disk_device {
- dev_t dev; /* Device ID (major + minor) */
- struct rtems_disk_device *phys_dev; /* Physical device ID (the same
- as dev if this entry specifies
- the physical device) */
- uint32_t capabilities; /* Driver capabilities. */
- char *name; /* Disk device name */
- int uses; /* Use counter. Device couldn't be
- removed if it is in use. */
- uint32_t start; /* Starting block number (0 for
- physical devices, block offset
- on the related physical device
- for logical device) */
- uint32_t size; /* Size of physical or logical disk
- in disk blocks */
- uint32_t block_size; /* Size of device block (minimum
- transfer unit) in bytes
- (must be power of 2) */
- uint32_t block_size_log2; /* log2 of block_size */
- rtems_bdpool_id pool; /* Buffer pool assigned to this
- device */
- rtems_block_device_ioctl ioctl; /* ioctl handler for this block
- device */
+ /**
+ * Device identifier (concatenation of major and minor number).
+ */
+ dev_t dev;
+
+ /**
+ * Physical device identifier (equals the @c dev entry if it specifies a
+ * physical device).
+ */
+ struct rtems_disk_device *phys_dev;
+
+ /**
+ * Driver capabilities.
+ */
+ uint32_t capabilities;
+
+ /**
+ * Disk device name.
+ */
+ char *name;
+
+ /**
+ * Usage counter.
+ *
+ * Devices cannot be removed if they are in use.
+ */
+ unsigned uses;
+
+ /**
+ * Start block number.
+ *
+ * Equals zero for physical devices. It is a block offset to the related
+ * physical device for logical device.
+ */
+ rtems_blkdev_bnum start;
+
+ /**
+ * Size of the physical or logical disk in blocks.
+ */
+ rtems_blkdev_bnum size;
+
+ /**
+ * Device block size in bytes.
+ *
+ * This is the minimum transfer unit and must be power of two.
+ */
+ uint32_t block_size;
+
+ /**
+ * Binary logarithm of the block size.
+ */
+ uint32_t block_size_log2;
+
+ /**
+ * Buffer pool assigned to this disk.
+ */
+ rtems_bdpool_id pool;
+
+ /**
+ * IO control handler for this disk.
+ */
+ rtems_block_device_ioctl ioctl;
} rtems_disk_device;
-/* rtems_disk_create_phys --
- * Create physical disk entry. This function usually invoked from
- * block device driver initialization code when physical device
- * detected in the system. Device driver should provide ioctl handler
- * to allow block device access operations. This primitive will register
- * device in rtems (invoke rtems_io_register_name).
- *
- * PARAMETERS:
- * dev - device identifier (major, minor numbers)
- * block_size - size of disk block (minimum data transfer unit); must be
- * power of 2
- * disk_size - number of blocks on device
- * handler - IOCTL handler (function providing basic block input/output
- * request handling BIOREQUEST and other device management
- * operations)
- * name - character name of device (e.g. /dev/hda)
- *
- * RETURNS:
- * RTEMS_SUCCESSFUL if information about new physical disk added, or
- * error code if error occured (device already registered, wrong block
- * size value, no memory available).
- */
-rtems_status_code
-rtems_disk_create_phys(dev_t dev, int block_size, int disk_size,
- rtems_block_device_ioctl handler,
- const char *name);
-
-/* rtems_disk_create_log --
- * Create logical disk entry. Logical disk is contiguous area on physical
- * disk. Disk may be splitted to several logical disks in several ways:
- * manually or using information stored in blocks on physical disk
- * (DOS-like partition table, BSD disk label, etc). This function usually
- * invoked from application when application-specific splitting are in use,
- * or from generic code which handle different logical disk organizations.
- * This primitive will register device in rtems (invoke
- * rtems_io_register_name).
- *
- * PARAMETERS:
- * dev - logical device identifier (major, minor numbers)
- * phys - physical device (block device which holds this logical disk)
- * identifier
- * start - starting block number on the physical device
- * size - logical disk size in blocks
- * name - logical disk name
- *
- * RETURNS:
- * RTEMS_SUCCESSFUL if logical device successfully added, or error code
- * if error occured (device already registered, no physical device
- * exists, logical disk is out of physical disk boundaries, no memory
- * available).
+/**
+ * Creates a physical disk with device identifier @a dev.
+ *
+ * The block size @a block_size must be a power of two. The disk size @a
+ * disk_size is the number of blocks provided by this disk. The block index
+ * starts with zero. The associated disk device driver will be invoked via the
+ * IO control handler @a handler. A device node will be registered in the file
+ * system with absolute path @a name. This function is usually invoked from a
+ * block device driver during initialization when a physical device is detected
+ * in the system. The device driver provides an IO control handler to allow
+ * block device operations.
*/
-rtems_status_code
-rtems_disk_create_log(dev_t dev, dev_t phys, int start, int size, char *name);
-
-/* rtems_disk_delete --
- * Delete physical or logical disk device. Device may be deleted if its
- * use counter (and use counters of all logical devices - if it is
- * physical device) equal to 0. When physical device deleted,
- * all logical devices deleted inherently. Appropriate devices removed
- * from "/dev" filesystem.
- *
- * PARAMETERS:
- * dev - device identifier (major, minor numbers)
- *
- * RETURNS:
- * RTEMS_SUCCESSFUL if block device successfully deleted, or error code
- * if error occured (device is not defined, device is in use).
+rtems_status_code rtems_disk_create_phys(
+ dev_t dev,
+ uint32_t block_size,
+ rtems_blkdev_bnum disk_size,
+ rtems_block_device_ioctl handler,
+ const char *name
+);
+
+/**
+ * Creates a logical disk with device identifier @a dev.
+ *
+ * A logical disk manages a subset of consecutive blocks containd in the
+ * physical disk with identifier @a phys. The start block index of the logical
+ * disk device is @a start. The block number of the logcal disk will be @a
+ * size. The blocks must be within the range of blocks managed by the
+ * associated physical disk device. A device node will be registered in the
+ * file system with absolute path @a name. The block size and IO control
+ * handler are inherited by the physical disk.
*/
-rtems_status_code
-rtems_disk_delete(dev_t dev);
+rtems_status_code rtems_disk_create_log(
+ dev_t dev,
+ dev_t phys,
+ rtems_blkdev_bnum start,
+ rtems_blkdev_bnum size,
+ const char *name
+);
-/* rtems_disk_obtain --
- * Find block device descriptor by its device identifier. This function
- * increment usage counter to 1. User should release disk_device structure
- * by invoking rtems_disk_release primitive.
- *
- * PARAMETERS:
- * dev - device identifier (major, minor numbers)
+/**
+ * Deletes a physical or logical disk device with identifier @a dev.
*
- * RETURNS:
- * pointer to the block device descriptor, or NULL if no such device
- * exists.
+ * Disk devices may be deleted if there usage counter (and the usage counters
+ * of all contained logical disks devices) equals zero. When a physical disk
+ * device is deleted, all logical disk devices will deleted too. The
+ * corresponding device nodes will be removed from the file system.
*/
-rtems_disk_device *
-rtems_disk_obtain(dev_t dev);
+rtems_status_code rtems_disk_delete(dev_t dev);
-/* rtems_disk_release --
- * Release disk_device structure (decrement usage counter to 1).
- *
- * PARAMETERS:
- * dd - pointer to disk device structure
- *
- * RETURNS:
- * RTEMS_SUCCESSFUL
+/**
+ * Returns the disk device descriptor for the device identifier @a dev.
*
- * NOTE:
- * It should be implemented as inline function.
+ * Increments usage counter by one. You should release the disk device
+ * descriptor with rtems_disk_release(). Returns @c NULL if no corresponding
+ * disk exists.
*/
-rtems_status_code
-rtems_disk_release(rtems_disk_device *dd);
+rtems_disk_device *rtems_disk_obtain(dev_t dev);
-/* rtems_disk_next --
- * Disk device enumerator. Looking for device having device number larger
- * than dev and return disk device descriptor for it. If there are no
- * such device, NULL value returned.
- *
- * PARAMETERS:
- * dev - device number (use -1 to start search)
+/**
+ * Releases the disk device description @a dd.
*
- * RETURNS:
- * Pointer to the disk descriptor for next disk device, or NULL if all
- * devices enumerated. */
-rtems_disk_device *
-rtems_disk_next(dev_t dev);
+ * Decrements usage counter by one.
+ */
+rtems_status_code rtems_disk_release(rtems_disk_device *dd);
-/* rtems_diskio_initialize --
- * Initialization of disk device library (initialize all data structures,
- * etc.)
+/**
+ * Disk device iterator.
*
- * PARAMETERS:
- * none
+ * Returns the next disk device descriptor with a device identifier larger than
+ * @a dev. If there is no such device, @c NULL will be returned. Use minus
+ * one to start the search.
*
- * RETURNS:
- * RTEMS_SUCCESSFUL if library initialized, or error code if error
- * occured.
+ * @code
+ * rtems_disk_device *dd = rtems_disk_next((dev_t) -1);
+ *
+ * while (dd != NULL) {
+ * dd = rtems_disk_next(dd->dev);
+ * }
+ * @endcode
*/
-rtems_status_code
-rtems_disk_io_initialize(void);
+rtems_disk_device *rtems_disk_next(dev_t dev);
-/* rtems_diskio_done --
- * Release all resources allocated for disk device interface.
- *
- * PARAMETERS:
- * none
+/**
+ * Initializes the disk device management.
*
- * RETURNS:
- * RTEMS_SUCCESSFUL if all resources released, or error code if error
- * occured.
+ * This functions returns successful if the disk device management is already
+ * initialized. There is no protection against concurrent access.
*/
-rtems_status_code
-rtems_disk_io_done(void);
+rtems_status_code rtems_disk_io_initialize(void);
+
+/**
+ * Releases all resources allocated for disk device management.
+ */
+rtems_status_code rtems_disk_io_done(void);
+
+/** @} */
#ifdef __cplusplus
}
diff --git a/cpukit/libblock/src/bdbuf.c b/cpukit/libblock/src/bdbuf.c
index 3d57a3c3b8..6ae6c4dccc 100644
--- a/cpukit/libblock/src/bdbuf.c
+++ b/cpukit/libblock/src/bdbuf.c
@@ -1,3 +1,9 @@
+/**
+ * @file
+ *
+ * Block device buffer management.
+ */
+
/*
* Disk I/O buffering
* Buffer managment
@@ -15,81 +21,6 @@
*/
/**
- * @file
- *
- * The Buffer Descriptor Buffer code implements a cache between the disk
- * devices and file systems. The code provides read ahead and write queuing to
- * the drivers and fast cache look up using an AVL tree.
- *
- * The buffers are held in pools based on size. Each pool has buffers and the
- * buffers follow this state machine:
- *
- * read/read ahead
- * +-------------------------------+
- * | v
- * +-----------+ read ahead +------------+
- * | READY, | complete | |---------+
- * | READ |<----------------| TRANSFER | |
- * | AHEAD | +-------------| |<--+ |
- * +-----------+ | read/write +------------+ | |
- * | get v complete swap | |
- * | +-----------+ modified +------------+ |
- * +--->| ACCESSED, |---------->| MODIFIED, | |
- * | ACCESSED |<----------| SYNC | |
- * +----| MODIFIED |<--+ get | | |
- * | +-----------+ | +------------+ |
- * | release get | |
- * | +-----------+ | |
- * +--->| |---+ read complete |
- * | CACHED | write complete |
- * | |<-------------------------+
- * +-----------+
- *
- * Empty buffers are added to the ready list and removed from this queue when a
- * caller requests a buffer. This is referred to as getting a buffer in the
- * code and the event get in the state diagram. The buffer is assigned to a
- * block and inserted to the AVL based on the block/device key. If the block is
- * to be read by the user and not in the cache (ready) it is transfered from
- * the disk into memory. If no ready buffers exist the buffer is taken from the
- * LRU list. If no buffers are on the LRU list the modified list is check. If
- * no buffers are on the modified list the request blocks. If buffers are on
- * the modified list the buffers hold timer is expired and the swap out task
- * woken.
- *
- * A block being accessed is given to the file system layer and not accessable
- * to another requester until released back to the cache. The same goes to a
- * buffer in the transfer state. The transfer state means being read or
- * written. If the file system has modifed the block and releases it as
- * modified it placed on the pool's modified list and a hold timer
- * initialised. The buffer is held for the hold time before being written to
- * disk. Buffers are held for a configurable period of time on the modified
- * list as a write sets the state to transfer and this locks the buffer out
- * from the file system until the write complete. Buffers are often repeatable
- * accessed and modified in a series of small updates so if sent to the disk
- * when released as modified the user would have to block waiting until it had
- * been written. This would be a performance problem.
- *
- * The code performs mulitple block reads and writes. Multiple block reads or
- * read ahead increases performance with hardware that supports it. It also
- * helps with a large cache as the disk head movement is reduced. It how-ever
- * is a speculative operation so excessive use can remove valuable and needed
- * blocks from the cache. The get call knows if a read is a for the file system
- * or if it is a read ahead get. If the get is for a read ahead block and the
- * block is already in the cache or no ready buffers are available the read
- * ahead is stopped. The transfer occurs with the blocks so far. If a buffer is
- * in the read ahead state and release it is placed on the ready list rather
- * than the LRU list. This means these buffers are used before buffers used by
- * the file system.
- *
- * The pool have the following lists of buffers:
- *
- * ready - Empty buffers created when the pool is initialised.
- * modified - Buffers waiting to be written to disk.
- * sync - Buffers to be synced to disk.
- * lru - Accessed buffers released in least recently used order.
- */
-
-/**
* Set to 1 to enable debug tracing.
*/
#define RTEMS_BDBUF_TRACE 0
@@ -100,6 +31,7 @@
#include <rtems.h>
#include <rtems/error.h>
+#include <rtems/malloc.h>
#include <limits.h>
#include <errno.h>
#include <assert.h>
@@ -430,7 +362,7 @@ rtems_bdbuf_avl_insert(rtems_bdbuf_buffer** root,
/**
* Removes the node from the tree.
*
- * @param root_addr Pointer to pointer to the root node
+ * @param root Pointer to pointer to the root node
* @param node Pointer to the node to remove
* @retval 0 Item removed
* @retval -1 No such item found
@@ -704,7 +636,7 @@ rtems_bdbuf_avl_remove(rtems_bdbuf_buffer** root,
/**
* Get the pool for the device.
*
- * @param pdd Physical disk device.
+ * @param pid Physical disk device.
*/
static rtems_bdbuf_pool*
rtems_bdbuf_get_pool (const rtems_bdpool_id pid)
@@ -923,11 +855,19 @@ static rtems_status_code
rtems_bdbuf_initialize_pool (rtems_bdbuf_pool_config* config,
rtems_bdpool_id pid)
{
+ int rv = 0;
unsigned char* buffer = config->mem_area;
rtems_bdbuf_pool* pool;
rtems_bdbuf_buffer* bd;
rtems_status_code sc;
uint32_t b;
+ int cache_aligment = 32 /* FIXME rtems_cache_get_data_line_size() */;
+
+ /* For unspecified cache alignments we use the CPU alignment */
+ if (cache_aligment <= 0)
+ {
+ cache_aligment = CPU_ALIGNMENT;
+ }
pool = rtems_bdbuf_get_pool (pid);
@@ -961,16 +901,21 @@ rtems_bdbuf_initialize_pool (rtems_bdbuf_pool_config* config,
return RTEMS_NO_MEMORY;
/*
- * Allocate memory for buffers if required.
+ * Allocate memory for buffers if required. The pool memory will be cache
+ * aligned. It is possible to free the memory allocated by rtems_memalign()
+ * with free().
*/
if (buffer == NULL)
{
- buffer = pool->buffers = malloc (config->num * config->size);
- if (!pool->buffers)
+ rv = rtems_memalign ((void **) &buffer,
+ cache_aligment,
+ config->num * config->size);
+ if (rv != 0)
{
free (pool->bds);
return RTEMS_NO_MEMORY;
}
+ pool->buffers = buffer;
}
for (b = 0, bd = pool->bds;
@@ -1079,16 +1024,6 @@ rtems_bdbuf_release_pool (rtems_bdpool_id pid)
return RTEMS_SUCCESSFUL;
}
-/**
- * Prepare buffering layer to work - initialize buffer descritors and (if it is
- * neccessary) buffers. Buffers will be allocated accoriding to the
- * configuration table, each entry describes the size of block and the size of
- * the pool. After initialization all blocks is placed into the ready state.
- * lists.
- *
- * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
- * successfully or error code if error is occured)
- */
rtems_status_code
rtems_bdbuf_init (void)
{
@@ -1209,7 +1144,7 @@ rtems_bdbuf_init (void)
* it will make sure the pool is locked when it returns. The pool will be
* unlocked if the call could block.
*
- * @param device The physical disk device
+ * @param pdd The physical disk device
* @param pool The pool reference
* @param block Absolute media block number
* @param read_ahead The get is for a read ahead buffer
@@ -1401,30 +1336,6 @@ rtems_bdbuf_get_buffer (rtems_disk_device* pdd,
return bd;
}
-/**
- * Get block buffer for data to be written into. The buffers is set to the
- * access or modifed access state. If the buffer is in the cache and modified
- * the state is access modified else the state is access. This buffer contents
- * are not initialised if the buffer is not already in the cache. If the block
- * is already resident in memory it is returned how-ever if not in memory the
- * buffer is not read from disk. This call is used when writing the whole block
- * on a disk rather than just changing a part of it. If there is no buffers
- * available this call will block. A buffer obtained with this call will not be
- * involved in a transfer request and will not be returned to another user
- * until released. If the buffer is already with a user when this call is made
- * the call is blocked until the buffer is returned. The highest priority
- * waiter will obtain the buffer first.
- *
- * The block number is the linear block number. This is relative to the start
- * of the partition on the media.
- *
- * @param device Device number (constructed of major and minor device number)
- * @param block Linear media block number
- * @param bd Reference to the buffer descriptor pointer.
- *
- * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
- * successfully or error code if error is occured)
- */
rtems_status_code
rtems_bdbuf_get (dev_t device,
rtems_blkdev_bnum block,
@@ -1447,17 +1358,16 @@ rtems_bdbuf_get (dev_t device,
return RTEMS_INVALID_NUMBER;
}
- block += dd->start;
-
pool = rtems_bdbuf_get_pool (dd->phys_dev->pool);
rtems_bdbuf_lock_pool (pool);
#if RTEMS_BDBUF_TRACE
- rtems_bdbuf_printf ("get: %d (dev = %08x)\n", block, device);
+ /* Print the block index relative to the physical disk */
+ rtems_bdbuf_printf ("get: %d (dev = %08x)\n", block + dd->start, device);
#endif
- bd = rtems_bdbuf_get_buffer (dd->phys_dev, pool, block, false);
+ bd = rtems_bdbuf_get_buffer (dd->phys_dev, pool, block + dd->start, false);
if (bd->state == RTEMS_BDBUF_STATE_MODIFIED)
bd->state = RTEMS_BDBUF_STATE_ACCESS_MODIFIED;
@@ -1494,31 +1404,6 @@ rtems_bdbuf_read_done (void* arg, rtems_status_code status, int error)
rtems_event_send (req->io_task, RTEMS_BDBUF_TRANSFER_SYNC);
}
-/**
- * Get the block buffer and if not already in the cache read from the disk. If
- * specified block already cached return. The buffer is set to the access or
- * modifed access state. If the buffer is in the cache and modified the state
- * is access modified else the state is access. If block is already being read
- * from disk for being written to disk this call blocks. If the buffer is
- * waiting to be written it is removed from modified queue and returned to the
- * user. If the buffer is not in the cache a new buffer is obtained and the
- * data read from disk. The call may block until these operations complete. A
- * buffer obtained with this call will not be involved in a transfer request
- * and will not be returned to another user until released. If the buffer is
- * already with a user when this call is made the call is blocked until the
- * buffer is returned. The highest priority waiter will obtain the buffer
- * first.
- *
- * @note Read ahead always reads buffers in sequence. All multi-block reads
- * read consecutive blocks.
- *
- * @param device Device number (constructed of major and minor device number)
- * @param block Linear media block number
- * @param bd Reference to the buffer descriptor pointer.
- *
- * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
- * successfully or error code if error is occured)
- */
rtems_status_code
rtems_bdbuf_read (dev_t device,
rtems_blkdev_bnum block,
@@ -1545,18 +1430,16 @@ rtems_bdbuf_read (dev_t device,
dd = rtems_disk_obtain (device);
if (dd == NULL)
return RTEMS_INVALID_ID;
-
- block += dd->start;
-
-#if RTEMS_BDBUF_TRACE
- rtems_bdbuf_printf ("read: %d (dev = %08x)\n", block, device);
-#endif
- if (block >= dd->size)
- {
+ if (block >= dd->size) {
rtems_disk_release(dd);
return RTEMS_INVALID_NUMBER;
}
+
+#if RTEMS_BDBUF_TRACE
+ /* Print the block index relative to the physical disk */
+ rtems_bdbuf_printf ("read: %d (dev = %08x)\n", block + dd->start, device);
+#endif
req->bufnum = 0;
@@ -1587,7 +1470,7 @@ rtems_bdbuf_read (dev_t device,
* caller.
*/
bd = rtems_bdbuf_get_buffer (dd->phys_dev, pool,
- block + req->bufnum,
+ block + dd->start + req->bufnum,
req->bufnum == 0 ? false : true);
/*
@@ -1711,19 +1594,6 @@ rtems_bdbuf_read (dev_t device,
return RTEMS_SUCCESSFUL;
}
-/**
- * Release the buffer obtained by a read call back to the cache. If the buffer
- * was obtained by a get call and was not already in the cache the release
- * modified call should be used. A buffer released with this call obtained by a
- * get call may not be in sync with the contents on disk. If the buffer was in
- * the cache and modified before this call it will be returned to the modified
- * queue. The buffers is returned to the end of the LRU list.
- *
- * @param bd Reference to the buffer descriptor.
- *
- * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
- * successfully or error code if error is occured)
- */
rtems_status_code
rtems_bdbuf_release (rtems_bdbuf_buffer* bd)
{
@@ -1785,21 +1655,6 @@ rtems_bdbuf_release (rtems_bdbuf_buffer* bd)
return RTEMS_SUCCESSFUL;
}
-/**
- * Release the buffer allocated with a get or read call placing it on the
- * modidied list. If the buffer was not released modified before the hold
- * timer is set to the configuration value. If the buffer had been released
- * modified before but not written to disk the hold timer is not updated. The
- * buffer will be written to disk when the hold timer has expired, there are
- * not more buffers available in the cache and a get or read buffer needs one
- * or a sync call has been made. If the buffer is obtained with a get or read
- * before the hold timer has expired the buffer will be returned to the user.
- *
- * @param bd Reference to the buffer descriptor.
- *
- * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
- * successfully or error code if error is occured)
- */
rtems_status_code
rtems_bdbuf_release_modified (rtems_bdbuf_buffer* bd)
{
@@ -1828,20 +1683,6 @@ rtems_bdbuf_release_modified (rtems_bdbuf_buffer* bd)
return RTEMS_SUCCESSFUL;
}
-/**
- * Release the buffer as modified and wait until it has been synchronized with
- * the disk by writing it. This buffer will be the first to be transfer to disk
- * and other buffers may also be written if the maximum number of blocks in a
- * requests allows it.
- *
- * @note This code does not lock the sync mutex and stop additions to the
- * modified queue.
- *
- * @param bd Reference to the buffer descriptor.
- *
- * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
- * successfully or error code if error is occured)
- */
rtems_status_code
rtems_bdbuf_sync (rtems_bdbuf_buffer* bd)
{
@@ -1895,17 +1736,6 @@ rtems_bdbuf_sync (rtems_bdbuf_buffer* bd)
return RTEMS_SUCCESSFUL;
}
-/**
- * Synchronize all modified buffers for this device with the disk and wait
- * until the transfers have completed. The sync mutex for the pool is locked
- * stopping the addition of any further modifed buffers. It is only the
- * currently modified buffers that are written.
- *
- * @param dev Block device number
- *
- * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
- * successfully or error code if error is occured)
- */
rtems_status_code
rtems_bdbuf_syncdev (dev_t dev)
{
@@ -2427,21 +2257,6 @@ rtems_bdbuf_swapout_task (rtems_task_argument arg)
rtems_task_delete (RTEMS_SELF);
}
-/**
- * Find first appropriate buffer pool. This primitive returns the index of
- * first buffer pool which block size is greater than or equal to specified
- * size.
- *
- * @param block_size Requested block size
- * @param pool The pool to use for the requested pool size.
- *
- * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
- * successfully or error code if error is occured)
- * @retval RTEMS_INVALID_SIZE The specified block size is invalid (not a power
- * of 2)
- * @retval RTEMS_NOT_DEFINED The buffer pool for this or greater block size
- * is not configured.
- */
rtems_status_code
rtems_bdbuf_find_pool (uint32_t block_size, rtems_bdpool_id *pool)
{
@@ -2480,23 +2295,11 @@ rtems_bdbuf_find_pool (uint32_t block_size, rtems_bdpool_id *pool)
}
}
-/**
- * Obtain characteristics of buffer pool with specified number.
- *
- * @param pool Buffer pool number
- * @param block_size Block size for which buffer pool is configured returned
- * there
- * @param blocks Number of buffers in buffer pool.
- *
- * RETURNS:
- * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
- * successfully or error code if error is occured)
- * @retval RTEMS_INVALID_SIZE The appropriate buffer pool is not configured.
- *
- * @note Buffer pools enumerated continuously starting from 0.
- */
-rtems_status_code
-rtems_bdbuf_get_pool_info (rtems_bdpool_id pool, int* block_size, int* blocks)
+rtems_status_code rtems_bdbuf_get_pool_info(
+ rtems_bdpool_id pool,
+ uint32_t *block_size,
+ uint32_t *blocks
+)
{
if (pool >= rtems_bdbuf_ctx.npools)
return RTEMS_INVALID_NUMBER;
diff --git a/cpukit/libblock/src/blkdev.c b/cpukit/libblock/src/blkdev.c
index 560ad224ec..fd5b7f09b0 100644
--- a/cpukit/libblock/src/blkdev.c
+++ b/cpukit/libblock/src/blkdev.c
@@ -1,3 +1,9 @@
+/**
+ * @file
+ *
+ * Block device management.
+ */
+
/*
* blkdev.h - block device driver generic support
*
diff --git a/cpukit/libblock/src/diskdevs.c b/cpukit/libblock/src/diskdevs.c
index a371d1a9ba..f888246e36 100644
--- a/cpukit/libblock/src/diskdevs.c
+++ b/cpukit/libblock/src/diskdevs.c
@@ -1,3 +1,9 @@
+/**
+ * @file
+ *
+ * Block device disk management.
+ */
+
/*
* diskdevs.c - Physical and logical block devices (disks) support
*
@@ -212,32 +218,13 @@ create_disk(dev_t dev, const char *name, rtems_disk_device **diskdev)
return RTEMS_SUCCESSFUL;
}
-/* rtems_disk_create_phys --
- * Create physical disk entry. This function usually invoked from
- * block device driver initialization code when physical device
- * detected in the system. Device driver should provide ioctl handler
- * to allow block device access operations. This primitive will register
- * device in rtems (invoke rtems_io_register_name).
- *
- * PARAMETERS:
- * dev - device identifier (major, minor numbers)
- * block_size - size of disk block (minimum data transfer unit); must be
- * power of 2
- * disk_size - number of blocks on device
- * handler - IOCTL handler (function providing basic block input/output
- * request handling BIOREQUEST and other device management
- * operations)
- * name - character name of device (e.g. /dev/hda)
- *
- * RETURNS:
- * RTEMS_SUCCESSFUL if information about new physical disk added, or
- * error code if error occured (device already registered, wrong block
- * size value, no memory available).
- */
-rtems_status_code
-rtems_disk_create_phys(dev_t dev, int block_size, int disk_size,
- rtems_block_device_ioctl handler,
- const char *name)
+rtems_status_code rtems_disk_create_phys(
+ dev_t dev,
+ uint32_t block_size,
+ rtems_blkdev_bnum disk_size,
+ rtems_block_device_ioctl handler,
+ const char *name
+)
{
int bs_log2;
int i;
@@ -297,163 +284,138 @@ rtems_disk_create_phys(dev_t dev, int block_size, int disk_size,
return rc;
}
-/* rtems_disk_create_log --
- * Create logical disk entry. Logical disk is contiguous area on physical
- * disk. Disk may be splitted to several logical disks in several ways:
- * manually or using information stored in blocks on physical disk
- * (DOS-like partition table, BSD disk label, etc). This function usually
- * invoked from application when application-specific splitting are in use,
- * or from generic code which handle different logical disk organizations.
- * This primitive will register device in rtems (invoke
- * rtems_io_register_name).
- *
- * PARAMETERS:
- * dev - logical device identifier (major, minor numbers)
- * phys - physical device (block device which holds this logical disk)
- * identifier
- * start - starting block number on the physical device
- * size - logical disk size in blocks
- * name - logical disk name
- *
- * RETURNS:
- * RTEMS_SUCCESSFUL if logical device successfully added, or error code
- * if error occured (device already registered, no physical device
- * exists, logical disk is out of physical disk boundaries, no memory
- * available).
- */
-rtems_status_code
-rtems_disk_create_log(dev_t dev, dev_t phys, int start, int size, char *name)
+rtems_status_code rtems_disk_create_log(
+ dev_t dev,
+ dev_t phys,
+ rtems_blkdev_bnum start,
+ rtems_blkdev_bnum size,
+ const char *name
+)
{
- rtems_disk_device *dd;
- rtems_disk_device *pdd;
- rtems_status_code rc;
- rtems_device_major_number major;
- rtems_device_minor_number minor;
-
- rtems_filesystem_split_dev_t (dev, major, minor);
+ rtems_disk_device *dd = NULL;
+ rtems_disk_device *pdd = NULL;
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+ rtems_device_major_number major = 0;
+ rtems_device_minor_number minor = 0;
+ rtems_blkdev_bnum end = start + size;
- rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
- if (rc != RTEMS_SUCCESSFUL)
- return rc;
- diskdevs_protected = true;
+ rtems_filesystem_split_dev_t (dev, major, minor);
- pdd = get_disk_entry(phys);
- if (pdd == NULL)
- {
- diskdevs_protected = false;
- rtems_semaphore_release(diskdevs_mutex);
- return RTEMS_INVALID_NUMBER;
- }
+ rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (rc != RTEMS_SUCCESSFUL) {
+ return rc;
+ }
+
+ diskdevs_protected = true;
+
+ pdd = get_disk_entry(phys);
+ if (
+ pdd == NULL
+ || pdd != pdd->phys_dev
+ || start >= pdd->size
+ || end <= start
+ || end > pdd->size
+ ) {
+ diskdevs_protected = false;
+ rtems_semaphore_release(diskdevs_mutex);
+ return RTEMS_INVALID_NUMBER;
+ }
- rc = create_disk(dev, name, &dd);
- if (rc != RTEMS_SUCCESSFUL)
- {
- diskdevs_protected = false;
- rtems_semaphore_release(diskdevs_mutex);
- return rc;
- }
+ rc = create_disk(dev, name, &dd);
+ if (rc != RTEMS_SUCCESSFUL) {
+ diskdevs_protected = false;
+ rtems_semaphore_release(diskdevs_mutex);
+ return rc;
+ }
- dd->phys_dev = pdd;
- dd->uses = 0;
- dd->start = start;
- dd->size = size;
- dd->block_size = pdd->block_size;
- dd->block_size_log2 = pdd->block_size_log2;
- dd->ioctl = pdd->ioctl;
+ dd->phys_dev = pdd;
+ dd->uses = 0;
+ dd->start = start;
+ dd->size = size;
+ dd->block_size = pdd->block_size;
+ dd->block_size_log2 = pdd->block_size_log2;
+ dd->ioctl = pdd->ioctl;
- rc = rtems_io_register_name(name, major, minor);
+ rc = rtems_io_register_name(name, major, minor);
- diskdevs_protected = false;
- rc = rtems_semaphore_release(diskdevs_mutex);
+ diskdevs_protected = false;
+ rc = rtems_semaphore_release(diskdevs_mutex);
- return rc;
+ return rc;
}
-/* rtems_disk_delete --
- * Delete physical or logical disk device. Device may be deleted if its
- * use counter (and use counters of all logical devices - if it is
- * physical device) equal to 0. When physical device deleted,
- * all logical devices deleted inherently. Appropriate devices removed
- * from "/dev" filesystem.
- *
- * PARAMETERS:
- * dev - device identifier (major, minor numbers)
- *
- * RETURNS:
- * RTEMS_SUCCESSFUL if block device successfully deleted, or error code
- * if error occured (device is not defined, device is in use).
- */
rtems_status_code
rtems_disk_delete(dev_t dev)
{
- rtems_status_code rc;
- int used;
- rtems_device_major_number maj;
- rtems_device_minor_number min;
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+ rtems_device_major_number maj = 0;
+ rtems_device_minor_number min = 0;
+ rtems_disk_device *dd = NULL;
+ bool physical_disk = true;
+
+ rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (rc != RTEMS_SUCCESSFUL) {
+ return rc;
+ }
+ diskdevs_protected = true;
- rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
- if (rc != RTEMS_SUCCESSFUL)
- return rc;
- diskdevs_protected = true;
+ /* Check if we have a physical or logical disk */
+ dd = get_disk_entry(dev);
+ if (dd == NULL) {
+ return RTEMS_INVALID_NUMBER;
+ }
+ physical_disk = dd->phys_dev == dd;
+
+ if (physical_disk) {
+ unsigned used = 0;
/* Check if this device is in use -- calculate usage counter */
- used = 0;
- for (maj = 0; maj < disktab_size; maj++)
- {
- rtems_disk_device_table *dtab = disktab + maj;
- if (dtab != NULL)
- {
- for (min = 0; min < dtab->size; min++)
- {
- rtems_disk_device *dd = dtab->minor[min];
- if ((dd != NULL) && (dd->phys_dev->dev == dev))
- used += dd->uses;
- }
+ for (maj = 0; maj < disktab_size; maj++) {
+ rtems_disk_device_table *dtab = disktab + maj;
+ if (dtab != NULL) {
+ for (min = 0; min < dtab->size; min++) {
+ dd = dtab->minor[min];
+ if ((dd != NULL) && (dd->phys_dev->dev == dev)) {
+ used += dd->uses;
+ }
}
+ }
}
- if (used != 0)
- {
- diskdevs_protected = false;
- rtems_semaphore_release(diskdevs_mutex);
- return RTEMS_RESOURCE_IN_USE;
+ if (used != 0) {
+ diskdevs_protected = false;
+ rtems_semaphore_release(diskdevs_mutex);
+ return RTEMS_RESOURCE_IN_USE;
}
/* Delete this device and all of its logical devices */
- for (maj = 0; maj < disktab_size; maj++)
- {
- rtems_disk_device_table *dtab = disktab +maj;
- if (dtab != NULL)
- {
- for (min = 0; min < dtab->size; min++)
- {
- rtems_disk_device *dd = dtab->minor[min];
- if ((dd != NULL) && (dd->phys_dev->dev == dev))
- {
- unlink(dd->name);
- free(dd->name);
- free(dd);
- dtab->minor[min] = NULL;
- }
- }
+ for (maj = 0; maj < disktab_size; maj++) {
+ rtems_disk_device_table *dtab = disktab + maj;
+ if (dtab != NULL) {
+ for (min = 0; min < dtab->size; min++) {
+ dd = dtab->minor[min];
+ if ((dd != NULL) && (dd->phys_dev->dev == dev)) {
+ unlink(dd->name);
+ free(dd->name);
+ free(dd);
+ dtab->minor[min] = NULL;
+ }
}
+ }
}
-
- diskdevs_protected = false;
- rc = rtems_semaphore_release(diskdevs_mutex);
- return rc;
+ } else {
+ rtems_filesystem_split_dev_t(dev, maj, min);
+ disktab[maj].minor[min] = NULL;
+ unlink(dd->name);
+ free(dd->name);
+ free(dd);
+ }
+
+ diskdevs_protected = false;
+ rc = rtems_semaphore_release(diskdevs_mutex);
+ return rc;
}
-/* rtems_disk_obtain --
- * Find block device descriptor by its device identifier.
- *
- * PARAMETERS:
- * dev - device identifier (major, minor numbers)
- *
- * RETURNS:
- * pointer to the block device descriptor, or NULL if no such device
- * exists.
- */
rtems_disk_device *
rtems_disk_obtain(dev_t dev)
{
@@ -486,15 +448,6 @@ rtems_disk_obtain(dev_t dev)
}
}
-/* rtems_disk_release --
- * Release rtems_disk_device structure (decrement usage counter to 1).
- *
- * PARAMETERS:
- * dd - pointer to disk device structure
- *
- * RETURNS:
- * RTEMS_SUCCESSFUL
- */
rtems_status_code
rtems_disk_release(rtems_disk_device *dd)
{
@@ -505,18 +458,6 @@ rtems_disk_release(rtems_disk_device *dd)
return RTEMS_SUCCESSFUL;
}
-/* rtems_disk_next --
- * Disk device enumerator. Looking for device having device number larger
- * than dev and return disk device descriptor for it. If there are no
- * such device, NULL value returned.
- *
- * PARAMETERS:
- * dev - device number (use -1 to start search)
- *
- * RETURNS:
- * Pointer to the disk descriptor for next disk device, or NULL if all
- * devices enumerated.
- */
rtems_disk_device *
rtems_disk_next(dev_t dev)
{
@@ -549,17 +490,6 @@ rtems_disk_next(dev_t dev)
}
}
-/* rtems_disk_initialize --
- * Initialization of disk device library (initialize all data structures,
- * etc.)
- *
- * PARAMETERS:
- * none
- *
- * RETURNS:
- * RTEMS_SUCCESSFUL if library initialized, or error code if error
- * occured.
- */
rtems_status_code
rtems_disk_io_initialize(void)
{
@@ -598,16 +528,6 @@ rtems_disk_io_initialize(void)
return RTEMS_SUCCESSFUL;
}
-/* rtems_disk_io_done --
- * Release all resources allocated for disk device interface.
- *
- * PARAMETERS:
- * none
- *
- * RETURNS:
- * RTEMS_SUCCESSFUL if all resources released, or error code if error
- * occured.
- */
rtems_status_code
rtems_disk_io_done(void)
{
diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
index b50ff01107..52a611b5f0 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -740,7 +740,7 @@ rtems_fs_init_functions_t rtems_fs_init_helper =
rtems_bdbuf_pool_config rtems_bdbuf_pool_configuration[] = {
{CONFIGURE_BDBUF_BUFFER_SIZE, CONFIGURE_BDBUF_BUFFER_COUNT, NULL}
};
- int rtems_bdbuf_pool_configuration_size =
+ size_t rtems_bdbuf_pool_configuration_size =
(sizeof(rtems_bdbuf_pool_configuration) /
sizeof(rtems_bdbuf_pool_configuration[0]));
#endif /* CONFIGURE_INIT */