summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 */