summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cpukit/ChangeLog87
-rw-r--r--cpukit/libblock/Makefile.am2
-rw-r--r--cpukit/libblock/include/rtems/bdbuf.h250
-rw-r--r--cpukit/libblock/include/rtems/blkdev.h113
-rw-r--r--cpukit/libblock/include/rtems/diskdevs.h71
-rw-r--r--cpukit/libblock/include/rtems/ide_part_table.h33
-rw-r--r--cpukit/libblock/include/rtems/nvdisk.h2
-rw-r--r--cpukit/libblock/include/rtems/ramdisk.h112
-rw-r--r--cpukit/libblock/src/bdbuf.c3567
-rw-r--r--cpukit/libblock/src/blkdev.c34
-rw-r--r--cpukit/libblock/src/diskdevs.c77
-rw-r--r--cpukit/libblock/src/flashdisk.c34
-rw-r--r--cpukit/libblock/src/ide_part_table.c64
-rw-r--r--cpukit/libblock/src/nvdisk.c122
-rw-r--r--cpukit/libblock/src/ramdisk.c72
-rw-r--r--cpukit/libfs/src/dosfs/fat.c204
-rw-r--r--cpukit/libfs/src/dosfs/fat.h228
-rw-r--r--cpukit/libfs/src/dosfs/fat_fat_operations.c24
-rw-r--r--cpukit/libfs/src/dosfs/fat_file.c38
-rw-r--r--cpukit/libfs/src/dosfs/msdos_create.c12
-rw-r--r--cpukit/libfs/src/dosfs/msdos_dir.c22
-rw-r--r--cpukit/libfs/src/dosfs/msdos_eval.c4
-rw-r--r--cpukit/libfs/src/dosfs/msdos_file.c20
-rw-r--r--cpukit/libfs/src/dosfs/msdos_format.c24
-rw-r--r--cpukit/libfs/src/dosfs/msdos_free.c2
-rw-r--r--cpukit/libfs/src/dosfs/msdos_initsupp.c6
-rw-r--r--cpukit/libfs/src/dosfs/msdos_misc.c6
-rw-r--r--cpukit/libfs/src/dosfs/msdos_mknod.c4
-rw-r--r--cpukit/libmisc/Makefile.am8
-rw-r--r--cpukit/libmisc/shell/cmp-ls.c200
-rw-r--r--cpukit/libmisc/shell/extern-cp.h2
-rw-r--r--cpukit/libmisc/shell/extern-ls.h195
-rw-r--r--cpukit/libmisc/shell/filemode.c150
-rw-r--r--cpukit/libmisc/shell/main_blksync.c2
-rw-r--r--cpukit/libmisc/shell/main_cp.c4
-rw-r--r--cpukit/libmisc/shell/main_ls.c822
-rw-r--r--cpukit/libmisc/shell/main_rm.c711
-rw-r--r--cpukit/libmisc/shell/print-ls.c480
-rw-r--r--cpukit/libmisc/shell/pwcache.c116
-rw-r--r--cpukit/libmisc/shell/shell.c2
-rw-r--r--cpukit/libmisc/shell/utils-cp.c4
-rw-r--r--cpukit/libmisc/shell/utils-ls.c113
-rw-r--r--cpukit/libmisc/shell/vis.c384
-rw-r--r--cpukit/libmisc/shell/vis.h91
-rw-r--r--cpukit/sapi/include/confdefs.h38
-rw-r--r--cpukit/score/src/coremutex.c4
-rw-r--r--cpukit/score/src/interr.c1
47 files changed, 6177 insertions, 2384 deletions
diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog
index 5d62e1f28d..9ee374f0ee 100644
--- a/cpukit/ChangeLog
+++ b/cpukit/ChangeLog
@@ -1,3 +1,90 @@
+2008-07-29 Chris Johns <chrisj@rtems.org>
+
+ * libblock/Makefile.am: Removed src/show_bdbuf.c.
+
+ * libblock/src/show_bdbuf.c: Removed.
+
+ * libblock/include/rtems/bdbuf.h, cpukit/libblock/src/bdbuf.c:
+ Rewritten the bdbuf code. Remove pre-emption disable, score
+ access, fixed many bugs and increased performance.
+
+ * libblock/include/rtems/blkdev.h: Added
+ RTEMS_BLKDEV_CAPABILITIES block device request. Cleaned up
+ comments. Added block and user fields to the sg buffer
+ request. Move to rtems_* namespace.
+
+ * libblock/include/rtems/diskdevs.h,
+ cpukit/libblock/src/diskdevs.c: Move to rtems_* namespace. Add a
+ capabilities field for drivers. Change rtems_disk_lookup to
+ rtems_disk_obtain to match the release call. You do not lookup and
+ release a disk, you obtain and release a disk.
+
+ * libblock/include/rtems/ide_part_table.h,
+ libblock/include/rtems/ramdisk.h, libblock/src/ide_part_table.c:
+ Move to rtems_* namespace.
+
+ * libblock/include/rtems/nvdisk.h: Formatting change.
+
+ * libblock/src/blkdev.c: Move to rtems_* namespace. Change
+ rtems_disk_lookup to rtems_disk_obtain
+
+ * libblock/src/flashdisk.c: Move to rtems_* namespace. Use the new
+ support for the block number in the scatter/grather request
+ struct. This allows non-continuous buffer requests for those
+ drivers that can support increasing performance.
+
+ * libblock/src/nvdisk.c: Move to rtems_* namespace. Removed
+ warnings. Added better error checking. Fixed some comments.
+
+ * libblock/src/ramdisk.c: Move to rtems_* namespace. Added some
+ trace functions to help debugging upper layers. Use the new
+ support for the block number in the scatter/grather request
+ struct. This allows non-continuous buffer requests for those
+ drivers that can support increasing performance.
+
+ * libfs/src/dosfs/fat.c, libfs/src/dosfs/fat.h: Use new chains
+ API. Removed temporary hack and changed
+ set_errno_and_return_minus_one to
+ rtems_set_errno_and_return_minus_one. Move fat_buf_access from
+ header and stopped it being inlined. Updated to libblock changes.
+
+ * libfs/src/dosfs/fat_fat_operations.c,
+ libfs/src/dosfs/fat_file.c, libfs/src/dosfs/msdos_create.c,
+ libfs/src/dosfs/msdos_dir.c, libfs/src/dosfs/msdos_eval.c,
+ libfs/src/dosfs/msdos_file.c, libfs/src/dosfs/msdos_format.c,
+ libfs/src/dosfs/msdos_free.c, libfs/src/dosfs/msdos_initsupp.c,
+ libfs/src/dosfs/msdos_misc.c, libfs/src/dosfs/msdos_mknod.c: Use
+ new chains API. Removed temporary hack and changed
+ set_errno_and_return_minus_one to
+ rtems_set_errno_and_return_minus_one. Updated to libblock changes.
+
+ * libmisc/Makefile.am: Add new ls and rm command files.
+
+ * libmisc/shell/cmp-ls.c, libmisc/shell/extern-ls.h,
+ libmisc/shell/filemode.c, libmisc/shell/print-ls.c,
+ libmisc/shell/pwcache.c, libmisc/shell/utils-ls.c,
+ libmisc/shell/vis.c, shell/vis.h: New.
+
+ * libmisc/shell/extern-cp.h, libmisc/shell/main_cp.c,
+ libmisc/shell/utils-cp.c: Fixed the usage call bug.
+
+ * libmisc/shell/main_blksync.c: Updated to the new block IO ioctl
+ command.
+
+ * libmisc/shell/main_ls.c, libmisc/shell/main_rm.c: Updated to BSD
+ commands with more features.
+
+ * score/src/coremutex.c: Fix the strick order mutex code.
+
+ * libmisc/shell/shell.c: Change shell tasks mode to be timeslice
+ and no ASR.
+
+ * sapi/include/confdefs.h: Change ata_driver_task_priority to
+ rtems_ata_driver_task_priority. Add the new BD buf cache
+ parameters with defaults.
+
+ * score/src/interr.c: Do not return if the CPU halt call returns.
+
2008-07-24 Sebastian Huber <sebastian.huber@embedded-brains.de>
* libcsupport/include/rtems/libcsupport.h: Moved declaration of
diff --git a/cpukit/libblock/Makefile.am b/cpukit/libblock/Makefile.am
index f48a5d977c..6da4ead942 100644
--- a/cpukit/libblock/Makefile.am
+++ b/cpukit/libblock/Makefile.am
@@ -8,7 +8,7 @@ include $(top_srcdir)/automake/compile.am
if !UNIX
noinst_LIBRARIES = libblock.a
libblock_a_SOURCES = src/bdbuf.c src/blkdev.c src/diskdevs.c src/flashdisk.c \
- src/ramdisk.c src/ide_part_table.c src/show_bdbuf.c src/nvdisk.c \
+ src/ramdisk.c src/ide_part_table.c src/nvdisk.c \
src/nvdisk-sram.c \
include/rtems/bdbuf.h include/rtems/blkdev.h \
include/rtems/diskdevs.h include/rtems/flashdisk.h \
diff --git a/cpukit/libblock/include/rtems/bdbuf.h b/cpukit/libblock/include/rtems/bdbuf.h
index f4308963dd..991da1fdaa 100644
--- a/cpukit/libblock/include/rtems/bdbuf.h
+++ b/cpukit/libblock/include/rtems/bdbuf.h
@@ -25,116 +25,143 @@ extern "C" {
#include "rtems/blkdev.h"
#include "rtems/diskdevs.h"
-
-/*
- * To manage buffers we using Buffer Descriptors.
- * To speed-up buffer lookup descriptors are organized in AVL-Tree.
- * The fields 'dev' and 'block' are search key.
+/**
+ * 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_buf_state;
-/* Buffer descriptors
- * Descriptors organized in AVL-tree to speedup buffer lookup.
- * dev and block fields are search key in AVL-tree.
- * Modified buffers, free buffers and used buffers linked in 'mod', 'free' and
- * 'lru' chains appropriately.
+/**
+ * To manage buffers we using buffer descriptors (BD). A BD holds a buffer plus
+ * a range of other information related to managing the buffer in the cache. To
+ * speed-up buffer lookup descriptors are organized in AVL-Tree. The fields
+ * 'dev' and 'block' are search keys.
*/
+typedef struct rtems_bdbuf_buffer
+{
+ rtems_chain_node link; /* Link in the BD onto a number of lists. */
-typedef struct bdbuf_buffer {
- Chain_Node link; /* Link in the lru, mod or free chains */
-
- struct bdbuf_avl_node {
- signed char cache; /* Cache */
+ 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 */
+ } avl;
- struct bdbuf_buffer* left; /* Left Child */
- struct bdbuf_buffer* right; /* Right Child */
+ dev_t dev; /* device number */
+ rtems_blkdev_bnum block; /* block number on the device */
- signed char bal; /* The balance of the sub-tree */
- } avl;
+ 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 */
- dev_t dev; /* device number */
- blkdev_bnum block; /* block number on the device */
+ volatile rtems_bdbuf_buf_state state; /* State of the buffer. */
- unsigned char *buffer; /* Pointer to the buffer memory area */
- rtems_status_code status; /* Last I/O operation completion status */
- int error; /* If status != RTEMS_SUCCESSFUL, this field contains
- errno value which can be used by user later */
- boolean modified:1; /* =1 if buffer was modified */
- boolean in_progress:1; /* =1 if exchange with disk is in progress;
- need to wait on semaphore */
- boolean actual:1; /* Buffer contains actual data */
- int use_count; /* Usage counter; incremented when somebody use
- this buffer; decremented when buffer released
- without modification or when buffer is flushed
- by swapout task */
+ volatile uint32_t waiters; /* The number of threads waiting on this
+ * buffer. */
+ rtems_bdpool_id pool; /* Identifier of buffer pool to which this buffer
+ belongs */
- rtems_bdpool_id pool; /* Identifier of buffer pool to which this buffer
- belongs */
- CORE_mutex_Control transfer_sema;
- /* Transfer operation semaphore */
-} bdbuf_buffer;
+ volatile uint32_t hold_timer; /* Timer to indicate how long a buffer
+ * has been held in the cache modified. */
+} rtems_bdbuf_buffer;
+/**
+ * The groups of the blocks with the same size are collected in a pool. Note
+ * that a several of the buffer's groups with the same size can exists.
+ */
+typedef struct rtems_bdbuf_pool
+{
+ int blksize; /* The size of the blocks (in bytes) */
+ int nblks; /* Number of blocks in this pool */
+
+ uint32_t flags; /* Configuration flags */
+
+ rtems_id lock; /* The pool lock. Lock this data and
+ * all BDs. */
+ rtems_id sync_lock; /* Sync calls lock writes. */
+ boolean 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
+ * 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_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
+ * TRANSFER state. */
+ 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. */
+
+ rtems_bdbuf_buffer* bds; /* Pointer to table of buffer descriptors
+ * allocated for this buffer pool. */
+ void* buffers; /* The buffer's memory. */
+} rtems_bdbuf_pool;
-/*
- * the following data structures are internal to the bdbuf layer,
- * but it is convenient to have them visible from the outside for inspection
+/**
+ * Configuration structure describes block configuration (size, amount, memory
+ * location) for buffering layer pool.
*/
-/*
- * The groups of the blocks with the same size are collected in the
- * bd_pool. Note that a several of the buffer's groups with the
- * same size can exists.
+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
+ * 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.
*/
-typedef struct bdbuf_pool
-{
- bdbuf_buffer *tree; /* Buffer descriptor lookup AVL tree root */
-
- Chain_Control free; /* Free buffers list */
- Chain_Control lru; /* Last recently used list */
-
- int blksize; /* The size of the blocks (in bytes) */
- int nblks; /* Number of blocks in this pool */
- rtems_id bufget_sema; /* Buffer obtain counting semaphore */
- void *mallocd_bufs; /* Pointer to the malloc'd buffer memory,
- or NULL, if buffer memory provided in
- buffer configuration */
- bdbuf_buffer *bdbufs; /* Pointer to table of buffer descriptors
- allocated for this buffer pool. */
-} bdbuf_pool;
-
-/* Buffering layer context definition */
-struct bdbuf_context {
- bdbuf_pool *pool; /* Table of buffer pools */
- int npools; /* Number of entries in pool table */
-
- Chain_Control mod; /* Modified buffers list */
- rtems_id flush_sema; /* Buffer flush semaphore; counting
- semaphore; incremented when buffer
- flushed to the disk; decremented when
- buffer modified */
- rtems_id swapout_task; /* Swapout task ID */
-};
- /*
- * the context of the buffering layer, visible for inspection
- */
-extern struct bdbuf_context rtems_bdbuf_ctx;
-
-/* bdbuf_config structure describes block configuration (size,
- * amount, memory location) for buffering layer
+extern rtems_bdbuf_pool_config rtems_bdbuf_pool_configuration[];
+extern int rtems_bdbuf_pool_configuration_size;
+
+/**
+ * Buffering configuration definition. See confdefs.h for support on using this
+ * structure.
*/
typedef struct rtems_bdbuf_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
- case memory for blocks will be allocated by
- Buffering Layer with the help of RTEMS partition
- manager */
+ int max_read_ahead_blocks; /*<< Number of blocks to read ahead. */
+ int 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;
-extern rtems_bdbuf_config rtems_bdbuf_configuration[];
-extern int rtems_bdbuf_configuration_size;
+/**
+ * External referernce to the configuration. The configuration is provided by
+ * the user.
+ */
+extern rtems_bdbuf_config rtems_bdbuf_configuration;
-#define SWAPOUT_TASK_DEFAULT_PRIORITY 15
-extern rtems_task_priority swapout_task_priority;
+/**
+ * The max_read_ahead_blocks value is altered if there are fewer buffers
+ * than this defined max. This stops thrashing in the cache.
+ */
+#define RTEMS_BDBUF_MAX_READ_AHEAD_BLOCKS_DEFAULT 32
+#define RTEMS_BDBUF_MAX_WRITE_BLOCKS_DEFAULT 16
+#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 */
/* rtems_bdbuf_init --
* Prepare buffering layer to work - initialize buffer descritors
@@ -143,17 +170,12 @@ extern rtems_task_priority swapout_task_priority;
* amount requested. After initialization all blocks is placed into
* free elements lists.
*
- * PARAMETERS:
- * conf_table - pointer to the buffers configuration table
- * size - number of entries in configuration table
- *
* RETURNS:
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
* or error code if error is occured)
*/
rtems_status_code
-rtems_bdbuf_init(rtems_bdbuf_config *conf_table, int size);
-
+rtems_bdbuf_init ();
/* rtems_bdbuf_get --
* Obtain block buffer. If specified block already cached (i.e. there's
@@ -177,8 +199,8 @@ rtems_bdbuf_init(rtems_bdbuf_config *conf_table, int size);
* SIDE EFFECTS:
* bufget_sema semaphore obtained by this primitive.
*/
-rtems_status_code
-rtems_bdbuf_get(dev_t device, blkdev_bnum block, bdbuf_buffer **bdb_ptr);
+ rtems_status_code
+ rtems_bdbuf_get(dev_t device, rtems_blkdev_bnum block, rtems_bdbuf_buffer** bd);
/* rtems_bdbuf_read --
* (Similar to the rtems_bdbuf_get, except reading data from media)
@@ -201,8 +223,8 @@ rtems_bdbuf_get(dev_t device, blkdev_bnum block, bdbuf_buffer **bdb_ptr);
* SIDE EFFECTS:
* bufget_sema and transfer_sema semaphores obtained by this primitive.
*/
-rtems_status_code
-rtems_bdbuf_read(dev_t device, blkdev_bnum block, bdbuf_buffer **bdb_ptr);
+ rtems_status_code
+ rtems_bdbuf_read(dev_t device, rtems_blkdev_bnum block, rtems_bdbuf_buffer** bd);
/* rtems_bdbuf_release --
* Release buffer allocated before. This primitive decrease the
@@ -223,8 +245,8 @@ rtems_bdbuf_read(dev_t device, blkdev_bnum block, bdbuf_buffer **bdb_ptr);
* SIDE EFFECTS:
* flush_sema and bufget_sema semaphores may be released by this primitive.
*/
-rtems_status_code
-rtems_bdbuf_release(bdbuf_buffer *bd_buf);
+ rtems_status_code
+ rtems_bdbuf_release(rtems_bdbuf_buffer* bd);
/* rtems_bdbuf_release_modified --
* Release buffer allocated before, assuming that it is _modified_ by
@@ -244,8 +266,8 @@ rtems_bdbuf_release(bdbuf_buffer *bd_buf);
* SIDE EFFECTS:
* flush_sema semaphore may be released by this primitive.
*/
-rtems_status_code
-rtems_bdbuf_release_modified(bdbuf_buffer *bd_buf);
+ rtems_status_code
+ rtems_bdbuf_release_modified(rtems_bdbuf_buffer* bd);
/* rtems_bdbuf_sync --
* Wait until specified buffer synchronized with disk. Invoked on exchanges
@@ -265,8 +287,8 @@ rtems_bdbuf_release_modified(bdbuf_buffer *bd_buf);
* SIDE EFFECTS:
* Primitive may be blocked on transfer_sema semaphore.
*/
-rtems_status_code
-rtems_bdbuf_sync(bdbuf_buffer *bd_buf);
+ rtems_status_code
+ rtems_bdbuf_sync(rtems_bdbuf_buffer* bd);
/* rtems_bdbuf_syncdev --
* Synchronize with disk all buffers containing the blocks belonging to
@@ -279,8 +301,8 @@ rtems_bdbuf_sync(bdbuf_buffer *bd_buf);
* 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);
+ rtems_status_code
+ rtems_bdbuf_syncdev(dev_t dev);
/* rtems_bdbuf_find_pool --
* Find first appropriate buffer pool. This primitive returns the index
@@ -297,8 +319,8 @@ rtems_bdbuf_syncdev(dev_t dev);
* of 2), RTEMS_NOT_DEFINED if buffer pool for this or greater block size
* is not configured.
*/
-rtems_status_code
-rtems_bdbuf_find_pool(int block_size, rtems_bdpool_id *pool);
+ rtems_status_code
+ rtems_bdbuf_find_pool(int block_size, rtems_bdpool_id *pool);
/* rtems_bdbuf_get_pool_info --
* Obtain characteristics of buffer pool with specified number.
@@ -316,8 +338,8 @@ rtems_bdbuf_find_pool(int block_size, rtems_bdpool_id *pool);
* NOTE:
* Buffer pools enumerated contiguously 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, int *block_size, int *blocks);
#ifdef __cplusplus
}
diff --git a/cpukit/libblock/include/rtems/blkdev.h b/cpukit/libblock/include/rtems/blkdev.h
index fadbdce9c7..03b639c73c 100644
--- a/cpukit/libblock/include/rtems/blkdev.h
+++ b/cpukit/libblock/include/rtems/blkdev.h
@@ -20,67 +20,92 @@
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.
+/*
+ * 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.
*/
-
-/* Block device block number datatype */
-typedef uint32_t blkdev_bnum;
+/*
+ * Block device block number datatype
+ */
+typedef uint32_t rtems_blkdev_bnum;
/* Block device request type */
-typedef enum blkdev_request_op {
- BLKDEV_REQ_READ, /* Read operation */
- BLKDEV_REQ_WRITE /* Write operation */
-} blkdev_request_op;
+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_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
+ * hack to work around the current ATA driver.
+ */
+#define RTEMS_BLKDEV_CAP_MULTISECTOR_CONT (1 << 0)
-/* Type for block device request done callback function.
+/*
+ * @typedef rtems_blkdev_request_cb
*
- * PARAMETERS:
- * arg - argument supplied in blkdev_request
- * status - rtems status code for this operation
- * errno - errno value to be passed to the user when
+ * 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
*/
-typedef void (* blkdev_request_cb)(void *arg,
- rtems_status_code status,
- int error);
+typedef void (* rtems_blkdev_request_cb)(void *arg,
+ rtems_status_code status,
+ int error);
-/* blkdev_sg_buffer
+/**
+ * @struct rtems_blkdev_sg_buffer
* Block device scatter/gather buffer structure
*/
-typedef struct blkdev_sg_buffer {
+typedef struct rtems_blkdev_sg_buffer {
+ uint32_t block; /* The block number */
uint32_t length; /* Buffer length */
- void *buffer; /* Buffer pointer */
-} blkdev_sg_buffer;
+ void *buffer; /* Buffer pointer */
+ void *user; /* User pointer */
+} rtems_blkdev_sg_buffer;
/* blkdev_request (Block Device Request) structure is
* used to read/write a number of blocks from/to device.
*/
-typedef struct blkdev_request {
- blkdev_request_op req; /* Block device operation (read or write) */
- blkdev_request_cb req_done; /* Callback function */
- void *done_arg; /* Argument to be passed to callback function*/
- rtems_status_code status; /* Last I/O operation completion status */
- int error; /* If status != RTEMS_SUCCESSFUL, this field
- * contains error code
- */
- blkdev_bnum start; /* Start block number */
- uint32_t count; /* Number of blocks to be exchanged */
- uint32_t bufnum; /* Number of buffers provided */
-
- blkdev_sg_buffer bufs[0];/* List of scatter/gather buffers */
-} blkdev_request;
+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;
+ /* Start block number */
+ rtems_blkdev_bnum start;
+ /* Number of blocks to be exchanged */
+ uint32_t count;
+ /* Number of buffers provided */
+ uint32_t bufnum;
+
+ /* The task requesting the IO operation. */
+ rtems_id io_task;
+
+ /* List of scatter/gather buffers */
+ rtems_blkdev_sg_buffer bufs[0];
+} rtems_blkdev_request;
/* Block device IOCTL request codes */
-#define BLKIO_REQUEST _IOWR('B', 1, blkdev_request)
-#define BLKIO_GETBLKSIZE _IO('B', 2)
-#define BLKIO_GETSIZE _IO('B', 3)
-#define BLKIO_SYNCDEV _IO('B', 4)
+#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)
/* Device driver interface conventions suppose that driver may
* contain initialize/open/close/read/write/ioctl entry points. These
@@ -90,7 +115,7 @@ typedef struct blkdev_request {
* all block devices and appropriate ioctl handlers.
*/
-#define GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES \
+#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
diff --git a/cpukit/libblock/include/rtems/diskdevs.h b/cpukit/libblock/include/rtems/diskdevs.h
index 6542d74775..3517ddede2 100644
--- a/cpukit/libblock/include/rtems/diskdevs.h
+++ b/cpukit/libblock/include/rtems/diskdevs.h
@@ -21,44 +21,47 @@ extern "C" {
#include <rtems/libio.h>
#include <stdlib.h>
-#include "rtems/blkdev.h"
-
/* Buffer pool identifier */
typedef int rtems_bdpool_id;
+#include "rtems/blkdev.h"
+
+/* Driver capabilities. */
+
/* Block device ioctl handler */
-typedef int (* block_device_ioctl) (dev_t dev, uint32_t req, void *argp);
+typedef int (* rtems_block_device_ioctl) (dev_t dev, uint32_t req, void *argp);
-/* disk_device: Entry of this type created for every disk device (both for
- * logical and physical disks).
+/* 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.
*/
-typedef struct disk_device {
- dev_t dev; /* Device ID (major + minor) */
- struct disk_device *phys_dev; /* Physical device ID (the same
- as dev if this entry specifies
- the physical device) */
- char *name; /* Disk device name */
- int uses; /* Use counter. Device couldn't be
- removed if it is in use. */
- int start; /* Starting block number (0 for
- physical devices, block offset
- on the related physical device
- for logical device) */
- int size; /* Size of physical or logical disk
- in disk blocks */
- int block_size; /* Size of device block (minimum
- transfer unit) in bytes
- (must be power of 2) */
- int block_size_log2; /* log2 of block_size */
- rtems_bdpool_id pool; /* Buffer pool assigned to this
- device */
- block_device_ioctl ioctl; /* ioctl handler for this block
- device */
-} disk_device;
+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. */
+ int start; /* Starting block number (0 for
+ physical devices, block offset
+ on the related physical device
+ for logical device) */
+ int size; /* Size of physical or logical disk
+ in disk blocks */
+ int block_size; /* Size of device block (minimum
+ transfer unit) in bytes
+ (must be power of 2) */
+ int 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 */
+} rtems_disk_device;
/* rtems_disk_create_phys --
* Create physical disk entry. This function usually invoked from
@@ -84,7 +87,7 @@ typedef struct disk_device {
*/
rtems_status_code
rtems_disk_create_phys(dev_t dev, int block_size, int disk_size,
- block_device_ioctl handler,
+ rtems_block_device_ioctl handler,
const char *name);
/* rtems_disk_create_log --
@@ -131,7 +134,7 @@ rtems_disk_create_log(dev_t dev, dev_t phys, int start, int size, char *name);
rtems_status_code
rtems_disk_delete(dev_t dev);
-/* rtems_disk_lookup --
+/* 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.
@@ -143,8 +146,8 @@ rtems_disk_delete(dev_t dev);
* pointer to the block device descriptor, or NULL if no such device
* exists.
*/
-disk_device *
-rtems_disk_lookup(dev_t dev);
+rtems_disk_device *
+rtems_disk_obtain(dev_t dev);
/* rtems_disk_release --
* Release disk_device structure (decrement usage counter to 1).
@@ -159,7 +162,7 @@ rtems_disk_lookup(dev_t dev);
* It should be implemented as inline function.
*/
rtems_status_code
-rtems_disk_release(disk_device *dd);
+rtems_disk_release(rtems_disk_device *dd);
/* rtems_disk_next --
* Disk device enumerator. Looking for device having device number larger
@@ -172,7 +175,7 @@ rtems_disk_release(disk_device *dd);
* RETURNS:
* Pointer to the disk descriptor for next disk device, or NULL if all
* devices enumerated. */
-disk_device *
+rtems_disk_device *
rtems_disk_next(dev_t dev);
/* rtems_diskio_initialize --
diff --git a/cpukit/libblock/include/rtems/ide_part_table.h b/cpukit/libblock/include/rtems/ide_part_table.h
index abbbb121c4..052f445f2f 100644
--- a/cpukit/libblock/include/rtems/ide_part_table.h
+++ b/cpukit/libblock/include/rtems/ide_part_table.h
@@ -77,16 +77,18 @@
* sector_data_t --
* corresponds to the sector on the device
*/
-typedef struct sector_data_s
+typedef struct rtems_sector_data_s
{
uint32_t sector_num; /* sector number on the device */
uint8_t data[0]; /* raw sector data */
-} sector_data_t;
+} rtems_sector_data_t;
/*
* Enum partition types
* see list at http://ata-atapi.com/hiwtab.htm
+ *
+ * @todo Should these have RTEMS before them.
*/
enum {
EMPTY_PARTITION = 0x00,
@@ -108,29 +110,32 @@ enum {
/* Forward declaration */
-struct disk_desc_s;
+struct rtems_disk_desc_s;
/*
* part_desc_t --
* contains all neccessary information about partition
*/
-typedef struct part_desc_s {
+typedef struct rtems_part_desc_s {
uint8_t bootable; /* is the partition active */
uint8_t sys_type; /* type of partition */
uint8_t log_id; /* logical number of partition */
- uint32_t start; /* first partition sector, in absolute numeration */
+ uint32_t start; /* first partition sector, in absolute
+ * numeration */
uint32_t size; /* size in sectors */
uint32_t end; /* last partition sector, end = start + size - 1 */
- struct disk_desc_s *disk_desc; /* descriptor of disk, partition contains in */
- struct part_desc_s *ext_part; /* extended partition containing this one */
+ struct rtems_disk_desc_s *disk_desc; /* descriptor of disk, partition
+ * contains in */
+ struct rtems_part_desc_s *ext_part; /* extended partition containing this
+ * one */
/* partitions, containing in this one */
- struct part_desc_s *sub_part[RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER];
-} part_desc_t;
+ struct rtems_part_desc_s *sub_part[RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER];
+} rtems_part_desc_t;
-typedef struct disk_desc_s {
+typedef struct rtems_disk_desc_s {
dev_t dev; /* device number */
/* device name in /dev filesystem */
@@ -142,8 +147,8 @@ typedef struct disk_desc_s {
int last_log_id; /* used for logical disks enumerating */
/* primary partition descriptors */
- part_desc_t *partitions[RTEMS_IDE_PARTITION_MAX_PARTITION_NUMBER];
-} disk_desc_t;
+ rtems_part_desc_t *partitions[RTEMS_IDE_PARTITION_MAX_PARTITION_NUMBER];
+} rtems_disk_desc_t;
#ifdef __cplusplus
extern "C" {
@@ -160,7 +165,7 @@ extern "C" {
* N/A
*/
void
-rtems_ide_part_table_free(disk_desc_t *disk_desc);
+rtems_ide_part_table_free(rtems_disk_desc_t *disk_desc);
/*
@@ -176,7 +181,7 @@ rtems_ide_part_table_free(disk_desc_t *disk_desc);
* RTEMS_SUCCESSFUL if success, or -1 and corresponding errno else
*/
rtems_status_code
-rtems_ide_part_table_get(const char *dev_name, disk_desc_t *disk_desc);
+rtems_ide_part_table_get(const char *dev_name, rtems_disk_desc_t *disk_desc);
/*
diff --git a/cpukit/libblock/include/rtems/nvdisk.h b/cpukit/libblock/include/rtems/nvdisk.h
index 5e2a0dd6af..24b62f665e 100644
--- a/cpukit/libblock/include/rtems/nvdisk.h
+++ b/cpukit/libblock/include/rtems/nvdisk.h
@@ -164,7 +164,7 @@ typedef struct rtems_nvdisk_config
const rtems_nvdisk_device_desc* devices; /**< The device descriptions. */
uint32_t flags; /**< Set of flags to control
driver. */
- uint32_t info_level; /**< Default info level. */
+ uint32_t info_level; /**< Default info level. */
} rtems_nvdisk_config;
/*
diff --git a/cpukit/libblock/include/rtems/ramdisk.h b/cpukit/libblock/include/rtems/ramdisk.h
index 64d9bad5e7..8fcc442d32 100644
--- a/cpukit/libblock/include/rtems/ramdisk.h
+++ b/cpukit/libblock/include/rtems/ramdisk.h
@@ -1,56 +1,56 @@
-/**
- * @file rtems/ramdisk.h
- * RAM disk block device implementation
- */
-
-/*
- * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
- * Author: Victor V. Vengerov <vvv@oktet.ru>
- *
- * @(#) $Id$
- */
-
-#ifndef _RTEMS_RAMDISK_H
-#define _RTEMS_RAMDISK_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <rtems.h>
-
-#include "rtems/blkdev.h"
-
-/* RAM disk configuration table entry */
-typedef struct rtems_ramdisk_config {
- int block_size; /* RAM disk block size */
- int block_num; /* Number of blocks on this RAM disk */
- void *location; /* RAM disk permanent location (out of RTEMS controlled
- memory), or NULL if RAM disk memory should be
- allocated dynamically */
-} rtems_ramdisk_config;
-
-/* If application want to use RAM disk, it should specify configuration of
- * available RAM disks.
- * The following is definitions for RAM disk configuration table
- */
-extern rtems_ramdisk_config rtems_ramdisk_configuration[];
-extern size_t rtems_ramdisk_configuration_size;
-
-/* ramdisk_initialize --
- * RAM disk driver initialization entry point.
- */
-rtems_device_driver
-ramdisk_initialize(
- rtems_device_major_number major,
- rtems_device_minor_number minor,
- void *arg);
-
-#define RAMDISK_DRIVER_TABLE_ENTRY \
- { ramdisk_initialize, GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES }
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/**
+ * @file rtems/ramdisk.h
+ * RAM disk block device implementation
+ */
+
+/*
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Victor V. Vengerov <vvv@oktet.ru>
+ *
+ * @(#) $Id$
+ */
+
+#ifndef _RTEMS_RAMDISK_H
+#define _RTEMS_RAMDISK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+
+#include "rtems/blkdev.h"
+
+/* RAM disk configuration table entry */
+typedef struct rtems_ramdisk_config {
+ int block_size; /* RAM disk block size */
+ int block_num; /* Number of blocks on this RAM disk */
+ void *location; /* RAM disk permanent location (out of RTEMS controlled
+ memory), or NULL if RAM disk memory should be
+ allocated dynamically */
+} rtems_ramdisk_config;
+
+/* If application want to use RAM disk, it should specify configuration of
+ * available RAM disks.
+ * The following is definitions for RAM disk configuration table
+ */
+extern rtems_ramdisk_config rtems_ramdisk_configuration[];
+extern size_t rtems_ramdisk_configuration_size;
+
+/* ramdisk_initialize --
+ * RAM disk driver initialization entry point.
+ */
+rtems_device_driver
+ramdisk_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg);
+
+#define RAMDISK_DRIVER_TABLE_ENTRY \
+ { ramdisk_initialize, RTEMS_GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libblock/src/bdbuf.c b/cpukit/libblock/src/bdbuf.c
index 17c710a668..07669d0c9e 100644
--- a/cpukit/libblock/src/bdbuf.c
+++ b/cpukit/libblock/src/bdbuf.c
@@ -10,657 +10,912 @@
* @(#) bdbuf.c,v 1.14 2004/04/17 08:15:17 ralf Exp
*/
+/**
+ * @file
+ *
+ * The Buffer Descriptor Buffer code implement a cache between the disk
+ * devices and file systems. The code provides a read ahead and qrite 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
+ * +-------------------------------+
+ * | v
+ * +-----------+ read complete +------------+
+ * | | write complete | |---------+
+ * | EMPTY | +---------| TRANSFER | |
+ * | | | | |<--+ |
+ * +-----------+ | +------------+ | |
+ * ^ | get v swap | |
+ * | | +-----------+ modified +------------+ |
+ * | +--->| |---------->| | |
+ * | | ACCESSED |<----------| MODIFIED | |
+ * | +----| |<--+ get | | |
+ * | | +-----------+ | +------------+ |
+ * | | | |
+ * | | release get | |
+ * | | | |
+ * | | +-----------+ | |
+ * expire | +--->| |---+ read complete |
+ * | | CACHED | write complete |
+ * +--------| |<-------------------------+
+ * +-----------+
+ *
+ * Empty buffers are added to the empty list and removed from this queue when a
+ * caller wishes to access a buffer. This is referred to 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. If the block is to be read by the user and
+ * not in the cache (empty) it is transfered from the disk into memory. If no
+ * empty buffers exist the buffer is expired from the cache. Currently the
+ * least recently used block is expired first. A block being accessed is given
+ * to the file system layer and not accessable to another requester until
+ * released back to the cache. If the user has modifed the block it is
+ * transfered to disk then placed on the LRU list.
+ *
+ * The pool have the following lists of buffers:
+ *
+ * empty - Empty buffers created when the pool is initialised.
+ * modided - Buffers waiting to be written to disk.
+ * cached_lru - Accessed buffers released in least recently used order.
+ * cached_unsed - Read ahead buffers that have not been accessed.
+ *
+ */
+
+/**
+ * Set to 1 to enable debug tracing.
+ */
+#define RTEMS_BDBUF_TRACE 0
+
#if HAVE_CONFIG_H
#include "config.h"
#endif
-#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
#include <rtems.h>
+#include <rtems/error.h>
#include <limits.h>
#include <errno.h>
#include <assert.h>
-#include "rtems/bdbuf.h"
-
-/* Fatal errors: */
-#define BLKDEV_FATAL_ERROR(n) (((uint32_t)'B' << 24) | ((uint32_t)(n) & (uint32_t)0x00FFFFFF))
-#define BLKDEV_FATAL_BDBUF_CONSISTENCY BLKDEV_FATAL_ERROR(1)
-#define BLKDEV_FATAL_BDBUF_SWAPOUT BLKDEV_FATAL_ERROR(2)
-
-
-#define SWAPOUT_TASK_STACK_SIZE (RTEMS_MINIMUM_STACK_SIZE * 2)
-
-#define READ_MULTIPLE
-
-#if defined(READ_MULTIPLE)
-#define READ_AHEAD_MAX_BLK_CNT 32
-typedef struct {
- blkdev_request req;
- blkdev_sg_buffer sg[READ_AHEAD_MAX_BLK_CNT];
-} blkdev_request_read_ahead;
-/*
- * list of bd_bufs related to one transfer request
- */
-typedef struct {
- int cnt;
- bdbuf_buffer *bd_bufs[READ_AHEAD_MAX_BLK_CNT];
-} read_ahead_bd_buf_group;
+#if RTEMS_BDBUF_TRACE
+#include <stdio.h>
#endif
-typedef struct {
- blkdev_request *req;
- bdbuf_buffer **write_store;
-} write_tfer_done_arg_t;
-
-static rtems_task bdbuf_swapout_task(rtems_task_argument unused);
+#include "rtems/bdbuf.h"
-static rtems_status_code bdbuf_release(bdbuf_buffer *bd_buf);
-/*
- * maximum number of blocks that might be chained together to one
- * write driver call
+/**
+ * The BD buffer context.
*/
-#define SWAP_OUT_MAX_BLK_CNT 32
-/*#define SWAP_OUT_MAX_BLK_CNT 1 */
-/*
- * XXX: this is a global buffer. It is used in the swapout task
- * and currently will be reused only after it is no longer in use
- *
+/* Buffering layer context definition */
+typedef struct rtems_bdbuf_context {
+ rtems_bdbuf_pool* pool; /* Table of buffer pools */
+ int npools; /* Number of entries in pool table */
+ rtems_id swapout; /* Swapout task ID */
+ boolean swapout_enabled;
+} rtems_bdbuf_context;
+
+/**
+ * Fatal errors
*/
-static bdbuf_buffer *bd_buf_write_store[SWAP_OUT_MAX_BLK_CNT];
-
-/* Block device request with a single buffer provided */
-typedef struct blkdev_request1 {
- blkdev_request req;
- blkdev_sg_buffer sg[1];
-} blkdev_request1;
-
-/* The context of buffering layer */
-struct bdbuf_context rtems_bdbuf_ctx;
-
-#define SAFE
-#ifdef SAFE
-typedef rtems_mode preemption_key;
-
-#define DISABLE_PREEMPTION(key) \
- do { \
- rtems_task_mode(RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &(key)); \
- } while (0)
-
-#define ENABLE_PREEMPTION(key) \
- do { \
- rtems_mode temp; \
- rtems_task_mode((key), RTEMS_PREEMPT_MASK, &temp); \
- } while (0)
-
-#else
+#define RTEMS_BLKDEV_FATAL_ERROR(n) (((uint32_t)'B' << 24) | \
+ ((uint32_t)(n) & (uint32_t)0x00FFFFFF))
+
+#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY RTEMS_BLKDEV_FATAL_ERROR(1)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SWAPOUT RTEMS_BLKDEV_FATAL_ERROR(2)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SYNC_LOCK RTEMS_BLKDEV_FATAL_ERROR(3)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SYNC_UNLOCK RTEMS_BLKDEV_FATAL_ERROR(4)
+#define RTEMS_BLKDEV_FATAL_BDBUF_POOL_LOCK RTEMS_BLKDEV_FATAL_ERROR(5)
+#define RTEMS_BLKDEV_FATAL_BDBUF_POOL_UNLOCK RTEMS_BLKDEV_FATAL_ERROR(6)
+#define RTEMS_BLKDEV_FATAL_BDBUF_POOL_WAIT RTEMS_BLKDEV_FATAL_ERROR(7)
+#define RTEMS_BLKDEV_FATAL_BDBUF_POOL_WAKE RTEMS_BLKDEV_FATAL_ERROR(8)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WAKE RTEMS_BLKDEV_FATAL_ERROR(9)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SO_NOMEM RTEMS_BLKDEV_FATAL_ERROR(10)
+#define BLKDEV_FATAL_BDBUF_SWAPOUT_RE RTEMS_BLKDEV_FATAL_ERROR(11)
+#define BLKDEV_FATAL_BDBUF_SWAPOUT_TS RTEMS_BLKDEV_FATAL_ERROR(12)
+
+#define RTEMS_BDBUF_TRANSFER_SYNC RTEMS_EVENT_1
+#define RTEMS_BDBUF_SWAPOUT_SYNC RTEMS_EVENT_2
+
+#define SWAPOUT_TASK_STACK_SIZE (8 * 1024)
+
+/**
+ * Lock semaphore attributes. This is used for locking type mutexes.
+ */
+#define RTEMS_BDBUF_POOL_LOCK_ATTRIBS \
+ (RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | \
+ RTEMS_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL)
-typedef boolean preemption_key;
+/**
+ * Waiter semaphore attributes.
+ *
+ * @note Do not configure as inherit priority. If a driver is in the driver
+ * initialisation table this locked semaphore will have the IDLE task as
+ * the holder and a blocking task will raise the priority of the IDLE
+ * task which can cause unsual side effects.
+ */
+#define RTEMS_BDBUF_POOL_WAITER_ATTRIBS \
+ (RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | \
+ RTEMS_NO_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL)
-#define DISABLE_PREEMPTION(key) \
- do { \
- (key) = _Thread_Executing->is_preemptible; \
- _Thread_Executing->is_preemptible = 0; \
- } while (0)
+/*
+ * The swap out task.
+ */
+static rtems_task rtems_bdbuf_swapout_task(rtems_task_argument arg);
-#define ENABLE_PREEMPTION(key) \
- do { \
- _Thread_Executing->is_preemptible = (key); \
- if (_Thread_Evaluate_mode()) \
- _Thread_Dispatch(); \
- } while (0)
+/**
+ * The context of buffering layer.
+ */
+static rtems_bdbuf_context rtems_bdbuf_ctx;
+/**
+ * Print a message to the bdbuf trace output and flush it.
+ *
+ * @param format The format string. See printf for details.
+ * @param ... The arguments for the format text.
+ * @return int The number of bytes written to the output.
+ */
+#if RTEMS_BDBUF_TRACE
+boolean rtems_bdbuf_tracer;
+static void
+rtems_bdbuf_printf (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ if (rtems_bdbuf_tracer)
+ {
+ fprintf (stdout, "bdbuf:");
+ vfprintf (stdout, format, args);
+ fflush (stdout);
+ }
+}
#endif
-
-/* The default maximum height of 32 allows for AVL trees having
- between 5,704,880 and 4,294,967,295 nodes, depending on order of
- insertion. You may change this compile-time constant as you
- wish. */
-#ifndef AVL_MAX_HEIGHT
-#define AVL_MAX_HEIGHT 32
+/**
+ * The default maximum height of 32 allows for AVL trees having between
+ * 5,704,880 and 4,294,967,295 nodes, depending on order of insertion. You may
+ * change this compile-time constant as you wish.
+ */
+#ifndef RTEMS_BDBUF_AVL_MAX_HEIGHT
+#define RTEMS_BDBUF_AVL_MAX_HEIGHT (32)
#endif
-/*
- * avl_search --
- * Searches for the node with specified dev/block.
- *
- * PARAMETERS:
- * root - pointer to the root node of the AVL-Tree.
- * dev, block - search key
+/**
+ * Searches for the node with specified dev/block.
*
- * RETURNS:
- * NULL if node with specified dev/block not found
- * non-NULL - pointer to the node with specified dev/block
+ * @param root pointer to the root node of the AVL-Tree
+ * @param dev device search key
+ * @param block block search key
+ * @retval NULL node with the specified dev/block is not found
+ * @return pointer to the node with specified dev/block
*/
-static bdbuf_buffer *
-avl_search(bdbuf_buffer **root, dev_t dev, blkdev_bnum block)
+static rtems_bdbuf_buffer *
+rtems_bdbuf_avl_search (rtems_bdbuf_buffer** root,
+ dev_t dev,
+ rtems_blkdev_bnum block)
{
- bdbuf_buffer *p = *root;
+ rtems_bdbuf_buffer* p = *root;
- while ((p != NULL) && ((p->dev != dev) || (p->block != block)))
+ while ((p != NULL) && ((p->dev != dev) || (p->block != block)))
+ {
+ if ((p->dev < dev) || ((p->dev == dev) && (p->block < block)))
{
- if ((p->dev < dev) || ((p->dev == dev) && (p->block < block)))
- {
- p = p->avl.right;
- }
- else
- {
- p = p->avl.left;
- }
+ p = p->avl.right;
+ }
+ else
+ {
+ p = p->avl.left;
}
+ }
- return p;
+ return p;
}
-
-/* avl_search_for_sync --
- * Search in AVL tree for first modified buffer belongs to specified
- * disk device.
+#if CCJ_REMOVE_IN_IN_CVS
+/**
+ * Search in AVL tree for first modified buffer belongs to specified
+ * disk device.
*
- * PARAMETERS:
- * root - pointer to tree root
- * dd - disk device descriptor
- *
- * RETURNS:
- * Block buffer, or NULL if no modified blocks on specified device
- * exists.
+ * @param root pointer to the root node of the AVL-Tree
+ * @param dd - disk device descriptor
+ * @retval NULL no modified blocks on the disk device
+ * @return pointer to the modified node
*/
-static bdbuf_buffer *
-avl_search_for_sync(bdbuf_buffer **root, disk_device *dd)
+static rtems_bdbuf_buffer *
+rtems_bdbuf_avl_search_for_sync (rtems_bdbuf_buffer** root,
+ rtems_disk_device* dd)
{
- dev_t dev = dd->phys_dev->dev;
- blkdev_bnum block_start = dd->start;
- blkdev_bnum block_end = dd->start + dd->size - 1;
-
- bdbuf_buffer *buf_stack[AVL_MAX_HEIGHT];
- bdbuf_buffer **buf_prev = buf_stack;
- bdbuf_buffer *p = *root;
-
- while (p != NULL)
+ dev_t dev = dd->phys_dev->dev;
+ rtems_blkdev_bnum block_start = dd->start;
+ rtems_blkdev_bnum block_end = dd->start + dd->size - 1;
+ rtems_bdbuf_buffer* buf_stack[RTEMS_BDBUF_AVL_MAX_HEIGHT];
+ rtems_bdbuf_buffer** buf_prev = buf_stack;
+ rtems_bdbuf_buffer* p = *root;
+
+ while (p != NULL)
+ {
+ if ((p->dev < dev) || ((p->dev == dev) && (p->block < block_start)))
{
- if ((p->dev < dev) || ((p->dev == dev) && (p->block < block_start)))
- {
- p = p->avl.right;
- }
- else if ((p->dev > dev) || ((p->dev == dev) && (p->block > block_end)))
- {
- p = p->avl.left;
- }
- else if (p->modified)
- {
- return p;
- }
- else
- {
- if (p->avl.right != NULL)
- {
- *buf_prev++ = p->avl.right;
- }
- p = p->avl.left;
- }
+ p = p->avl.right;
+ }
+ else if ((p->dev > dev) || ((p->dev == dev) && (p->block > block_end)))
+ {
+ p = p->avl.left;
+ }
+ else if (p->state == RTEMS_BDBUF_STATE_MODIFIED)
+ {
+ return p;
+ }
+ else
+ {
+ if (p->avl.right != NULL)
+ {
+ *buf_prev++ = p->avl.right;
+ }
+ p = p->avl.left;
+ }
- if ((p == NULL) && (buf_prev > buf_stack))
- {
- p = *--buf_prev;
- }
+ if ((p == NULL) && (buf_prev > buf_stack))
+ {
+ p = *--buf_prev;
}
+ }
- return p;
+ return p;
}
+#endif
-
-/*
- * avl_insert --
- * Inserts the specified node to the AVl-Tree.
- *
- * PARAMETERS:
- * root - Pointer to pointer to the root node
- * node - Pointer to the node to add.
+/**
+ * Inserts the specified node to the AVl-Tree.
*
- * RETURNS:
- * 0 - The node added successfully
- * -1 - An error occured
+ * @param root pointer to the root node of the AVL-Tree
+ * @param node Pointer to the node to add.
+ * @retval 0 The node added successfully
+ * @retval -1 An error occured
*/
static int
-avl_insert(bdbuf_buffer **root, bdbuf_buffer *node)
+rtems_bdbuf_avl_insert(rtems_bdbuf_buffer** root,
+ rtems_bdbuf_buffer* node)
{
- dev_t dev = node->dev;
- blkdev_bnum block = node->block;
-
- bdbuf_buffer *p = *root;
- bdbuf_buffer *q, *p1, *p2;
- bdbuf_buffer *buf_stack[AVL_MAX_HEIGHT];
- bdbuf_buffer **buf_prev = buf_stack;
+ dev_t dev = node->dev;
+ rtems_blkdev_bnum block = node->block;
+
+ rtems_bdbuf_buffer* p = *root;
+ rtems_bdbuf_buffer* q;
+ rtems_bdbuf_buffer* p1;
+ rtems_bdbuf_buffer* p2;
+ rtems_bdbuf_buffer* buf_stack[RTEMS_BDBUF_AVL_MAX_HEIGHT];
+ rtems_bdbuf_buffer** buf_prev = buf_stack;
+
+ boolean modified = FALSE;
+
+ if (p == NULL)
+ {
+ *root = node;
+ node->avl.left = NULL;
+ node->avl.right = NULL;
+ node->avl.bal = 0;
+ return 0;
+ }
- boolean modified = FALSE;
+ while (p != NULL)
+ {
+ *buf_prev++ = p;
- if (p == NULL)
+ if ((p->dev < dev) || ((p->dev == dev) && (p->block < block)))
{
- *root = node;
- node->avl.left = NULL;
- node->avl.right = NULL;
- node->avl.bal = 0;
- return 0;
+ p->avl.cache = 1;
+ q = p->avl.right;
+ if (q == NULL)
+ {
+ q = node;
+ p->avl.right = q = node;
+ break;
+ }
}
-
- while (p != NULL)
+ else if ((p->dev != dev) || (p->block != block))
{
- *buf_prev++ = p;
-
- if ((p->dev < dev) || ((p->dev == dev) && (p->block < block)))
- {
- p->avl.cache = 1;
- q = p->avl.right;
- if (q == NULL)
- {
- q = node;
- p->avl.right = q = node;
- break;
- }
- }
- else if ((p->dev != dev) || (p->block != block))
- {
- p->avl.cache = -1;
- q = p->avl.left;
- if (q == NULL)
- {
- q = node;
- p->avl.left = q;
- break;
- }
- }
- else
- {
- return -1;
- }
-
- p = q;
+ p->avl.cache = -1;
+ q = p->avl.left;
+ if (q == NULL)
+ {
+ q = node;
+ p->avl.left = q;
+ break;
+ }
+ }
+ else
+ {
+ return -1;
}
- q->avl.left = q->avl.right = NULL;
- q->avl.bal = 0;
- modified = TRUE;
- buf_prev--;
+ p = q;
+ }
- while (modified)
- {
- if (p->avl.cache == -1)
- {
- switch (p->avl.bal)
- {
- case 1:
- p->avl.bal = 0;
- modified = FALSE;
- break;
-
- case 0:
- p->avl.bal = -1;
- break;
-
- case -1:
- p1 = p->avl.left;
- if (p1->avl.bal == -1) /* simple LL-turn */
- {
- p->avl.left = p1->avl.right;
- p1->avl.right = p;
- p->avl.bal = 0;
- p = p1;
- }
- else /* double LR-turn */
- {
- p2 = p1->avl.right;
- p1->avl.right = p2->avl.left;
- p2->avl.left = p1;
- p->avl.left = p2->avl.right;
- p2->avl.right = p;
- if (p2->avl.bal == -1) p->avl.bal = +1; else p->avl.bal = 0;
- if (p2->avl.bal == +1) p1->avl.bal = -1; else p1->avl.bal = 0;
- p = p2;
- }
- p->avl.bal = 0;
- modified = FALSE;
- break;
-
- default:
- break;
- }
- }
- else
- {
- switch (p->avl.bal)
- {
- case -1:
- p->avl.bal = 0;
- modified = FALSE;
- break;
-
- case 0:
- p->avl.bal = 1;
- break;
-
- case 1:
- p1 = p->avl.right;
- if (p1->avl.bal == 1) /* simple RR-turn */
- {
- p->avl.right = p1->avl.left;
- p1->avl.left = p;
- p->avl.bal = 0;
- p = p1;
- }
- else /* double RL-turn */
- {
- p2 = p1->avl.left;
- p1->avl.left = p2->avl.right;
- p2->avl.right = p1;
- p->avl.right = p2->avl.left;
- p2->avl.left = p;
- if (p2->avl.bal == +1) p->avl.bal = -1; else p->avl.bal = 0;
- if (p2->avl.bal == -1) p1->avl.bal = +1; else p1->avl.bal = 0;
- p = p2;
- }
- p->avl.bal = 0;
- modified = FALSE;
- break;
-
- default:
- break;
- }
- }
- q = p;
- if (buf_prev > buf_stack)
- {
- p = *--buf_prev;
+ q->avl.left = q->avl.right = NULL;
+ q->avl.bal = 0;
+ modified = TRUE;
+ buf_prev--;
- if (p->avl.cache == -1)
- {
- p->avl.left = q;
- }
- else
- {
- p->avl.right = q;
- }
- }
- else
- {
- *root = p;
- break;
- }
- };
+ while (modified)
+ {
+ if (p->avl.cache == -1)
+ {
+ switch (p->avl.bal)
+ {
+ case 1:
+ p->avl.bal = 0;
+ modified = FALSE;
+ break;
+
+ case 0:
+ p->avl.bal = -1;
+ break;
+
+ case -1:
+ p1 = p->avl.left;
+ if (p1->avl.bal == -1) /* simple LL-turn */
+ {
+ p->avl.left = p1->avl.right;
+ p1->avl.right = p;
+ p->avl.bal = 0;
+ p = p1;
+ }
+ else /* double LR-turn */
+ {
+ p2 = p1->avl.right;
+ p1->avl.right = p2->avl.left;
+ p2->avl.left = p1;
+ p->avl.left = p2->avl.right;
+ p2->avl.right = p;
+ if (p2->avl.bal == -1) p->avl.bal = +1; else p->avl.bal = 0;
+ if (p2->avl.bal == +1) p1->avl.bal = -1; else p1->avl.bal = 0;
+ p = p2;
+ }
+ p->avl.bal = 0;
+ modified = FALSE;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch (p->avl.bal)
+ {
+ case -1:
+ p->avl.bal = 0;
+ modified = FALSE;
+ break;
+
+ case 0:
+ p->avl.bal = 1;
+ break;
+
+ case 1:
+ p1 = p->avl.right;
+ if (p1->avl.bal == 1) /* simple RR-turn */
+ {
+ p->avl.right = p1->avl.left;
+ p1->avl.left = p;
+ p->avl.bal = 0;
+ p = p1;
+ }
+ else /* double RL-turn */
+ {
+ p2 = p1->avl.left;
+ p1->avl.left = p2->avl.right;
+ p2->avl.right = p1;
+ p->avl.right = p2->avl.left;
+ p2->avl.left = p;
+ if (p2->avl.bal == +1) p->avl.bal = -1; else p->avl.bal = 0;
+ if (p2->avl.bal == -1) p1->avl.bal = +1; else p1->avl.bal = 0;
+ p = p2;
+ }
+ p->avl.bal = 0;
+ modified = FALSE;
+ break;
+
+ default:
+ break;
+ }
+ }
+ q = p;
+ if (buf_prev > buf_stack)
+ {
+ p = *--buf_prev;
+
+ if (p->avl.cache == -1)
+ {
+ p->avl.left = q;
+ }
+ else
+ {
+ p->avl.right = q;
+ }
+ }
+ else
+ {
+ *root = p;
+ break;
+ }
+ };
- return 0;
+ return 0;
}
-/* avl_remove --
- * removes the node from the tree.
+/**
+ * Removes the node from the tree.
*
- * PARAMETERS:
- * root_addr - Pointer to pointer to the root node
- * node - Pointer to the node to remove
- *
- * RETURNS:
- * 0 - Item removed
- * -1 - No such item found
+ * @param root_addr 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
*/
static int
-avl_remove(bdbuf_buffer **root, const bdbuf_buffer *node)
+rtems_bdbuf_avl_remove(rtems_bdbuf_buffer** root,
+ const rtems_bdbuf_buffer* node)
{
- dev_t dev = node->dev;
- blkdev_bnum block = node->block;
+ dev_t dev = node->dev;
+ rtems_blkdev_bnum block = node->block;
- bdbuf_buffer *p = *root;
- bdbuf_buffer *q, *r, *s, *p1, *p2;
- bdbuf_buffer *buf_stack[AVL_MAX_HEIGHT];
- bdbuf_buffer **buf_prev = buf_stack;
+ rtems_bdbuf_buffer* p = *root;
+ rtems_bdbuf_buffer* q;
+ rtems_bdbuf_buffer* r;
+ rtems_bdbuf_buffer* s;
+ rtems_bdbuf_buffer* p1;
+ rtems_bdbuf_buffer* p2;
+ rtems_bdbuf_buffer* buf_stack[RTEMS_BDBUF_AVL_MAX_HEIGHT];
+ rtems_bdbuf_buffer** buf_prev = buf_stack;
- boolean modified = FALSE;
+ boolean modified = FALSE;
- memset(buf_stack, 0, sizeof(buf_stack));
+ memset (buf_stack, 0, sizeof(buf_stack));
- while (p != NULL)
- {
- *buf_prev++ = p;
+ while (p != NULL)
+ {
+ *buf_prev++ = p;
- if ((p->dev < dev) || ((p->dev == dev) && (p->block < block)))
- {
- p->avl.cache = 1;
- p = p->avl.right;
- }
- else if ((p->dev != dev) || (p->block != block))
- {
- p->avl.cache = -1;
- p = p->avl.left;
- }
- else
- {
- /* node found */
- break;
- }
+ if ((p->dev < dev) || ((p->dev == dev) && (p->block < block)))
+ {
+ p->avl.cache = 1;
+ p = p->avl.right;
+ }
+ else if ((p->dev != dev) || (p->block != block))
+ {
+ p->avl.cache = -1;
+ p = p->avl.left;
}
+ else
+ {
+ /* node found */
+ break;
+ }
+ }
+
+ if (p == NULL)
+ {
+ /* there is no such node */
+ return -1;
+ }
+
+ q = p;
- if (p == NULL)
+ buf_prev--;
+ if (buf_prev > buf_stack)
+ {
+ p = *(buf_prev - 1);
+ }
+ else
+ {
+ p = NULL;
+ }
+
+ /* at this moment q - is a node to delete, p is q's parent */
+ if (q->avl.right == NULL)
+ {
+ r = q->avl.left;
+ if (r != NULL)
{
- /* there is no such node */
- return -1;
+ r->avl.bal = 0;
}
+ q = r;
+ }
+ else
+ {
+ rtems_bdbuf_buffer **t;
- q = p;
+ r = q->avl.right;
- buf_prev--;
- if (buf_prev > buf_stack)
+ if (r->avl.left == NULL)
{
- p = *(buf_prev - 1);
+ r->avl.left = q->avl.left;
+ r->avl.bal = q->avl.bal;
+ r->avl.cache = 1;
+ *buf_prev++ = q = r;
}
else
{
- p = NULL;
+ t = buf_prev++;
+ s = r;
+
+ while (s->avl.left != NULL)
+ {
+ *buf_prev++ = r = s;
+ s = r->avl.left;
+ r->avl.cache = -1;
+ }
+
+ s->avl.left = q->avl.left;
+ r->avl.left = s->avl.right;
+ s->avl.right = q->avl.right;
+ s->avl.bal = q->avl.bal;
+ s->avl.cache = 1;
+
+ *t = q = s;
}
+ }
- /* at this moment q - is a node to delete, p is q's parent */
- if (q->avl.right == NULL)
+ if (p != NULL)
+ {
+ if (p->avl.cache == -1)
{
- r = q->avl.left;
- if (r != NULL)
- {
- r->avl.bal = 0;
- }
- q = r;
+ p->avl.left = q;
}
else
{
- bdbuf_buffer **t;
-
- r = q->avl.right;
-
- if (r->avl.left == NULL)
- {
- r->avl.left = q->avl.left;
- r->avl.bal = q->avl.bal;
- r->avl.cache = 1;
- *buf_prev++ = q = r;
- }
- else
- {
- t = buf_prev++;
- s = r;
-
- while (s->avl.left != NULL)
- {
- *buf_prev++ = r = s;
- s = r->avl.left;
- r->avl.cache = -1;
- }
-
- s->avl.left = q->avl.left;
- r->avl.left = s->avl.right;
- s->avl.right = q->avl.right;
- s->avl.bal = q->avl.bal;
- s->avl.cache = 1;
-
- *t = q = s;
- }
+ p->avl.right = q;
}
+ }
+ else
+ {
+ *root = q;
+ }
+
+ modified = TRUE;
- if (p != NULL)
+ while (modified)
+ {
+ if (buf_prev > buf_stack)
{
- if (p->avl.cache == -1)
- {
- p->avl.left = q;
- }
- else
- {
- p->avl.right = q;
- }
+ p = *--buf_prev;
}
else
{
- *root = q;
+ break;
}
- modified = TRUE;
-
- while (modified)
+ if (p->avl.cache == -1)
{
- if (buf_prev > buf_stack)
- {
- p = *--buf_prev;
- }
- else
- {
- break;
- }
-
- if (p->avl.cache == -1)
- {
- /* rebalance left branch */
- switch (p->avl.bal)
+ /* rebalance left branch */
+ switch (p->avl.bal)
+ {
+ case -1:
+ p->avl.bal = 0;
+ break;
+ case 0:
+ p->avl.bal = 1;
+ modified = FALSE;
+ break;
+
+ case +1:
+ p1 = p->avl.right;
+
+ if (p1->avl.bal >= 0) /* simple RR-turn */
+ {
+ p->avl.right = p1->avl.left;
+ p1->avl.left = p;
+
+ if (p1->avl.bal == 0)
{
- case -1:
- p->avl.bal = 0;
- break;
- case 0:
- p->avl.bal = 1;
- modified = FALSE;
- break;
-
- case +1:
- p1 = p->avl.right;
-
- if (p1->avl.bal >= 0) /* simple RR-turn */
- {
- p->avl.right = p1->avl.left;
- p1->avl.left = p;
-
- if (p1->avl.bal == 0)
- {
- p1->avl.bal = -1;
- modified = FALSE;
- }
- else
- {
- p->avl.bal = 0;
- p1->avl.bal = 0;
- }
- p = p1;
- }
- else /* double RL-turn */
- {
- p2 = p1->avl.left;
-
- p1->avl.left = p2->avl.right;
- p2->avl.right = p1;
- p->avl.right = p2->avl.left;
- p2->avl.left = p;
-
- if (p2->avl.bal == +1) p->avl.bal = -1; else p->avl.bal = 0;
- if (p2->avl.bal == -1) p1->avl.bal = 1; else p1->avl.bal = 0;
-
- p = p2;
- p2->avl.bal = 0;
- }
- break;
-
- default:
- break;
+ p1->avl.bal = -1;
+ modified = FALSE;
}
- }
- else
- {
- /* rebalance right branch */
- switch (p->avl.bal)
+ else
{
- case +1:
- p->avl.bal = 0;
- break;
-
- case 0:
- p->avl.bal = -1;
- modified = FALSE;
- break;
-
- case -1:
- p1 = p->avl.left;
-
- if (p1->avl.bal <= 0) /* simple LL-turn */
- {
- p->avl.left = p1->avl.right;
- p1->avl.right = p;
- if (p1->avl.bal == 0)
- {
- p1->avl.bal = 1;
- modified = FALSE;
- }
- else
- {
- p->avl.bal = 0;
- p1->avl.bal = 0;
- }
- p = p1;
- }
- else /* double LR-turn */
- {
- p2 = p1->avl.right;
-
- p1->avl.right = p2->avl.left;
- p2->avl.left = p1;
- p->avl.left = p2->avl.right;
- p2->avl.right = p;
-
- if (p2->avl.bal == -1) p->avl.bal = 1; else p->avl.bal = 0;
- if (p2->avl.bal == +1) p1->avl.bal = -1; else p1->avl.bal = 0;
-
- p = p2;
- p2->avl.bal = 0;
- }
- break;
-
- default:
- break;
+ p->avl.bal = 0;
+ p1->avl.bal = 0;
}
- }
-
- if (buf_prev > buf_stack)
- {
- q = *(buf_prev - 1);
-
- if (q->avl.cache == -1)
+ p = p1;
+ }
+ else /* double RL-turn */
+ {
+ p2 = p1->avl.left;
+
+ p1->avl.left = p2->avl.right;
+ p2->avl.right = p1;
+ p->avl.right = p2->avl.left;
+ p2->avl.left = p;
+
+ if (p2->avl.bal == +1) p->avl.bal = -1; else p->avl.bal = 0;
+ if (p2->avl.bal == -1) p1->avl.bal = 1; else p1->avl.bal = 0;
+
+ p = p2;
+ p2->avl.bal = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ /* rebalance right branch */
+ switch (p->avl.bal)
+ {
+ case +1:
+ p->avl.bal = 0;
+ break;
+
+ case 0:
+ p->avl.bal = -1;
+ modified = FALSE;
+ break;
+
+ case -1:
+ p1 = p->avl.left;
+
+ if (p1->avl.bal <= 0) /* simple LL-turn */
+ {
+ p->avl.left = p1->avl.right;
+ p1->avl.right = p;
+ if (p1->avl.bal == 0)
{
- q->avl.left = p;
+ p1->avl.bal = 1;
+ modified = FALSE;
}
else
{
- q->avl.right = p;
+ p->avl.bal = 0;
+ p1->avl.bal = 0;
}
- }
- else
- {
- *root = p;
- break;
- }
+ p = p1;
+ }
+ else /* double LR-turn */
+ {
+ p2 = p1->avl.right;
+
+ p1->avl.right = p2->avl.left;
+ p2->avl.left = p1;
+ p->avl.left = p2->avl.right;
+ p2->avl.right = p;
+
+ if (p2->avl.bal == -1) p->avl.bal = 1; else p->avl.bal = 0;
+ if (p2->avl.bal == +1) p1->avl.bal = -1; else p1->avl.bal = 0;
+
+ p = p2;
+ p2->avl.bal = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ if (buf_prev > buf_stack)
+ {
+ q = *(buf_prev - 1);
+
+ if (q->avl.cache == -1)
+ {
+ q->avl.left = p;
+ }
+ else
+ {
+ q->avl.right = p;
+ }
+ }
+ else
+ {
+ *root = p;
+ break;
}
- return 0;
+ }
+
+ return 0;
+}
+
+/**
+ * Get the pool for the device.
+ *
+ * @param pdd Physical disk device.
+ */
+static rtems_bdbuf_pool*
+rtems_bdbuf_get_pool (const rtems_bdpool_id pid)
+{
+ return &rtems_bdbuf_ctx.pool[pid];
+}
+
+/**
+ * Lock the pool. A single task can nest calls.
+ *
+ * @param pool The pool to lock.
+ */
+static void
+rtems_bdbuf_lock_pool (rtems_bdbuf_pool* pool)
+{
+ rtems_status_code sc = rtems_semaphore_obtain (pool->lock,
+ RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_POOL_LOCK);
+}
+
+/**
+ * Unlock the pool.
+ *
+ * @param pool The pool to unlock.
+ */
+static void
+rtems_bdbuf_unlock_pool (rtems_bdbuf_pool* pool)
+{
+ rtems_status_code sc = rtems_semaphore_release (pool->lock);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_POOL_UNLOCK);
+}
+
+/**
+ * Lock the pool's sync. A single task can nest calls.
+ *
+ * @param pool The pool's sync to lock.
+ */
+static void
+rtems_bdbuf_lock_sync (rtems_bdbuf_pool* pool)
+{
+ rtems_status_code sc = rtems_semaphore_obtain (pool->sync_lock,
+ RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_SYNC_LOCK);
+}
+
+/**
+ * Unlock the pool's sync.
+ *
+ * @param pool The pool's sync to unlock.
+ */
+static void
+rtems_bdbuf_unlock_sync (rtems_bdbuf_pool* pool)
+{
+ rtems_status_code sc = rtems_semaphore_release (pool->sync_lock);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_SYNC_UNLOCK);
+}
+
+/**
+ * Wait until woken. Semaphores are used so a number of tasks can wait and
+ * can be woken at once. Task events would require we maintain a list
+ * of tasks to be woken and this would require storgage and we do not
+ * know the number of tasks that could be waiting.
+ *
+ * While we have the pool locked we can try and claim the semaphore and
+ * therefore know when we release the lock to the pool we will block until the
+ * semaphore is released. This may even happen before we get to block.
+ *
+ * A counter is used to save the release call when no one is waiting.
+ *
+ * The function assumes the pool is locked on entry and it will have locked
+ * the pool on exit.
+ *
+ * @param pool The pool to wait for a buffer to return.
+ * @param sema The semaphore to block on and wait.
+ * @param waiters The wait counter for this semaphore.
+ */
+static void
+rtems_bdbuf_wait (rtems_bdbuf_pool* pool, rtems_id* sema,
+ volatile uint32_t* waiters)
+{
+ rtems_status_code sc;
+ rtems_mode prev_mode;
+
+ /*
+ * Indicate we are waiting.
+ */
+ *waiters += 1;
+
+ /*
+ * Disable preemption then unlock the pool and block.
+ * There is no POSIX condition variable in the core API so
+ * this is a work around.
+ *
+ * The issue is a task could preempt after the pool is unlocked
+ * because it is blocking or just hits that window, and before
+ * this task has blocked on the semaphore. If the preempting task
+ * flushes the queue this task will not see the flush and may
+ * block for ever or until another transaction flushes this
+ * semaphore.
+ */
+ sc = rtems_task_mode (RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &prev_mode);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_POOL_WAIT);
+
+ /*
+ * Unlock the pool, wait, and lock the pool when we return.
+ */
+ rtems_bdbuf_unlock_pool (pool);
+
+ sc = rtems_semaphore_obtain (*sema, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+
+ if (sc != RTEMS_UNSATISFIED)
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_POOL_WAIT);
+
+ rtems_bdbuf_lock_pool (pool);
+
+ sc = rtems_task_mode (prev_mode, RTEMS_ALL_MODE_MASKS, &prev_mode);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_POOL_WAIT);
+
+ *waiters -= 1;
+}
+
+/**
+ * Wake a blocked resource. The resource has a counter that lets us know if
+ * there are any waiters.
+ *
+ * @param sema The semaphore to release.
+ * @param waiters The wait counter for this semaphore.
+ */
+static void
+rtems_bdbuf_wake (rtems_id sema, volatile uint32_t* waiters)
+{
+ if (*waiters)
+ {
+ rtems_status_code sc;
+
+ sc = rtems_semaphore_flush (sema);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_POOL_WAKE);
+ }
+}
+
+/**
+ * Add a buffer descriptor to the modified list. This modified list is treated
+ * a litte differently to the other lists. To access it you must have the pool
+ * locked and this is assumed to be the case on entry to this call and you must
+ * hold the sync lock. The sync lock is used to block writes while a sync is
+ * active.
+ *
+ * @param sema The semaphore to release.
+ * @param waiters The wait counter for this semaphore.
+ */
+static void
+rtems_bdbuf_append_modified (rtems_bdbuf_pool* pool, rtems_bdbuf_buffer* bd)
+{
+ /*
+ * Take a copy of the sync_active variable as it will change after
+ * we unlock the pool and wait for the sync to finish.
+ */
+ int sync_active = pool->sync_active;
+ if (0 && sync_active)
+ {
+ rtems_bdbuf_unlock_pool (pool);
+ rtems_bdbuf_lock_sync (pool);
+ rtems_bdbuf_lock_pool (pool);
+ }
+
+ bd->state = RTEMS_BDBUF_STATE_MODIFIED;
+
+ rtems_chain_append (&pool->modified, &bd->link);
+
+ if (0 && sync_active)
+ rtems_bdbuf_unlock_sync (pool);
+}
+
+static void
+rtems_bdbuf_wake_swapper ()
+{
+ rtems_status_code sc = rtems_event_send (rtems_bdbuf_ctx.swapout,
+ RTEMS_BDBUF_SWAPOUT_SYNC);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_SO_WAKE);
}
/* bdbuf_initialize_pool --
@@ -675,70 +930,134 @@ avl_remove(bdbuf_buffer **root, const bdbuf_buffer *node)
* code if error occured.
*/
static rtems_status_code
-bdbuf_initialize_pool(rtems_bdbuf_config *config, int pool)
+rtems_bdbuf_initialize_pool (rtems_bdbuf_pool_config* config,
+ rtems_bdpool_id pid)
{
- bdbuf_pool *p = rtems_bdbuf_ctx.pool + pool;
- unsigned char *bufs;
- bdbuf_buffer *b;
- rtems_status_code rc;
- int i;
-
- p->blksize = config->size;
- p->nblks = config->num;
- p->tree = NULL;
-
- rtems_chain_initialize_empty(&p->free);
- rtems_chain_initialize_empty(&p->lru);
-
- /* Allocate memory for buffer descriptors */
- p->bdbufs = calloc(config->num, sizeof(bdbuf_buffer));
- if (p->bdbufs == NULL)
- {
- return RTEMS_NO_MEMORY;
- }
+ unsigned char* buffer = config->mem_area;
+ rtems_bdbuf_pool* pool;
+ rtems_bdbuf_buffer* bd;
+ rtems_status_code sc;
+ int b;
- /* Allocate memory for buffers if required */
- if (config->mem_area == NULL)
- {
- bufs = p->mallocd_bufs = malloc(config->num * config->size);
- if (bufs == NULL)
- {
- free(p->bdbufs);
- return RTEMS_NO_MEMORY;
- }
- }
- else
+ pool = rtems_bdbuf_get_pool (pid);
+
+ pool->blksize = config->size;
+ pool->nblks = config->num;
+ pool->tree = NULL;
+ pool->buffers = NULL;
+
+ rtems_chain_initialize_empty (&pool->ready);
+ rtems_chain_initialize_empty (&pool->lru);
+ rtems_chain_initialize_empty (&pool->modified);
+ rtems_chain_initialize_empty (&pool->sync);
+
+ pool->access = 0;
+ pool->access_waiters = 0;
+ pool->transfer = 0;
+ pool->transfer_waiters = 0;
+ pool->waiting = 0;
+ pool->wait_waiters = 0;
+
+ /*
+ * Allocate memory for buffer descriptors
+ */
+ pool->bds = calloc (config->num, sizeof (rtems_bdbuf_buffer));
+
+ if (!pool->bds)
+ return RTEMS_NO_MEMORY;
+
+ /*
+ * Allocate memory for buffers if required.
+ */
+ if (buffer == NULL)
+ {
+ buffer = pool->buffers = malloc (config->num * config->size);
+ if (!pool->buffers)
{
- bufs = config->mem_area;
- p->mallocd_bufs = NULL;
+ free (pool->bds);
+ return RTEMS_NO_MEMORY;
}
+ }
- for (i = 0, b = p->bdbufs; i < p->nblks; i++, b++, bufs += p->blksize)
- {
- b->dev = -1; b->block = 0;
- b->buffer = bufs;
- b->actual = b->modified = b->in_progress = FALSE;
- b->use_count = 0;
- b->pool = pool;
- rtems_chain_append(&p->free, &b->link);
- }
+ for (b = 0, bd = pool->bds;
+ b < pool->nblks;
+ b++, bd++, buffer += pool->blksize)
+ {
+ bd->dev = -1;
+ bd->block = 0;
+ bd->buffer = buffer;
+ bd->avl.left = NULL;
+ bd->avl.right = NULL;
+ bd->state = RTEMS_BDBUF_STATE_EMPTY;
+ bd->pool = pid;
+ bd->error = 0;
+ bd->waiters = 0;
+ bd->hold_timer = 0;
+
+ rtems_chain_append (&pool->ready, &bd->link);
+ }
- rc = rtems_semaphore_create(
- rtems_build_name('B', 'U', 'F', 'G'),
- p->nblks,
- RTEMS_FIFO | RTEMS_COUNTING_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY |
- RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL,
- 0,
- &p->bufget_sema);
+ sc = rtems_semaphore_create (rtems_build_name ('B', 'P', '0' + pid, 'L'),
+ 1, RTEMS_BDBUF_POOL_LOCK_ATTRIBS, 0,
+ &pool->lock);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ free (pool->buffers);
+ free (pool->bds);
+ return sc;
+ }
- if (rc != RTEMS_SUCCESSFUL)
- {
- free(p->bdbufs);
- free(p->mallocd_bufs);
- return rc;
- }
+ sc = rtems_semaphore_create (rtems_build_name ('B', 'P', '0' + pid, 's'),
+ 0, RTEMS_BDBUF_POOL_WAITER_ATTRIBS, 0,
+ &pool->sync_lock);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ rtems_semaphore_delete (pool->lock);
+ free (pool->buffers);
+ free (pool->bds);
+ return sc;
+ }
+
+ sc = rtems_semaphore_create (rtems_build_name ('B', 'P', '0' + pid, 'a'),
+ 0, RTEMS_BDBUF_POOL_WAITER_ATTRIBS, 0,
+ &pool->access);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ rtems_semaphore_delete (pool->sync_lock);
+ rtems_semaphore_delete (pool->lock);
+ free (pool->buffers);
+ free (pool->bds);
+ return sc;
+ }
- return RTEMS_SUCCESSFUL;
+ sc = rtems_semaphore_create (rtems_build_name ('B', 'P', '0' + pid, 't'),
+ 0, RTEMS_BDBUF_POOL_WAITER_ATTRIBS, 0,
+ &pool->transfer);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ rtems_semaphore_delete (pool->access);
+ rtems_semaphore_delete (pool->sync_lock);
+ rtems_semaphore_delete (pool->lock);
+ free (pool->buffers);
+ free (pool->bds);
+ return sc;
+ }
+
+ sc = rtems_semaphore_create (rtems_build_name ('B', 'P', '0' + pid, 'w'),
+ 0, RTEMS_BDBUF_POOL_WAITER_ATTRIBS, 0,
+ &pool->waiting);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ rtems_semaphore_delete (pool->transfer);
+ rtems_semaphore_delete (pool->access);
+ rtems_semaphore_delete (pool->sync_lock);
+ rtems_semaphore_delete (pool->lock);
+ free (pool->buffers);
+ free (pool->bds);
+ return sc;
+ }
+
+ return RTEMS_SUCCESSFUL;
}
/* bdbuf_release_pool --
@@ -751,21 +1070,29 @@ bdbuf_initialize_pool(rtems_bdbuf_config *config, int pool)
* RTEMS_SUCCESSFUL
*/
static rtems_status_code
-bdbuf_release_pool(rtems_bdpool_id pool)
+rtems_bdbuf_release_pool (rtems_bdpool_id pid)
{
- bdbuf_pool *p = rtems_bdbuf_ctx.pool + pool;
- rtems_semaphore_delete(p->bufget_sema);
- free(p->bdbufs);
- free(p->mallocd_bufs);
- return RTEMS_SUCCESSFUL;
+ rtems_bdbuf_pool* pool = rtems_bdbuf_get_pool (pid);
+
+ rtems_bdbuf_lock_pool (pool);
+
+ rtems_semaphore_delete (pool->waiting);
+ rtems_semaphore_delete (pool->transfer);
+ rtems_semaphore_delete (pool->access);
+ rtems_semaphore_delete (pool->lock);
+
+ free (pool->buffers);
+ free (pool->bds);
+
+ return RTEMS_SUCCESSFUL;
}
/* rtems_bdbuf_init --
* Prepare buffering layer to work - initialize buffer descritors
- * and (if it is neccessary)buffers. Buffers will be allocated accoriding
+ * and (if it is neccessary) buffers. Buffers will be allocated according
* to the configuration table, each entry describes kind of block and
- * amount requested. After initialization all blocks is placed into
- * free elements lists.
+ * amount requested. After initialization all blocks are placed onto
+ * empty elements lists.
*
* PARAMETERS:
* conf_table - pointer to the buffers configuration table
@@ -776,107 +1103,124 @@ bdbuf_release_pool(rtems_bdpool_id pool)
* or error code if error is occured)
*/
rtems_status_code
-rtems_bdbuf_init(rtems_bdbuf_config *conf_table, int size)
+rtems_bdbuf_init ()
{
- rtems_bdpool_id i;
- rtems_status_code rc;
+ rtems_bdpool_id p;
+ rtems_status_code sc;
- if (size <= 0)
- return RTEMS_INVALID_SIZE;
+#if RTEMS_BDBUF_TRACE
+ rtems_bdbuf_printf ("init\n");
+#endif
- rtems_bdbuf_ctx.npools = size;
+ if (rtems_bdbuf_pool_configuration_size <= 0)
+ return RTEMS_INVALID_SIZE;
- /*
- * Allocate memory for buffer pool descriptors
- */
- rtems_bdbuf_ctx.pool = calloc(size, sizeof(bdbuf_pool));
- if (rtems_bdbuf_ctx.pool == NULL)
- {
- return RTEMS_NO_MEMORY;
- }
+ if (rtems_bdbuf_ctx.npools)
+ return RTEMS_RESOURCE_IN_USE;
- rtems_chain_initialize_empty(&rtems_bdbuf_ctx.mod);
+ rtems_bdbuf_ctx.npools = rtems_bdbuf_pool_configuration_size;
- /* Initialize buffer pools and roll out if something failed */
- for (i = 0; i < size; i++)
+ /*
+ * Allocate memory for buffer pool descriptors
+ */
+ rtems_bdbuf_ctx.pool = calloc (rtems_bdbuf_pool_configuration_size,
+ sizeof (rtems_bdbuf_pool));
+
+ if (rtems_bdbuf_ctx.pool == NULL)
+ return RTEMS_NO_MEMORY;
+
+ /*
+ * Initialize buffer pools and roll out if something failed,
+ */
+ for (p = 0; p < rtems_bdbuf_ctx.npools; p++)
+ {
+ sc = rtems_bdbuf_initialize_pool (&rtems_bdbuf_pool_configuration[p], p);
+ if (sc != RTEMS_SUCCESSFUL)
{
- rc = bdbuf_initialize_pool(conf_table + i, i);
- if (rc != RTEMS_SUCCESSFUL)
- {
- rtems_bdpool_id j;
- for (j = 0; j < i - 1; j++)
- {
- bdbuf_release_pool(j);
- }
- return rc;
- }
+ rtems_bdpool_id j;
+ for (j = 0; j < p - 1; j++)
+ rtems_bdbuf_release_pool (j);
+ return sc;
}
+ }
- /* Create buffer flush semaphore */
- rc = rtems_semaphore_create(
- rtems_build_name('B', 'F', 'L', 'U'), 0,
- RTEMS_FIFO | RTEMS_COUNTING_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY |
- RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL, 0,
- &rtems_bdbuf_ctx.flush_sema);
- if (rc != RTEMS_SUCCESSFUL)
- {
- for (i = 0; i < size; i++)
- bdbuf_release_pool(i);
- free(rtems_bdbuf_ctx.pool);
- return rc;
- }
+ /*
+ * Create and start swapout task
+ */
- /* Create and start swapout task */
- rc = rtems_task_create(
- rtems_build_name('B', 'S', 'W', 'P'),
- ((swapout_task_priority > 0)
- ? swapout_task_priority
- : SWAPOUT_TASK_DEFAULT_PRIORITY),
- SWAPOUT_TASK_STACK_SIZE,
- RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT,
- RTEMS_DEFAULT_ATTRIBUTES,
- &rtems_bdbuf_ctx.swapout_task);
- if (rc != RTEMS_SUCCESSFUL)
- {
- rtems_semaphore_delete(rtems_bdbuf_ctx.flush_sema);
- for (i = 0; i < size; i++)
- bdbuf_release_pool(i);
- free(rtems_bdbuf_ctx.pool);
- return rc;
- }
+ rtems_bdbuf_ctx.swapout_enabled = TRUE;
+
+ sc = rtems_task_create (rtems_build_name('B', 'S', 'W', 'P'),
+ (rtems_bdbuf_configuration.swapout_priority ?
+ rtems_bdbuf_configuration.swapout_priority :
+ RTEMS_BDBUF_SWAPOUT_TASK_PRIORITY_DEFAULT),
+ SWAPOUT_TASK_STACK_SIZE,
+ RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
+ RTEMS_LOCAL | RTEMS_NO_FLOATING_POINT,
+ &rtems_bdbuf_ctx.swapout);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ for (p = 0; p < rtems_bdbuf_ctx.npools; p++)
+ rtems_bdbuf_release_pool (p);
+ free (rtems_bdbuf_ctx.pool);
+ return sc;
+ }
- rc = rtems_task_start(rtems_bdbuf_ctx.swapout_task, bdbuf_swapout_task, 0);
- if (rc != RTEMS_SUCCESSFUL)
- {
- rtems_task_delete(rtems_bdbuf_ctx.swapout_task);
- rtems_semaphore_delete(rtems_bdbuf_ctx.flush_sema);
- for (i = 0; i < size; i++)
- bdbuf_release_pool(i);
- free(rtems_bdbuf_ctx.pool);
- return rc;
- }
+ sc = rtems_task_start (rtems_bdbuf_ctx.swapout,
+ rtems_bdbuf_swapout_task,
+ (rtems_task_argument) &rtems_bdbuf_ctx);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ rtems_task_delete (rtems_bdbuf_ctx.swapout);
+ for (p = 0; p < rtems_bdbuf_ctx.npools; p++)
+ rtems_bdbuf_release_pool (p);
+ free (rtems_bdbuf_ctx.pool);
+ return sc;
+ }
- return RTEMS_SUCCESSFUL;
+ return RTEMS_SUCCESSFUL;
}
-/* find_or_assign_buffer --
- * Looks for buffer already assigned for this dev/block. If one is found
- * obtain block buffer. If specified block already cached (i.e. there's
- * block in the _modified_, or _recently_used_), return address
- * of appropriate buffer descriptor and increment reference counter to 1.
- * If block is not cached, allocate new buffer and return it. Data
- * shouldn't be read to the buffer from media; buffer contains arbitrary
- * data. This primitive may be blocked if there are no free buffer
- * descriptors available and there are no unused non-modified (or
- * synchronized with media) buffers available.
+/**
+ * Get a buffer for this device and block. This function returns a buffer once
+ * placed into the AVL tree. If no buffer is available and it is not a read
+ * ahead request wait until one is available. If the buffer is for a read ahead
+ * transfer return NULL if there is not buffer or it is in the cache.
*
- * PARAMETERS:
- * device - device number (constructed of major and minor device number
- * block - linear media block number
- * ret_buf - address of the variable to store address of found descriptor
+ * The AVL tree of buffers for the pool is searched and if not located check
+ * obtain a buffer and insert it into the AVL tree. Buffers are first obtained
+ * from the ready list until all empty buffers are used. Once all buffers are
+ * in use buffers are taken from the LRU list with the least recently used
+ * buffer taken first. A buffer taken from the LRU list is removed from the AVL
+ * tree. The empty list or LRU list buffer is initialised to this device and
+ * block. If no buffers are available due to the empty and LRU lists being
+ * empty the caller is blocked on the waiting semaphore and counter. When
+ * buffers return from the upper layers (access) or lower driver (transfer) the
+ * blocked caller task is woken and this procedure is repeated. The repeat
+ * handles a case of a another thread pre-empting getting a buffer first and
+ * adding it to the AVL tree.
+ *
+ * A buffer located in the AVL tree means it is already in the cache and maybe
+ * in use somewhere. The buffer can be either:
+ *
+ * # Cached. Not being accessed or part of a media transfer.
+ * # Access. Is with an upper layer being accessed.
+ * # Transfer. Is with the driver and part of a media transfer.
+ *
+ * If cached we assign the state new state extract it from any list it maybe
+ * part of and return to the user. The buffer could be part of the LRU list or
+ * the modifed list waiting to be swapped out by the swap out task.
+ *
+ * This function assumes the pool the buffer is being taken from is locked and
+ * it insure the pool is locked when it returns.
*
+ * @param device The physical disk device
+ * @param block Linear media block number
+ * @param
+ * @param bd Address to store of found descriptor
+
* RETURNS:
- * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
+ * RTEMS status code ( if operation completed successfully
* or error code if error is occured)
*
* SIDE EFFEECTS:
@@ -885,252 +1229,251 @@ rtems_bdbuf_init(rtems_bdbuf_config *conf_table, int size)
* NOTE:
* It is assumed that primitive invoked when thread preemption is disabled.
*/
-static rtems_status_code
-find_or_assign_buffer(disk_device *dd,
- blkdev_bnum block,
- bdbuf_buffer **ret_buf)
+static rtems_bdbuf_buffer*
+rtems_bdbuf_get_buffer (rtems_disk_device* pdd,
+ rtems_bdbuf_pool* pool,
+ rtems_blkdev_bnum block,
+ boolean read_ahead)
{
- bdbuf_buffer *bd_buf;
- bdbuf_pool *bd_pool;
- rtems_status_code rc;
- dev_t device;
- ISR_Level level;
-
- int blksize;
-
- device = dd->dev;
- bd_pool = rtems_bdbuf_ctx.pool + dd->pool;
- blksize = dd->block_size;
-
-again:
- /* Looking for buffer descriptor used for this dev/block. */
- bd_buf = avl_search(&bd_pool->tree, device, block);
+ dev_t device = pdd->dev;
+ rtems_bdbuf_buffer* bd;
+ boolean available;
+
+ /*
+ * Loop until we get a buffer. Under load we could find no buffers are
+ * available so in the case of the required block this task needs to wait
+ * until some return before proceeding. There is no timeout. If the buffer is
+ * for a read ahead buffer return NULL.
+ *
+ * The search procedure is repeated as another thread could have pre-empted
+ * us while we waited for a buffer, obtained an empty buffer and loaded the
+ * AVL tree with it.
+ */
+ do
+ {
+ /*
+ * Search for buffer descriptor for this dev/block key.
+ */
+ bd = rtems_bdbuf_avl_search (&pool->tree, device, block);
- if (bd_buf == NULL)
+ /*
+ * No buffer in the cache for this block. We need to obtain a buffer and
+ * this means take a buffer that is ready to use. If all buffers are in use
+ * take the least recently used buffer. If there are none then the cache is
+ * empty. All the buffers are either queued to be written to disk or with
+ * the user. We cannot do much with the buffers with the user how-ever with
+ * the modified buffers waiting to be written to disk flush the maximum
+ * number transfered in a block to disk. After this all that be done is to
+ * wait for a buffer to return to the cache.
+ */
+ if (!bd)
{
- /* Try to obtain semaphore without waiting first. It is the most
- frequent case when reasonable number of buffers configured. If
- it is failed, obtain semaphore blocking on it. In this case
- it should be checked that appropriate buffer hasn't been loaded
- by another thread, because this thread is preempted */
- rc = rtems_semaphore_obtain(bd_pool->bufget_sema, RTEMS_NO_WAIT, 0);
- if (rc == RTEMS_UNSATISFIED)
+ /*
+ * Assign new buffer descriptor from the empty list if one is present. If
+ * the empty queue is empty get the oldest buffer from LRU list. If the
+ * LRU list is empty there are no available buffers so we need to wait
+ * until some are returned.
+ */
+ if (rtems_chain_is_empty (&pool->ready))
+ {
+ /*
+ * No unsed or read-ahead buffers.
+ *
+ * If this is a read ahead buffer just return. No need to place
+ * further pressure on the cache by reading something that may be
+ * needed when we have data in the cache that was needed.
+ */
+ if (read_ahead)
+ return NULL;
+
+ /*
+ * Check the LRU list.
+ */
+ bd = (rtems_bdbuf_buffer *) rtems_chain_get (&pool->lru);
+
+ if (bd)
{
- rc = rtems_semaphore_obtain(bd_pool->bufget_sema,
- RTEMS_WAIT, RTEMS_NO_TIMEOUT);
- bd_buf = avl_search(&bd_pool->tree, device, block);
- if (bd_buf != NULL)
- rtems_semaphore_release(bd_pool->bufget_sema);
+ /*
+ * Remove the buffer from the AVL tree.
+ */
+ if (rtems_bdbuf_avl_remove (&pool->tree, bd) != 0)
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY);
}
- }
-
- if (bd_buf == NULL)
- {
- /* Assign new buffer descriptor */
- if (rtems_chain_is_empty(&bd_pool->free))
+ else
{
- bd_buf = (bdbuf_buffer *)rtems_chain_get(&bd_pool->lru);
- if (bd_buf != NULL)
+ /*
+ * If there are buffers on the modified list expire the hold timer
+ * and wake the swap out task.
+ */
+ if (!rtems_chain_is_empty (&pool->modified))
+ {
+ rtems_chain_node* node = rtems_chain_head (&pool->modified);
+ int write_blocks = 0;
+
+ node = node->next;
+ while ((write_blocks < rtems_bdbuf_configuration.max_write_blocks) &&
+ !rtems_chain_is_tail (&pool->modified, node))
{
- int avl_result;
- avl_result = avl_remove(&bd_pool->tree, bd_buf);
- if (avl_result != 0)
- {
- rtems_fatal_error_occurred(BLKDEV_FATAL_BDBUF_CONSISTENCY);
- return RTEMS_INTERNAL_ERROR;
- }
+ rtems_bdbuf_buffer* bd = (rtems_bdbuf_buffer*) node;
+ bd->hold_timer = 0;
+ write_blocks++;
+ node = node->next;
}
- }
- else
- {
- bd_buf = (bdbuf_buffer *)rtems_chain_get(&(bd_pool->free));
- }
- if (bd_buf == NULL)
- {
- goto again;
+ rtems_bdbuf_wake_swapper ();
+ }
+
+ /*
+ * Wait for a buffer to be returned to the pool. The buffer will be
+ * placed on the LRU list.
+ */
+ rtems_bdbuf_wait (pool, &pool->waiting, &pool->wait_waiters);
}
- else
- {
- bd_buf->dev = device;
- bd_buf->block = block;
-#ifdef AVL_GPL
- bd_buf->avl.link[0] = NULL;
- bd_buf->avl.link[1] = NULL;
-#else
- bd_buf->avl.left = NULL;
- bd_buf->avl.right = NULL;
-#endif
- bd_buf->use_count = 1;
- bd_buf->modified = bd_buf->actual = bd_buf->in_progress = FALSE;
- bd_buf->status = RTEMS_SUCCESSFUL;
+ }
+ else
+ {
+ bd = (rtems_bdbuf_buffer *) rtems_chain_get (&(pool->ready));
- if (avl_insert(&bd_pool->tree, bd_buf) != 0)
- {
- rtems_fatal_error_occurred(BLKDEV_FATAL_BDBUF_CONSISTENCY);
- return RTEMS_INTERNAL_ERROR;
- }
+ if ((bd->state != RTEMS_BDBUF_STATE_EMPTY) &&
+ (bd->state != RTEMS_BDBUF_STATE_READ_AHEAD))
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY);
- *ret_buf = bd_buf;
-
- return RTEMS_SUCCESSFUL;
+ if (bd->state == RTEMS_BDBUF_STATE_READ_AHEAD)
+ {
+ if (rtems_bdbuf_avl_remove (&pool->tree, bd) != 0)
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY);
}
+ }
+
+ if (bd)
+ {
+ bd->dev = device;
+ bd->block = block;
+ bd->avl.left = NULL;
+ bd->avl.right = NULL;
+ bd->state = RTEMS_BDBUF_STATE_EMPTY;
+ bd->error = 0;
+ bd->waiters = 0;
+
+ if (rtems_bdbuf_avl_insert (&pool->tree, bd) != 0)
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY);
+
+ return bd;
+ }
}
- else
+ }
+ while (!bd);
+
+ /*
+ * If the buffer is for read ahead and it exists in the AVL cache or is being
+ * accessed or being transfered then return NULL.
+ */
+ if (read_ahead)
+ return NULL;
+
+ /*
+ * Loop waiting for the buffer to enter the cached state. If the buffer
+ * is in the access or transfer state then wait until it is not.
+ */
+ available = FALSE;
+ while (!available)
+ {
+ switch (bd->state)
{
- /* Buffer descriptor already assigned for this dev/block */
- if (bd_buf->use_count == 0)
- {
- /* If we are removing from lru list, obtain the bufget_sema
- * first. If we are removing from mod list, obtain flush sema.
- * It should be obtained without blocking because we know
- * that our buffer descriptor is in the list. */
- if (bd_buf->modified)
- {
- rc = rtems_semaphore_obtain(rtems_bdbuf_ctx.flush_sema,
- RTEMS_NO_WAIT, 0);
- }
- else
- {
- rc = rtems_semaphore_obtain(bd_pool->bufget_sema,
- RTEMS_NO_WAIT, 0);
- }
- /* It is possible that we couldn't obtain flush or bufget sema
- * although buffer in the appropriate chain is available:
- * semaphore may be released to swapout task, but this task
- * actually did not start to process it. */
- if (rc == RTEMS_UNSATISFIED)
- rc = RTEMS_SUCCESSFUL;
- if (rc != RTEMS_SUCCESSFUL)
- {
- rtems_fatal_error_occurred(BLKDEV_FATAL_BDBUF_CONSISTENCY);
- return RTEMS_INTERNAL_ERROR;
- }
+ case RTEMS_BDBUF_STATE_CACHED:
+ case RTEMS_BDBUF_STATE_MODIFIED:
+ case RTEMS_BDBUF_STATE_READ_AHEAD:
+ available = TRUE;
+ break;
+
+ case RTEMS_BDBUF_STATE_ACCESS:
+ case RTEMS_BDBUF_STATE_ACCESS_MODIFIED:
+ bd->waiters++;
+ rtems_bdbuf_wait (pool, &pool->access, &pool->access_waiters);
+ bd->waiters--;
+ break;
+
+ case RTEMS_BDBUF_STATE_SYNC:
+ case RTEMS_BDBUF_STATE_TRANSFER:
+ bd->waiters++;
+ rtems_bdbuf_wait (pool, &pool->transfer, &pool->transfer_waiters);
+ bd->waiters--;
+ break;
+
+ default:
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY);
+ }
+ }
- /* Buffer descriptor is linked to the lru or mod chain. Remove
- it from there. */
- rtems_chain_extract(&bd_buf->link);
- }
- bd_buf->use_count++;
- while (bd_buf->in_progress != 0)
- {
- rtems_interrupt_disable(level);
- _CORE_mutex_Seize(&bd_buf->transfer_sema, 0, TRUE,
- WATCHDOG_NO_TIMEOUT, level);
- }
+ /*
+ * Buffer is linked to the LRU, modifed, or sync lists. Remove it from there.
+ */
+ rtems_chain_extract (&bd->link);
- *ret_buf = bd_buf;
- return RTEMS_SUCCESSFUL;
- }
+ return bd;
}
-/* rtems_bdbuf_get --
- * Obtain block buffer. If specified block already cached (i.e. there's
- * block in the _modified_, or _recently_used_), return address
- * of appropriate buffer descriptor and increment reference counter to 1.
- * If block is not cached, allocate new buffer and return it. Data
- * shouldn't be read to the buffer from media; buffer may contains
- * arbitrary data. This primitive may be blocked if there are no free
- * buffer descriptors available and there are no unused non-modified
- * (or synchronized with media) buffers available.
+/**
+ * Obtain block buffer. If specified block already cached (i.e. there's block
+ * in the _modified_, or _recently_used_), return address of appropriate buffer
+ * descriptor. If block is not cached, allocate new buffer and return it. Data
+ * shouldn't be read to the buffer from media; buffer may contains arbitrary
+ * data. This primitive may be blocked if there are no free buffer descriptors
+ * available and there are no unused non-modified (or synchronized with media)
+ * buffers available.
*
- * PARAMETERS:
- * device - device number (constructed of major and minor device number)
- * block - linear media block number
- * bd - address of variable to store pointer to the buffer descriptor
- *
- * RETURNS:
- * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
- * or error code if error is occured)
- *
- * SIDE EFFECTS:
- * bufget_sema semaphore obtained by this primitive.
+ * @param device device number (constructed of major and minor device number)
+ * @param block linear media block number
+ * @param bd address of variable to store pointer 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_get(dev_t device, blkdev_bnum block, bdbuf_buffer **bd)
+rtems_bdbuf_get (dev_t device,
+ rtems_blkdev_bnum block,
+ rtems_bdbuf_buffer** bdp)
{
- rtems_status_code rc;
- disk_device *dd;
- disk_device *pdd;
- preemption_key key;
-
- /*
- * Convert logical dev/block to physical one
- */
- dd = rtems_disk_lookup(device);
- if (dd == NULL)
- return RTEMS_INVALID_ID;
+ rtems_disk_device* dd;
+ rtems_bdbuf_pool* pool;
+ rtems_bdbuf_buffer* bd;
+
+ /*
+ * Do not hold the pool lock when obtaining the disk table.
+ */
+ dd = rtems_disk_obtain (device);
+ if (dd == NULL)
+ return RTEMS_INVALID_ID;
+
+ if (block >= dd->size)
+ {
+ rtems_disk_release (dd);
+ return RTEMS_INVALID_NUMBER;
+ }
- if (block >= dd->size)
- {
- rtems_disk_release(dd);
- return RTEMS_INVALID_NUMBER;
- }
+ block += dd->start;
- pdd = dd->phys_dev;
- block += dd->start;
- rtems_disk_release(dd);
+ pool = rtems_bdbuf_get_pool (dd->phys_dev->pool);
+
+ rtems_disk_release(dd);
- DISABLE_PREEMPTION(key);
- rc = find_or_assign_buffer(pdd, block, bd);
- ENABLE_PREEMPTION(key);
+ rtems_bdbuf_lock_pool (pool);
- if (rc != RTEMS_SUCCESSFUL)
- return rc;
+#if RTEMS_BDBUF_TRACE
+ rtems_bdbuf_printf ("get: %d (dev = %08x)\n", block, device);
+#endif
- return RTEMS_SUCCESSFUL;
-}
+ bd = rtems_bdbuf_get_buffer (dd->phys_dev, pool, block, FALSE);
-/* bdbuf_initialize_transfer_sema --
- * Initialize transfer_sema mutex semaphore associated with buffer
- * descriptor.
- */
-static inline void
-bdbuf_initialize_transfer_sema(bdbuf_buffer *bd_buf)
-{
- CORE_mutex_Attributes mutex_attr;
- mutex_attr.lock_nesting_behavior = CORE_MUTEX_NESTING_BLOCKS;
- mutex_attr.only_owner_release = FALSE;
- mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_FIFO;
- mutex_attr.priority_ceiling = 0;
-
- _CORE_mutex_Initialize(&bd_buf->transfer_sema,
- &mutex_attr, CORE_MUTEX_LOCKED);
-}
+ if (bd->state == RTEMS_BDBUF_STATE_MODIFIED)
+ bd->state = RTEMS_BDBUF_STATE_ACCESS_MODIFIED;
+ else
+ bd->state = RTEMS_BDBUF_STATE_ACCESS;
+
+ rtems_bdbuf_unlock_pool (pool);
-/* bdbuf_write_transfer_done --
- * Callout function. Invoked by block device driver when data transfer
- * to device (write) is completed. This function may be invoked from
- * interrupt handler.
- *
- * PARAMETERS:
- * arg - arbitrary argument specified in block device request
- * structure (in this case - pointer to the appropriate
- * bdbuf_buffer buffer descriptor structure).
- * status - I/O completion status
- * error - errno error code if status != RTEMS_SUCCESSFUL
- *
- * RETURNS:
- * none
- */
-static void
-bdbuf_write_transfer_done(void *arg, rtems_status_code status, int error)
-{
- int i;
- write_tfer_done_arg_t *wtd_arg = arg;
- blkdev_request *req = wtd_arg->req;
- bdbuf_buffer **bd_buf_write_store = wtd_arg->write_store;
- bdbuf_buffer *bd_buf;
- for (i = 0;i < req->count;i++) {
- bd_buf = bd_buf_write_store[i];
- bd_buf->status = status;
- bd_buf->error = RTEMS_IO_ERROR;
-
- bd_buf->in_progress = FALSE;
- _CORE_mutex_Surrender(&bd_buf->transfer_sema, 0, NULL);
- _CORE_mutex_Flush(&bd_buf->transfer_sema, NULL,
- CORE_MUTEX_STATUS_SUCCESSFUL);
- }
+ *bdp = bd;
+
+ return RTEMS_SUCCESSFUL;
}
/* bdbuf_read_transfer_done --
@@ -1149,658 +1492,882 @@ bdbuf_write_transfer_done(void *arg, rtems_status_code status, int error)
* none
*/
static void
-bdbuf_read_transfer_done(void *arg, rtems_status_code status, int error)
+rtems_bdbuf_read_done (void* arg, rtems_status_code status, int error)
{
-#if defined(READ_MULTIPLE)
-
- read_ahead_bd_buf_group *bd_buf_group = arg;
- bdbuf_buffer *bd_buf;
- int i;
- for (i = 0;i < bd_buf_group->cnt;i++) {
- bd_buf = bd_buf_group->bd_bufs[i];
-
- bd_buf->status = status;
- bd_buf->error = RTEMS_IO_ERROR;
- _CORE_mutex_Surrender(&bd_buf->transfer_sema, 0, NULL);
- _CORE_mutex_Flush(&bd_buf->transfer_sema, NULL,
- CORE_MUTEX_STATUS_SUCCESSFUL);
- }
-#else
- bdbuf_buffer *bd_buf = arg;
- bd_buf->status = status;
- bd_buf->error = RTEMS_IO_ERROR;
- _CORE_mutex_Surrender(&bd_buf->transfer_sema, 0, NULL);
- _CORE_mutex_Flush(&bd_buf->transfer_sema, NULL,
- CORE_MUTEX_STATUS_SUCCESSFUL);
-#endif
+ rtems_blkdev_request* req = (rtems_blkdev_request*) arg;
+
+ req->error = error;
+ req->status = status;
+
+ rtems_event_send (req->io_task, RTEMS_BDBUF_TRANSFER_SYNC);
}
-/* rtems_bdbuf_read --
- * (Similar to the rtems_bdbuf_get, except reading data from media)
- * Obtain block buffer. If specified block already cached, return address
- * of appropriate buffer and increment reference counter to 1. If block is
- * not cached, allocate new buffer and read data to it from the media.
- * This primitive may be blocked on waiting until data to be read from
- * media, if there are no free buffer descriptors available and there are
- * no unused non-modified (or synchronized with media) buffers available.
- *
- * PARAMETERS:
- * device - device number (consists of major and minor device number)
- * block - linear media block number
- * bd - address of variable to store pointer to the buffer descriptor
- *
- * RETURNS:
- * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
- * or error code if error is occured)
+/**
+ * Read a block into memory. If the block is not is the cache it is read into
+ * memory. The caller is blocked until the block is read and placed into the
+ * cache.
*
- * SIDE EFFECTS:
- * bufget_sema and transfer_sema semaphores obtained by this primitive.
+ * @param device The device number (consists of major and minor device number)
+ * @param block Linear media block number
+ * @param bd Pointer to the buffer BD address.
+ * @retval RTEMS_SUCCESSFUL Operation completed successfully.
+ * @return rtems_status_code An error code. Buffer still passed to caller.
*/
-#if !defined(READ_MULTIPLE)
+
rtems_status_code
-rtems_bdbuf_read(dev_t device,
- blkdev_bnum block,
- bdbuf_buffer **bd)
+rtems_bdbuf_read (dev_t device,
+ rtems_blkdev_bnum block,
+ rtems_bdbuf_buffer** bdp)
{
- preemption_key key;
- ISR_Level level;
+ rtems_disk_device* dd;
+ rtems_bdbuf_pool* pool;
+ rtems_bdbuf_buffer* bd = NULL;
+ int read_ahead_count;
+ rtems_blkdev_request* req;
+
+ /*
+ * @todo This type of request structure is wrong and should be removed.
+ */
+#define bdbuf_alloc(size) __builtin_alloca (size)
+
+ req = bdbuf_alloc (sizeof (rtems_blkdev_request) +
+ (sizeof ( rtems_blkdev_sg_buffer) *
+ rtems_bdbuf_configuration.max_read_ahead_blocks));
+
+ /*
+ * Do not hold the pool lock when obtaining the disk table.
+ */
+ 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)
+ {
+ rtems_disk_release(dd);
+ return RTEMS_INVALID_NUMBER;
+ }
- bdbuf_buffer *bd_buf;
- rtems_status_code rc;
- int result;
- disk_device *dd;
- disk_device *pdd;
- blkdev_request1 req;
+ req->count = 0;
+ req->bufnum = 0;
- dd = rtems_disk_lookup(device);
- if (dd == NULL)
- return RTEMS_INVALID_ID;
+ /*
+ * Read the block plus the required number of blocks ahead. The number of
+ * blocks to read ahead is configured by the user and limited by the size of
+ * the disk or reaching a read ahead block that is also cached.
+ *
+ * Limit the blocks read by the size of the disk.
+ */
+ if ((rtems_bdbuf_configuration.max_read_ahead_blocks + block) < dd->size)
+ read_ahead_count = rtems_bdbuf_configuration.max_read_ahead_blocks;
+ else
+ read_ahead_count = dd->size - block;
- if (block >= dd->size)
- {
- rtems_disk_release(dd);
- return RTEMS_INVALID_NUMBER;
- }
+ pool = rtems_bdbuf_get_pool (dd->phys_dev->pool);
- pdd = dd->phys_dev;
- block += dd->start;
+ rtems_bdbuf_lock_pool (pool);
- DISABLE_PREEMPTION(key);
- rc = find_or_assign_buffer(pdd, block, &bd_buf);
+ while (req->count < read_ahead_count)
+ {
+ /*
+ * Get the buffer for the requested block. If the block is cached then
+ * return it. If it is not cached transfer the block from the disk media
+ * into memory.
+ *
+ * We need to clean up any buffers allocated and not passed back to the
+ * caller.
+ */
+ bd = rtems_bdbuf_get_buffer (dd->phys_dev, pool,
+ block + req->count,
+ req->count == 0 ? FALSE : TRUE);
- if (rc != RTEMS_SUCCESSFUL)
- {
- ENABLE_PREEMPTION(key);
- rtems_disk_release(dd);
- return rc;
- }
+ /*
+ * Read ahead buffer is in the cache or none available. Read what we
+ * can.
+ */
+ if (!bd)
+ break;
- if (!bd_buf->actual)
- {
- bd_buf->in_progress = 1;
-
- req.req.req = BLKDEV_REQ_READ;
- req.req.req_done = bdbuf_read_transfer_done;
- req.req.done_arg = bd_buf;
- req.req.start = block;
- req.req.count = 1;
- req.req.bufnum = 1;
- req.req.bufs[0].length = dd->block_size;
- req.req.bufs[0].buffer = bd_buf->buffer;
-
- bdbuf_initialize_transfer_sema(bd_buf);
- result = dd->ioctl(pdd->dev, BLKIO_REQUEST, &req);
- if (result == -1)
- {
- bd_buf->status = RTEMS_IO_ERROR;
- bd_buf->error = errno;
- bd_buf->actual = FALSE;
- }
- else
- {
- rtems_interrupt_disable(level);
- _CORE_mutex_Seize(&bd_buf->transfer_sema, 0, TRUE,
- WATCHDOG_NO_TIMEOUT, level);
- bd_buf->actual = TRUE;
- }
- bd_buf->in_progress = FALSE;
- }
- rtems_disk_release(dd);
+ /*
+ * Is the block we are interested in the cache ?
+ */
+ if ((bd->state == RTEMS_BDBUF_STATE_CACHED) ||
+ (bd->state == RTEMS_BDBUF_STATE_MODIFIED))
+ break;
- ENABLE_PREEMPTION(key);
+ bd->state = RTEMS_BDBUF_STATE_TRANSFER;
+ bd->error = 0;
- *bd = bd_buf;
-
- return RTEMS_SUCCESSFUL;
-}
-#else /* READ_MULTIPLE */
-rtems_status_code
-rtems_bdbuf_read(dev_t device,
- blkdev_bnum block,
- bdbuf_buffer **bd)
-{
- preemption_key key;
- ISR_Level level;
+ /*
+ * @todo The use of these req blocks is not a great design.
+ * The req is a struct with a single 'bufs' declared in the
+ * req struct and the others are added in the outer level
+ * struct. This relies on the structs joining as a single
+ * array and that assumes the compiler packs the structs.
+ * Why not just place on a list ? The BD has a node that
+ * can be used.
+ */
+ req->bufs[req->count].user = bd;
+ req->bufs[req->count].block = bd->block;
+ req->bufs[req->count].length = dd->block_size;
+ req->bufs[req->count].buffer = bd->buffer;
+ req->count++;
+ req->bufnum++;
+ }
- bdbuf_buffer *bd_buf,*first_bd_buf;
- rtems_status_code rc;
+ /*
+ * Transfer any requested buffers. If the request count is 0 we have found
+ * the block in the cache so return it.
+ */
+ if (req->count)
+ {
+ /*
+ * Unlock the pool. We have the buffer for the block and it will be in the
+ * access or transfer state. We may also have a number of read ahead blocks
+ * if we need to transfer data. At this point any other threads can gain
+ * access to the pool and if they are after any of the buffers we have they
+ * will block and be woken when the buffer is returned to the pool.
+ *
+ * If a transfer is needed the I/O operation will occur with pre-emption
+ * enabled and the pool unlocked. This is a change to the previous version
+ * of the bdbuf code.
+ */
int result;
- disk_device *dd;
- disk_device *pdd;
- blkdev_request_read_ahead req;
- read_ahead_bd_buf_group bd_buf_group;
- boolean find_more_buffers;
- int i;
-
- dd = rtems_disk_lookup(device);
- if (dd == NULL)
- return RTEMS_INVALID_ID;
-
- if (block >= dd->size)
+ int b;
+
+ rtems_bdbuf_unlock_pool (pool);
+
+ req->req = RTEMS_BLKDEV_REQ_READ;
+ req->req_done = rtems_bdbuf_read_done;
+ req->done_arg = req;
+ req->io_task = rtems_task_self ();
+ req->status = RTEMS_RESOURCE_IN_USE;
+ req->error = 0;
+ req->start = dd->start;
+
+ result = dd->ioctl (dd->phys_dev->dev, RTEMS_BLKIO_REQUEST, req);
+
+ /*
+ * Inspection of the DOS FS code shows the result from this function is
+ * handled and a buffer must be returned.
+ */
+ if (result < 0)
{
- rtems_disk_release(dd);
- return RTEMS_INVALID_NUMBER;
+ req->error = errno;
+ req->status = RTEMS_IO_ERROR;
+ }
+ else
+ {
+ rtems_status_code sc;
+ rtems_event_set out;
+ sc = rtems_event_receive (RTEMS_BDBUF_TRANSFER_SYNC,
+ RTEMS_EVENT_ALL | RTEMS_WAIT,
+ 0, &out);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (BLKDEV_FATAL_BDBUF_SWAPOUT_RE);
}
-
- pdd = dd->phys_dev;
- block += dd->start;
- DISABLE_PREEMPTION(key);
- rc = find_or_assign_buffer(pdd, block, &first_bd_buf);
+ rtems_bdbuf_lock_pool (pool);
- if (rc != RTEMS_SUCCESSFUL)
+ for (b = 1; b < req->count; b++)
{
- ENABLE_PREEMPTION(key);
- rtems_disk_release(dd);
- return rc;
+ bd = req->bufs[b].user;
+ bd->error = req->error;
+ bd->state = RTEMS_BDBUF_STATE_READ_AHEAD;
+ rtems_bdbuf_release (bd);
}
- if (!first_bd_buf->actual)
- {
- bd_buf_group.bd_bufs[0] = first_bd_buf;
- bd_buf_group.cnt = 1;
+ bd = req->bufs[0].user;
+ }
- first_bd_buf->in_progress = TRUE;
+ /*
+ * The data for this block is cached in the buffer.
+ */
+ if (bd->state == RTEMS_BDBUF_STATE_MODIFIED)
+ bd->state = RTEMS_BDBUF_STATE_ACCESS_MODIFIED;
+ else
+ bd->state = RTEMS_BDBUF_STATE_ACCESS;
- req.req.req = BLKDEV_REQ_READ;
- req.req.req_done = bdbuf_read_transfer_done;
- req.req.done_arg = &bd_buf_group;
- req.req.start = block;
- req.req.count = 1;
- req.req.bufnum = 1;
- req.req.bufs[0].length = dd->block_size;
- req.req.bufs[0].buffer = first_bd_buf->buffer;
-
- bdbuf_initialize_transfer_sema(first_bd_buf);
- /*
- * FIXME: check for following blocks to be:
- * - still in range of partition size
- * - not yet assigned
- * - buffer available
- * allocate for read call, if possible
- */
- find_more_buffers = TRUE;
- while (find_more_buffers) {
- block++;
- /*
- * still bd_buf_group entries free and
- * still in range of this disk?
- */
- if ((bd_buf_group.cnt >= READ_AHEAD_MAX_BLK_CNT) ||
- (block >= dd->size)) {
- find_more_buffers = FALSE;
- }
- if (find_more_buffers) {
- rc = find_or_assign_buffer(pdd, block, &bd_buf);
- if (rc != RTEMS_SUCCESSFUL) {
- find_more_buffers = FALSE;
- }
- else if (bd_buf->actual) {
- find_more_buffers = FALSE;
- bdbuf_release(bd_buf);
- }
- }
- if (find_more_buffers) {
- bdbuf_initialize_transfer_sema(bd_buf);
- bd_buf->in_progress = TRUE;
-
- req.req.bufs[req.req.count].length = dd->block_size;
- req.req.bufs[req.req.count].buffer = bd_buf->buffer;
- req.req.count++;
- req.req.bufnum++;
- bd_buf_group.bd_bufs[bd_buf_group.cnt] = bd_buf;
- bd_buf_group.cnt++;
- }
- }
-
- /* do the actual read call here
- */
- result = dd->ioctl(pdd->dev, BLKIO_REQUEST, &req);
-
- /*
- * cleanup:
- * wait, until all bd_bufs are processed
- * set status in all bd_bufs
- */
- for (i = 0;i < bd_buf_group.cnt;i++) {
- bd_buf = bd_buf_group.bd_bufs[i];
- if (result == -1)
- {
- bd_buf->status = RTEMS_IO_ERROR;
- bd_buf->error = errno;
- bd_buf->actual = FALSE;
- }
- else
- {
- rtems_interrupt_disable(level);
- _CORE_mutex_Seize(&bd_buf->transfer_sema, 0, TRUE,
- WATCHDOG_NO_TIMEOUT, level);
- bd_buf->actual = TRUE;
- }
- bd_buf->in_progress = FALSE;
- /* release any pre-read buffers */
- if (i > 0) {
- bdbuf_release(bd_buf);
- }
- }
- }
- rtems_disk_release(dd);
-
- ENABLE_PREEMPTION(key);
+ rtems_bdbuf_unlock_pool (pool);
+ rtems_disk_release (dd);
- *bd = first_bd_buf;
-
- return RTEMS_SUCCESSFUL;
-}
-#endif /* READ_MULTIPLE */
+ *bdp = bd;
+ return RTEMS_SUCCESSFUL;
+}
-/* bdbuf_release --
- * Release buffer. Decrease buffer usage counter. If it is zero, further
- * processing depends on modified attribute. If buffer was modified, it
- * is inserted into mod chain and swapout task waken up. If buffer was
- * not modified, it is returned to the end of lru chain making it available
- * for further use.
+/**
+ * Release buffer that has been in use. The buffer could have been in the
+ * access state and so with a user of the cache or it was being transfered to
+ * or from the disk media and so with a driver. Wake any waiters. If no one is
+ * waiting and this is the only buffer on the LRU list see if anyone is
+ * waiting. Wake them if they are.
*
- * PARAMETERS:
- * bd_buf - pointer to the released buffer descriptor.
- *
- * RETURNS:
- * RTEMS_SUCCESSFUL if buffer released successfully, or error code if
- * error occured.
+ * If the buffer has been modified use the modified release call.
*
- * NOTE:
- * This is internal function. It is assumed that task made non-preemptive
- * before its invocation.
+ * @param bd The buffer to return to the pool.
+ * @retval RTEMS_SUCCESSFUL This operation always succeeds.
*/
-static rtems_status_code
-bdbuf_release(bdbuf_buffer *bd_buf)
+
+rtems_status_code
+rtems_bdbuf_release (rtems_bdbuf_buffer* bd)
{
- bdbuf_pool *bd_pool;
- rtems_status_code rc = RTEMS_SUCCESSFUL;
+ rtems_bdbuf_pool* pool;
- if (bd_buf->use_count <= 0)
- return RTEMS_INTERNAL_ERROR;
+ if (bd == NULL)
+ return RTEMS_INVALID_ADDRESS;
- bd_pool = rtems_bdbuf_ctx.pool + bd_buf->pool;
+ pool = rtems_bdbuf_get_pool (bd->pool);
- bd_buf->use_count--;
+ rtems_bdbuf_lock_pool (pool);
- if (bd_buf->use_count == 0)
+#if RTEMS_BDBUF_TRACE
+ rtems_bdbuf_printf ("release: %d\n", bd->block);
+#endif
+
+ if (bd->state == RTEMS_BDBUF_STATE_ACCESS_MODIFIED)
+ {
+ rtems_bdbuf_append_modified (pool, bd);
+ }
+ else
+ {
+ /*
+ * If this is a read ahead buffer place the ready queue. Buffers are
+ * taken from here first. If we prepend then get from the queue the
+ * buffers furthermost from the read buffer will be used.
+ */
+ if (bd->state == RTEMS_BDBUF_STATE_READ_AHEAD)
+ rtems_chain_prepend (&pool->ready, &bd->link);
+ else
{
- if (bd_buf->modified)
- {
-
- /* Buffer was modified. Insert buffer to the modified buffers
- * list and initiate flushing. */
- rtems_chain_append(&rtems_bdbuf_ctx.mod, &bd_buf->link);
-
- /* Release the flush_sema */
- rc = rtems_semaphore_release(rtems_bdbuf_ctx.flush_sema);
- }
- else
- {
- /* Buffer was not modified. Add this descriptor to the
- * end of lru chain and make it available for reuse. */
- rtems_chain_append(&bd_pool->lru, &bd_buf->link);
- rc = rtems_semaphore_release(bd_pool->bufget_sema);
- }
+ bd->state = RTEMS_BDBUF_STATE_CACHED;
+ rtems_chain_append (&pool->lru, &bd->link);
}
- return rc;
-}
+ }
+
+ /*
+ * If there are threads waiting to access the buffer wake them. Wake any
+ * waiters if this is the first buffer to placed back onto the queue.
+ */
+ if (bd->waiters)
+ rtems_bdbuf_wake (pool->access, &pool->access_waiters);
+ else
+ {
+ if (bd->state == RTEMS_BDBUF_STATE_READ_AHEAD)
+ {
+ if (rtems_chain_has_only_one_node (&pool->ready))
+ rtems_bdbuf_wake (pool->waiting, &pool->wait_waiters);
+ }
+ else
+ {
+ if (rtems_chain_has_only_one_node (&pool->lru))
+ rtems_bdbuf_wake (pool->waiting, &pool->wait_waiters);
+ }
+ }
+
+ rtems_bdbuf_unlock_pool (pool);
+ return RTEMS_SUCCESSFUL;
+}
-/* rtems_bdbuf_release --
- * Release buffer allocated before. This primitive decrease the
- * usage counter. If it is zero, further destiny of buffer depends on
- * 'modified' status. If buffer was modified, it is placed to the end of
- * mod list and flush task waken up. If buffer was not modified,
- * it is placed to the end of lru list, and bufget_sema released, allowing
- * to reuse this buffer.
- *
- * PARAMETERS:
- * bd_buf - pointer to the bdbuf_buffer structure previously obtained using
- * get/read primitive.
+/**
+ * Release buffer that has been in use and has been modified. The buffer could
+ * have been in the access state and so with a user of the cache or it was
+ * being transfered to or from the disk media and so with a driver. Wake any
+ * waiters. If no one is waiting and this is the only buffer on the LRU list
+ * see if anyone is waiting. Wake them if they are.
*
- * RETURNS:
- * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
- * or error code if error is occured)
+ * If the buffer has been modified use the modified release call.
*
- * SIDE EFFECTS:
- * flush_sema and bufget_sema semaphores may be released by this primitive.
+ * @param bd The buffer to return to the pool.
+ * @retval RTEMS_SUCCESSFUL This operation always succeeds.
*/
+
rtems_status_code
-rtems_bdbuf_release(bdbuf_buffer *bd_buf)
+rtems_bdbuf_release_modified (rtems_bdbuf_buffer* bd)
{
- preemption_key key;
- rtems_status_code rc = RTEMS_SUCCESSFUL;
+ rtems_bdbuf_pool* pool;
- if (bd_buf == NULL)
- return RTEMS_INVALID_ADDRESS;
+ if (bd == NULL)
+ return RTEMS_INVALID_ADDRESS;
- DISABLE_PREEMPTION(key);
+ pool = rtems_bdbuf_get_pool (bd->pool);
- rc = bdbuf_release(bd_buf);
+ rtems_bdbuf_lock_pool (pool);
- ENABLE_PREEMPTION(key);
+#if RTEMS_BDBUF_TRACE
+ rtems_bdbuf_printf ("release modified: %d\n", bd->block);
+#endif
- return rc;
+ bd->hold_timer = rtems_bdbuf_configuration.swap_block_hold;
+
+ rtems_bdbuf_append_modified (pool, bd);
+
+ if (bd->waiters)
+ rtems_bdbuf_wake (pool->access, &pool->access_waiters);
+
+ rtems_bdbuf_unlock_pool (pool);
+
+ return RTEMS_SUCCESSFUL;
}
-/* rtems_bdbuf_release_modified --
- * Release buffer allocated before, assuming that it is _modified_ by
- * it's owner. This primitive decrease usage counter for buffer, mark
- * buffer descriptor as modified. If usage counter is 0, insert it at
- * end of mod chain and release flush_sema semaphore to activate the
- * flush task.
- *
- * PARAMETERS:
- * bd_buf - pointer to the bdbuf_buffer structure previously obtained using
- * get/read primitive.
+/**
+ * Wait until specified buffer synchronized with disk. Invoked on exchanges
+ * critical for data consistency on the media. The buffer is placed on the sync
+ * list and the swapper is woken. No sync lock is taken as the buffers on the
+ * sync list are taken first and passed to the driver before buffers on the
+ * modified list.
*
- * RETURNS:
- * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
- * or error code if error is occured)
+ * @note This code does not lock the sync mutex and stop additions to the
+ * modified queue. This means the buffer could be written and then
+ * returned to the modified list but will not happen as the buffer's
+ * state is sync.
*
- * SIDE EFFECTS:
- * flush_sema semaphore may be released by this primitive.
+ * @param bd Pointer to the bdbuf_buffer structure previously obtained using
+ * get/read primitive.
+ * @retval RTEMS_SUCCESSFUL Always returned.
*/
+
rtems_status_code
-rtems_bdbuf_release_modified(bdbuf_buffer *bd_buf)
+rtems_bdbuf_sync (rtems_bdbuf_buffer* bd)
{
- preemption_key key;
- rtems_status_code rc = RTEMS_SUCCESSFUL;
+ rtems_bdbuf_pool* pool;
+ boolean available;
+
+#if RTEMS_BDBUF_TRACE
+ rtems_bdbuf_printf ("sync: %d\n", bd->block);
+#endif
+
+ if (bd == NULL)
+ return RTEMS_INVALID_ADDRESS;
- if (bd_buf == NULL)
- return RTEMS_INVALID_ADDRESS;
+ pool = rtems_bdbuf_get_pool (bd->pool);
- DISABLE_PREEMPTION(key);
+ rtems_bdbuf_lock_pool (pool);
- if (!bd_buf->modified)
+ bd->state = RTEMS_BDBUF_STATE_SYNC;
+
+ rtems_chain_append (&pool->sync, &bd->link);
+
+ rtems_bdbuf_wake_swapper ();
+
+ available = FALSE;
+ while (!available)
+ {
+ switch (bd->state)
{
- bdbuf_initialize_transfer_sema(bd_buf);
+ case RTEMS_BDBUF_STATE_CACHED:
+ case RTEMS_BDBUF_STATE_READ_AHEAD:
+ case RTEMS_BDBUF_STATE_MODIFIED:
+ case RTEMS_BDBUF_STATE_ACCESS:
+ case RTEMS_BDBUF_STATE_ACCESS_MODIFIED:
+ available = TRUE;
+ break;
+
+ case RTEMS_BDBUF_STATE_SYNC:
+ case RTEMS_BDBUF_STATE_TRANSFER:
+ bd->waiters++;
+ rtems_bdbuf_wait (pool, &pool->transfer, &pool->transfer_waiters);
+ bd->waiters--;
+ break;
+
+ default:
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY);
}
- bd_buf->modified = TRUE;
- bd_buf->actual = TRUE;
- rc = bdbuf_release(bd_buf);
-
- ENABLE_PREEMPTION(key);
+ }
- return rc;
+ rtems_bdbuf_unlock_pool (pool);
+
+ return RTEMS_SUCCESSFUL;
}
-/* rtems_bdbuf_sync --
- * Wait until specified buffer synchronized with disk. Invoked on exchanges
- * critical for data consistency on the media. This primitive mark owned
- * block as modified, decrease usage counter. If usage counter is 0,
- * block inserted to the mod chain and flush_sema semaphore released.
- * Finally, primitives blocked on transfer_sema semaphore.
+/* rtems_bdbuf_syncdev --
+ * Synchronize with disk all buffers containing the blocks belonging to
+ * specified device.
*
* PARAMETERS:
- * bd_buf - pointer to the bdbuf_buffer structure previously obtained using
- * get/read primitive.
+ * dev - block device number
*
* RETURNS:
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
* or error code if error is occured)
- *
- * SIDE EFFECTS:
- * Primitive may be blocked on transfer_sema semaphore.
*/
rtems_status_code
-rtems_bdbuf_sync(bdbuf_buffer *bd_buf)
+rtems_bdbuf_syncdev (dev_t dev)
{
- preemption_key key;
- ISR_Level level;
- rtems_status_code rc = RTEMS_SUCCESSFUL;
+ rtems_disk_device* dd;
+ rtems_bdbuf_pool* pool;
+ rtems_status_code sc;
+ rtems_event_set out;
- if (bd_buf == NULL)
- return RTEMS_INVALID_ADDRESS;
-
- DISABLE_PREEMPTION(key);
+#if RTEMS_BDBUF_TRACE
+ rtems_bdbuf_printf ("syncdev: %08x\n", dev);
+#endif
- if (!bd_buf->modified)
- {
- bdbuf_initialize_transfer_sema(bd_buf);
- }
- bd_buf->modified = TRUE;
- bd_buf->actual = TRUE;
+ /*
+ * Do not hold the pool lock when obtaining the disk table.
+ */
+ dd = rtems_disk_obtain (dev);
+ if (dd == NULL)
+ return RTEMS_INVALID_ID;
+
+ pool = rtems_bdbuf_get_pool (dd->pool);
+
+ /*
+ * Take the sync lock before locking the pool. Once we have the sync lock
+ * we can lock the pool. If another thread has the sync lock it will cause
+ * this thread to block until it owns the sync lock then it can own the
+ * pool. The sync lock can only be obtained with the pool unlocked.
+ */
+
+ rtems_bdbuf_lock_sync (pool);
+ rtems_bdbuf_lock_pool (pool);
- rc = bdbuf_release(bd_buf);
+ pool->sync_active = TRUE;
+ pool->sync_requester = rtems_task_self ();
+ pool->sync_device = dev;
+
+ rtems_bdbuf_wake_swapper ();
+ rtems_bdbuf_unlock_pool (pool);
+
+ sc = rtems_event_receive (RTEMS_BDBUF_TRANSFER_SYNC,
+ RTEMS_EVENT_ALL | RTEMS_WAIT,
+ 0, &out);
- if (rc == RTEMS_SUCCESSFUL)
- {
- rtems_interrupt_disable(level);
- _CORE_mutex_Seize(&bd_buf->transfer_sema, 0, TRUE,
- WATCHDOG_NO_TIMEOUT, level);
- }
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (BLKDEV_FATAL_BDBUF_SWAPOUT_RE);
+
+ rtems_bdbuf_lock_pool (pool);
- ENABLE_PREEMPTION(key);
+ pool->sync_active = FALSE;
- return rc;
+ rtems_bdbuf_unlock_sync (pool);
+ rtems_bdbuf_unlock_pool (pool);
+
+ return rtems_disk_release(dd);
}
-/* rtems_bdbuf_syncdev --
- * Synchronize with disk all buffers containing the blocks belonging to
- * specified device.
+/* bdbuf_write_transfer_done --
+ * Callout function. Invoked by block device driver when data transfer
+ * to device (write) is completed. This function may be invoked from
+ * interrupt handler.
*
* PARAMETERS:
- * dev - block device number
+ * arg - arbitrary argument specified in block device request
+ * structure (in this case - pointer to the appropriate
+ * bdbuf_buffer buffer descriptor structure).
+ * status - I/O completion status
+ * error - errno error code if status != RTEMS_SUCCESSFUL
*
* RETURNS:
- * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
- * or error code if error is occured)
+ * none
*/
-rtems_status_code
-rtems_bdbuf_syncdev(dev_t dev)
+static void
+rtems_bdbuf_write_done(void *arg, rtems_status_code status, int error)
+{
+ rtems_blkdev_request* req = (rtems_blkdev_request*) arg;
+
+ req->error = error;
+ req->status = status;
+
+ rtems_event_send (req->io_task, RTEMS_BDBUF_TRANSFER_SYNC);
+}
+
+/**
+ * Process the modified list of buffers. We can have a sync or modified
+ * list that needs to be handled.
+ */
+static void
+rtems_bdbuf_swapout_modified_processing (rtems_bdpool_id pid,
+ dev_t* dev,
+ rtems_chain_control* chain,
+ rtems_chain_control* transfer,
+ boolean sync_active,
+ boolean update_timers,
+ uint32_t timer_delta)
{
- preemption_key key;
- ISR_Level level;
+ if (!rtems_chain_is_empty (chain))
+ {
+ rtems_chain_node* node = rtems_chain_head (chain);
+ node = node->next;
+
+ while (!rtems_chain_is_tail (chain, node))
+ {
+ rtems_bdbuf_buffer* bd = (rtems_bdbuf_buffer*) node;
+
+ if (bd->pool == pid)
+ {
+ /*
+ * Check if the buffer's hold timer has reached 0. If a sync
+ * is active force all the timers to 0.
+ *
+ * @note Lots of sync requests will skew this timer. It should
+ * be based on TOD to be accurate. Does it matter ?
+ */
+ if (sync_active)
+ bd->hold_timer = 0;
+
+ if (bd->hold_timer)
+ {
+ if (update_timers)
+ {
+ if (bd->hold_timer > timer_delta)
+ bd->hold_timer -= timer_delta;
+ else
+ bd->hold_timer = 0;
+ }
+
+ if (bd->hold_timer)
+ {
+ node = node->next;
+ continue;
+ }
+ }
- bdbuf_buffer *bd_buf;
- disk_device *dd;
- bdbuf_pool *pool;
+ /*
+ * This assumes we can set dev_t to -1 which is just an
+ * assumption. Cannot use the transfer list being empty
+ * the sync dev calls sets the dev to use.
+ */
+ if (*dev == -1)
+ *dev = bd->dev;
- dd = rtems_disk_lookup(dev);
+ if (bd->dev == *dev)
+ {
+ rtems_chain_node* next_node = node->next;
+ rtems_chain_extract (node);
+ rtems_chain_append (transfer, node);
+ node = next_node;
+ bd->state = RTEMS_BDBUF_STATE_TRANSFER;
+ }
+ else
+ {
+ node = node->next;
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Process the pool.
+ */
+static boolean
+rtems_bdbuf_swapout_pool_processing (rtems_bdpool_id pid,
+ unsigned long timer_delta,
+ boolean update_timers,
+ rtems_blkdev_request* write_req)
+{
+ rtems_bdbuf_pool* pool = rtems_bdbuf_get_pool (pid);
+ rtems_chain_control transfer;
+ dev_t dev = -1;
+ rtems_disk_device* dd;
+ boolean result = TRUE;
+
+ rtems_chain_initialize_empty (&transfer);
+
+ rtems_bdbuf_lock_pool (pool);
+
+ if (pool->sync_active)
+ dev = pool->sync_device;
+
+#if 1
+ /*
+ * If we have any buffers in the sync queue move then to the
+ * modified list. The first sync buffer will select the
+ * device we use.
+ */
+ rtems_bdbuf_swapout_modified_processing (pid, &dev,
+ &pool->sync, &transfer,
+ TRUE, FALSE,
+ timer_delta);
+
+ /*
+ * Process the pool's modified list.
+ */
+ rtems_bdbuf_swapout_modified_processing (pid, &dev,
+ &pool->modified, &transfer,
+ pool->sync_active,
+ update_timers,
+ timer_delta);
+
+ /*
+ * We have all the buffers that have been modified for this device so
+ * the pool can be unlocked because the state is set to TRANSFER.
+ */
+#endif
+ rtems_bdbuf_unlock_pool (pool);
+
+ /*
+ * If there are buffers to transfer to the media tranfer them.
+ */
+ if (rtems_chain_is_empty (&transfer))
+ result = FALSE;
+ else
+ {
+ /*
+ * Obtain the disk device. Release the pool mutex to avoid a dead
+ * lock.
+ */
+ dd = rtems_disk_obtain (dev);
if (dd == NULL)
- return RTEMS_INVALID_ID;
+ result = FALSE;
+ else
+ {
+ /*
+ * The last block number used when the driver only supports
+ * continuous blocks in a single request.
+ */
+ uint32_t last_block = 0;
+
+ /*
+ * Take as many buffers are configured and pass to the driver. Note,
+ * the API to the drivers has the array of buffers and if a chain was
+ * passed we could have just passed the list. If the driver API is
+ * updated it should be possible to make this change with little effect
+ * in this code. The array that is passed is broken in design and
+ * should be removed. Merging to members of a struct into the first
+ * member is trouble waiting to happen.
+ */
+
+ write_req->status = RTEMS_RESOURCE_IN_USE;
+ write_req->start = dd->start;
+ write_req->error = 0;
+ write_req->count = 0;
+ write_req->bufnum = 0;
+
+ while (!rtems_chain_is_empty (&transfer))
+ {
+ rtems_bdbuf_buffer* bd =
+ (rtems_bdbuf_buffer*) rtems_chain_get (&transfer);
+
+ boolean write = FALSE;
+
+ /*
+ * If the device only accepts sequential buffers and
+ * this is not the first buffer (the first is always
+ * sequential, and the buffer is not sequential then
+ * put the buffer back on the transfer chain and
+ * write the committed buffers.
+ */
+
+ if ((dd->capabilities & RTEMS_BLKDEV_CAP_MULTISECTOR_CONT) &&
+ write_req->count &&
+ (bd->block != (last_block + 1)))
+ {
+ rtems_chain_prepend (&transfer, &bd->link);
+ write = TRUE;
+ }
+ else
+ {
+ write_req->bufs[write_req->count].user = bd;
+ write_req->bufs[write_req->count].block = bd->block;
+ write_req->bufs[write_req->count].length = dd->block_size;
+ write_req->bufs[write_req->count].buffer = bd->buffer;
+ write_req->count++;
+ write_req->bufnum++;
+ last_block = bd->block;
+ }
- pool = rtems_bdbuf_ctx.pool + dd->pool;
+ /*
+ * Perform the transfer if there are no more buffers, or the
+ * transfer size has reached the configured max. value.
+ */
- DISABLE_PREEMPTION(key);
- do {
- bd_buf = avl_search_for_sync(&pool->tree, dd);
- if (bd_buf != NULL /* && bd_buf->modified */)
+ if (rtems_chain_is_empty (&transfer) ||
+ (write_req->count >= rtems_bdbuf_configuration.max_write_blocks))
+ write = TRUE;
+
+ if (write)
{
- rtems_interrupt_disable(level);
- _CORE_mutex_Seize(&bd_buf->transfer_sema, 0, TRUE,
- WATCHDOG_NO_TIMEOUT, level);
+ int result;
+ int b;
+
+ /*
+ * Perform the transfer. No pool locks, no preemption, only the
+ * disk device is being held.
+ */
+ result = dd->ioctl (dd->phys_dev->dev,
+ RTEMS_BLKIO_REQUEST, write_req);
+
+ if (result < 0)
+ {
+ rtems_bdbuf_lock_pool (pool);
+
+ for (b = 0; b < write_req->count; b++)
+ {
+ bd = write_req->bufs[b].user;
+ bd->state = RTEMS_BDBUF_STATE_MODIFIED;
+ bd->error = errno;
+
+ /*
+ * Place back on the pools modified queue and try again.
+ *
+ * @warning Not sure this is the best option but I do
+ * not know what else can be done.
+ */
+ rtems_chain_append (&pool->modified, &bd->link);
+ }
+ }
+ else
+ {
+ rtems_status_code sc = 0;
+ rtems_event_set out;
+
+ sc = rtems_event_receive (RTEMS_BDBUF_TRANSFER_SYNC,
+ RTEMS_EVENT_ALL | RTEMS_WAIT,
+ 0, &out);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (BLKDEV_FATAL_BDBUF_SWAPOUT_RE);
+
+ rtems_bdbuf_lock_pool (pool);
+
+ for (b = 0; b < write_req->count; b++)
+ {
+ bd = write_req->bufs[b].user;
+ bd->state = RTEMS_BDBUF_STATE_CACHED;
+ bd->error = 0;
+
+ rtems_chain_append (&pool->lru, &bd->link);
+
+ if (bd->waiters)
+ rtems_bdbuf_wake (pool->transfer, &pool->transfer_waiters);
+ else
+ {
+ if (rtems_chain_has_only_one_node (&pool->lru))
+ rtems_bdbuf_wake (pool->waiting, &pool->wait_waiters);
+ }
+ }
+ }
+
+ rtems_bdbuf_unlock_pool (pool);
+
+ write_req->status = RTEMS_RESOURCE_IN_USE;
+ write_req->error = 0;
+ write_req->count = 0;
+ write_req->bufnum = 0;
}
- } while (bd_buf != NULL);
- ENABLE_PREEMPTION(key);
- return rtems_disk_release(dd);
+ }
+
+ rtems_disk_release (dd);
+ }
+ }
+
+ if (pool->sync_active)
+ rtems_event_send (pool->sync_requester, RTEMS_BDBUF_TRANSFER_SYNC);
+
+ return result;
}
-/* bdbuf_swapout_task --
- * Body of task which take care on flushing modified buffers to the
- * disk.
+/**
+ * Body of task which take care on flushing modified buffers to the disk.
*/
static rtems_task
-bdbuf_swapout_task(rtems_task_argument unused)
+rtems_bdbuf_swapout_task (rtems_task_argument arg)
{
- rtems_status_code rc;
- int result;
- int i;
- ISR_Level level;
- bdbuf_buffer *bd_buf;
- bdbuf_buffer *nxt_bd_buf;
- bdbuf_pool *bd_pool = NULL;
- disk_device *dd = NULL;
- struct {
- blkdev_request req;
- blkdev_sg_buffer sg[SWAP_OUT_MAX_BLK_CNT];
- } req;
- write_tfer_done_arg_t write_tfer_done_arg;
+ rtems_bdbuf_context* context = (rtems_bdbuf_context*) arg;
+ rtems_blkdev_request* write_req;
+ uint32_t period_in_ticks;
+ const uint32_t period_in_msecs = rtems_bdbuf_configuration.swapout_period;
+ uint32_t timer_delta;
+ rtems_status_code sc;
+
+ /*
+ * @note chrisj The rtems_blkdev_request and the array at the end is a hack.
+ * I am disappointment at finding code like this in RTEMS. The request should
+ * have been a rtems_chain_control. Simple, fast and less storage as the node
+ * is already part of the buffer structure.
+ */
+ write_req =
+ malloc (sizeof (rtems_blkdev_request) +
+ (rtems_bdbuf_configuration.max_write_blocks *
+ sizeof (rtems_blkdev_sg_buffer)));
+
+ if (!write_req)
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_SO_NOMEM);
+
+ write_req->req = RTEMS_BLKDEV_REQ_WRITE;
+ write_req->req_done = rtems_bdbuf_write_done;
+ write_req->done_arg = write_req;
+ write_req->io_task = rtems_task_self ();
+
+ period_in_ticks = TOD_MICROSECONDS_TO_TICKS (period_in_msecs * 1000);
+
+ /*
+ * This is temporary. Needs to be changed to use the real clock.
+ */
+ timer_delta = period_in_msecs;
+
+ while (context->swapout_enabled)
+ {
+ rtems_event_set out;
/*
- * provide info needed for write_transfer_done function
+ * Only update the timers once in the processing cycle.
*/
- write_tfer_done_arg.req = (blkdev_request *)&req.req;
- write_tfer_done_arg.write_store = bd_buf_write_store;
- nxt_bd_buf = NULL;
- while (1)
+ boolean update_timers = TRUE;
+
+ /*
+ * If we write buffers to any disk perform a check again. We only
+ * write a single device at a time and a pool may have more than
+ * one devices buffers modified waiting to be written.
+ */
+ boolean transfered_buffers;
+
+ do
{
- req.req.req = BLKDEV_REQ_WRITE;
- req.req.req_done = bdbuf_write_transfer_done;
- req.req.done_arg = &write_tfer_done_arg;
- req.req.count = 0;
- req.req.bufnum = 0;
- bd_buf = NULL;
- do {
- /*
- * if a buffer was left over from last loop, then use this buffer
- * otherwise fetch new buffer from chain.
- * Wait for buffer, if this is the first one of the request,
- * otherwise do not wait, if no buffer available
- */
- if (nxt_bd_buf == NULL) {
- rc = rtems_semaphore_obtain(rtems_bdbuf_ctx.flush_sema,
- (req.req.count == 0)
- ? RTEMS_WAIT
- : RTEMS_NO_WAIT,
- 0);
- if (rc == RTEMS_SUCCESSFUL) {
- nxt_bd_buf = (bdbuf_buffer *)rtems_chain_get(&rtems_bdbuf_ctx.mod);
- if (nxt_bd_buf != NULL) {
- nxt_bd_buf->in_progress = TRUE;
- /* IMD try: clear "modified" bit early */
- /* (and not in bdbuf_write_transfer_done) to allow */
- /* another modification during write processing */
- nxt_bd_buf->modified = FALSE;
-
- nxt_bd_buf->use_count++;
- }
- }
- else if ((rc != RTEMS_UNSATISFIED) &&
- (rc != RTEMS_TIMEOUT)) {
- rtems_fatal_error_occurred(BLKDEV_FATAL_BDBUF_SWAPOUT);
- }
- }
- /*
- * It is possible that flush_sema semaphore will be released, but
- * buffer to be removed from mod chain before swapout task start
- * its processing.
- */
- if ((req.req.count == 0) || /* first bd_buf for this request */
- ((nxt_bd_buf != NULL) &&
- (nxt_bd_buf->dev == bd_buf->dev) && /* same device */
- (nxt_bd_buf->block == bd_buf->block+1))) {/* next block */
- bd_buf = nxt_bd_buf;
- nxt_bd_buf = NULL;
- }
- else {
- bd_buf = NULL;
- }
- /*
- * here we have three possible states:
- * bd_buf == NULL, nxt_bd_buf == NULL: no further block available
- * bd_buf != NULL, nxt_bd_buf == NULL: append bd_buf to request
- * bd_buf == NULL, nxt_bd_buf != NULL: nxt_bd_buf canot be appended
- * to current request, keep it
- * for next main loop
- */
- if (bd_buf != NULL) {
- bd_pool = rtems_bdbuf_ctx.pool + bd_buf->pool;
- if (req.req.count == 0) {
- /*
- * this is the first block, so use its address
- */
- dd = rtems_disk_lookup(bd_buf->dev);
- req.req.start = bd_buf->block + dd->start;
- }
- req.req.bufs[req.req.bufnum].length = dd->block_size;
- req.req.bufs[req.req.bufnum].buffer = bd_buf->buffer;
- /*
- * keep bd_buf for postprocessing
- */
- bd_buf_write_store[req.req.bufnum] = bd_buf;
- req.req.count++;
- req.req.bufnum++;
- }
- } while ((bd_buf != NULL) &&
- (req.req.count < SWAP_OUT_MAX_BLK_CNT));
-
- /* transfer_sema initialized when bd_buf inserted in the mod chain
- first time */
- result = dd->ioctl(dd->phys_dev->dev, BLKIO_REQUEST, &req);
-
- rtems_disk_release(dd);
-
- for (i = 0;i < req.req.count;i++) {
- bd_buf = bd_buf_write_store[i];
- if (result == -1)
- {
-
- bd_buf->status = RTEMS_IO_ERROR;
- bd_buf->error = errno;
- /* Release tasks waiting on syncing this buffer */
- _CORE_mutex_Flush(&bd_buf->transfer_sema, NULL,
- CORE_MUTEX_STATUS_SUCCESSFUL);
- }
- else
- {
- if (bd_buf->in_progress)
- {
- rtems_interrupt_disable(level);
- _CORE_mutex_Seize(&bd_buf->transfer_sema, 0, TRUE, 0, level);
- }
- }
- bd_buf->use_count--;
-
- /* Another task have chance to use this buffer, or even
- * modify it. If buffer is not in use, insert it in appropriate chain
- * and release semaphore */
- if (bd_buf->use_count == 0)
- {
- if (bd_buf->modified)
- {
- rtems_chain_append(&rtems_bdbuf_ctx.mod, &bd_buf->link);
- rc = rtems_semaphore_release(rtems_bdbuf_ctx.flush_sema);
- }
- else
- {
- rtems_chain_append(&bd_pool->lru, &bd_buf->link);
- rc = rtems_semaphore_release(bd_pool->bufget_sema);
- }
- }
+ rtems_bdpool_id pid;
+
+ transfered_buffers = FALSE;
+
+ /*
+ * Loop over each pool extacting all the buffers we find for a specific
+ * device. The device is the first one we find on a modified list of a
+ * pool. Process the sync queue of buffers first.
+ */
+ for (pid = 0; pid < context->npools; pid++)
+ {
+ if (rtems_bdbuf_swapout_pool_processing (pid,
+ timer_delta,
+ update_timers,
+ write_req))
+ {
+ transfered_buffers = TRUE;
}
+ }
+
+ /*
+ * Only update the timers once.
+ */
+ update_timers = FALSE;
}
+ while (transfered_buffers);
+
+ sc = rtems_event_receive (RTEMS_BDBUF_SWAPOUT_SYNC,
+ RTEMS_EVENT_ALL | RTEMS_WAIT,
+ period_in_ticks,
+ &out);
+
+ if ((sc != RTEMS_SUCCESSFUL) && (sc != RTEMS_TIMEOUT))
+ rtems_fatal_error_occurred (BLKDEV_FATAL_BDBUF_SWAPOUT_RE);
+ }
+
+ free (write_req);
+
+ rtems_task_delete (RTEMS_SELF);
}
-/* rtems_bdbuf_find_pool --
- * 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.
+/**
+ * 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.
*
* PARAMETERS:
* block_size - requested block size
@@ -1813,44 +2380,45 @@ bdbuf_swapout_task(rtems_task_argument unused)
* is not configured.
*/
rtems_status_code
-rtems_bdbuf_find_pool(int block_size, rtems_bdpool_id *pool)
+rtems_bdbuf_find_pool (int block_size, rtems_bdpool_id *pool)
{
- rtems_bdpool_id i;
- bdbuf_pool *p;
- int cursize = INT_MAX;
- rtems_bdpool_id curid = -1;
- rtems_boolean found = FALSE;
- int j;
-
- for (j = block_size; (j != 0) && ((j & 1) == 0); j >>= 1);
- if (j != 1)
- return RTEMS_INVALID_SIZE;
-
- for (i = 0, p = rtems_bdbuf_ctx.pool; i < rtems_bdbuf_ctx.npools; i++, p++)
+ rtems_bdbuf_pool* p;
+ rtems_bdpool_id i;
+ rtems_bdpool_id curid = -1;
+ rtems_boolean found = FALSE;
+ int cursize = INT_MAX;
+ int j;
+
+ for (j = block_size; (j != 0) && ((j & 1) == 0); j >>= 1);
+ if (j != 1)
+ return RTEMS_INVALID_SIZE;
+
+ for (i = 0; i < rtems_bdbuf_ctx.npools; i++)
+ {
+ p = rtems_bdbuf_get_pool (i);
+ if ((p->blksize >= block_size) &&
+ (p->blksize < cursize))
{
- if ((p->blksize >= block_size) &&
- (p->blksize < cursize))
- {
- curid = i;
- cursize = p->blksize;
- found = TRUE;
- }
+ curid = i;
+ cursize = p->blksize;
+ found = TRUE;
}
+ }
- if (found)
- {
- if (pool != NULL)
- *pool = curid;
- return RTEMS_SUCCESSFUL;
- }
- else
- {
- return RTEMS_NOT_DEFINED;
- }
+ if (found)
+ {
+ if (pool != NULL)
+ *pool = curid;
+ return RTEMS_SUCCESSFUL;
+ }
+ else
+ {
+ return RTEMS_NOT_DEFINED;
+ }
}
-/* rtems_bdbuf_get_pool_info --
- * Obtain characteristics of buffer pool with specified number.
+/**
+ * Obtain characteristics of buffer pool with specified number.
*
* PARAMETERS:
* pool - buffer pool number
@@ -1866,21 +2434,20 @@ rtems_bdbuf_find_pool(int block_size, rtems_bdpool_id *pool)
* Buffer pools enumerated contiguously starting from 0.
*/
rtems_status_code
-rtems_bdbuf_get_pool_info(rtems_bdpool_id pool, int *block_size,
- int *blocks)
+rtems_bdbuf_get_pool_info(rtems_bdpool_id pool, int* block_size, int* blocks)
{
- if (pool >= rtems_bdbuf_ctx.npools)
- return RTEMS_INVALID_NUMBER;
+ if (pool >= rtems_bdbuf_ctx.npools)
+ return RTEMS_INVALID_NUMBER;
- if (block_size != NULL)
- {
- *block_size = rtems_bdbuf_ctx.pool[pool].blksize;
- }
+ if (block_size != NULL)
+ {
+ *block_size = rtems_bdbuf_ctx.pool[pool].blksize;
+ }
- if (blocks != NULL)
- {
- *blocks = rtems_bdbuf_ctx.pool[pool].nblks;
- }
+ if (blocks != NULL)
+ {
+ *blocks = rtems_bdbuf_ctx.pool[pool].nblks;
+ }
- return RTEMS_SUCCESSFUL;
+ return RTEMS_SUCCESSFUL;
}
diff --git a/cpukit/libblock/src/blkdev.c b/cpukit/libblock/src/blkdev.c
index e133e5eaf2..a93875c9a2 100644
--- a/cpukit/libblock/src/blkdev.c
+++ b/cpukit/libblock/src/blkdev.c
@@ -38,10 +38,10 @@ rtems_blkdev_generic_read(
unsigned int block;
unsigned int blkofs;
dev_t dev;
- disk_device *dd;
+ rtems_disk_device *dd;
dev = rtems_filesystem_make_dev_t(major, minor);
- dd = rtems_disk_lookup(dev);
+ dd = rtems_disk_obtain(dev);
if (dd == NULL)
return RTEMS_INVALID_NUMBER;
@@ -57,7 +57,7 @@ rtems_blkdev_generic_read(
while (count > 0)
{
- bdbuf_buffer *diskbuf;
+ rtems_bdbuf_buffer *diskbuf;
int copy;
rtems_status_code rc;
@@ -99,10 +99,10 @@ rtems_blkdev_generic_write(
unsigned int blkofs;
dev_t dev;
rtems_status_code rc;
- disk_device *dd;
+ rtems_disk_device *dd;
dev = rtems_filesystem_make_dev_t(major, minor);
- dd = rtems_disk_lookup(dev);
+ dd = rtems_disk_obtain(dev);
if (dd == NULL)
return RTEMS_INVALID_NUMBER;
@@ -118,7 +118,7 @@ rtems_blkdev_generic_write(
while (count > 0)
{
- bdbuf_buffer *diskbuf;
+ rtems_bdbuf_buffer *diskbuf;
int copy;
if ((blkofs == 0) && (count >= block_size))
@@ -156,10 +156,10 @@ rtems_blkdev_generic_open(
void * arg)
{
dev_t dev;
- disk_device *dd;
+ rtems_disk_device *dd;
dev = rtems_filesystem_make_dev_t(major, minor);
- dd = rtems_disk_lookup(dev);
+ dd = rtems_disk_obtain(dev);
if (dd == NULL)
return RTEMS_INVALID_NUMBER;
@@ -181,10 +181,10 @@ rtems_blkdev_generic_close(
void * arg)
{
dev_t dev;
- disk_device *dd;
+ rtems_disk_device *dd;
dev = rtems_filesystem_make_dev_t(major, minor);
- dd = rtems_disk_lookup(dev);
+ dd = rtems_disk_obtain(dev);
if (dd == NULL)
return RTEMS_INVALID_NUMBER;
@@ -206,32 +206,32 @@ rtems_blkdev_generic_ioctl(
{
rtems_libio_ioctl_args_t *args = arg;
dev_t dev;
- disk_device *dd;
+ rtems_disk_device *dd;
int rc;
dev = rtems_filesystem_make_dev_t(major, minor);
- dd = rtems_disk_lookup(dev);
+ dd = rtems_disk_obtain(dev);
if (dd == NULL)
return RTEMS_INVALID_NUMBER;
switch (args->command)
{
- case BLKIO_GETBLKSIZE:
+ case RTEMS_BLKIO_GETBLKSIZE:
args->ioctl_return = dd->block_size;
break;
- case BLKIO_GETSIZE:
+ case RTEMS_BLKIO_GETSIZE:
args->ioctl_return = dd->size;
break;
- case BLKIO_SYNCDEV:
+ case RTEMS_BLKIO_SYNCDEV:
rc = rtems_bdbuf_syncdev(dd->dev);
args->ioctl_return = (rc == RTEMS_SUCCESSFUL ? 0 : -1);
break;
- case BLKIO_REQUEST:
+ case RTEMS_BLKIO_REQUEST:
{
- blkdev_request *req = args->buffer;
+ rtems_blkdev_request *req = args->buffer;
req->start += dd->start;
args->ioctl_return = dd->ioctl(dd->phys_dev->dev, args->command,
req);
diff --git a/cpukit/libblock/src/diskdevs.c b/cpukit/libblock/src/diskdevs.c
index 545a4096e7..94a58daa6f 100644
--- a/cpukit/libblock/src/diskdevs.c
+++ b/cpukit/libblock/src/diskdevs.c
@@ -23,13 +23,13 @@
#define DISKTAB_INITIAL_SIZE 32
/* Table of disk devices having the same major number */
-struct disk_device_table {
- disk_device **minor; /* minor-indexed disk device table */
+typedef struct rtems_disk_device_table {
+ rtems_disk_device **minor; /* minor-indexed disk device table */
int size; /* Number of entries in the table */
-};
+} rtems_disk_device_table;
/* Pointer to [major].minor[minor] indexed array of disk devices */
-static struct disk_device_table *disktab;
+static rtems_disk_device_table *disktab;
/* Number of allocated entries in disktab table */
static int disktab_size;
@@ -64,24 +64,24 @@ static volatile rtems_boolean diskdevs_protected;
* pointer to the disk device descriptor entry, or NULL if no memory
* available for its creation.
*/
-static disk_device *
+static rtems_disk_device *
create_disk_entry(dev_t dev)
{
rtems_device_major_number major;
rtems_device_minor_number minor;
- struct disk_device **d;
+ rtems_disk_device **d;
rtems_filesystem_split_dev_t (dev, major, minor);
if (major >= disktab_size)
{
- struct disk_device_table *p;
+ rtems_disk_device_table *p;
int newsize;
int i;
newsize = disktab_size * 2;
if (major >= newsize)
newsize = major + 1;
- p = realloc(disktab, sizeof(struct disk_device_table) * newsize);
+ p = realloc(disktab, sizeof(rtems_disk_device_table) * newsize);
if (p == NULL)
return NULL;
p += disktab_size;
@@ -97,7 +97,7 @@ create_disk_entry(dev_t dev)
(minor >= disktab[major].size))
{
int newsize;
- disk_device **p;
+ rtems_disk_device **p;
int i;
int s = disktab[major].size;
@@ -108,7 +108,8 @@ create_disk_entry(dev_t dev)
if (minor >= newsize)
newsize = minor + 1;
- p = realloc(disktab[major].minor, sizeof(disk_device *) * newsize);
+ p = realloc(disktab[major].minor,
+ sizeof(rtems_disk_device *) * newsize);
if (p == NULL)
return NULL;
disktab[major].minor = p;
@@ -121,7 +122,7 @@ create_disk_entry(dev_t dev)
d = disktab[major].minor + minor;
if (*d == NULL)
{
- *d = calloc(1, sizeof(disk_device));
+ *d = calloc(1, sizeof(rtems_disk_device));
}
return *d;
}
@@ -136,12 +137,12 @@ create_disk_entry(dev_t dev)
* Pointer to the disk device descriptor corresponding to the specified
* device number, or NULL if disk device with such number not exists.
*/
-static inline disk_device *
+static rtems_disk_device *
get_disk_entry(dev_t dev)
{
rtems_device_major_number major;
rtems_device_minor_number minor;
- struct disk_device_table *dtab;
+ rtems_disk_device_table *dtab;
rtems_filesystem_split_dev_t (dev, major, minor);
@@ -171,9 +172,9 @@ get_disk_entry(dev_t dev)
* no memory available).
*/
static rtems_status_code
-create_disk(dev_t dev, const char *name, disk_device **diskdev)
+create_disk(dev_t dev, const char *name, rtems_disk_device **diskdev)
{
- disk_device *dd;
+ rtems_disk_device *dd;
char *n;
dd = get_disk_entry(dev);
@@ -234,12 +235,12 @@ create_disk(dev_t dev, const char *name, disk_device **diskdev)
*/
rtems_status_code
rtems_disk_create_phys(dev_t dev, int block_size, int disk_size,
- block_device_ioctl handler,
+ rtems_block_device_ioctl handler,
const char *name)
{
int bs_log2;
int i;
- disk_device *dd;
+ rtems_disk_device *dd;
rtems_status_code rc;
rtems_bdpool_id pool;
rtems_device_major_number major;
@@ -284,6 +285,11 @@ rtems_disk_create_phys(dev_t dev, int block_size, int disk_size,
rc = rtems_io_register_name(name, major, minor);
+ if (handler (dd->phys_dev->dev,
+ RTEMS_BLKDEV_CAPABILITIES,
+ &dd->capabilities) < 0)
+ dd->capabilities = 0;
+
diskdevs_protected = FALSE;
rtems_semaphore_release(diskdevs_mutex);
@@ -317,8 +323,8 @@ rtems_disk_create_phys(dev_t dev, int block_size, int disk_size,
rtems_status_code
rtems_disk_create_log(dev_t dev, dev_t phys, int start, int size, char *name)
{
- disk_device *dd;
- disk_device *pdd;
+ rtems_disk_device *dd;
+ rtems_disk_device *pdd;
rtems_status_code rc;
rtems_device_major_number major;
rtems_device_minor_number minor;
@@ -393,12 +399,12 @@ rtems_disk_delete(dev_t dev)
used = 0;
for (maj = 0; maj < disktab_size; maj++)
{
- struct disk_device_table *dtab = disktab + maj;
+ rtems_disk_device_table *dtab = disktab + maj;
if (dtab != NULL)
{
for (min = 0; min < dtab->size; min++)
{
- disk_device *dd = dtab->minor[min];
+ rtems_disk_device *dd = dtab->minor[min];
if ((dd != NULL) && (dd->phys_dev->dev == dev))
used += dd->uses;
}
@@ -415,12 +421,12 @@ rtems_disk_delete(dev_t dev)
/* Delete this device and all of its logical devices */
for (maj = 0; maj < disktab_size; maj++)
{
- struct disk_device_table *dtab = disktab +maj;
+ rtems_disk_device_table *dtab = disktab +maj;
if (dtab != NULL)
{
for (min = 0; min < dtab->size; min++)
{
- disk_device *dd = dtab->minor[min];
+ rtems_disk_device *dd = dtab->minor[min];
if ((dd != NULL) && (dd->phys_dev->dev == dev))
{
unlink(dd->name);
@@ -437,7 +443,7 @@ rtems_disk_delete(dev_t dev)
return rc;
}
-/* rtems_disk_lookup --
+/* rtems_disk_obtain --
* Find block device descriptor by its device identifier.
*
* PARAMETERS:
@@ -447,11 +453,11 @@ rtems_disk_delete(dev_t dev)
* pointer to the block device descriptor, or NULL if no such device
* exists.
*/
-disk_device *
-rtems_disk_lookup(dev_t dev)
+rtems_disk_device *
+rtems_disk_obtain(dev_t dev)
{
rtems_interrupt_level level;
- disk_device *dd;
+ rtems_disk_device *dd;
rtems_status_code rc;
rtems_interrupt_disable(level);
@@ -480,7 +486,7 @@ rtems_disk_lookup(dev_t dev)
}
/* rtems_disk_release --
- * Release disk_device structure (decrement usage counter to 1).
+ * Release rtems_disk_device structure (decrement usage counter to 1).
*
* PARAMETERS:
* dd - pointer to disk device structure
@@ -489,7 +495,7 @@ rtems_disk_lookup(dev_t dev)
* RTEMS_SUCCESSFUL
*/
rtems_status_code
-rtems_disk_release(disk_device *dd)
+rtems_disk_release(rtems_disk_device *dd)
{
rtems_interrupt_level level;
rtems_interrupt_disable(level);
@@ -510,12 +516,12 @@ rtems_disk_release(disk_device *dd)
* Pointer to the disk descriptor for next disk device, or NULL if all
* devices enumerated.
*/
-disk_device *
+rtems_disk_device *
rtems_disk_next(dev_t dev)
{
rtems_device_major_number major;
rtems_device_minor_number minor;
- struct disk_device_table *dtab;
+ rtems_disk_device_table *dtab;
dev++;
rtems_filesystem_split_dev_t (dev, major, minor);
@@ -562,7 +568,7 @@ rtems_disk_io_initialize(void)
return RTEMS_SUCCESSFUL;
disktab_size = DISKTAB_INITIAL_SIZE;
- disktab = calloc(disktab_size, sizeof(struct disk_device_table));
+ disktab = calloc(disktab_size, sizeof(rtems_disk_device_table));
if (disktab == NULL)
return RTEMS_NO_MEMORY;
@@ -578,8 +584,7 @@ rtems_disk_io_initialize(void)
return rc;
}
- rc = rtems_bdbuf_init(rtems_bdbuf_configuration,
- rtems_bdbuf_configuration_size);
+ rc = rtems_bdbuf_init();
if (rc != RTEMS_SUCCESSFUL)
{
@@ -612,12 +617,12 @@ rtems_disk_io_done(void)
/* Free data structures */
for (maj = 0; maj < disktab_size; maj++)
{
- struct disk_device_table *dtab = disktab + maj;
+ rtems_disk_device_table *dtab = disktab + maj;
if (dtab != NULL)
{
for (min = 0; min < dtab->size; min++)
{
- disk_device *dd = dtab->minor[min];
+ rtems_disk_device *dd = dtab->minor[min];
unlink(dd->name);
free(dd->name);
free(dd);
diff --git a/cpukit/libblock/src/flashdisk.c b/cpukit/libblock/src/flashdisk.c
index 4e8b261a93..d67d4a02bf 100644
--- a/cpukit/libblock/src/flashdisk.c
+++ b/cpukit/libblock/src/flashdisk.c
@@ -2057,14 +2057,13 @@ rtems_fdisk_write_block (rtems_flashdisk* fd,
* @retval int The ioctl return value.
*/
static int
-rtems_fdisk_read (rtems_flashdisk* fd, blkdev_request* req)
+rtems_fdisk_read (rtems_flashdisk* fd, rtems_blkdev_request* req)
{
- blkdev_sg_buffer* sg = req->bufs;
- uint32_t block = req->start;
- uint32_t b;
- int ret = 0;
+ rtems_blkdev_sg_buffer* sg = req->bufs;
+ uint32_t b;
+ int ret = 0;
- for (b = 0; b < req->bufnum; b++, block++, sg++)
+ for (b = 0; b < req->bufnum; b++, sg++)
{
uint32_t length = sg->length;
@@ -2077,7 +2076,7 @@ rtems_fdisk_read (rtems_flashdisk* fd, blkdev_request* req)
length = fd->block_size;
}
- ret = rtems_fdisk_read_block (fd, block, sg->buffer);
+ ret = rtems_fdisk_read_block (fd, sg->block, sg->buffer);
if (ret)
break;
@@ -2098,14 +2097,13 @@ rtems_fdisk_read (rtems_flashdisk* fd, blkdev_request* req)
* @retval int The ioctl return value.
*/
static int
-rtems_fdisk_write (rtems_flashdisk* fd, blkdev_request* req)
+rtems_fdisk_write (rtems_flashdisk* fd, rtems_blkdev_request* req)
{
- blkdev_sg_buffer* sg = req->bufs;
- uint32_t block = req->start;
- uint32_t b;
- int ret = 0;
+ rtems_blkdev_sg_buffer* sg = req->bufs;
+ uint32_t b;
+ int ret = 0;
- for (b = 0; b < req->bufnum; b++, block++, sg++)
+ for (b = 0; b < req->bufnum; b++, sg++)
{
if (sg->length != fd->block_size)
{
@@ -2113,7 +2111,7 @@ rtems_fdisk_write (rtems_flashdisk* fd, blkdev_request* req)
"bd:%d fd:%d", sg->length, fd->block_size);
}
- ret = rtems_fdisk_write_block (fd, block, sg->buffer);
+ ret = rtems_fdisk_write_block (fd, sg->block, sg->buffer);
if (ret)
break;
@@ -2356,7 +2354,7 @@ static int
rtems_fdisk_ioctl (dev_t dev, uint32_t req, void* argp)
{
rtems_device_minor_number minor = rtems_filesystem_dev_minor_t (dev);
- blkdev_request* r = argp;
+ rtems_blkdev_request* r = argp;
rtems_status_code sc;
errno = 0;
@@ -2368,7 +2366,7 @@ rtems_fdisk_ioctl (dev_t dev, uint32_t req, void* argp)
{
switch (req)
{
- case BLKIO_REQUEST:
+ case RTEMS_BLKIO_REQUEST:
if ((minor >= rtems_flashdisk_count) ||
(rtems_flashdisks[minor].device_count == 0))
{
@@ -2378,11 +2376,11 @@ rtems_fdisk_ioctl (dev_t dev, uint32_t req, void* argp)
{
switch (r->req)
{
- case BLKDEV_REQ_READ:
+ case RTEMS_BLKDEV_REQ_READ:
errno = rtems_fdisk_read (&rtems_flashdisks[minor], r);
break;
- case BLKDEV_REQ_WRITE:
+ case RTEMS_BLKDEV_REQ_WRITE:
errno = rtems_fdisk_write (&rtems_flashdisks[minor], r);
break;
diff --git a/cpukit/libblock/src/ide_part_table.c b/cpukit/libblock/src/ide_part_table.c
index 2b5b46138b..5d44c9a960 100644
--- a/cpukit/libblock/src/ide_part_table.c
+++ b/cpukit/libblock/src/ide_part_table.c
@@ -46,18 +46,18 @@
* and does not support devices with sector size other than 512 bytes
*/
static rtems_status_code
-get_sector(dev_t dev, uint32_t sector_num, sector_data_t **sector)
+get_sector(dev_t dev, uint32_t sector_num, rtems_sector_data_t **sector)
{
- sector_data_t *s;
- bdbuf_buffer *buf;
- rtems_status_code rc;
+ rtems_sector_data_t *s;
+ rtems_bdbuf_buffer *buf;
+ rtems_status_code rc;
if (sector == NULL)
{
return RTEMS_INTERNAL_ERROR;
}
- s = (sector_data_t *) malloc(sizeof(sector_data_t) + RTEMS_IDE_SECTOR_SIZE);
+ s = (rtems_sector_data_t *) malloc(sizeof(rtems_sector_data_t) + RTEMS_IDE_SECTOR_SIZE);
if (s == NULL)
{
return RTEMS_NO_MEMORY;
@@ -92,7 +92,7 @@ get_sector(dev_t dev, uint32_t sector_num, sector_data_t **sector)
* TRUE if sector has msdos signature, FALSE otherwise
*/
static rtems_boolean
-msdos_signature_check (sector_data_t *sector)
+msdos_signature_check (rtems_sector_data_t *sector)
{
uint8_t *p = sector->data + RTEMS_IDE_PARTITION_MSDOS_SIGNATURE_OFFSET;
@@ -156,10 +156,10 @@ is_fat_partition(uint8_t type)
* RTEMS_INTERNAL_ERROR, if other error occurs.
*/
static rtems_status_code
-data_to_part_desc(uint8_t *data, part_desc_t **new_part_desc)
+data_to_part_desc(uint8_t *data, rtems_part_desc_t **new_part_desc)
{
- part_desc_t *part_desc;
- uint32_t temp;
+ rtems_part_desc_t *part_desc;
+ uint32_t temp;
if (new_part_desc == NULL)
{
@@ -168,7 +168,7 @@ data_to_part_desc(uint8_t *data, part_desc_t **new_part_desc)
*new_part_desc = NULL;
- if ((part_desc = calloc(1, sizeof(part_desc_t))) == NULL)
+ if ((part_desc = calloc(1, sizeof(rtems_part_desc_t))) == NULL)
{
return RTEMS_NO_MEMORY;
}
@@ -219,15 +219,15 @@ data_to_part_desc(uint8_t *data, part_desc_t **new_part_desc)
* RTEMS_INTERNAL_ERROR if other error occurs.
*/
static rtems_status_code
-read_extended_partition(uint32_t start, part_desc_t *ext_part)
+read_extended_partition(uint32_t start, rtems_part_desc_t *ext_part)
{
- int i;
- dev_t dev;
- sector_data_t *sector;
- uint32_t here;
- uint8_t *data;
- part_desc_t *new_part_desc;
- rtems_status_code rc;
+ int i;
+ dev_t dev;
+ rtems_sector_data_t *sector;
+ uint32_t here;
+ uint8_t *data;
+ rtems_part_desc_t *new_part_desc;
+ rtems_status_code rc;
if ((ext_part == NULL) || (ext_part->disk_desc == NULL))
{
@@ -286,7 +286,7 @@ read_extended_partition(uint32_t start, part_desc_t *ext_part)
}
else
{
- disk_desc_t *disk_desc = new_part_desc->disk_desc;
+ rtems_disk_desc_t *disk_desc = new_part_desc->disk_desc;
disk_desc->partitions[disk_desc->last_log_id] = new_part_desc;
new_part_desc->log_id = ++disk_desc->last_log_id;
new_part_desc->start += here;
@@ -314,14 +314,14 @@ read_extended_partition(uint32_t start, part_desc_t *ext_part)
* RTEMS_INTERNAL_ERROR otherwise
*/
static rtems_status_code
-read_mbr(disk_desc_t *disk_desc)
+read_mbr(rtems_disk_desc_t *disk_desc)
{
- int part_num;
- sector_data_t *sector;
- part_desc_t *part_desc;
- uint8_t *data;
- rtems_status_code rc;
- dev_t dev = disk_desc->dev;
+ int part_num;
+ rtems_sector_data_t *sector;
+ rtems_part_desc_t *part_desc;
+ uint8_t *data;
+ rtems_status_code rc;
+ dev_t dev = disk_desc->dev;
/* get MBR sector */
rc = get_sector(dev, 0, &sector);
@@ -398,7 +398,7 @@ read_mbr(disk_desc_t *disk_desc)
* N/A
*/
static void
-partition_free(part_desc_t *part_desc)
+partition_free(rtems_part_desc_t *part_desc)
{
int part_num;
@@ -429,7 +429,7 @@ partition_free(part_desc_t *part_desc)
* N/A
*/
void
-rtems_ide_part_table_free(disk_desc_t *disk_desc)
+rtems_ide_part_table_free(rtems_disk_desc_t *disk_desc)
{
int part_num;
@@ -455,7 +455,7 @@ rtems_ide_part_table_free(disk_desc_t *disk_desc)
* RTEMS_INTERNAL_ERROR otherwise
*/
rtems_status_code
-rtems_ide_part_table_get(const char *dev_name, disk_desc_t *disk_desc)
+rtems_ide_part_table_get(const char *dev_name, rtems_disk_desc_t *disk_desc)
{
struct stat dev_stat;
rtems_status_code rc;
@@ -494,16 +494,16 @@ rtems_ide_part_table_initialize(char *dev_name)
{
int part_num;
dev_t dev;
- disk_desc_t *disk_desc;
+ rtems_disk_desc_t *disk_desc;
rtems_device_major_number major;
rtems_device_minor_number minor;
rtems_status_code rc;
- part_desc_t *part_desc;
+ rtems_part_desc_t *part_desc;
/* logical device name /dev/hdxyy */
char name[RTEMS_IDE_PARTITION_DEV_NAME_LENGTH_MAX];
- disk_desc = (disk_desc_t *) calloc(1, sizeof(disk_desc_t));
+ disk_desc = (rtems_disk_desc_t *) calloc(1, sizeof(rtems_disk_desc_t));
if (disk_desc == NULL)
{
return RTEMS_NO_MEMORY;
diff --git a/cpukit/libblock/src/nvdisk.c b/cpukit/libblock/src/nvdisk.c
index 0ee094bdc6..4166d79c98 100644
--- a/cpukit/libblock/src/nvdisk.c
+++ b/cpukit/libblock/src/nvdisk.c
@@ -51,7 +51,7 @@
* footprint targets. Leave in by default.
*/
#if !defined (RTEMS_NVDISK_TRACE)
-#define RTEMS_NVDISK_TRACE 1
+#define RTEMS_NVDISK_TRACE 0
#endif
/**
@@ -165,7 +165,7 @@ rtems_nvdisk_crc16_gen_factors (uint16_t pattern)
/**
* Print a message to the nvdisk output and flush it.
*
- * @param fd The flashdisk control structure.
+ * @param nvd The nvdisk control structure.
* @param format The format string. See printf for details.
* @param ... The arguments for the format text.
* @return int The number of bytes written to the output.
@@ -189,7 +189,7 @@ rtems_nvdisk_printf (const rtems_nvdisk* nvd, const char *format, ...)
/**
* Print a info message to the nvdisk output and flush it.
*
- * @param fd The flashdisk control structure.
+ * @param nvd The nvdisk control structure.
* @param format The format string. See printf for details.
* @param ... The arguments for the format text.
* @return int The number of bytes written to the output.
@@ -213,7 +213,7 @@ rtems_nvdisk_info (const rtems_nvdisk* nvd, const char *format, ...)
/**
* Print a warning to the nvdisk output and flush it.
*
- * @param fd The flashdisk control structure.
+ * @param nvd The nvdisk control structure.
* @param format The format string. See printf for details.
* @param ... The arguments for the format text.
* @return int The number of bytes written to the output.
@@ -256,24 +256,6 @@ rtems_nvdisk_error (const char *format, ...)
}
/**
- * Print an abort message, flush it then abort the program.
- *
- * @param format The format string. See printf for details.
- * @param ... The arguments for the format text.
- */
-static void
-rtems_nvdisk_abort (const char *format, ...)
-{
- va_list args;
- va_start (args, format);
- fprintf (stderr, "nvdisk:abort:");
- vfprintf (stderr, format, args);
- fprintf (stderr, "\n");
- fflush (stderr);
- exit (1);
-}
-
-/**
* Get the descriptor for a device.
*/
static const rtems_nvdisk_device_desc*
@@ -324,6 +306,7 @@ rtems_nvdisk_device_write (const rtems_nvdisk* nvd,
return ops->write (device, dd->flags, dd->base, offset, buffer, size);
}
+#if NOT_USED
/**
* Verify the data with the data in a segment.
*/
@@ -344,6 +327,7 @@ rtems_nvdisk_device_verify (const rtems_nvdisk* nvd,
#endif
return ops->verify (device, dd->flags, dd->base, offset, buffer, size);
}
+#endif
/**
* Read a page of data from the device.
@@ -374,20 +358,6 @@ rtems_nvdisk_write_page (const rtems_nvdisk* nvd,
}
/**
- * Verify a page of data with the data in the device.
- */
-static int
-rtems_nvdisk_verify_page (const rtems_nvdisk* nvd,
- uint32_t device,
- uint32_t page,
- const void* buffer)
-{
- return rtems_nvdisk_device_verify (nvd, device,
- page * nvd->block_size,
- buffer, nvd->block_size);
-}
-
-/**
* Read the checksum from the device.
*/
static int
@@ -532,7 +502,9 @@ rtems_nvdisk_read_block (rtems_nvdisk* nvd, uint32_t block, uint8_t* buffer)
if (crc == 0xffff)
{
+#if RTEMS_NVDISK_TRACE
rtems_nvdisk_warning (nvd, "read-block: crc not set: %d", block);
+#endif
memset (buffer, 0, nvd->block_size);
return 0;
}
@@ -605,13 +577,12 @@ rtems_nvdisk_write_block (rtems_nvdisk* nvd,
* @retval int The ioctl return value.
*/
static int
-rtems_nvdisk_read (rtems_nvdisk* nvd, blkdev_request* req)
+rtems_nvdisk_read (rtems_nvdisk* nvd, rtems_blkdev_request* req)
{
- blkdev_sg_buffer* sg = req->bufs;
- uint32_t block = req->start;
- uint32_t b;
- int32_t remains;
- int ret = 0;
+ rtems_blkdev_sg_buffer* sg = req->bufs;
+ uint32_t b;
+ int32_t remains;
+ int ret = 0;
#if RTEMS_NVDISK_TRACE
rtems_nvdisk_info (nvd, "read: blocks=%d", req->bufnum);
@@ -619,7 +590,7 @@ rtems_nvdisk_read (rtems_nvdisk* nvd, blkdev_request* req)
remains = req->count * nvd->block_size;
- for (b = 0; b < req->bufnum; b++, block++, sg++)
+ for (b = 0; b < req->bufnum; b++, sg++)
{
uint32_t length = sg->length;
@@ -658,18 +629,17 @@ rtems_nvdisk_read (rtems_nvdisk* nvd, blkdev_request* req)
* @retval int The ioctl return value.
*/
static int
-rtems_nvdisk_write (rtems_nvdisk* nvd, blkdev_request* req)
+rtems_nvdisk_write (rtems_nvdisk* nvd, rtems_blkdev_request* req)
{
- blkdev_sg_buffer* sg = req->bufs;
- uint32_t block = req->start;
- uint32_t b;
- int ret = 0;
+ rtems_blkdev_sg_buffer* sg = req->bufs;
+ uint32_t b;
+ int ret = 0;
#if RTEMS_NVDISK_TRACE
rtems_nvdisk_info (nvd, "write: blocks=%d", req->bufnum);
#endif
- for (b = 0; b < req->bufnum; b++, block++, sg++)
+ for (b = 0; b < req->bufnum; b++, sg++)
{
if (sg->length != nvd->block_size)
{
@@ -720,7 +690,7 @@ rtems_nvdisk_erase_disk (rtems_nvdisk* nvd)
}
/**
- * MV disk IOCTL handler.
+ * NV disk IOCTL handler.
*
* @param dev Device number (major, minor number).
* @param req IOCTL request code.
@@ -731,9 +701,21 @@ static int
rtems_nvdisk_ioctl (dev_t dev, uint32_t req, void* argp)
{
rtems_device_minor_number minor = rtems_filesystem_dev_minor_t (dev);
- blkdev_request* r = argp;
+ rtems_blkdev_request* r = argp;
rtems_status_code sc;
+ if (minor >= rtems_nvdisk_count)
+ {
+ errno = ENODEV;
+ return -1;
+ }
+
+ if (rtems_nvdisks[minor].device_count == 0)
+ {
+ errno = ENODEV;
+ return -1;
+ }
+
errno = 0;
sc = rtems_semaphore_obtain (rtems_nvdisks[minor].lock, RTEMS_WAIT, 0);
@@ -743,39 +725,31 @@ rtems_nvdisk_ioctl (dev_t dev, uint32_t req, void* argp)
{
switch (req)
{
- case BLKIO_REQUEST:
- if ((minor >= rtems_nvdisk_count) ||
- (rtems_nvdisks[minor].device_count == 0))
- {
- errno = ENODEV;
- }
- else
+ case RTEMS_BLKIO_REQUEST:
+ switch (r->req)
{
- switch (r->req)
- {
- case BLKDEV_REQ_READ:
- errno = rtems_nvdisk_read (&rtems_nvdisks[minor], r);
- break;
-
- case BLKDEV_REQ_WRITE:
- errno = rtems_nvdisk_write (&rtems_nvdisks[minor], r);
- break;
-
- default:
- errno = EBADRQC;
- break;
- }
+ case RTEMS_BLKDEV_REQ_READ:
+ errno = rtems_nvdisk_read (&rtems_nvdisks[minor], r);
+ break;
+
+ case RTEMS_BLKDEV_REQ_WRITE:
+ errno = rtems_nvdisk_write (&rtems_nvdisks[minor], r);
+ break;
+
+ default:
+ errno = EBADRQC;
+ break;
}
break;
case RTEMS_NVDISK_IOCTL_ERASE_DISK:
errno = rtems_nvdisk_erase_disk (&rtems_nvdisks[minor]);
break;
-
+
case RTEMS_NVDISK_IOCTL_INFO_LEVEL:
rtems_nvdisks[minor].info_level = (uint32_t) argp;
break;
-
+
default:
errno = EBADRQC;
break;
diff --git a/cpukit/libblock/src/ramdisk.c b/cpukit/libblock/src/ramdisk.c
index b72e3ae795..3b3f3f29b0 100644
--- a/cpukit/libblock/src/ramdisk.c
+++ b/cpukit/libblock/src/ramdisk.c
@@ -22,6 +22,14 @@
#include "rtems/diskdevs.h"
#include "rtems/ramdisk.h"
+/**
+ * Control tracing. It can be compiled out of the code for small
+ * footprint targets. Leave in by default.
+ */
+#if !defined (RTEMS_RAMDISK_TRACE)
+#define RTEMS_RAMDISK_TRACE 0
+#endif
+
#define RAMDISK_DEVICE_BASE_NAME "/dev/ramdisk"
/* Internal RAM disk descriptor */
@@ -32,11 +40,40 @@ struct ramdisk {
rtems_boolean initialized;/* RAM disk is initialized */
rtems_boolean malloced; /* != 0, if memory allocated by malloc for this
RAM disk */
+#if RTEMS_RAMDISK_TRACE
+ int info_level; /* Trace level */
+#endif
};
static struct ramdisk *ramdisk;
static int nramdisks;
+#if RTEMS_RAMDISK_TRACE
+/**
+ * Print a message to the ramdisk output and flush it.
+ *
+ * @param rd The ramdisk control structure.
+ * @param format The format string. See printf for details.
+ * @param ... The arguments for the format text.
+ * @return int The number of bytes written to the output.
+ */
+static int
+rtems_ramdisk_printf (struct ramdisk *rd, const char *format, ...)
+{
+ int ret = 0;
+ if (rd->info_level >= 1)
+ {
+ va_list args;
+ va_start (args, format);
+ fprintf (stdout, "ramdisk:");
+ ret = vfprintf (stdout, format, args);
+ fprintf (stdout, "\n");
+ fflush (stdout);
+ }
+ return ret;
+}
+#endif
+
/* ramdisk_read --
* RAM disk READ request handler. This primitive copies data from RAM
* disk to supplied buffer and invoke the callout function to inform
@@ -49,19 +86,25 @@ static int nramdisks;
* ioctl return value
*/
static int
-ramdisk_read(struct ramdisk *rd, blkdev_request *req)
+ramdisk_read(struct ramdisk *rd, rtems_blkdev_request *req)
{
char *from;
uint32_t i;
- blkdev_sg_buffer *sg;
+ rtems_blkdev_sg_buffer *sg;
uint32_t remains;
- from = (char *)rd->area + (req->start * rd->block_size);
+#if RTEMS_RAMDISK_TRACE
+ rtems_ramdisk_printf (rd, "ramdisk read: start=%d, blocks=%d remains=%d",
+ req->bufs[0].block, req->bufnum,
+ rd->block_size * req->count);
+#endif
+
remains = rd->block_size * req->count;
sg = req->bufs;
for (i = 0; (remains > 0) && (i < req->bufnum); i++, sg++)
{
int count = sg->length;
+ from = ((char *)rd->area + (sg->block * rd->block_size));
if (count > remains)
count = remains;
memcpy(sg->buffer, from, count);
@@ -84,19 +127,24 @@ ramdisk_read(struct ramdisk *rd, blkdev_request *req)
* ioctl return value
*/
static int
-ramdisk_write(struct ramdisk *rd, blkdev_request *req)
+ramdisk_write(struct ramdisk *rd, rtems_blkdev_request *req)
{
char *to;
uint32_t i;
- blkdev_sg_buffer *sg;
+ rtems_blkdev_sg_buffer *sg;
uint32_t remains;
- to = (char *)rd->area + (req->start * rd->block_size);
+#if RTEMS_RAMDISK_TRACE
+ rtems_ramdisk_printf (rd, "ramdisk write: start=%d, blocks=%d remains=%d",
+ req->bufs[0].block, req->bufnum,
+ rd->block_size * req->count);
+#endif
remains = rd->block_size * req->count;
sg = req->bufs;
for (i = 0; (remains > 0) && (i < req->bufnum); i++, sg++)
{
int count = sg->length;
+ to = ((char *)rd->area + (sg->block * rd->block_size));
if (count > remains)
count = remains;
memcpy(to, sg->buffer, count);
@@ -123,10 +171,10 @@ ramdisk_ioctl(dev_t dev, uint32_t req, void *argp)
{
switch (req)
{
- case BLKIO_REQUEST:
+ case RTEMS_BLKIO_REQUEST:
{
rtems_device_minor_number minor;
- blkdev_request *r = argp;
+ rtems_blkdev_request *r = argp;
struct ramdisk *rd;
minor = rtems_filesystem_dev_minor_t(dev);
@@ -140,10 +188,10 @@ ramdisk_ioctl(dev_t dev, uint32_t req, void *argp)
switch (r->req)
{
- case BLKDEV_REQ_READ:
+ case RTEMS_BLKDEV_REQ_READ:
return ramdisk_read(rd, r);
- case BLKDEV_REQ_WRITE:
+ case RTEMS_BLKDEV_REQ_WRITE:
return ramdisk_write(rd, r);
default:
@@ -188,7 +236,9 @@ ramdisk_initialize(
r = ramdisk = calloc(rtems_ramdisk_configuration_size,
sizeof(struct ramdisk));
-
+#if RTEMS_RAMDISK_TRACE
+ r->info_level = 1;
+#endif
for (i = 0; i < rtems_ramdisk_configuration_size; i++, c++, r++)
{
dev_t dev = rtems_filesystem_make_dev_t(major, i);
diff --git a/cpukit/libfs/src/dosfs/fat.c b/cpukit/libfs/src/dosfs/fat.c
index 65bf30e624..4dd61afdd9 100644
--- a/cpukit/libfs/src/dosfs/fat.c
+++ b/cpukit/libfs/src/dosfs/fat.c
@@ -26,6 +26,137 @@
#include "fat.h"
#include "fat_fat_operations.h"
+int
+fat_buf_access(fat_fs_info_t *fs_info, uint32_t blk, int op_type,
+ rtems_bdbuf_buffer **buf)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ uint8_t i;
+ rtems_boolean sec_of_fat;
+
+
+ if (fs_info->c.state == FAT_CACHE_EMPTY)
+ {
+ if (op_type == FAT_OP_TYPE_READ)
+ sc = rtems_bdbuf_read(fs_info->vol.dev, blk, &fs_info->c.buf);
+ else
+ sc = rtems_bdbuf_get(fs_info->vol.dev, blk, &fs_info->c.buf);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_set_errno_and_return_minus_one(EIO);
+ fs_info->c.blk_num = blk;
+ fs_info->c.modified = 0;
+ fs_info->c.state = FAT_CACHE_ACTUAL;
+ }
+
+ sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
+ (fs_info->c.blk_num < fs_info->vol.rdir_loc));
+
+ if (fs_info->c.blk_num != blk)
+ {
+ if (fs_info->c.modified)
+ {
+ if (sec_of_fat && !fs_info->vol.mirror)
+ memcpy(fs_info->sec_buf, fs_info->c.buf->buffer,
+ fs_info->vol.bps);
+
+ sc = rtems_bdbuf_release_modified(fs_info->c.buf);
+ fs_info->c.state = FAT_CACHE_EMPTY;
+ fs_info->c.modified = 0;
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_set_errno_and_return_minus_one(EIO);
+
+ if (sec_of_fat && !fs_info->vol.mirror)
+ {
+ rtems_bdbuf_buffer *b;
+
+ for (i = 1; i < fs_info->vol.fats; i++)
+ {
+ sc = rtems_bdbuf_get(fs_info->vol.dev,
+ fs_info->c.blk_num +
+ fs_info->vol.fat_length * i,
+ &b);
+ if ( sc != RTEMS_SUCCESSFUL)
+ rtems_set_errno_and_return_minus_one(ENOMEM);
+ memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
+ sc = rtems_bdbuf_release_modified(b);
+ if ( sc != RTEMS_SUCCESSFUL)
+ rtems_set_errno_and_return_minus_one(ENOMEM);
+ }
+ }
+ }
+ else
+ {
+ sc = rtems_bdbuf_release(fs_info->c.buf);
+ fs_info->c.state = FAT_CACHE_EMPTY;
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_set_errno_and_return_minus_one(EIO);
+
+ }
+ if (op_type == FAT_OP_TYPE_READ)
+ sc = rtems_bdbuf_read(fs_info->vol.dev, blk, &fs_info->c.buf);
+ else
+ sc = rtems_bdbuf_get(fs_info->vol.dev, blk, &fs_info->c.buf);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_set_errno_and_return_minus_one(EIO);
+ fs_info->c.blk_num = blk;
+ fs_info->c.state = FAT_CACHE_ACTUAL;
+ }
+ *buf = fs_info->c.buf;
+ return RC_OK;
+}
+
+int
+fat_buf_release(fat_fs_info_t *fs_info)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ uint8_t i;
+ rtems_boolean sec_of_fat;
+
+ if (fs_info->c.state == FAT_CACHE_EMPTY)
+ return RC_OK;
+
+ sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
+ (fs_info->c.blk_num < fs_info->vol.rdir_loc));
+
+ if (fs_info->c.modified)
+ {
+ if (sec_of_fat && !fs_info->vol.mirror)
+ memcpy(fs_info->sec_buf, fs_info->c.buf->buffer, fs_info->vol.bps);
+
+ sc = rtems_bdbuf_release_modified(fs_info->c.buf);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_set_errno_and_return_minus_one(EIO);
+ fs_info->c.modified = 0;
+
+ if (sec_of_fat && !fs_info->vol.mirror)
+ {
+ rtems_bdbuf_buffer *b;
+
+ for (i = 1; i < fs_info->vol.fats; i++)
+ {
+ sc = rtems_bdbuf_get(fs_info->vol.dev,
+ fs_info->c.blk_num +
+ fs_info->vol.fat_length * i,
+ &b);
+ if ( sc != RTEMS_SUCCESSFUL)
+ rtems_set_errno_and_return_minus_one(ENOMEM);
+ memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
+ sc = rtems_bdbuf_release_modified(b);
+ if ( sc != RTEMS_SUCCESSFUL)
+ rtems_set_errno_and_return_minus_one(ENOMEM);
+ }
+ }
+ }
+ else
+ {
+ sc = rtems_bdbuf_release(fs_info->c.buf);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_set_errno_and_return_minus_one(EIO);
+ }
+ fs_info->c.state = FAT_CACHE_EMPTY;
+ return RC_OK;
+}
+
/* _fat_block_read --
* This function reads 'count' bytes from device filesystem is mounted on,
* starts at 'start+offset' position where 'start' computed in sectors
@@ -57,7 +188,7 @@ _fat_block_read(
ssize_t cmpltd = 0;
uint32_t blk = start;
uint32_t ofs = offset;
- bdbuf_buffer *block = NULL;
+ rtems_bdbuf_buffer *block = NULL;
uint32_t c = 0;
while (count > 0)
@@ -102,13 +233,13 @@ _fat_block_write(
uint32_t count,
const void *buff)
{
- int rc = RC_OK;
- fat_fs_info_t *fs_info = mt_entry->fs_info;
- ssize_t cmpltd = 0;
- uint32_t blk = start;
- uint32_t ofs = offset;
- bdbuf_buffer *block = NULL;
- uint32_t c = 0;
+ int rc = RC_OK;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ ssize_t cmpltd = 0;
+ uint32_t blk = start;
+ uint32_t ofs = offset;
+ rtems_bdbuf_buffer *block = NULL;
+ uint32_t c = 0;
while(count > 0)
{
@@ -133,9 +264,6 @@ _fat_block_write(
return cmpltd;
}
-
-
-
/* fat_cluster_read --
* wrapper for reading a whole cluster at once
*
@@ -215,7 +343,7 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
ssize_t ret = 0;
struct stat stat_buf;
int i = 0;
- bdbuf_buffer *block = NULL;
+ rtems_bdbuf_buffer *block = NULL;
rc = stat(mt_entry->dev, &stat_buf);
if (rc == -1)
@@ -223,12 +351,12 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
/* rtmes feature: no block devices, all are character devices */
if (!S_ISCHR(stat_buf.st_mode))
- set_errno_and_return_minus_one(ENOTBLK);
+ rtems_set_errno_and_return_minus_one(ENOTBLK);
- /* check that device is registred as block device and lock it */
- vol->dd = rtems_disk_lookup(stat_buf.st_dev);
+ /* check that device is registred as block device and lock it */
+ vol->dd = rtems_disk_obtain(stat_buf.st_dev);
if (vol->dd == NULL)
- set_errno_and_return_minus_one(ENOTBLK);
+ rtems_set_errno_and_return_minus_one(ENOTBLK);
vol->dev = stat_buf.st_dev;
@@ -238,7 +366,7 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
if (sc != RTEMS_SUCCESSFUL)
{
rtems_disk_release(vol->dd);
- set_errno_and_return_minus_one( EIO);
+ rtems_set_errno_and_return_minus_one( EIO);
}
memcpy( boot_rec, block->buffer, FAT_MAX_BPB_SIZE);
@@ -247,7 +375,7 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
if (sc != RTEMS_SUCCESSFUL)
{
rtems_disk_release(vol->dd);
- set_errno_and_return_minus_one( EIO);
+ rtems_set_errno_and_return_minus_one( EIO );
}
/* Evaluate boot record */
@@ -259,7 +387,7 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
(vol->bps != 4096))
{
rtems_disk_release(vol->dd);
- set_errno_and_return_minus_one( EINVAL );
+ rtems_set_errno_and_return_minus_one( EINVAL );
}
for (vol->sec_mul = 0, i = (vol->bps >> FAT_SECTOR512_BITS); (i & 1) == 0;
@@ -275,7 +403,7 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
if (vol->spc == 0)
{
rtems_disk_release(vol->dd);
- set_errno_and_return_minus_one(EINVAL);
+ rtems_set_errno_and_return_minus_one(EINVAL);
}
for (vol->spc_log2 = 0, i = vol->spc; (i & 1) == 0;
@@ -287,7 +415,7 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
if ((vol->bpc = vol->bps << vol->spc_log2) > MS_BYTES_PER_CLUSTER_LIMIT)
{
rtems_disk_release(vol->dd);
- set_errno_and_return_minus_one(EINVAL);
+ rtems_set_errno_and_return_minus_one(EINVAL);
}
for (vol->bpc_log2 = 0, i = vol->bpc; (i & 1) == 0;
@@ -361,7 +489,7 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
if( vol->info_sec == 0 )
{
rtems_disk_release(vol->dd);
- set_errno_and_return_minus_one( EINVAL );
+ rtems_set_errno_and_return_minus_one( EINVAL );
}
else
{
@@ -377,7 +505,7 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
FAT_FSINFO_LEAD_SIGNATURE_VALUE)
{
rtems_disk_release(vol->dd);
- set_errno_and_return_minus_one( EINVAL );
+ rtems_set_errno_and_return_minus_one( EINVAL );
}
else
{
@@ -412,25 +540,25 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
vol->afat_loc = vol->fat_loc + vol->fat_length * vol->afat;
/* set up collection of fat-files fd */
- fs_info->vhash = calloc(FAT_HASH_SIZE, sizeof(Chain_Control));
+ fs_info->vhash = calloc(FAT_HASH_SIZE, sizeof(rtems_chain_control));
if ( fs_info->vhash == NULL )
{
rtems_disk_release(vol->dd);
- set_errno_and_return_minus_one( ENOMEM );
+ rtems_set_errno_and_return_minus_one( ENOMEM );
}
for (i = 0; i < FAT_HASH_SIZE; i++)
- _Chain_Initialize_empty(fs_info->vhash + i);
+ rtems_chain_initialize_empty(fs_info->vhash + i);
- fs_info->rhash = calloc(FAT_HASH_SIZE, sizeof(Chain_Control));
+ fs_info->rhash = calloc(FAT_HASH_SIZE, sizeof(rtems_chain_control));
if ( fs_info->rhash == NULL )
{
rtems_disk_release(vol->dd);
free(fs_info->vhash);
- set_errno_and_return_minus_one( ENOMEM );
+ rtems_set_errno_and_return_minus_one( ENOMEM );
}
for (i = 0; i < FAT_HASH_SIZE; i++)
- _Chain_Initialize_empty(fs_info->rhash + i);
+ rtems_chain_initialize_empty(fs_info->rhash + i);
fs_info->uino_pool_size = FAT_UINO_POOL_INIT_SIZE;
fs_info->uino_base = (vol->tot_secs << vol->sec_mul) << 4;
@@ -441,7 +569,7 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
rtems_disk_release(vol->dd);
free(fs_info->vhash);
free(fs_info->rhash);
- set_errno_and_return_minus_one( ENOMEM );
+ rtems_set_errno_and_return_minus_one( ENOMEM );
}
fs_info->sec_buf = (uint8_t *)calloc(vol->bps, sizeof(uint8_t));
if (fs_info->sec_buf == NULL)
@@ -450,7 +578,7 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
free(fs_info->vhash);
free(fs_info->rhash);
free(fs_info->uino);
- set_errno_and_return_minus_one( ENOMEM );
+ rtems_set_errno_and_return_minus_one( ENOMEM );
}
return RC_OK;
@@ -488,19 +616,19 @@ fat_shutdown_drive(rtems_filesystem_mount_table_entry_t *mt_entry)
for (i = 0; i < FAT_HASH_SIZE; i++)
{
- Chain_Node *node = NULL;
- Chain_Control *the_chain = fs_info->vhash + i;
+ rtems_chain_node *node = NULL;
+ rtems_chain_control *the_chain = fs_info->vhash + i;
- while ( (node = _Chain_Get(the_chain)) != NULL )
+ while ( (node = rtems_chain_get(the_chain)) != NULL )
free(node);
}
for (i = 0; i < FAT_HASH_SIZE; i++)
{
- Chain_Node *node = NULL;
- Chain_Control *the_chain = fs_info->rhash + i;
+ rtems_chain_node *node = NULL;
+ rtems_chain_control *the_chain = fs_info->rhash + i;
- while ( (node = _Chain_Get(the_chain)) != NULL )
+ while ( (node = rtems_chain_get(the_chain)) != NULL )
free(node);
}
@@ -541,7 +669,7 @@ fat_init_clusters_chain(
buf = calloc(fs_info->vol.bpc, sizeof(char));
if ( buf == NULL )
- set_errno_and_return_minus_one( EIO );
+ rtems_set_errno_and_return_minus_one( EIO );
while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
{
diff --git a/cpukit/libfs/src/dosfs/fat.h b/cpukit/libfs/src/dosfs/fat.h
index 3a951b114e..244e57f087 100644
--- a/cpukit/libfs/src/dosfs/fat.h
+++ b/cpukit/libfs/src/dosfs/fat.h
@@ -25,11 +25,6 @@ extern "C" {
#include <rtems/seterr.h>
-/* XXX: temporary hack :(( */
-#ifndef set_errno_and_return_minus_one
-#define set_errno_and_return_minus_one rtems_set_errno_and_return_minus_one
-#endif /* set_errno_and_return_minus_one */
-
#include <rtems/score/cpu.h>
#include <errno.h>
#include <rtems/bdbuf.h>
@@ -297,45 +292,45 @@ extern "C" {
*/
typedef struct fat_vol_s
{
- uint16_t bps; /* bytes per sector */
- uint8_t sec_log2; /* log2 of bps */
- uint8_t sec_mul; /* log2 of 512bts sectors number per sector */
- uint8_t spc; /* sectors per cluster */
- uint8_t spc_log2; /* log2 of spc */
- uint16_t bpc; /* bytes per cluster */
- uint8_t bpc_log2; /* log2 of bytes per cluster */
- uint8_t fats; /* number of FATs */
- uint8_t type; /* FAT type */
- uint32_t mask;
- uint32_t eoc_val;
- uint16_t fat_loc; /* FAT start */
- uint32_t fat_length; /* sectors per FAT */
- uint32_t rdir_loc; /* root directory start */
- uint16_t rdir_entrs; /* files per root directory */
- uint32_t rdir_secs; /* sectors per root directory */
- uint32_t rdir_size; /* root directory size in bytes */
- uint32_t tot_secs; /* total count of sectors */
- uint32_t data_fsec; /* first data sector */
- uint32_t data_cls; /* count of data clusters */
- uint32_t rdir_cl; /* first cluster of the root directory */
- uint16_t info_sec; /* FSInfo Sector Structure location */
- uint32_t free_cls; /* last known free clusters count */
- uint32_t next_cl; /* next free cluster number */
- uint8_t mirror; /* mirroring enabla/disable */
- uint32_t afat_loc; /* active FAT location */
- uint8_t afat; /* the number of active FAT */
- dev_t dev; /* device ID */
- disk_device *dd; /* disk device (see libblock) */
- void *private_data; /* reserved */
+ uint16_t bps; /* bytes per sector */
+ uint8_t sec_log2; /* log2 of bps */
+ uint8_t sec_mul; /* log2 of 512bts sectors number per sector */
+ uint8_t spc; /* sectors per cluster */
+ uint8_t spc_log2; /* log2 of spc */
+ uint16_t bpc; /* bytes per cluster */
+ uint8_t bpc_log2; /* log2 of bytes per cluster */
+ uint8_t fats; /* number of FATs */
+ uint8_t type; /* FAT type */
+ uint32_t mask;
+ uint32_t eoc_val;
+ uint16_t fat_loc; /* FAT start */
+ uint32_t fat_length; /* sectors per FAT */
+ uint32_t rdir_loc; /* root directory start */
+ uint16_t rdir_entrs; /* files per root directory */
+ uint32_t rdir_secs; /* sectors per root directory */
+ uint32_t rdir_size; /* root directory size in bytes */
+ uint32_t tot_secs; /* total count of sectors */
+ uint32_t data_fsec; /* first data sector */
+ uint32_t data_cls; /* count of data clusters */
+ uint32_t rdir_cl; /* first cluster of the root directory */
+ uint16_t info_sec; /* FSInfo Sector Structure location */
+ uint32_t free_cls; /* last known free clusters count */
+ uint32_t next_cl; /* next free cluster number */
+ uint8_t mirror; /* mirroring enabla/disable */
+ uint32_t afat_loc; /* active FAT location */
+ uint8_t afat; /* the number of active FAT */
+ dev_t dev; /* device ID */
+ rtems_disk_device *dd; /* disk device (see libblock) */
+ void *private_data; /* reserved */
} fat_vol_t;
typedef struct fat_cache_s
{
- uint32_t blk_num;
- rtems_boolean modified;
- uint8_t state;
- bdbuf_buffer *buf;
+ uint32_t blk_num;
+ rtems_boolean modified;
+ uint8_t state;
+ rtems_bdbuf_buffer *buf;
} fat_cache_t;
/*
@@ -344,15 +339,15 @@ typedef struct fat_cache_s
*/
typedef struct fat_fs_info_s
{
- fat_vol_t vol; /* volume descriptor */
- Chain_Control *vhash; /* "vhash" of fat-file descriptors */
- Chain_Control *rhash; /* "rhash" of fat-file descriptors */
- char *uino; /* array of unique ino numbers */
- uint32_t index;
- uint32_t uino_pool_size; /* size */
- uint32_t uino_base;
- fat_cache_t c; /* cache */
- uint8_t *sec_buf; /* just placeholder for anything */
+ fat_vol_t vol; /* volume descriptor */
+ rtems_chain_control *vhash; /* "vhash" of fat-file descriptors */
+ rtems_chain_control *rhash; /* "rhash" of fat-file descriptors */
+ char *uino; /* array of unique ino numbers */
+ uint32_t index;
+ uint32_t uino_pool_size; /* size */
+ uint32_t uino_base;
+ fat_cache_t c; /* cache */
+ uint8_t *sec_buf; /* just placeholder for anything */
} fat_fs_info_t;
/*
@@ -415,145 +410,18 @@ fat_cluster_num_to_sector512_num(
fs_info->vol.sec_mul);
}
-static inline int
-fat_buf_access(fat_fs_info_t *fs_info, uint32_t blk, int op_type,
- bdbuf_buffer **buf)
-{
- rtems_status_code sc = RTEMS_SUCCESSFUL;
- uint8_t i;
- rtems_boolean sec_of_fat;
-
-
- if (fs_info->c.state == FAT_CACHE_EMPTY)
- {
- if (op_type == FAT_OP_TYPE_READ)
- sc = rtems_bdbuf_read(fs_info->vol.dev, blk, &fs_info->c.buf);
- else
- sc = rtems_bdbuf_get(fs_info->vol.dev, blk, &fs_info->c.buf);
- if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
- fs_info->c.blk_num = blk;
- fs_info->c.modified = 0;
- fs_info->c.state = FAT_CACHE_ACTUAL;
- }
-
- sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
- (fs_info->c.blk_num < fs_info->vol.rdir_loc));
-
- if (fs_info->c.blk_num != blk)
- {
- if (fs_info->c.modified)
- {
- if (sec_of_fat && !fs_info->vol.mirror)
- memcpy(fs_info->sec_buf, fs_info->c.buf->buffer,
- fs_info->vol.bps);
-
- sc = rtems_bdbuf_release_modified(fs_info->c.buf);
- fs_info->c.state = FAT_CACHE_EMPTY;
- fs_info->c.modified = 0;
- if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
-
- if (sec_of_fat && !fs_info->vol.mirror)
- {
- bdbuf_buffer *b;
-
- for (i = 1; i < fs_info->vol.fats; i++)
- {
- sc = rtems_bdbuf_get(fs_info->vol.dev,
- fs_info->c.blk_num +
- fs_info->vol.fat_length * i,
- &b);
- if ( sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(ENOMEM);
- memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
- sc = rtems_bdbuf_release_modified(b);
- if ( sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(ENOMEM);
- }
- }
- }
- else
- {
- sc = rtems_bdbuf_release(fs_info->c.buf);
- fs_info->c.state = FAT_CACHE_EMPTY;
- if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
-
- }
- if (op_type == FAT_OP_TYPE_READ)
- sc = rtems_bdbuf_read(fs_info->vol.dev, blk, &fs_info->c.buf);
- else
- sc = rtems_bdbuf_get(fs_info->vol.dev, blk, &fs_info->c.buf);
- if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
- fs_info->c.blk_num = blk;
- fs_info->c.state = FAT_CACHE_ACTUAL;
- }
- *buf = fs_info->c.buf;
- return RC_OK;
-}
-
-
-static inline int
-fat_buf_release(fat_fs_info_t *fs_info)
-{
- rtems_status_code sc = RTEMS_SUCCESSFUL;
- uint8_t i;
- rtems_boolean sec_of_fat;
-
- if (fs_info->c.state == FAT_CACHE_EMPTY)
- return RC_OK;
-
- sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
- (fs_info->c.blk_num < fs_info->vol.rdir_loc));
-
- if (fs_info->c.modified)
- {
- if (sec_of_fat && !fs_info->vol.mirror)
- memcpy(fs_info->sec_buf, fs_info->c.buf->buffer, fs_info->vol.bps);
-
- sc = rtems_bdbuf_release_modified(fs_info->c.buf);
- if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
- fs_info->c.modified = 0;
-
- if (sec_of_fat && !fs_info->vol.mirror)
- {
- bdbuf_buffer *b;
-
- for (i = 1; i < fs_info->vol.fats; i++)
- {
- sc = rtems_bdbuf_get(fs_info->vol.dev,
- fs_info->c.blk_num +
- fs_info->vol.fat_length * i,
- &b);
- if ( sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(ENOMEM);
- memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
- sc = rtems_bdbuf_release_modified(b);
- if ( sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(ENOMEM);
- }
- }
- }
- else
- {
- sc = rtems_bdbuf_release(fs_info->c.buf);
- if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
- }
- fs_info->c.state = FAT_CACHE_EMPTY;
- return RC_OK;
-}
-
static inline void
fat_buf_mark_modified(fat_fs_info_t *fs_info)
{
fs_info->c.modified = TRUE;
}
+int
+fat_buf_access(fat_fs_info_t *fs_info, uint32_t blk, int op_type,
+ rtems_bdbuf_buffer **buf);
+int
+fat_buf_release(fat_fs_info_t *fs_info);
ssize_t
_fat_block_read(rtems_filesystem_mount_table_entry_t *mt_entry,
diff --git a/cpukit/libfs/src/dosfs/fat_fat_operations.c b/cpukit/libfs/src/dosfs/fat_fat_operations.c
index 0e6411f799..9d677dc3db 100644
--- a/cpukit/libfs/src/dosfs/fat_fat_operations.c
+++ b/cpukit/libfs/src/dosfs/fat_fat_operations.c
@@ -229,13 +229,13 @@ fat_get_fat_cluster(
{
int rc = RC_OK;
register fat_fs_info_t *fs_info = mt_entry->fs_info;
- bdbuf_buffer *block0 = NULL;
+ rtems_bdbuf_buffer *block0 = NULL;
uint32_t sec = 0;
uint32_t ofs = 0;
/* sanity check */
if ( (cln < 2) || (cln > (fs_info->vol.data_cls + 1)) )
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
sec = (FAT_FAT_OFFSET(fs_info->vol.type, cln) >> fs_info->vol.sec_log2) +
fs_info->vol.afat_loc;
@@ -284,7 +284,7 @@ fat_get_fat_cluster(
break;
default:
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
break;
}
@@ -311,17 +311,17 @@ fat_set_fat_cluster(
uint32_t in_val
)
{
- int rc = RC_OK;
- fat_fs_info_t *fs_info = mt_entry->fs_info;
- uint32_t sec = 0;
- uint32_t ofs = 0;
- uint16_t fat16_clv = 0;
- uint32_t fat32_clv = 0;
- bdbuf_buffer *block0 = NULL;
+ int rc = RC_OK;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t sec = 0;
+ uint32_t ofs = 0;
+ uint16_t fat16_clv = 0;
+ uint32_t fat32_clv = 0;
+ rtems_bdbuf_buffer *block0 = NULL;
/* sanity check */
if ( (cln < 2) || (cln > (fs_info->vol.data_cls + 1)) )
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
sec = (FAT_FAT_OFFSET(fs_info->vol.type, cln) >> fs_info->vol.sec_log2) +
fs_info->vol.afat_loc;
@@ -428,7 +428,7 @@ fat_set_fat_cluster(
break;
default:
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
break;
}
diff --git a/cpukit/libfs/src/dosfs/fat_file.c b/cpukit/libfs/src/dosfs/fat_file.c
index 69e1d9a7e0..6bf482e927 100644
--- a/cpukit/libfs/src/dosfs/fat_file.c
+++ b/cpukit/libfs/src/dosfs/fat_file.c
@@ -10,6 +10,8 @@
*
*/
+#define MSDOS_TRACE 1
+
#if HAVE_CONFIG_H
#include "config.h"
#endif
@@ -112,7 +114,7 @@ fat_file_open(
lfat_fd = (*fat_fd) = (fat_file_fd_t*)malloc(sizeof(fat_file_fd_t));
if ( lfat_fd == NULL )
- set_errno_and_return_minus_one( ENOMEM );
+ rtems_set_errno_and_return_minus_one( ENOMEM );
lfat_fd->links_num = 1;
lfat_fd->flags &= ~FAT_FILE_REMOVED;
@@ -131,7 +133,7 @@ fat_file_open(
* XXX: kernel resource is unsufficient, but not the memory,
* but there is no suitable errno :(
*/
- set_errno_and_return_minus_one( ENOMEM );
+ rtems_set_errno_and_return_minus_one( ENOMEM );
}
}
_hash_insert(fs_info->vhash, key, lfat_fd->ino, lfat_fd);
@@ -383,11 +385,11 @@ fat_file_write(
return cmpltd;
if ( start > fat_fd->fat_file_size )
- set_errno_and_return_minus_one( EIO );
+ rtems_set_errno_and_return_minus_one( EIO );
if ((count > fat_fd->size_limit) ||
(start > fat_fd->size_limit - count))
- set_errno_and_return_minus_one( EIO );
+ rtems_set_errno_and_return_minus_one( EIO );
rc = fat_file_extend(mt_entry, fat_fd, start + count, &c);
if (rc != RC_OK)
@@ -493,7 +495,7 @@ fat_file_extend(
if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
(fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
- set_errno_and_return_minus_one( ENOSPC );
+ rtems_set_errno_and_return_minus_one( ENOSPC );
bytes_remain = (fs_info->vol.bpc -
(fat_fd->fat_file_size & (fs_info->vol.bpc - 1))) &
@@ -525,7 +527,7 @@ fat_file_extend(
/* this means that no space left on device */
if ((cls_added == 0) && (bytes_remain == 0))
- set_errno_and_return_minus_one(ENOSPC);
+ rtems_set_errno_and_return_minus_one(ENOSPC);
/* check wether we satisfied request for 'cls2add' clusters */
if (cls2add != cls_added)
@@ -687,7 +689,7 @@ fat_file_ioctl(
/* sanity check */
if ( pos >= fat_fd->fat_file_size )
- set_errno_and_return_minus_one( EIO );
+ rtems_set_errno_and_return_minus_one( EIO );
if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
(fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
@@ -759,13 +761,13 @@ fat_file_datasync(
fat_file_fd_t *fat_fd
)
{
- int rc = RC_OK;
- rtems_status_code sc = RTEMS_SUCCESSFUL;
- fat_fs_info_t *fs_info = mt_entry->fs_info;
- uint32_t cur_cln = fat_fd->cln;
- bdbuf_buffer *block = NULL;
- uint32_t sec = 0;
- uint32_t i = 0;
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t cur_cln = fat_fd->cln;
+ rtems_bdbuf_buffer *block = NULL;
+ uint32_t sec = 0;
+ uint32_t i = 0;
if (fat_fd->fat_file_size == 0)
return RC_OK;
@@ -788,11 +790,11 @@ fat_file_datasync(
/* ... sync it */
sc = rtems_bdbuf_read(fs_info->vol.dev, (sec + i), &block);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one( EIO );
+ rtems_set_errno_and_return_minus_one( EIO );
sc = rtems_bdbuf_sync(block);
if ( sc != RTEMS_SUCCESSFUL )
- set_errno_and_return_minus_one( EIO );
+ rtems_set_errno_and_return_minus_one( EIO );
}
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
@@ -947,9 +949,7 @@ fat_file_lseek(
)
{
int rc = RC_OK;
-/*
- assert(fat_fd->fat_file_size);
- */
+
if (file_cln == fat_fd->map.file_cln)
*disk_cln = fat_fd->map.disk_cln;
else
diff --git a/cpukit/libfs/src/dosfs/msdos_create.c b/cpukit/libfs/src/dosfs/msdos_create.c
index 8c238d396c..c790dd740f 100644
--- a/cpukit/libfs/src/dosfs/msdos_create.c
+++ b/cpukit/libfs/src/dosfs/msdos_create.c
@@ -129,9 +129,9 @@ msdos_creat_node(
*MSDOS_DIR_FILE_SIZE(new_node) =*MSDOS_DIR_FILE_SIZE(link_node);
*MSDOS_DIR_FIRST_CLUSTER_LOW(new_node) =
- *MSDOS_DIR_FIRST_CLUSTER_LOW(link_node);
+ *MSDOS_DIR_FIRST_CLUSTER_LOW(link_node);
*MSDOS_DIR_FIRST_CLUSTER_HI(new_node) =
- *MSDOS_DIR_FIRST_CLUSTER_HI(link_node);
+ *MSDOS_DIR_FIRST_CLUSTER_HI(link_node);
/*
* set "archive bit" due to changes
*/
@@ -302,14 +302,14 @@ msdos_file_link(rtems_filesystem_location_info_t *to_loc,
* check spelling and format new node name
*/
if (MSDOS_NAME != msdos_get_token(token, new_name, &len)) {
- set_errno_and_return_minus_one(ENAMETOOLONG);
+ rtems_set_errno_and_return_minus_one(ENAMETOOLONG);
}
/*
* verify, that the existing node can be linked to
* check that nodes are in same FS/volume?
*/
if (to_loc->mt_entry->fs_info != par_loc->mt_entry->fs_info) {
- set_errno_and_return_minus_one(EXDEV);
+ rtems_set_errno_and_return_minus_one(EXDEV);
}
/*
* lock volume
@@ -317,7 +317,7 @@ msdos_file_link(rtems_filesystem_location_info_t *to_loc,
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
/*
@@ -334,7 +334,7 @@ msdos_file_link(rtems_filesystem_location_info_t *to_loc,
to_fat_fd->cln = FAT_EOF;
rc = msdos_set_first_cluster_num(to_loc->mt_entry, to_fat_fd);
if (rc == RC_OK) {
- rc = msdos_set_file_size(par_loc->mt_entry, to_fat_fd);
+ rc = msdos_set_file_size(par_loc->mt_entry, to_fat_fd);
}
}
/*
diff --git a/cpukit/libfs/src/dosfs/msdos_dir.c b/cpukit/libfs/src/dosfs/msdos_dir.c
index f76fa147a3..c2fb72aedd 100644
--- a/cpukit/libfs/src/dosfs/msdos_dir.c
+++ b/cpukit/libfs/src/dosfs/msdos_dir.c
@@ -56,7 +56,7 @@ msdos_dir_open(rtems_libio_t *iop, const char *pathname, uint32_t flag,
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one( EIO );
+ rtems_set_errno_and_return_minus_one( EIO );
rc = fat_file_reopen(fat_fd);
if (rc != RC_OK)
@@ -91,7 +91,7 @@ msdos_dir_close(rtems_libio_t *iop)
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one( EIO );
+ rtems_set_errno_and_return_minus_one( EIO );
rc = fat_file_close(iop->pathinfo.mt_entry, fat_fd);
if (rc != RC_OK)
@@ -233,7 +233,7 @@ msdos_dir_read(rtems_libio_t *iop, void *buffer, size_t count)
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
while (count > 0)
{
@@ -248,7 +248,7 @@ msdos_dir_read(rtems_libio_t *iop, void *buffer, size_t count)
if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
{
rtems_semaphore_release(fs_info->vol_sema);
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
}
for (i = 0; i < ret; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
@@ -377,7 +377,7 @@ msdos_dir_lseek(rtems_libio_t *iop, off_t offset, int whence)
*/
case SEEK_END:
default:
- set_errno_and_return_minus_one( EINVAL );
+ rtems_set_errno_and_return_minus_one( EINVAL );
break;
}
return RC_OK;
@@ -416,7 +416,7 @@ msdos_dir_stat(
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
buf->st_dev = fs_info->fat.vol.dev;
buf->st_ino = fat_fd->ino;
@@ -463,7 +463,7 @@ msdos_dir_sync(rtems_libio_t *iop)
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
@@ -495,7 +495,7 @@ msdos_dir_rmnod(rtems_filesystem_location_info_t *pathloc)
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
/*
* We deny attemp to delete open directory (if directory is current
@@ -504,7 +504,7 @@ msdos_dir_rmnod(rtems_filesystem_location_info_t *pathloc)
if (fat_fd->links_num > 1)
{
rtems_semaphore_release(fs_info->vol_sema);
- set_errno_and_return_minus_one(EBUSY);
+ rtems_set_errno_and_return_minus_one(EBUSY);
}
/*
@@ -520,7 +520,7 @@ msdos_dir_rmnod(rtems_filesystem_location_info_t *pathloc)
if (!is_empty)
{
rtems_semaphore_release(fs_info->vol_sema);
- set_errno_and_return_minus_one(ENOTEMPTY);
+ rtems_set_errno_and_return_minus_one(ENOTEMPTY);
}
/*
@@ -529,7 +529,7 @@ msdos_dir_rmnod(rtems_filesystem_location_info_t *pathloc)
if (pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access)
{
rtems_semaphore_release(fs_info->vol_sema);
- set_errno_and_return_minus_one(EBUSY);
+ rtems_set_errno_and_return_minus_one(EBUSY);
}
/*
diff --git a/cpukit/libfs/src/dosfs/msdos_eval.c b/cpukit/libfs/src/dosfs/msdos_eval.c
index 3e620b96a8..a1a9b4401a 100644
--- a/cpukit/libfs/src/dosfs/msdos_eval.c
+++ b/cpukit/libfs/src/dosfs/msdos_eval.c
@@ -89,7 +89,7 @@ msdos_eval_path(
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
if (!pathloc->node_access)
{
@@ -271,7 +271,7 @@ msdos_eval4make(
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
if (!pathloc->node_access)
{
diff --git a/cpukit/libfs/src/dosfs/msdos_file.c b/cpukit/libfs/src/dosfs/msdos_file.c
index 95c8a8d1fa..c8293d5b24 100644
--- a/cpukit/libfs/src/dosfs/msdos_file.c
+++ b/cpukit/libfs/src/dosfs/msdos_file.c
@@ -53,7 +53,7 @@ msdos_file_open(rtems_libio_t *iop, const char *pathname, uint32_t flag,
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
rc = fat_file_reopen(fat_fd);
if (rc != RC_OK)
@@ -94,7 +94,7 @@ msdos_file_close(rtems_libio_t *iop)
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
/*
* if fat-file descriptor is not marked as "removed", synchronize
@@ -154,7 +154,7 @@ msdos_file_read(rtems_libio_t *iop, void *buffer, size_t count)
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
ret = fat_file_read(iop->pathinfo.mt_entry, fat_fd, iop->offset, count,
buffer);
@@ -187,7 +187,7 @@ msdos_file_write(rtems_libio_t *iop,const void *buffer, size_t count)
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
ret = fat_file_write(iop->pathinfo.mt_entry, fat_fd, iop->offset, count,
buffer);
@@ -235,7 +235,7 @@ msdos_file_lseek(rtems_libio_t *iop, off_t offset, int whence)
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
rc = fat_file_extend(iop->pathinfo.mt_entry, fat_fd, iop->offset,
&real_size);
@@ -276,7 +276,7 @@ msdos_file_stat(
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
buf->st_dev = fs_info->fat.vol.dev;
buf->st_ino = fat_fd->ino;
@@ -315,7 +315,7 @@ msdos_file_ftruncate(rtems_libio_t *iop, off_t length)
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
rc = fat_file_truncate(iop->pathinfo.mt_entry, fat_fd, length);
if (rc != RC_OK)
@@ -356,7 +356,7 @@ msdos_file_sync(rtems_libio_t *iop)
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
/* synchronize file data */
rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
@@ -416,7 +416,7 @@ msdos_file_datasync(rtems_libio_t *iop)
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
/* synchronize file data */
rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
@@ -466,7 +466,7 @@ msdos_file_rmnod(rtems_filesystem_location_info_t *pathloc)
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
/* mark file removed */
rc = msdos_set_first_char4file_name(pathloc->mt_entry, fat_fd->info_cln,
diff --git a/cpukit/libfs/src/dosfs/msdos_format.c b/cpukit/libfs/src/dosfs/msdos_format.c
index ba3e1042d8..bbd4689dc0 100644
--- a/cpukit/libfs/src/dosfs/msdos_format.c
+++ b/cpukit/libfs/src/dosfs/msdos_format.c
@@ -277,7 +277,7 @@ static int msdos_format_eval_sectors_per_cluster
} while (!finished);
if (ret_val != 0) {
- set_errno_and_return_minus_one(ret_val);
+ rtems_set_errno_and_return_minus_one(ret_val);
}
else {
*sectors_per_cluster_adj = sectors_per_cluster;
@@ -298,9 +298,9 @@ static int msdos_format_determine_fmt_params
+---------------------------------------------------------------------------+
| Input Parameters: |
\*-------------------------------------------------------------------------*/
- const disk_device *dd, /* disk device structure */
+ const rtems_disk_device *dd, /* disk device structure */
const msdos_format_request_param_t *rqdata, /* requested fmt parameters */
- msdos_format_param_t *fmt_params/* computed fmt parameters */
+ msdos_format_param_t *fmt_params/* computed fmt parameters */
)
/*-------------------------------------------------------------------------*\
| Return Value: |
@@ -613,7 +613,7 @@ static int msdos_format_determine_fmt_params
* Phuuu.... That's it.
*/
if (ret_val != 0) {
- set_errno_and_return_minus_one(ret_val);
+ rtems_set_errno_and_return_minus_one(ret_val);
}
else {
return 0;
@@ -791,13 +791,13 @@ int msdos_format
| 0, if success, -1 and errno if failed |
\*=========================================================================*/
{
- char tmp_sec[FAT_TOTAL_MBR_SIZE];
- int rc;
- disk_device *dd = NULL;
- struct stat stat_buf;
- int ret_val = 0;
- int fd = -1;
- int i;
+ char tmp_sec[FAT_TOTAL_MBR_SIZE];
+ int rc;
+ rtems_disk_device *dd = NULL;
+ struct stat stat_buf;
+ int ret_val = 0;
+ int fd = -1;
+ int i;
msdos_format_param_t fmt_params;
/*
@@ -817,7 +817,7 @@ int msdos_format
/* check that device is registered as block device and lock it */
if (ret_val == 0) {
- dd = rtems_disk_lookup(stat_buf.st_dev);
+ dd = rtems_disk_obtain(stat_buf.st_dev);
if (dd == NULL) {
errno = ENOTBLK;
ret_val = -1;
diff --git a/cpukit/libfs/src/dosfs/msdos_free.c b/cpukit/libfs/src/dosfs/msdos_free.c
index 2fb74e2387..90fc586a10 100644
--- a/cpukit/libfs/src/dosfs/msdos_free.c
+++ b/cpukit/libfs/src/dosfs/msdos_free.c
@@ -47,7 +47,7 @@ msdos_free_node_info(rtems_filesystem_location_info_t *pathloc)
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
rc = fat_file_close(pathloc->mt_entry, pathloc->node_access);
diff --git a/cpukit/libfs/src/dosfs/msdos_initsupp.c b/cpukit/libfs/src/dosfs/msdos_initsupp.c
index ce86fa22b0..42495c7622 100644
--- a/cpukit/libfs/src/dosfs/msdos_initsupp.c
+++ b/cpukit/libfs/src/dosfs/msdos_initsupp.c
@@ -61,7 +61,7 @@ msdos_initialize_support(
fs_info = (msdos_fs_info_t *)calloc(1, sizeof(msdos_fs_info_t));
if (!fs_info)
- set_errno_and_return_minus_one(ENOMEM);
+ rtems_set_errno_and_return_minus_one(ENOMEM);
temp_mt_entry->fs_info = fs_info;
@@ -124,7 +124,7 @@ msdos_initialize_support(
fat_file_close(temp_mt_entry, fat_fd);
fat_shutdown_drive(temp_mt_entry);
free(fs_info);
- set_errno_and_return_minus_one(ENOMEM);
+ rtems_set_errno_and_return_minus_one(ENOMEM);
}
sc = rtems_semaphore_create(3,
@@ -138,7 +138,7 @@ msdos_initialize_support(
fat_shutdown_drive(temp_mt_entry);
free(fs_info->cl_buf);
free(fs_info);
- set_errno_and_return_minus_one( EIO );
+ rtems_set_errno_and_return_minus_one( EIO );
}
temp_mt_entry->mt_fs_root.node_access = fat_fd;
diff --git a/cpukit/libfs/src/dosfs/msdos_misc.c b/cpukit/libfs/src/dosfs/msdos_misc.c
index b7e6ab3523..077fb945b9 100644
--- a/cpukit/libfs/src/dosfs/msdos_misc.c
+++ b/cpukit/libfs/src/dosfs/msdos_misc.c
@@ -11,6 +11,8 @@
* @(#) $Id$
*/
+#define MSDOS_TRACE 1
+
#if HAVE_CONFIG_H
#include "config.h"
#endif
@@ -786,7 +788,7 @@ int msdos_find_name_in_fat_file(
fs_info->cl_buf)) != FAT_EOF)
{
if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
assert(ret == bts2rd);
@@ -903,7 +905,7 @@ int msdos_find_node_by_cluster_num_in_fat_file(
fs_info->cl_buf)) != FAT_EOF)
{
if ( ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE )
- set_errno_and_return_minus_one( EIO );
+ rtems_set_errno_and_return_minus_one( EIO );
assert(ret == bts2rd);
diff --git a/cpukit/libfs/src/dosfs/msdos_mknod.c b/cpukit/libfs/src/dosfs/msdos_mknod.c
index cdc12da092..ac2a142cce 100644
--- a/cpukit/libfs/src/dosfs/msdos_mknod.c
+++ b/cpukit/libfs/src/dosfs/msdos_mknod.c
@@ -74,12 +74,12 @@ int msdos_mknod(
type = MSDOS_REGULAR_FILE;
}
else
- set_errno_and_return_minus_one(EINVAL);
+ rtems_set_errno_and_return_minus_one(EINVAL);
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
- set_errno_and_return_minus_one(EIO);
+ rtems_set_errno_and_return_minus_one(EIO);
/* Create an MSDOS node */
rc = msdos_creat_node(pathloc, type, new_name, mode, NULL);
diff --git a/cpukit/libmisc/Makefile.am b/cpukit/libmisc/Makefile.am
index db79e248cf..e262348016 100644
--- a/cpukit/libmisc/Makefile.am
+++ b/cpukit/libmisc/Makefile.am
@@ -65,7 +65,7 @@ if LIBSHELL
noinst_LIBRARIES += libshell.a
libshell_a_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/shell
libshell_a_SOURCES = shell/cat_file.c shell/cmds.c shell/internal.h \
- shell/main_alias.c shell/main_cat.c shell/main_cd.c \
+ shell/main_alias.c shell/main_cat.c shell/main_cd.c shell/cmp-ls.c \
shell/main_chdir.c shell/main_chmod.c shell/main_chroot.c \
shell/main_cp.c shell/main_cpuuse.c shell/main_date.c shell/main_dir.c \
shell/main_echo.c shell/main_exit.c shell/main_help.c shell/main_id.c \
@@ -78,8 +78,10 @@ libshell_a_SOURCES = shell/cat_file.c shell/cmds.c shell/internal.h \
shell/main_stackuse.c shell/main_tty.c shell/main_umask.c \
shell/main_unmount.c shell/main_blksync.c shell/main_whoami.c \
shell/shell.c shell/shell_cmdset.c shell/shell_getchar.c shell/shellconfig.c \
- shell/shellconfig.h shell/shell.h shell/shell_makeargs.c shell/str2int.c \
- shell/write_file.c shell/utils-cp.c shell/err.c shell/errx.c shell/verr.c \
+ shell/shellconfig.h shell/shell.h shell/shell_makeargs.c \
+ shell/str2int.c shell/filemode.c shell/pwcache.c shell/print-ls.c\
+ shell/write_file.c shell/utils-cp.c shell/utils-ls.c \
+ shell/err.c shell/errx.c shell/verr.c shell/vis.c \
shell/verrx.c shell/vwarn.c shell/vwarnx.c shell/warn.c shell/warnx.c \
shell/fts.c shell/print_heapinfo.c shell/main_wkspaceinfo.c \
shell/shell_script.c
diff --git a/cpukit/libmisc/shell/cmp-ls.c b/cpukit/libmisc/shell/cmp-ls.c
new file mode 100644
index 0000000000..e146762f08
--- /dev/null
+++ b/cpukit/libmisc/shell/cmp-ls.c
@@ -0,0 +1,200 @@
+/* $NetBSD: cmp.c,v 1.17 2003/08/07 09:05:14 agc Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Michael Fischbein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)cmp.c 8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: cmp.c,v 1.17 2003/08/07 09:05:14 agc Exp $");
+#endif
+#endif /* not lint */
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <fts.h>
+#include <string.h>
+
+#include "extern-ls.h"
+
+#if defined(__rtems__) || defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) || \
+ defined(_XOPEN_SOURCE) || defined(__NetBSD__)
+#define ATIMENSEC_CMP(x, op, y) ((x)->st_atime op (y)->st_atime)
+#define CTIMENSEC_CMP(x, op, y) ((x)->st_ctime op (y)->st_ctime)
+#define MTIMENSEC_CMP(x, op, y) ((x)->st_mtime op (y)->st_mtime)
+#else
+#define ATIMENSEC_CMP(x, op, y) \
+ ((x)->st_atime.tv_nsec op (y)->st_atime.tv_nsec)
+#define CTIMENSEC_CMP(x, op, y) \
+ ((x)->st_ctime.tv_nsec op (y)->st_ctime.tv_nsec)
+#define MTIMENSEC_CMP(x, op, y) \
+ ((x)->st_mtime.tv_nsec op (y)->st_mtime.tv_nsec)
+#endif
+
+int
+namecmp(const FTSENT *a, const FTSENT *b)
+{
+
+ return (strcmp(a->fts_name, b->fts_name));
+}
+
+int
+revnamecmp(const FTSENT *a, const FTSENT *b)
+{
+
+ return (strcmp(b->fts_name, a->fts_name));
+}
+
+int
+modcmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if (b->fts_statp->st_mtime > a->fts_statp->st_mtime)
+ return (1);
+ else if (b->fts_statp->st_mtime < a->fts_statp->st_mtime)
+ return (-1);
+ else if (MTIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
+ return (1);
+ else if (MTIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
+ return (-1);
+ else
+ return (namecmp(a, b));
+}
+
+int
+revmodcmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if (b->fts_statp->st_mtime > a->fts_statp->st_mtime)
+ return (-1);
+ else if (b->fts_statp->st_mtime < a->fts_statp->st_mtime)
+ return (1);
+ else if (MTIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
+ return (-1);
+ else if (MTIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
+ return (1);
+ else
+ return (revnamecmp(a, b));
+}
+
+int
+acccmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if (b->fts_statp->st_atime > a->fts_statp->st_atime)
+ return (1);
+ else if (b->fts_statp->st_atime < a->fts_statp->st_atime)
+ return (-1);
+ else if (ATIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
+ return (1);
+ else if (ATIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
+ return (-1);
+ else
+ return (namecmp(a, b));
+}
+
+int
+revacccmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if (b->fts_statp->st_atime > a->fts_statp->st_atime)
+ return (-1);
+ else if (b->fts_statp->st_atime < a->fts_statp->st_atime)
+ return (1);
+ else if (ATIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
+ return (-1);
+ else if (ATIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
+ return (1);
+ else
+ return (revnamecmp(a, b));
+}
+
+int
+statcmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if (b->fts_statp->st_ctime > a->fts_statp->st_ctime)
+ return (1);
+ else if (b->fts_statp->st_ctime < a->fts_statp->st_ctime)
+ return (-1);
+ else if (CTIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
+ return (1);
+ else if (CTIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
+ return (-1);
+ else
+ return (namecmp(a, b));
+}
+
+int
+revstatcmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if (b->fts_statp->st_ctime > a->fts_statp->st_ctime)
+ return (-1);
+ else if (b->fts_statp->st_ctime < a->fts_statp->st_ctime)
+ return (1);
+ else if (CTIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
+ return (-1);
+ else if (CTIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
+ return (1);
+ else
+ return (revnamecmp(a, b));
+}
+
+int
+sizecmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if (b->fts_statp->st_size > a->fts_statp->st_size)
+ return (1);
+ if (b->fts_statp->st_size < a->fts_statp->st_size)
+ return (-1);
+ else
+ return (namecmp(a, b));
+}
+
+int
+revsizecmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if (b->fts_statp->st_size > a->fts_statp->st_size)
+ return (-1);
+ if (b->fts_statp->st_size < a->fts_statp->st_size)
+ return (1);
+ else
+ return (revnamecmp(a, b));
+}
diff --git a/cpukit/libmisc/shell/extern-cp.h b/cpukit/libmisc/shell/extern-cp.h
index ba6ff9c4de..093b30ff10 100644
--- a/cpukit/libmisc/shell/extern-cp.h
+++ b/cpukit/libmisc/shell/extern-cp.h
@@ -84,7 +84,7 @@ int set_utimes(const char *, struct stat *);
int setfile(rtems_shell_cp_globals* cp_globals, struct stat *, int);
int preserve_dir_acls(struct stat *, char *, char *);
int preserve_fd_acls(int, int);
-void usage();
+void usage(rtems_shell_cp_globals* cp_globals);
__END_DECLS
diff --git a/cpukit/libmisc/shell/extern-ls.h b/cpukit/libmisc/shell/extern-ls.h
new file mode 100644
index 0000000000..01575ba7df
--- /dev/null
+++ b/cpukit/libmisc/shell/extern-ls.h
@@ -0,0 +1,195 @@
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Michael Fischbein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)ls.h 8.1 (Berkeley) 5/31/93
+ * $FreeBSD: src/bin/ls/ls.h,v 1.23 2008/04/04 03:57:46 grog Exp $
+ */
+
+#ifndef _EXTERN_LS_H_
+#define _EXTERN_LS_H_
+
+#define NO_PRINT 1
+//#define COLORLS 1
+
+#include <sys/cdefs.h>
+#include <setjmp.h>
+
+#define major(d) rtems_filesystem_dev_major_t(d)
+#define minor(d) rtems_filesystem_dev_minor_t(d)
+
+const char *user_from_uid(uid_t uid, int nouser);
+
+typedef struct {
+ int blocksize;
+ int termwidth;
+ int sortkey;
+ int rval;
+ int output;
+ time_t now;
+
+ int f_accesstime;
+ int f_column;
+ int f_columnacross;
+ int f_flags;
+ int f_grouponly;
+ int f_humanize;
+ int f_inode;
+ int f_listdir;
+ int f_listdot;
+ int f_longform;
+ int f_nonprint;
+ int f_nosort;
+ int f_numericonly;
+ int f_octal;
+ int f_octal_escape;
+ int f_recursive;
+ int f_reversesort;
+ int f_sectime;
+ int f_singlecol;
+ int f_size;
+ int f_statustime;
+ int f_stream;
+ int f_type;
+ int f_typedir;
+ int f_whiteout;
+
+ int exit_code;
+ jmp_buf exit_jmp;
+} rtems_shell_ls_globals;
+
+#define blocksize globals->blocksize
+#define termwidth globals->termwidth
+#define sortkey globals->sortkey
+#define rval globals->rval
+#define output globals->output
+#define now globals->now
+
+#define f_accesstime globals->f_accesstime
+#define f_column globals->f_column
+#define f_columnacross globals->f_columnacross
+#define f_flags globals->f_flags
+#define f_grouponly globals->f_grouponly
+#define f_humanize globals->f_humanize
+#define f_inode globals->f_inode
+#define f_listdir globals->f_listdir
+#define f_listdot globals->f_listdot
+#define f_longform globals->f_longform
+#define f_nonprint globals->f_nonprint
+#define f_nosort globals->f_nosort
+#define f_numericonly globals->f_numericonly
+#define f_octal globals->f_octal
+#define f_octal_escape globals->f_octal_escape
+#define f_recursive globals->f_recursive
+#define f_reversesort globals->f_reversesort
+#define f_sectime globals->f_sectime
+#define f_singlecol globals->f_singlecol
+#define f_size globals->f_size
+#define f_statustime globals->f_statustime
+#define f_stream globals->f_stream
+#define f_type globals->f_type
+#define f_typedir globals->f_typedir
+#define f_whiteout globals->f_whiteout
+
+#define exit_jump &(globals->exit_jmp)
+
+void rtems_shell_ls_exit(rtems_shell_ls_globals* globals, int code);
+
+#define exit(ec) rtems_shell_ls_exit(globals, ec)
+
+
+typedef struct {
+ FTSENT *list;
+ u_int64_t btotal;
+ u_int64_t stotal;
+ int entries;
+ int maxlen;
+ int s_block;
+ int s_flags;
+ int s_group;
+ int s_inode;
+ int s_nlink;
+ int s_size;
+ int s_user;
+ int s_major;
+ int s_minor;
+} DISPLAY;
+
+typedef struct {
+ char *user;
+ char *group;
+ char *flags;
+ char data[1];
+} NAMES;
+
+#define acccmp rtems_shell_ls_acccmp
+#define revacccmp rtems_shell_ls_revacccmp
+#define modcmp rtems_shell_ls_modcmp
+#define revmodcmp rtems_shell_ls_revmodcmp
+#define namecmp rtems_shell_ls_namecmp
+#define revnamecmp rtems_shell_ls_revnamecmp
+#define statcmp rtems_shell_ls_statcmp
+#define revstatcmp rtems_shell_ls_revstatcmp
+#define sizecmp rtems_shell_ls_sizecmp
+#define revsizecmp rtems_shell_ls_revsizecmp
+#define printescaped rtems_shell_ls_printescaped
+#define printacol rtems_shell_ls_printacol
+#define printcol rtems_shell_ls_printcol
+#define printlong rtems_shell_ls_printlong
+#define printscol rtems_shell_ls_printscol
+#define printstream rtems_shell_ls_printstream
+#define usage rtems_shell_ls_usage
+
+int acccmp(const FTSENT *, const FTSENT *);
+int revacccmp(const FTSENT *, const FTSENT *);
+int modcmp(const FTSENT *, const FTSENT *);
+int revmodcmp(const FTSENT *, const FTSENT *);
+int namecmp(const FTSENT *, const FTSENT *);
+int revnamecmp(const FTSENT *, const FTSENT *);
+int statcmp(const FTSENT *, const FTSENT *);
+int revstatcmp(const FTSENT *, const FTSENT *);
+int sizecmp(const FTSENT *, const FTSENT *);
+int revsizecmp(const FTSENT *, const FTSENT *);
+
+int printescaped(rtems_shell_ls_globals* globals, const char *);
+void printacol(rtems_shell_ls_globals* globals, DISPLAY *);
+void printcol(rtems_shell_ls_globals* globals, DISPLAY *);
+void printlong(rtems_shell_ls_globals* globals, DISPLAY *);
+void printscol(rtems_shell_ls_globals* globals, DISPLAY *);
+void printstream(rtems_shell_ls_globals* globals, DISPLAY *);
+int safe_print(rtems_shell_ls_globals* globals, const char *);
+void usage(rtems_shell_ls_globals* globals);
+
+void strmode(mode_t mode, char *p);
+
+#define DAYSPERNYEAR 365
+#define SECSPERDAY (60 * 60 * 24)
+
+#endif /* !_EXTERN_H_ */
diff --git a/cpukit/libmisc/shell/filemode.c b/cpukit/libmisc/shell/filemode.c
new file mode 100644
index 0000000000..6d77a1be95
--- /dev/null
+++ b/cpukit/libmisc/shell/filemode.c
@@ -0,0 +1,150 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strmode.c 8.3 (Berkeley) 8/15/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/strmode.c,v 1.5 2007/01/09 00:28:12 imp Exp $");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+
+void
+strmode(mode, p)
+ mode_t mode;
+ char *p;
+{
+ /* print type */
+ switch (mode & S_IFMT) {
+ case S_IFDIR: /* directory */
+ *p++ = 'd';
+ break;
+ case S_IFCHR: /* character special */
+ *p++ = 'c';
+ break;
+ case S_IFBLK: /* block special */
+ *p++ = 'b';
+ break;
+ case S_IFREG: /* regular */
+ *p++ = '-';
+ break;
+ case S_IFLNK: /* symbolic link */
+ *p++ = 'l';
+ break;
+ case S_IFSOCK: /* socket */
+ *p++ = 's';
+ break;
+#ifdef S_IFIFO
+ case S_IFIFO: /* fifo */
+ *p++ = 'p';
+ break;
+#endif
+#ifdef S_IFWHT
+ case S_IFWHT: /* whiteout */
+ *p++ = 'w';
+ break;
+#endif
+ default: /* unknown */
+ *p++ = '?';
+ break;
+ }
+ /* usr */
+ if (mode & S_IRUSR)
+ *p++ = 'r';
+ else
+ *p++ = '-';
+ if (mode & S_IWUSR)
+ *p++ = 'w';
+ else
+ *p++ = '-';
+ switch (mode & (S_IXUSR | S_ISUID)) {
+ case 0:
+ *p++ = '-';
+ break;
+ case S_IXUSR:
+ *p++ = 'x';
+ break;
+ case S_ISUID:
+ *p++ = 'S';
+ break;
+ case S_IXUSR | S_ISUID:
+ *p++ = 's';
+ break;
+ }
+ /* group */
+ if (mode & S_IRGRP)
+ *p++ = 'r';
+ else
+ *p++ = '-';
+ if (mode & S_IWGRP)
+ *p++ = 'w';
+ else
+ *p++ = '-';
+ switch (mode & (S_IXGRP | S_ISGID)) {
+ case 0:
+ *p++ = '-';
+ break;
+ case S_IXGRP:
+ *p++ = 'x';
+ break;
+ case S_ISGID:
+ *p++ = 'S';
+ break;
+ case S_IXGRP | S_ISGID:
+ *p++ = 's';
+ break;
+ }
+ /* other */
+ if (mode & S_IROTH)
+ *p++ = 'r';
+ else
+ *p++ = '-';
+ if (mode & S_IWOTH)
+ *p++ = 'w';
+ else
+ *p++ = '-';
+ switch (mode & (S_IXOTH | S_ISVTX)) {
+ case 0:
+ *p++ = '-';
+ break;
+ case S_IXOTH:
+ *p++ = 'x';
+ break;
+ case S_ISVTX:
+ *p++ = 'T';
+ break;
+ case S_IXOTH | S_ISVTX:
+ *p++ = 't';
+ break;
+ }
+ *p++ = ' '; /* will be a '+' if ACL's implemented */
+ *p = '\0';
+}
diff --git a/cpukit/libmisc/shell/main_blksync.c b/cpukit/libmisc/shell/main_blksync.c
index 0089a75adf..8226aefc9a 100644
--- a/cpukit/libmisc/shell/main_blksync.c
+++ b/cpukit/libmisc/shell/main_blksync.c
@@ -58,7 +58,7 @@ int rtems_shell_main_blksync(
return 1;
}
- if (ioctl (fd, BLKIO_SYNCDEV) < 0) {
+ if (ioctl (fd, RTEMS_BLKIO_SYNCDEV) < 0) {
fprintf( stderr, "%s: driver sync failed: %s\n", argv[0], strerror (errno));
return 1;
}
diff --git a/cpukit/libmisc/shell/main_cp.c b/cpukit/libmisc/shell/main_cp.c
index 3111a4db74..773ec5ad69 100644
--- a/cpukit/libmisc/shell/main_cp.c
+++ b/cpukit/libmisc/shell/main_cp.c
@@ -175,14 +175,14 @@ main_cp(rtems_shell_cp_globals* cp_globals, int argc, char *argv[])
vflag = 1;
break;
default:
- usage();
+ usage(cp_globals);
break;
}
argc -= getopt_reent.optind;
argv += getopt_reent.optind;
if (argc < 2)
- usage();
+ usage(cp_globals);
fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
if (Rflag && rflag)
diff --git a/cpukit/libmisc/shell/main_ls.c b/cpukit/libmisc/shell/main_ls.c
index c81e35efda..d52229b521 100644
--- a/cpukit/libmisc/shell/main_ls.c
+++ b/cpukit/libmisc/shell/main_ls.c
@@ -1,104 +1,758 @@
+/* $NetBSD: ls.c,v 1.58 2005/10/26 02:24:22 jschauma Exp $ */
+
/*
- * LS Shell Command Implmentation
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
*
- * Author: Fernando RUIZ CASAS
- * Work: fernando.ruiz@ctv.es
- * Home: correo@fernando-ruiz.com
+ * This code is derived from software contributed to Berkeley by
+ * Michael Fischbein.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
*
- * $Id$
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
+#if 0
+#include <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)ls.c 8.7 (Berkeley) 8/5/94";
+#else
+__RCSID("$NetBSD: ls.c,v 1.58 2005/10/26 02:24:22 jschauma Exp $");
+#endif
+#endif /* not lint */
#endif
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/shellconfig.h>
+#include <getopt.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <fts.h>
+#include <locale.h>
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
-#include <ctype.h>
-#include <dirent.h>
-#include <time.h>
-#include <fcntl.h>
+#include <string.h>
#include <unistd.h>
+#include <termios.h>
#include <pwd.h>
#include <grp.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stddef.h>
-#include <rtems.h>
-#include <rtems/shell.h>
-#include "internal.h"
+#include "extern-ls.h"
+
+static void display(rtems_shell_ls_globals* globals, FTSENT *, FTSENT *);
+static int mastercmp_listdir(const FTSENT **, const FTSENT **);
+static int mastercmp_no_listdir(const FTSENT **, const FTSENT **);
+static void traverse(rtems_shell_ls_globals* globals, int, char **, int);
+
+static void (*printfcn)(rtems_shell_ls_globals* globals, DISPLAY *);
+static int (*sortfcn)(const FTSENT *, const FTSENT *);
+
+#define BY_NAME 0
+#define BY_SIZE 1
+#define BY_TIME 2
+
+#if RTEMS_REMOVED
+long blocksize; /* block size units */
+int termwidth = 80; /* default terminal width */
+int sortkey = BY_NAME;
+int rval = EXIT_SUCCESS; /* exit value - set if error encountered */
+
+/* flags */
+int f_accesstime; /* use time of last access */
+int f_column; /* columnated format */
+int f_columnacross; /* columnated format, sorted across */
+int f_flags; /* show flags associated with a file */
+int f_grouponly; /* long listing without owner */
+int f_humanize; /* humanize the size field */
+int f_inode; /* print inode */
+int f_listdir; /* list actual directory, not contents */
+int f_listdot; /* list files beginning with . */
+int f_longform; /* long listing format */
+int f_nonprint; /* show unprintables as ? */
+int f_nosort; /* don't sort output */
+int f_numericonly; /* don't convert uid/gid to name */
+int f_octal; /* print octal escapes for nongraphic characters */
+int f_octal_escape; /* like f_octal but use C escapes if possible */
+int f_recursive; /* ls subdirectories also */
+int f_reversesort; /* reverse whatever sort is used */
+int f_sectime; /* print the real time for all files */
+int f_singlecol; /* use single column output */
+int f_size; /* list size in short listing */
+int f_statustime; /* use time of last mode change */
+int f_stream; /* stream format */
+int f_type; /* add type character for non-regular files */
+int f_typedir; /* add type character for directories */
+int f_whiteout; /* show whiteout entries */
+#endif
+
+void
+rtems_shell_ls_exit (rtems_shell_ls_globals* globals, int code)
+{
+ globals->exit_code = code;
+ longjmp (globals->exit_jmp, 1);
+}
+
+static int main_ls(rtems_shell_ls_globals* globals, int argc, char *argv[]);
+
+int
+rtems_shell_main_ls(int argc, char *argv[])
+{
+ rtems_shell_ls_globals ls_globals;
+ rtems_shell_ls_globals* globals = &ls_globals;
+ memset (globals, 0, sizeof (ls_globals));
+ termwidth = 80;
+ sortkey = BY_NAME;
+ rval = EXIT_SUCCESS;
+ ls_globals.exit_code = 1;
+ if (setjmp (ls_globals.exit_jmp) == 0)
+ return main_ls (globals, argc, argv);
+ return ls_globals.exit_code;
+}
+
+int
+main_ls(rtems_shell_ls_globals* globals, int argc, char *argv[])
+{
+ static char dot[] = ".", *dotav[] = { dot, NULL };
+ //struct winsize win;
+ int ch, fts_options;
+ int kflag = 0;
+ const char *p;
+
+ struct getopt_data getopt_reent;
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+
+#if RTEMS_REMOVED
+ setprogname(argv[0]);
+#endif
+ setlocale(LC_ALL, "");
+
+ /* Terminal defaults to -Cq, non-terminal defaults to -1. */
+ if (isatty(STDOUT_FILENO)) {
+#if RTEMS_REMOVED
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == 0 &&
+ win.ws_col > 0)
+ termwidth = win.ws_col;
+ f_column = f_nonprint = 1;
+#endif
+ } else
+ f_singlecol = 1;
+
+ /* Root is -A automatically. */
+ if (!getuid())
+ f_listdot = 1;
+
+ fts_options = FTS_PHYSICAL;
+ while ((ch = getopt_r(argc, argv,
+ "1ABCFLRSTWabcdfghiklmnopqrstuwx", &getopt_reent)) != -1) {
+ switch (ch) {
+ /*
+ * The -1, -C, -l, -m and -x options all override each other so
+ * shell aliasing works correctly.
+ */
+ case '1':
+ f_singlecol = 1;
+ f_column = f_columnacross = f_longform = f_stream = 0;
+ break;
+ case 'C':
+ f_column = 1;
+ f_columnacross = f_longform = f_singlecol = f_stream =
+ 0;
+ break;
+ case 'g':
+ if (f_grouponly != -1)
+ f_grouponly = 1;
+ f_longform = 1;
+ f_column = f_columnacross = f_singlecol = f_stream = 0;
+ break;
+ case 'l':
+ f_longform = 1;
+ f_column = f_columnacross = f_singlecol = f_stream = 0;
+ /* Never let -g take precedence over -l. */
+ f_grouponly = -1;
+ break;
+ case 'm':
+ f_stream = 1;
+ f_column = f_columnacross = f_longform = f_singlecol =
+ 0;
+ break;
+ case 'x':
+ f_columnacross = 1;
+ f_column = f_longform = f_singlecol = f_stream = 0;
+ break;
+ /* The -c and -u options override each other. */
+ case 'c':
+ f_statustime = 1;
+ f_accesstime = 0;
+ break;
+ case 'u':
+ f_accesstime = 1;
+ f_statustime = 0;
+ break;
+ case 'F':
+ f_type = 1;
+ break;
+ case 'L':
+ fts_options &= ~FTS_PHYSICAL;
+ fts_options |= FTS_LOGICAL;
+ break;
+ case 'R':
+ f_recursive = 1;
+ break;
+ case 'a':
+ fts_options |= FTS_SEEDOT;
+ /* FALLTHROUGH */
+ case 'A':
+ f_listdot = 1;
+ break;
+ /* The -B option turns off the -b, -q and -w options. */
+ case 'B':
+ f_nonprint = 0;
+ f_octal = 1;
+ f_octal_escape = 0;
+ break;
+ /* The -b option turns off the -B, -q and -w options. */
+ case 'b':
+ f_nonprint = 0;
+ f_octal = 0;
+ f_octal_escape = 1;
+ break;
+ /* The -d option turns off the -R option. */
+ case 'd':
+ f_listdir = 1;
+ f_recursive = 0;
+ break;
+ case 'f':
+ f_nosort = 1;
+ break;
+ case 'i':
+ f_inode = 1;
+ break;
+ case 'k':
+ blocksize = 1024;
+ kflag = 1;
+ break;
+ /* The -h option forces all sizes to be measured in bytes. */
+ case 'h':
+ f_humanize = 1;
+ break;
+ case 'n':
+ f_numericonly = 1;
+ break;
+ case 'o':
+ f_flags = 1;
+ break;
+ case 'p':
+ f_typedir = 1;
+ break;
+ /* The -q option turns off the -B, -b and -w options. */
+ case 'q':
+ f_nonprint = 1;
+ f_octal = 0;
+ f_octal_escape = 0;
+ break;
+ case 'r':
+ f_reversesort = 1;
+ break;
+ case 'S':
+ sortkey = BY_SIZE;
+ break;
+ case 's':
+ f_size = 1;
+ break;
+ case 'T':
+ f_sectime = 1;
+ break;
+ case 't':
+ sortkey = BY_TIME;
+ break;
+ case 'W':
+ f_whiteout = 1;
+ break;
+ /* The -w option turns off the -B, -b and -q options. */
+ case 'w':
+ f_nonprint = 0;
+ f_octal = 0;
+ f_octal_escape = 0;
+ break;
+ default:
+ case '?':
+ usage(globals);
+ }
+ }
+ argc -= getopt_reent.optind;
+ argv += getopt_reent.optind;
+
+ if (f_column || f_columnacross || f_stream) {
+ if ((p = getenv("COLUMNS")) != NULL)
+ termwidth = atoi(p);
+ }
+
+ /*
+ * If both -g and -l options, let -l take precedence.
+ */
+ if (f_grouponly == -1)
+ f_grouponly = 0;
+
+ /*
+ * If not -F, -i, -l, -p, -S, -s or -t options, don't require stat
+ * information.
+ */
+ if (!f_inode && !f_longform && !f_size && !f_type && !f_typedir &&
+ sortkey == BY_NAME)
+ fts_options |= FTS_NOSTAT;
+
+ /*
+ * If not -F, -d or -l options, follow any symbolic links listed on
+ * the command line.
+ */
+ if (!f_longform && !f_listdir && !f_type)
+ fts_options |= FTS_COMFOLLOW;
+
+ /*
+ * If -W, show whiteout entries
+ */
+#ifdef FTS_WHITEOUT
+ if (f_whiteout)
+ fts_options |= FTS_WHITEOUT;
+#endif
+
+ /* If -l or -s, figure out block size. */
+ if (f_inode || f_longform || f_size) {
+#if RTEMS_REMOVED
+ if (!kflag)
+ (void)getbsize(NULL, &blocksize);
+#else
+ blocksize = 1024;
+#endif
+ blocksize /= 512;
+ }
+
+ /* Select a sort function. */
+ if (f_reversesort) {
+ switch (sortkey) {
+ case BY_NAME:
+ sortfcn = revnamecmp;
+ break;
+ case BY_SIZE:
+ sortfcn = revsizecmp;
+ break;
+ case BY_TIME:
+ if (f_accesstime)
+ sortfcn = revacccmp;
+ else if (f_statustime)
+ sortfcn = revstatcmp;
+ else /* Use modification time. */
+ sortfcn = revmodcmp;
+ break;
+ }
+ } else {
+ switch (sortkey) {
+ case BY_NAME:
+ sortfcn = namecmp;
+ break;
+ case BY_SIZE:
+ sortfcn = sizecmp;
+ break;
+ case BY_TIME:
+ if (f_accesstime)
+ sortfcn = acccmp;
+ else if (f_statustime)
+ sortfcn = statcmp;
+ else /* Use modification time. */
+ sortfcn = modcmp;
+ break;
+ }
+ }
+
+ /* Select a print function. */
+ if (f_singlecol)
+ printfcn = printscol;
+ else if (f_columnacross)
+ printfcn = printacol;
+ else if (f_longform)
+ printfcn = printlong;
+ else if (f_stream)
+ printfcn = printstream;
+ else
+ printfcn = printcol;
+
+ if (argc)
+ traverse(globals, argc, argv, fts_options);
+ else
+ traverse(globals, 1, dotav, fts_options);
+ exit(rval);
+ /* NOTREACHED */
+ return 0;
+}
+
+#if RTEMS_REMOVED
+static int output; /* If anything output. */
+#endif
-int rtems_shell_main_ls(
- int argc,
- char *argv[]
-)
+/*
+ * Traverse() walks the logical directory structure specified by the argv list
+ * in the order specified by the mastercmp() comparison function. During the
+ * traversal it passes linked lists of structures to display() which represent
+ * a superset (may be exact set) of the files to be displayed.
+ */
+static void
+traverse(rtems_shell_ls_globals* globals, int argc, char *argv[], int options)
{
- char *fname;
- DIR *dirp;
- struct dirent *dp;
- struct stat stat_buf;
- struct passwd *pwd;
- struct group *grp;
- char *user;
- char *group;
- char sbuf[256];
- char nbuf[1024];
- int n;
- int size;
-
- fname = ".";
- if (argc>1)
- fname = argv[1];
-
- if ((dirp = opendir(fname)) == NULL) {
- fprintf(stderr,"%s: %s: No such file or directory.\n", argv[0], fname);
- return errno;
- }
- n = 0;
- size = 0;
- while ((dp = readdir(dirp)) != NULL) {
- strcpy(nbuf,fname);
- if (nbuf[strlen(nbuf)-1]!='/')
- strcat(nbuf,"/");
- strcat(nbuf,dp->d_name); /* always the fullpathname. Avoid ftpd problem.*/
- if (stat(nbuf, &stat_buf) == 0) { /* AWFUL but works...*/
- strftime(sbuf,sizeof(sbuf)-1,"%b %d %H:%M", gmtime(&stat_buf.st_mtime));
- pwd = getpwuid(stat_buf.st_uid);
- user = pwd?pwd->pw_name:"nouser";
- grp = getgrgid(stat_buf.st_gid);
- group = grp?grp->gr_name:"nogrp";
- printf("%c%c%c%c%c%c%c%c%c%c %3d %6.6s %6.6s %11d %s %s%c\n",
- (S_ISLNK(stat_buf.st_mode)?('l'):
- (S_ISDIR(stat_buf.st_mode)?('d'):('-'))),
- (stat_buf.st_mode & S_IRUSR)?('r'):('-'),
- (stat_buf.st_mode & S_IWUSR)?('w'):('-'),
- (stat_buf.st_mode & S_IXUSR)?('x'):('-'),
- (stat_buf.st_mode & S_IRGRP)?('r'):('-'),
- (stat_buf.st_mode & S_IWGRP)?('w'):('-'),
- (stat_buf.st_mode & S_IXGRP)?('x'):('-'),
- (stat_buf.st_mode & S_IROTH)?('r'):('-'),
- (stat_buf.st_mode & S_IWOTH)?('w'):('-'),
- (stat_buf.st_mode & S_IXOTH)?('x'):('-'),
- (int)stat_buf.st_nlink,
- user,group,
- (int)stat_buf.st_size,
- sbuf,
- dp->d_name,
- S_ISDIR(stat_buf.st_mode)?'/':' ');
- n++;
- size += stat_buf.st_size;
+ FTS *ftsp;
+ FTSENT *p, *chp;
+ int ch_options;
+
+ if ((ftsp =
+ fts_open(argv, options,
+ f_nosort ? NULL : f_listdir ?
+ mastercmp_listdir : mastercmp_no_listdir)) == NULL)
+ err(exit_jump, EXIT_FAILURE, NULL);
+
+ display(globals, NULL, fts_children(ftsp, 0));
+ if (f_listdir)
+ {
+ fts_close(ftsp);
+ return;
}
- }
- printf("%d files %d bytes occupied\n",n,size);
- closedir(dirp);
- return 0;
+
+ /*
+ * If not recursing down this tree and don't need stat info, just get
+ * the names.
+ */
+ ch_options = !f_recursive && options & FTS_NOSTAT ? FTS_NAMEONLY : 0;
+
+ while ((p = fts_read(ftsp)) != NULL)
+ switch (p->fts_info) {
+ case FTS_DC:
+ warnx("%s: directory causes a cycle", p->fts_name);
+ break;
+ case FTS_DNR:
+ case FTS_ERR:
+ warnx("%s: %s", p->fts_name, strerror(p->fts_errno));
+ rval = EXIT_FAILURE;
+ break;
+ case FTS_D:
+ if (p->fts_level != FTS_ROOTLEVEL &&
+ p->fts_name[0] == '.' && !f_listdot)
+ break;
+
+ /*
+ * If already output something, put out a newline as
+ * a separator. If multiple arguments, precede each
+ * directory with its name.
+ */
+ if (output)
+ (void)printf("\n%s:\n", p->fts_path);
+ else if (argc > 1) {
+ (void)printf("%s:\n", p->fts_path);
+ output = 1;
+ }
+
+ chp = fts_children(ftsp, ch_options);
+ display(globals, p, chp);
+
+ if (!f_recursive && chp != NULL)
+ (void)fts_set(ftsp, p, FTS_SKIP);
+ break;
+ }
+ fts_close(ftsp);
+ if (errno)
+ err(exit_jump, EXIT_FAILURE, "fts_read");
+}
+
+/*
+ * Display() takes a linked list of FTSENT structures and passes the list
+ * along with any other necessary information to the print function. P
+ * points to the parent directory of the display list.
+ */
+static void
+display(rtems_shell_ls_globals* globals, FTSENT *p, FTSENT *list)
+{
+ struct stat *sp;
+ DISPLAY d;
+ FTSENT *cur;
+ NAMES *np;
+ u_int64_t btotal, stotal, maxblock, maxsize;
+ int maxinode, maxnlink, maxmajor, maxminor;
+ int bcfile, entries, flen, glen, ulen, maxflags, maxgroup, maxlen;
+ int maxuser, needstats;
+ const char *user, *group;
+ char buf[21]; /* 64 bits == 20 digits, +1 for NUL */
+ char nuser[12], ngroup[12];
+ char *flags = NULL;
+
+#ifdef __GNUC__
+ /* This outrageous construct just to shut up a GCC warning. */
+ (void) &maxsize;
+#endif
+
+ /*
+ * If list is NULL there are two possibilities: that the parent
+ * directory p has no children, or that fts_children() returned an
+ * error. We ignore the error case since it will be replicated
+ * on the next call to fts_read() on the post-order visit to the
+ * directory p, and will be signalled in traverse().
+ */
+ if (list == NULL)
+ return;
+
+ needstats = f_inode || f_longform || f_size;
+ flen = 0;
+ maxinode = maxnlink = 0;
+ bcfile = 0;
+ maxuser = maxgroup = maxflags = maxlen = 0;
+ btotal = stotal = maxblock = maxsize = 0;
+ maxmajor = maxminor = 0;
+ for (cur = list, entries = 0; cur; cur = cur->fts_link) {
+ if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) {
+ warnx("%s: %s",
+ cur->fts_name, strerror(cur->fts_errno));
+ cur->fts_number = NO_PRINT;
+ rval = EXIT_FAILURE;
+ continue;
+ }
+
+ /*
+ * P is NULL if list is the argv list, to which different rules
+ * apply.
+ */
+ if (p == NULL) {
+ /* Directories will be displayed later. */
+ if (cur->fts_info == FTS_D && !f_listdir) {
+ cur->fts_number = NO_PRINT;
+ continue;
+ }
+ } else {
+ /* Only display dot file if -a/-A set. */
+ if (cur->fts_name[0] == '.' && !f_listdot) {
+ cur->fts_number = NO_PRINT;
+ continue;
+ }
+ }
+ if (cur->fts_namelen > maxlen)
+ maxlen = cur->fts_namelen;
+ if (needstats) {
+ sp = cur->fts_statp;
+ if (sp->st_blocks > maxblock)
+ maxblock = sp->st_blocks;
+ if (sp->st_ino > maxinode)
+ maxinode = sp->st_ino;
+ if (sp->st_nlink > maxnlink)
+ maxnlink = sp->st_nlink;
+ if (sp->st_size > maxsize)
+ maxsize = sp->st_size;
+ if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) {
+ bcfile = 1;
+ if (major(sp->st_rdev) > maxmajor)
+ maxmajor = major(sp->st_rdev);
+ if (minor(sp->st_rdev) > maxminor)
+ maxminor = minor(sp->st_rdev);
+ }
+
+ btotal += sp->st_blocks;
+ stotal += sp->st_size;
+ if (f_longform) {
+ if (f_numericonly ||
+ (user = user_from_uid(sp->st_uid, 0)) ==
+ NULL) {
+ (void)snprintf(nuser, sizeof(nuser),
+ "%u", sp->st_uid);
+ user = nuser;
+ }
+ if (f_numericonly ||
+ (group = group_from_gid(sp->st_gid, 0)) ==
+ NULL) {
+ (void)snprintf(ngroup, sizeof(ngroup),
+ "%u", sp->st_gid);
+ group = ngroup;
+ }
+ if ((ulen = strlen(user)) > maxuser)
+ maxuser = ulen;
+ if ((glen = strlen(group)) > maxgroup)
+ maxgroup = glen;
+#if RTEMS_REMOVED
+ if (f_flags) {
+ flags =
+ flags_to_string(sp->st_flags, "-");
+ if ((flen = strlen(flags)) > maxflags)
+ maxflags = flen;
+ } else
+#endif
+ flen = 0;
+
+ if ((np = malloc(sizeof(NAMES) +
+ ulen + glen + flen + 3)) == NULL)
+ err(exit_jump, EXIT_FAILURE, NULL);
+
+ np->user = &np->data[0];
+ (void)strcpy(np->user, user);
+ np->group = &np->data[ulen + 1];
+ (void)strcpy(np->group, group);
+
+ if (f_flags) {
+ np->flags = &np->data[ulen + glen + 2];
+ (void)strcpy(np->flags, flags);
+ }
+ cur->fts_pointer = np;
+ }
+ }
+ ++entries;
+ }
+
+ if (!entries)
+ return;
+
+ d.list = list;
+ d.entries = entries;
+ d.maxlen = maxlen;
+ if (needstats) {
+ d.btotal = btotal;
+ d.stotal = stotal;
+ if (f_humanize) {
+ d.s_block = 4; /* min buf length for humanize_number */
+ } else {
+ (void)snprintf(buf, sizeof(buf), "%llu",
+ (long long)howmany(maxblock, blocksize));
+ d.s_block = strlen(buf);
+ }
+ d.s_flags = maxflags;
+ d.s_group = maxgroup;
+ (void)snprintf(buf, sizeof(buf), "%u", maxinode);
+ d.s_inode = strlen(buf);
+ (void)snprintf(buf, sizeof(buf), "%u", maxnlink);
+ d.s_nlink = strlen(buf);
+ if (f_humanize) {
+ d.s_size = 4; /* min buf length for humanize_number */
+ } else {
+ (void)snprintf(buf, sizeof(buf), "%llu",
+ (long long)maxsize);
+ d.s_size = strlen(buf);
+ }
+ d.s_user = maxuser;
+ if (bcfile) {
+ (void)snprintf(buf, sizeof(buf), "%u", maxmajor);
+ d.s_major = strlen(buf);
+ (void)snprintf(buf, sizeof(buf), "%u", maxminor);
+ d.s_minor = strlen(buf);
+ if (d.s_major + d.s_minor + 2 > d.s_size)
+ d.s_size = d.s_major + d.s_minor + 2;
+ else if (d.s_size - d.s_minor - 2 > d.s_major)
+ d.s_major = d.s_size - d.s_minor - 2;
+ } else {
+ d.s_major = 0;
+ d.s_minor = 0;
+ }
+ }
+
+ printfcn(globals, &d);
+ output = 1;
+
+ if (f_longform)
+ for (cur = list; cur; cur = cur->fts_link)
+ free(cur->fts_pointer);
+}
+
+/*
+ * Ordering for mastercmp:
+ * If ordering the argv (fts_level = FTS_ROOTLEVEL) return non-directories
+ * as larger than directories. Within either group, use the sort function.
+ * All other levels use the sort function. Error entries remain unsorted.
+ */
+static int
+mastercmp_no_listdir(const FTSENT **a, const FTSENT **b)
+{
+ int a_info, b_info;
+ int l_f_listdir = 0;
+
+ a_info = (*a)->fts_info;
+ if (a_info == FTS_ERR)
+ return (0);
+ b_info = (*b)->fts_info;
+ if (b_info == FTS_ERR)
+ return (0);
+
+ if (a_info == FTS_NS || b_info == FTS_NS) {
+ if (b_info != FTS_NS)
+ return (1);
+ else if (a_info != FTS_NS)
+ return (-1);
+ else
+ return (namecmp(*a, *b));
+ }
+
+ if (a_info != b_info && !l_f_listdir &&
+ (*a)->fts_level == FTS_ROOTLEVEL) {
+ if (a_info == FTS_D)
+ return (1);
+ else if (b_info == FTS_D)
+ return (-1);
+ }
+ return (sortfcn(*a, *b));
+}
+
+static int
+mastercmp_listdir(const FTSENT **a, const FTSENT **b)
+{
+ int a_info, b_info;
+ int l_f_listdir = 1;
+
+ a_info = (*a)->fts_info;
+ if (a_info == FTS_ERR)
+ return (0);
+ b_info = (*b)->fts_info;
+ if (b_info == FTS_ERR)
+ return (0);
+
+ if (a_info == FTS_NS || b_info == FTS_NS) {
+ if (b_info != FTS_NS)
+ return (1);
+ else if (a_info != FTS_NS)
+ return (-1);
+ else
+ return (namecmp(*a, *b));
+ }
+
+ if (a_info != b_info && !l_f_listdir &&
+ (*a)->fts_level == FTS_ROOTLEVEL) {
+ if (a_info == FTS_D)
+ return (1);
+ else if (b_info == FTS_D)
+ return (-1);
+ }
+ return (sortfcn(*a, *b));
}
rtems_shell_cmd_t rtems_shell_LS_Command = {
diff --git a/cpukit/libmisc/shell/main_rm.c b/cpukit/libmisc/shell/main_rm.c
index 9bf60b61cf..f833fc6b39 100644
--- a/cpukit/libmisc/shell/main_rm.c
+++ b/cpukit/libmisc/shell/main_rm.c
@@ -1,50 +1,699 @@
-/*
- * RM Shell Command Implmentation
- *
- * Author: Fernando RUIZ CASAS
- * Work: fernando.ruiz@ctv.es
- * Home: correo@fernando-ruiz.com
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
*
- * $Id$
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
+#if 0
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1990, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)rm.c 8.5 (Berkeley) 4/18/94";
+#endif /* not lint */
#endif
+#if 0
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/rm/rm.c,v 1.58 2006/10/31 02:22:36 delphij Exp $");
+#endif
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/shellconfig.h>
+#include <getopt.h>
+
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <grp.h>
+#include <pwd.h>
#include <stdio.h>
-#include <unistd.h>
+#include <stdlib.h>
#include <string.h>
-#include <errno.h>
+#include <unistd.h>
-#include <rtems.h>
-#include <rtems/shell.h>
-#include "internal.h"
+/* RTEMS specific changes */
+typedef struct {
+ int dflag, eval, fflag, iflag, Pflag, vflag, Wflag, stdin_ok;
+ int rflag, Iflag;
+ uid_t uid;
+ int exit_code;
+ jmp_buf exit_jmp;
+} rtems_shell_rm_globals;
+
+#define dflag globals->dflag
+#define eval globals->eval
+#define fflag globals->fflag
+#define iflag globals->iflag
+#define Pflag globals->Pflag
+#define vflag globals->vflag
+#define Wflag globals->Wflag
+#define stdin_ok globals->stdin_ok
+#define rflag globals->rflag
+#define Iflag globals->Iflag
+#define xuid globals->uid
+#define exit_jump &(globals->exit_jmp)
+
+#include <setjmp.h>
+
+#define exit(ec) rtems_shell_rm_exit(globals, ec)
+void
+rtems_shell_rm_exit (rtems_shell_rm_globals* globals, int code)
+{
+ globals->exit_code = code;
+ longjmp (globals->exit_jmp, 1);
+}
+
+static int main_rm(rtems_shell_rm_globals* globals, int argc, char *argv[]);
+
+int
+rtems_shell_main_rm(int argc, char *argv[])
+{
+ rtems_shell_rm_globals rm_globals;
+ memset (&rm_globals, 0, sizeof (rm_globals));
+ rm_globals.exit_code = 1;
+ if (setjmp (rm_globals.exit_jmp) == 0)
+ return main_rm (&rm_globals, argc, argv);
+ return rm_globals.exit_code;
+}
+
+#define check(a1, a2, a3) check_rm(globals, a1, a2, a3)
+#define check2(a1) check2_rm(globals, a1)
+#define checkdot(a1) checkdot_rm(globals, a1)
+#define checkslash(a1) checkslash_rm(globals, a1)
+#define rm_file(a1) rm_file_rm(globals, a1)
+#define rm_overwrite(a1, a2) rm_overwrite_rm(globals, a1, a2)
+#define rm_tree(a1) rm_tree_rm(globals, a1)
+#define usage() usage_rm(globals)
+
+
+/* RTEMS changes */
+
+static int check_rm(rtems_shell_rm_globals* globals, char *, char *, struct stat *);
+static int check2_rm(rtems_shell_rm_globals* globals, char **);
+static void checkdot_rm(rtems_shell_rm_globals* globals, char **);
+static void checkslash_rm(rtems_shell_rm_globals* globals, char **);
+static void rm_file_rm(rtems_shell_rm_globals* globals, char **);
+static int rm_overwrite_rm(rtems_shell_rm_globals* globals, char *, struct stat *);
+static void rm_tree_rm(rtems_shell_rm_globals* globals, char **);
+static void usage_rm(rtems_shell_rm_globals* globals);
+
+/*
+ * rm --
+ * This rm is different from historic rm's, but is expected to match
+ * POSIX 1003.2 behavior. The most visible difference is that -f
+ * has two specific effects now, ignore non-existent files and force
+ * file removal.
+ */
+int
+main_rm(rtems_shell_rm_globals* globals, int argc, char *argv[])
+{
+ int ch;
+ char *p;
+
+ struct getopt_data getopt_reent;
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+
+ /*
+ * Test for the special case where the utility is called as
+ * "unlink", for which the functionality provided is greatly
+ * simplified.
+ */
+ if ((p = rindex(argv[0], '/')) == NULL)
+ p = argv[0];
+ else
+ ++p;
+ if (strcmp(p, "unlink") == 0) {
+ while (getopt_r(argc, argv, "", &getopt_reent) != -1)
+ usage();
+ argc -= getopt_reent.optind;
+ argv += getopt_reent.optind;
+ if (argc != 1)
+ usage();
+ rm_file(&argv[0]);
+ exit(eval);
+ }
+
+ Pflag = rflag = 0;
+ while ((ch = getopt_r(argc, argv, "dfiIPRrvW", &getopt_reent)) != -1)
+ switch(ch) {
+ case 'd':
+ dflag = 1;
+ break;
+ case 'f':
+ fflag = 1;
+ iflag = 0;
+ break;
+ case 'i':
+ fflag = 0;
+ iflag = 1;
+ break;
+ case 'I':
+ Iflag = 1;
+ break;
+ case 'P':
+ Pflag = 1;
+ break;
+ case 'R':
+ case 'r': /* Compatibility. */
+ rflag = 1;
+ break;
+ case 'v':
+ vflag = 1;
+ break;
+ case 'W':
+ Wflag = 1;
+ break;
+ default:
+ usage();
+ }
+ argc -= getopt_reent.optind;
+ argv += getopt_reent.optind;
+
+ if (argc < 1) {
+ if (fflag)
+ return (0);
+ usage();
+ }
+
+ checkdot(argv);
+ if (getenv("POSIXLY_CORRECT") == NULL)
+ checkslash(argv);
+ xuid = geteuid();
+
+ if (*argv) {
+ stdin_ok = isatty(STDIN_FILENO);
+
+ if (Iflag) {
+ if (check2(argv) == 0)
+ exit (1);
+ }
+ if (rflag)
+ rm_tree(argv);
+ else
+ rm_file(argv);
+ }
+
+ exit (eval);
+ return 0;
+}
+
+void
+rm_tree_rm(rtems_shell_rm_globals* globals, char **argv)
+{
+ FTS *fts;
+ FTSENT *p;
+ int needstat;
+ int flags;
+ int rval;
+
+ /*
+ * Remove a file hierarchy. If forcing removal (-f), or interactive
+ * (-i) or can't ask anyway (stdin_ok), don't stat the file.
+ */
+ needstat = !xuid || (!fflag && !iflag && stdin_ok);
+
+ /*
+ * If the -i option is specified, the user can skip on the pre-order
+ * visit. The fts_number field flags skipped directories.
+ */
+#define SKIPPED 1
+
+ flags = FTS_PHYSICAL;
+ if (!needstat)
+ flags |= FTS_NOSTAT;
+ if (Wflag)
+ flags |= FTS_WHITEOUT;
+ if (!(fts = fts_open(argv, flags, NULL))) {
+ if (fflag && errno == ENOENT)
+ return;
+ err(exit_jump, 1, "fts_open");
+ }
+ while ((p = fts_read(fts)) != NULL) {
+ switch (p->fts_info) {
+ case FTS_DNR:
+ if (!fflag || p->fts_errno != ENOENT) {
+ warnx("%s: %s",
+ p->fts_path, strerror(p->fts_errno));
+ eval = 1;
+ }
+ continue;
+ case FTS_ERR:
+ errx(exit_jump, 1, "%s: %s", p->fts_path, strerror(p->fts_errno));
+ case FTS_NS:
+ /*
+ * Assume that since fts_read() couldn't stat the
+ * file, it can't be unlinked.
+ */
+ if (!needstat)
+ break;
+ if (!fflag || p->fts_errno != ENOENT) {
+ warnx("%s: %s",
+ p->fts_path, strerror(p->fts_errno));
+ eval = 1;
+ }
+ continue;
+ case FTS_D:
+ /* Pre-order: give user chance to skip. */
+ if (!fflag && !check(p->fts_path, p->fts_accpath,
+ p->fts_statp)) {
+ (void)fts_set(fts, p, FTS_SKIP);
+ p->fts_number = SKIPPED;
+ }
+#if RTEMS_REMOVED
+ else if (!xuid &&
+ (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
+ !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
+ chflags(p->fts_accpath,
+ p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0)
+ goto err;
+#endif
+ continue;
+ case FTS_DP:
+ /* Post-order: see if user skipped. */
+ if (p->fts_number == SKIPPED)
+ continue;
+ break;
+ default:
+ if (!fflag &&
+ !check(p->fts_path, p->fts_accpath, p->fts_statp))
+ continue;
+ }
+
+ rval = 0;
+#if RTEMS_REMOVED
+ if (!xuid &&
+ (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
+ !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)))
+ rval = chflags(p->fts_accpath,
+ p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
+#endif
+ if (rval == 0) {
+ /*
+ * If we can't read or search the directory, may still be
+ * able to remove it. Don't print out the un{read,search}able
+ * message unless the remove fails.
+ */
+ switch (p->fts_info) {
+ case FTS_DP:
+ case FTS_DNR:
+ rval = rmdir(p->fts_accpath);
+ if (rval == 0 || (fflag && errno == ENOENT)) {
+ if (rval == 0 && vflag)
+ (void)printf("%s\n",
+ p->fts_path);
+ continue;
+ }
+ break;
+
+#if RTEMS_REMOVED
+ case FTS_W:
+ rval = undelete(p->fts_accpath);
+ if (rval == 0 && (fflag && errno == ENOENT)) {
+ if (vflag)
+ (void)printf("%s\n",
+ p->fts_path);
+ continue;
+ }
+ break;
+#endif
+
+ case FTS_NS:
+ /*
+ * Assume that since fts_read() couldn't stat
+ * the file, it can't be unlinked.
+ */
+ if (fflag)
+ continue;
+ /* FALLTHROUGH */
+ default:
+ if (Pflag)
+ if (!rm_overwrite(p->fts_accpath, NULL))
+ continue;
+ rval = unlink(p->fts_accpath);
+ if (rval == 0 || (fflag && errno == ENOENT)) {
+ if (rval == 0 && vflag)
+ (void)printf("%s\n",
+ p->fts_path);
+ continue;
+ }
+ }
+ }
+#if RTEMS_REMOVED
+err:
+#endif
+ warn("%s", p->fts_path);
+ eval = 1;
+ }
+ if (errno)
+ err(exit_jump, 1, "fts_read");
+ fts_close(fts);
+}
+
+#define S_ISWHT(m) (0)
+
+void
+rm_file_rm(rtems_shell_rm_globals* globals, char **argv)
+{
+ struct stat sb;
+ int rval;
+ char *f;
+
+ /*
+ * Remove a file. POSIX 1003.2 states that, by default, attempting
+ * to remove a directory is an error, so must always stat the file.
+ */
+ while ((f = *argv++) != NULL) {
+ /* Assume if can't stat the file, can't unlink it. */
+ if (lstat(f, &sb)) {
+#if RTEMS_REMOVED
+ if (Wflag) {
+ sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR;
+ } else {
+#endif
+ if (!fflag || errno != ENOENT) {
+ warn("%s", f);
+ eval = 1;
+ }
+ continue;
+#if RTEMS_REMOVED
+ }
+#endif
+ } else if (Wflag) {
+ warnx("%s: %s", f, strerror(EEXIST));
+ eval = 1;
+ continue;
+ }
+
+ if (S_ISDIR(sb.st_mode) && !dflag) {
+ warnx("%s: is a directory", f);
+ eval = 1;
+ continue;
+ }
+ if (!fflag && !S_ISWHT(sb.st_mode) && !check(f, f, &sb))
+ continue;
+ rval = 0;
+#if RTEMS_REMOVED
+ if (!xuid && !S_ISWHT(sb.st_mode) &&
+ (sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
+ !(sb.st_flags & (SF_APPEND|SF_IMMUTABLE)))
+ rval = chflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
+#endif
+ if (rval == 0) {
+ if (S_ISWHT(sb.st_mode))
+#if RTEMS_REMOVED
+ rval = undelete(f);
+#endif
+ ;
+ else if (S_ISDIR(sb.st_mode))
+ rval = rmdir(f);
+ else {
+ if (Pflag)
+ if (!rm_overwrite(f, &sb))
+ continue;
+ rval = unlink(f);
+ }
+ }
+ if (rval && (!fflag || errno != ENOENT)) {
+ warn("%s", f);
+ eval = 1;
+ }
+ if (vflag && rval == 0)
+ (void)printf("%s\n", f);
+ }
+}
+
+/*
+ * rm_overwrite --
+ * Overwrite the file 3 times with varying bit patterns.
+ *
+ * XXX
+ * This is a cheap way to *really* delete files. Note that only regular
+ * files are deleted, directories (and therefore names) will remain.
+ * Also, this assumes a fixed-block file system (like FFS, or a V7 or a
+ * System V file system). In a logging file system, you'll have to have
+ * kernel support.
+ */
+int
+rm_overwrite_rm(rtems_shell_rm_globals* globals, char *file, struct stat *sbp)
+{
+ struct stat sb;
+#if RTEMS_REMOVED
+ struct statfs fsb;
+#endif
+ off_t len;
+ int bsize, fd, wlen;
+ char *buf = NULL;
+
+ fd = -1;
+ if (sbp == NULL) {
+ if (lstat(file, &sb))
+ goto err;
+ sbp = &sb;
+ }
+ if (!S_ISREG(sbp->st_mode))
+ return (1);
+ if (sbp->st_nlink > 1 && !fflag) {
+ warnx("%s (inode %lu): not overwritten due to multiple links",
+ file, sbp->st_ino);
+ return (0);
+ }
+ if ((fd = open(file, O_WRONLY, 0)) == -1)
+ goto err;
+#if RTEMS_REMOVED
+ if (fstatfs(fd, &fsb) == -1)
+ goto err;
+ bsize = MAX(fsb.f_iosize, 1024);
+#endif
+ bsize = 1024;
+ if ((buf = malloc(bsize)) == NULL)
+ err(exit_jump, 1, "%s: malloc", file);
+
+#define PASS(byte) { \
+ memset(buf, byte, bsize); \
+ for (len = sbp->st_size; len > 0; len -= wlen) { \
+ wlen = len < bsize ? len : bsize; \
+ if (write(fd, buf, wlen) != wlen) \
+ goto err; \
+ } \
+}
+ PASS(0xff);
+ if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET))
+ goto err;
+ PASS(0x00);
+ if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET))
+ goto err;
+ PASS(0xff);
+ if (!fsync(fd) && !close(fd)) {
+ free(buf);
+ return (1);
+ }
+
+err: eval = 1;
+ if (buf)
+ free(buf);
+ if (fd != -1)
+ close(fd);
+ warn("%s", file);
+ return (0);
+}
+
+void strmode(mode_t mode, char *p);
+char *fflagstostr(u_long flags);
+const char *user_from_uid(uid_t uid, int nouser);
+
+int
+check_rm(rtems_shell_rm_globals* globals, char *path, char *name, struct stat *sp)
+{
+ int ch, first;
+ char modep[15], *flagsp;
+
+ /* Check -i first. */
+ if (iflag)
+ (void)fprintf(stderr, "remove %s? ", path);
+ else {
+ /*
+ * If it's not a symbolic link and it's unwritable and we're
+ * talking to a terminal, ask. Symbolic links are excluded
+ * because their permissions are meaningless. Check stdin_ok
+ * first because we may not have stat'ed the file.
+ */
+#if RTEMS_REMOVED
+ if (!stdin_ok || S_ISLNK(sp->st_mode) ||
+ (!access(name, W_OK) &&
+ !(sp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
+ (!(sp->st_flags & (UF_APPEND|UF_IMMUTABLE)) || !xuid)))
+#endif
+ if (!stdin_ok || S_ISLNK(sp->st_mode) ||
+ (!access(name, W_OK)))
+ return (1);
+ strmode(sp->st_mode, modep);
+#if RTEMS_REMOVED
+ if ((flagsp = fflagstostr(sp->st_flags)) == NULL)
+ err(exit_jump, 1, "fflagstostr");
+#else
+ flagsp = "no supported";
+#endif
+ if (Pflag)
+ errx(exit_jump, 1,
+ "%s: -P was specified, but file is not writable",
+ path);
+ (void)fprintf(stderr, "override %s%s%s/%s %s%sfor %s? ",
+ modep + 1, modep[9] == ' ' ? "" : " ",
+ user_from_uid(sp->st_uid, 0),
+ group_from_gid(sp->st_gid, 0),
+ *flagsp ? flagsp : "", *flagsp ? " " : "",
+ path);
+ free(flagsp);
+ }
+ (void)fflush(stderr);
+
+ first = ch = getchar();
+ while (ch != '\n' && ch != EOF)
+ ch = getchar();
+ return (first == 'y' || first == 'Y');
+}
+
+#define ISSLASH(a) ((a)[0] == '/' && (a)[1] == '\0')
+void
+checkslash_rm(rtems_shell_rm_globals* globals, char **argv)
+{
+ char **t, **u;
+ int complained;
+
+ complained = 0;
+ for (t = argv; *t;) {
+ if (ISSLASH(*t)) {
+ if (!complained++)
+ warnx("\"/\" may not be removed");
+ eval = 1;
+ for (u = t; u[0] != NULL; ++u)
+ u[0] = u[1];
+ } else {
+ ++t;
+ }
+ }
+}
+
+int
+check2_rm(rtems_shell_rm_globals* globals, char **argv)
+{
+ struct stat st;
+ int first;
+ int ch;
+ int fcount = 0;
+ int dcount = 0;
+ int i;
+ const char *dname = NULL;
+
+ for (i = 0; argv[i]; ++i) {
+ if (lstat(argv[i], &st) == 0) {
+ if (S_ISDIR(st.st_mode)) {
+ ++dcount;
+ dname = argv[i]; /* only used if 1 dir */
+ } else {
+ ++fcount;
+ }
+ }
+ }
+ first = 0;
+ while (first != 'n' && first != 'N' && first != 'y' && first != 'Y') {
+ if (dcount && rflag) {
+ fprintf(stderr, "recursively remove");
+ if (dcount == 1)
+ fprintf(stderr, " %s", dname);
+ else
+ fprintf(stderr, " %d dirs", dcount);
+ if (fcount == 1)
+ fprintf(stderr, " and 1 file");
+ else if (fcount > 1)
+ fprintf(stderr, " and %d files", fcount);
+ } else if (dcount + fcount > 3) {
+ fprintf(stderr, "remove %d files", dcount + fcount);
+ } else {
+ return(1);
+ }
+ fprintf(stderr, "? ");
+ fflush(stderr);
+
+ first = ch = getchar();
+ while (ch != '\n' && ch != EOF)
+ ch = getchar();
+ if (ch == EOF)
+ break;
+ }
+ return (first == 'y' || first == 'Y');
+}
+
+#define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2])))
+void
+checkdot_rm(rtems_shell_rm_globals* globals, char **argv)
+{
+ char *p, **save, **t;
+ int complained;
+
+ complained = 0;
+ for (t = argv; *t;) {
+ if ((p = strrchr(*t, '/')) != NULL)
+ ++p;
+ else
+ p = *t;
+ if (ISDOT(p)) {
+ if (!complained++)
+ warnx("\".\" and \"..\" may not be removed");
+ eval = 1;
+ for (save = t; (t[0] = t[1]) != NULL; ++t)
+ continue;
+ t = save;
+ } else
+ ++t;
+ }
+}
-int rtems_shell_main_rm(
- int argc,
- char *argv[]
-)
+void
+usage_rm(rtems_shell_rm_globals* globals)
{
- int n = 1;
- while ( n<argc ) {
- if (unlink(argv[n])) {
- fprintf(stderr,"%s: %s: %s\n", argv[0], argv[n], strerror(errno));
- return -1;
- }
- n++;
- }
- return 0;
+ (void)fprintf(stderr, "%s\n%s\n",
+ "usage: rm [-f | -i] [-dIPRrvW] file ...",
+ " unlink file");
+ exit(1);
}
rtems_shell_cmd_t rtems_shell_RM_Command = {
"rm", /* name */
- "rm n1 [n2 [n3...]] # remove files", /* usage */
+ "[-f | -i] [-dIPRrvW] file ...", /* usage */
"files", /* topic */
rtems_shell_main_rm, /* command */
NULL, /* alias */
diff --git a/cpukit/libmisc/shell/print-ls.c b/cpukit/libmisc/shell/print-ls.c
new file mode 100644
index 0000000000..de7e757cf8
--- /dev/null
+++ b/cpukit/libmisc/shell/print-ls.c
@@ -0,0 +1,480 @@
+/* $NetBSD: print.c,v 1.40 2004/11/17 17:00:00 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Michael Fischbein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)print.c 8.5 (Berkeley) 7/28/94";
+#else
+__RCSID("$NetBSD: print.c,v 1.40 2004/11/17 17:00:00 mycroft Exp $");
+#endif
+#endif /* not lint */
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fts.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+//#include <tzfile.h>
+#include <unistd.h>
+//#include <util.h>
+
+#include "extern-ls.h"
+
+#if RTEMS_REMOVED
+extern int termwidth;
+#endif
+
+static int printaname(rtems_shell_ls_globals* globals, FTSENT *, int, int);
+static void printlink(rtems_shell_ls_globals* globals, FTSENT *);
+static void printtime(rtems_shell_ls_globals* globals, time_t);
+static int printtype(u_int);
+
+#if RTEMS_REMOVED
+static time_t now;
+#endif
+
+#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT)
+
+void
+printscol(rtems_shell_ls_globals* globals, DISPLAY *dp)
+{
+ FTSENT *p;
+
+ for (p = dp->list; p; p = p->fts_link) {
+ if (IS_NOPRINT(p))
+ continue;
+ (void)printaname(globals, p, dp->s_inode, dp->s_block);
+ (void)putchar('\n');
+ }
+}
+
+void
+printlong(rtems_shell_ls_globals* globals, DISPLAY *dp)
+{
+ struct stat *sp;
+ FTSENT *p;
+ NAMES *np;
+ char buf[20]; //, szbuf[5];
+
+ now = time(NULL);
+
+ if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) {
+#if RTEMS_REMOVED
+ if (f_humanize) {
+ if ((humanize_number(szbuf, sizeof(szbuf), dp->stotal,
+ "", HN_AUTOSCALE,
+ (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
+ err(exit_jump, 1, "humanize_number");
+ (void)printf("total %s\n", szbuf);
+ } else {
+#endif
+ (void)printf("total %llu\n",
+ (long long)(howmany(dp->btotal, blocksize)));
+#if RTEMS_REMOVED
+ }
+#endif
+ }
+
+ for (p = dp->list; p; p = p->fts_link) {
+ if (IS_NOPRINT(p))
+ continue;
+ sp = p->fts_statp;
+ if (f_inode)
+ (void)printf("%*lu ", dp->s_inode,
+ (unsigned long)sp->st_ino);
+ if (f_size && !f_humanize) {
+ (void)printf("%*llu ", dp->s_block,
+ (long long)howmany(sp->st_blocks, blocksize));
+ }
+ (void)strmode(sp->st_mode, buf);
+ np = p->fts_pointer;
+ (void)printf("%s %*lu ", buf, dp->s_nlink,
+ (unsigned long)sp->st_nlink);
+ if (!f_grouponly)
+ (void)printf("%-*s ", dp->s_user, np->user);
+ (void)printf("%-*s ", dp->s_group, np->group);
+ if (f_flags)
+ (void)printf("%-*s ", dp->s_flags, np->flags);
+ if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
+ (void)printf("%*lu, %*lu ",
+ dp->s_major, major(sp->st_rdev), dp->s_minor,
+ minor(sp->st_rdev));
+ else
+#if RTEMS_REMOVED
+ if (f_humanize) {
+ if ((humanize_number(szbuf, sizeof(szbuf),
+ sp->st_size, "", HN_AUTOSCALE,
+ (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
+ err(1, "humanize_number");
+ (void)printf("%*s ", dp->s_size, szbuf);
+ } else {
+#endif
+ (void)printf("%*llu ", dp->s_size,
+ (long long)sp->st_size);
+#if RTEMS_REMOVED
+ }
+#endif
+ if (f_accesstime)
+ printtime(globals, sp->st_atime);
+ else if (f_statustime)
+ printtime(globals, sp->st_ctime);
+ else
+ printtime(globals, sp->st_mtime);
+ if (f_octal || f_octal_escape)
+ (void)safe_print(globals, p->fts_name);
+ else if (f_nonprint)
+ (void)printescaped(globals, p->fts_name);
+ else
+ (void)printf("%s", p->fts_name);
+
+ if (f_type || (f_typedir && S_ISDIR(sp->st_mode)))
+ (void)printtype(sp->st_mode);
+ if (S_ISLNK(sp->st_mode))
+ printlink(globals, p);
+ (void)putchar('\n');
+ }
+}
+
+void
+printcol(rtems_shell_ls_globals* globals, DISPLAY *dp)
+{
+ static FTSENT **array;
+ static int lastentries = -1;
+ FTSENT *p;
+ int base, chcnt, col, colwidth, num;
+ int numcols, numrows, row;
+ //char szbuf[5];
+
+ colwidth = dp->maxlen;
+ if (f_inode)
+ colwidth += dp->s_inode + 1;
+ if (f_size) {
+ if (f_humanize)
+ colwidth += dp->s_size + 1;
+ else
+ colwidth += dp->s_block + 1;
+ }
+ if (f_type || f_typedir)
+ colwidth += 1;
+
+ colwidth += 1;
+
+ if (termwidth < 2 * colwidth) {
+ printscol(globals, dp);
+ return;
+ }
+
+ /*
+ * Have to do random access in the linked list -- build a table
+ * of pointers.
+ */
+ if (dp->entries > lastentries) {
+ lastentries = dp->entries;
+ if ((array =
+ realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) {
+ warn(NULL);
+ printscol(globals, dp);
+ }
+ }
+ for (p = dp->list, num = 0; p; p = p->fts_link)
+ if (p->fts_number != NO_PRINT)
+ array[num++] = p;
+
+ numcols = termwidth / colwidth;
+ colwidth = termwidth / numcols; /* spread out if possible */
+ numrows = num / numcols;
+ if (num % numcols)
+ ++numrows;
+
+ if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) {
+#if RTEMS_REMOVED
+ if (f_humanize) {
+ if ((humanize_number(szbuf, sizeof(szbuf), dp->stotal,
+ "", HN_AUTOSCALE,
+ (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
+ err(1, "humanize_number");
+ (void)printf("total %s\n", szbuf);
+ } else {
+#endif
+ (void)printf("total %llu\n",
+ (long long)(howmany(dp->btotal, blocksize)));
+#if RTEMS_REMOVED
+ }
+#endif
+ }
+ for (row = 0; row < numrows; ++row) {
+ for (base = row, chcnt = col = 0; col < numcols; ++col) {
+ chcnt = printaname(globals, array[base], dp->s_inode,
+ f_humanize && 0 ? dp->s_size : dp->s_block);
+ if ((base += numrows) >= num)
+ break;
+ while (chcnt++ < colwidth)
+ (void)putchar(' ');
+ }
+ (void)putchar('\n');
+ }
+}
+
+void
+printacol(rtems_shell_ls_globals* globals, DISPLAY *dp)
+{
+ FTSENT *p;
+ int chcnt, col, colwidth;
+ int numcols;
+ //char szbuf[5];
+
+ colwidth = dp->maxlen;
+ if (f_inode)
+ colwidth += dp->s_inode + 1;
+ if (f_size) {
+ if (f_humanize)
+ colwidth += dp->s_size + 1;
+ else
+ colwidth += dp->s_block + 1;
+ }
+ if (f_type || f_typedir)
+ colwidth += 1;
+
+ colwidth += 1;
+
+ if (termwidth < 2 * colwidth) {
+ printscol(globals, dp);
+ return;
+ }
+
+ numcols = termwidth / colwidth;
+ colwidth = termwidth / numcols; /* spread out if possible */
+
+ if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) {
+#if RTEMS_REMOVED
+ if (f_humanize) {
+ if ((humanize_number(szbuf, sizeof(szbuf), dp->stotal,
+ "", HN_AUTOSCALE,
+ (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
+ err(1, "humanize_number");
+ (void)printf("total %s\n", szbuf);
+ } else {
+#endif
+ (void)printf("total %llu\n",
+ (long long)(howmany(dp->btotal, blocksize)));
+#if RTEMS_REMOVED
+ }
+#endif
+ }
+ chcnt = col = 0;
+ for (p = dp->list; p; p = p->fts_link) {
+ if (IS_NOPRINT(p))
+ continue;
+ if (col >= numcols) {
+ chcnt = col = 0;
+ (void)putchar('\n');
+ }
+ chcnt = printaname(globals, p, dp->s_inode,
+ f_humanize && 0 ? dp->s_size : dp->s_block);
+ while (chcnt++ < colwidth)
+ (void)putchar(' ');
+ col++;
+ }
+ (void)putchar('\n');
+}
+
+void
+printstream(rtems_shell_ls_globals* globals, DISPLAY *dp)
+{
+ FTSENT *p;
+ int col;
+ int extwidth;
+
+ extwidth = 0;
+ if (f_inode)
+ extwidth += dp->s_inode + 1;
+ if (f_size) {
+ if (f_humanize)
+ extwidth += dp->s_size + 1;
+ else
+ extwidth += dp->s_block + 1;
+ }
+ if (f_type)
+ extwidth += 1;
+
+ for (col = 0, p = dp->list; p != NULL; p = p->fts_link) {
+ if (IS_NOPRINT(p))
+ continue;
+ if (col > 0) {
+ (void)putchar(','), col++;
+ if (col + 1 + extwidth + p->fts_namelen >= termwidth)
+ (void)putchar('\n'), col = 0;
+ else
+ (void)putchar(' '), col++;
+ }
+ col += printaname(globals, p, dp->s_inode,
+ f_humanize && 0 ? dp->s_size : dp->s_block);
+ }
+ (void)putchar('\n');
+}
+
+/*
+ * print [inode] [size] name
+ * return # of characters printed, no trailing characters.
+ */
+static int
+printaname(rtems_shell_ls_globals* globals,
+ FTSENT *p, int inodefield, int sizefield)
+{
+ struct stat *sp;
+ int chcnt;
+ //char szbuf[5];
+
+ sp = p->fts_statp;
+ chcnt = 0;
+ if (f_inode)
+ chcnt += printf("%*lu ", inodefield, (unsigned long)sp->st_ino);
+ if (f_size) {
+#if RTEMS_REMOVED
+ if (f_humanize) {
+ if ((humanize_number(szbuf, sizeof(szbuf), sp->st_size,
+ "", HN_AUTOSCALE,
+ (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
+ err(1, "humanize_number");
+ chcnt += printf("%*s ", sizefield, szbuf);
+ } else {
+#endif
+ chcnt += printf("%*llu ", sizefield,
+ (long long)howmany(sp->st_blocks, blocksize));
+#if RTEMS_REMOVED
+ }
+#endif
+ }
+ if (f_octal || f_octal_escape)
+ chcnt += safe_print(globals, p->fts_name);
+ else if (f_nonprint)
+ chcnt += printescaped(globals, p->fts_name);
+ else
+ chcnt += printf("%s", p->fts_name);
+ if (f_type || (f_typedir && S_ISDIR(sp->st_mode)))
+ chcnt += printtype(sp->st_mode);
+ return (chcnt);
+}
+
+static void
+printtime(rtems_shell_ls_globals* globals, time_t ftime)
+{
+ int i;
+ char *longstring;
+
+ longstring = ctime(&ftime);
+ for (i = 4; i < 11; ++i)
+ (void)putchar(longstring[i]);
+
+#define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY)
+ if (f_sectime)
+ for (i = 11; i < 24; i++)
+ (void)putchar(longstring[i]);
+ else if (ftime + SIXMONTHS > now && ftime - SIXMONTHS < now)
+ for (i = 11; i < 16; ++i)
+ (void)putchar(longstring[i]);
+ else {
+ (void)putchar(' ');
+ for (i = 20; i < 24; ++i)
+ (void)putchar(longstring[i]);
+ }
+ (void)putchar(' ');
+}
+
+static int
+printtype(u_int mode)
+{
+ switch (mode & S_IFMT) {
+ case S_IFDIR:
+ (void)putchar('/');
+ return (1);
+ case S_IFIFO:
+ (void)putchar('|');
+ return (1);
+ case S_IFLNK:
+ (void)putchar('@');
+ return (1);
+ case S_IFSOCK:
+ (void)putchar('=');
+ return (1);
+#if RTEMS_REMOVED
+ case S_IFWHT:
+ (void)putchar('%');
+ return (1);
+#endif
+ }
+ if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
+ (void)putchar('*');
+ return (1);
+ }
+ return (0);
+}
+
+static void
+printlink(rtems_shell_ls_globals* globals, FTSENT *p)
+{
+ int lnklen;
+ char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1];
+
+ if (p->fts_level == FTS_ROOTLEVEL)
+ (void)snprintf(name, sizeof(name), "%s", p->fts_name);
+ else
+ (void)snprintf(name, sizeof(name),
+ "%s/%s", p->fts_parent->fts_accpath, p->fts_name);
+ if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) {
+ (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno));
+ return;
+ }
+ path[lnklen] = '\0';
+ (void)printf(" -> ");
+ if (f_octal || f_octal_escape)
+ (void)safe_print(globals, path);
+ else if (f_nonprint)
+ (void)printescaped(globals, path);
+ else
+ (void)printf("%s", path);
+}
diff --git a/cpukit/libmisc/shell/pwcache.c b/cpukit/libmisc/shell/pwcache.c
new file mode 100644
index 0000000000..6b50bd6eb1
--- /dev/null
+++ b/cpukit/libmisc/shell/pwcache.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)pwcache.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/pwcache.c,v 1.11 2007/01/09 00:27:55 imp Exp $");
+
+#include <sys/types.h>
+
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+//#include <utmp.h>
+
+#define UT_NAMESIZE 64
+
+#define NCACHE 64 /* power of 2 */
+#define MASK (NCACHE - 1) /* bits to store with */
+
+const char *
+user_from_uid(uid_t uid, int nouser)
+{
+ static struct ncache {
+ uid_t uid;
+ int found;
+ char name[UT_NAMESIZE + 1];
+ } c_uid[NCACHE];
+ static int pwopen;
+ struct passwd *pw;
+ struct ncache *cp;
+
+ cp = c_uid + (uid & MASK);
+ if (cp->uid != uid || !*cp->name) {
+ if (pwopen == 0) {
+ //setpassent(1);
+ pwopen = 1;
+ }
+ pw = getpwuid(uid);
+ cp->uid = uid;
+ if (pw != NULL) {
+ cp->found = 1;
+ (void)strncpy(cp->name, pw->pw_name, UT_NAMESIZE);
+ cp->name[UT_NAMESIZE] = '\0';
+ } else {
+ cp->found = 0;
+ (void)snprintf(cp->name, UT_NAMESIZE, "%u", uid);
+ if (nouser)
+ return (NULL);
+ }
+ }
+ return ((nouser && !cp->found) ? NULL : cp->name);
+}
+
+char *
+group_from_gid(gid_t gid, int nogroup)
+{
+ static struct ncache {
+ gid_t gid;
+ int found;
+ char name[UT_NAMESIZE + 1];
+ } c_gid[NCACHE];
+ static int gropen;
+ struct group *gr;
+ struct ncache *cp;
+
+ cp = c_gid + (gid & MASK);
+ if (cp->gid != gid || !*cp->name) {
+ if (gropen == 0) {
+ //setgroupent(1);
+ gropen = 1;
+ }
+ gr = getgrgid(gid);
+ cp->gid = gid;
+ if (gr != NULL) {
+ cp->found = 1;
+ (void)strncpy(cp->name, gr->gr_name, UT_NAMESIZE);
+ cp->name[UT_NAMESIZE] = '\0';
+ } else {
+ cp->found = 0;
+ (void)snprintf(cp->name, UT_NAMESIZE, "%u", gid);
+ if (nogroup)
+ return (NULL);
+ }
+ }
+ return ((nogroup && !cp->found) ? NULL : cp->name);
+}
+
diff --git a/cpukit/libmisc/shell/shell.c b/cpukit/libmisc/shell/shell.c
index 3b002b5548..02f6bfbd4d 100644
--- a/cpukit/libmisc/shell/shell.c
+++ b/cpukit/libmisc/shell/shell.c
@@ -980,7 +980,7 @@ static rtems_status_code rtems_shell_run (
name,
task_priority,
task_stacksize,
- RTEMS_DEFAULT_MODES,
+ RTEMS_PREEMPT | RTEMS_TIMESLICE | RTEMS_NO_ASR,
RTEMS_LOCAL | RTEMS_FLOATING_POINT,
&task_id
);
diff --git a/cpukit/libmisc/shell/utils-cp.c b/cpukit/libmisc/shell/utils-cp.c
index defd5dd021..6c525c982f 100644
--- a/cpukit/libmisc/shell/utils-cp.c
+++ b/cpukit/libmisc/shell/utils-cp.c
@@ -465,11 +465,11 @@ preserve_dir_acls(struct stat *fs, char *source_dir, char *dest_dir)
}
void
-usage(void)
+usage(rtems_shell_cp_globals* cp_globals)
{
-
(void)fprintf(stderr, "%s\n%s\n",
"usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpv] source_file target_file",
" cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpv] source_file ... "
"target_directory");
+ longjmp (cp_globals->exit_jmp, 1);
}
diff --git a/cpukit/libmisc/shell/utils-ls.c b/cpukit/libmisc/shell/utils-ls.c
new file mode 100644
index 0000000000..c7629e786a
--- /dev/null
+++ b/cpukit/libmisc/shell/utils-ls.c
@@ -0,0 +1,113 @@
+/* $NetBSD: util.c,v 1.28 2005/06/17 14:36:16 hira Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Michael Fischbein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)util.c 8.5 (Berkeley) 4/28/95";
+#else
+__RCSID("$NetBSD: util.c,v 1.28 2005/06/17 14:36:16 hira Exp $");
+#endif
+#endif /* not lint */
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <fts.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <vis.h>
+
+#include "extern-ls.h"
+
+#define SIZE_T_MAX 255
+
+int
+safe_print(rtems_shell_ls_globals* globals, const char *src)
+{
+ size_t len;
+ char *name;
+ int flags;
+
+ flags = VIS_NL | VIS_OCTAL;
+ if (f_octal_escape)
+ flags |= VIS_CSTYLE;
+
+ len = strlen(src);
+ if (len != 0 && SIZE_T_MAX/len <= 4) {
+ errx(exit_jump, EXIT_FAILURE, "%s: name too long", src);
+ /* NOTREACHED */
+ }
+
+ name = (char *)malloc(4*len+1);
+ if (name != NULL) {
+ len = strvis(name, src, flags);
+ printf("%s", name);
+ free(name);
+ return len;
+ } else
+ errx(exit_jump, EXIT_FAILURE, "out of memory!");
+ /* NOTREACHED */
+}
+
+int
+printescaped(rtems_shell_ls_globals* globals, const char *src)
+{
+ unsigned char c;
+ int n;
+
+ for (n = 0; (c = *src) != '\0'; ++src, ++n)
+ if (isprint(c))
+ (void)putchar(c);
+ else
+ (void)putchar('?');
+ return n;
+}
+
+void
+usage(rtems_shell_ls_globals* globals)
+{
+
+ (void)fprintf(stderr,
+ "usage: %s [-AaBbCcdFfghikLlmnopqRrSsTtuWwx1] [file ...]\n",
+ "ls");
+ exit(EXIT_FAILURE);
+ /* NOTREACHED */
+}
diff --git a/cpukit/libmisc/shell/vis.c b/cpukit/libmisc/shell/vis.c
new file mode 100644
index 0000000000..3ae560d53b
--- /dev/null
+++ b/cpukit/libmisc/shell/vis.c
@@ -0,0 +1,384 @@
+/* $NetBSD: vis.c,v 1.33 2005/05/28 13:11:14 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1999, 2005 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define _DIAGASSERT(a)
+
+#if 0
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: vis.c,v 1.33 2005/05/28 13:11:14 lukem Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <vis.h>
+#include <stdlib.h>
+
+#if !HAVE_VIS || !HAVE_SVIS
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#undef BELL
+#define BELL '\a'
+
+#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
+#define iswhite(c) (c == ' ' || c == '\t' || c == '\n')
+#define issafe(c) (c == '\b' || c == BELL || c == '\r')
+#define xtoa(c) "0123456789abcdef"[c]
+
+#define MAXEXTRAS 5
+
+
+#define MAKEEXTRALIST(flag, extra, orig) \
+do { \
+ const char *o = orig; \
+ char *e; \
+ while (*o++) \
+ continue; \
+ extra = malloc((size_t)((o - orig) + MAXEXTRAS)); \
+ if (!extra) break; \
+ for (o = orig, e = extra; (*e++ = *o++) != '\0';) \
+ continue; \
+ e--; \
+ if (flag & VIS_SP) *e++ = ' '; \
+ if (flag & VIS_TAB) *e++ = '\t'; \
+ if (flag & VIS_NL) *e++ = '\n'; \
+ if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \
+ *e = '\0'; \
+} while (/*CONSTCOND*/0)
+
+
+/*
+ * This is HVIS, the macro of vis used to HTTP style (RFC 1808)
+ */
+#define HVIS(dst, c, flag, nextc, extra) \
+do \
+ if (!isascii(c) || !isalnum(c) || strchr("$-_.+!*'(),", c) != NULL) { \
+ *dst++ = '%'; \
+ *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); \
+ *dst++ = xtoa((unsigned int)c & 0xf); \
+ } else { \
+ SVIS(dst, c, flag, nextc, extra); \
+ } \
+while (/*CONSTCOND*/0)
+
+/*
+ * This is SVIS, the central macro of vis.
+ * dst: Pointer to the destination buffer
+ * c: Character to encode
+ * flag: Flag word
+ * nextc: The character following 'c'
+ * extra: Pointer to the list of extra characters to be
+ * backslash-protected.
+ */
+#define SVIS(dst, c, flag, nextc, extra) \
+do { \
+ int isextra; \
+ isextra = strchr(extra, c) != NULL; \
+ if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || \
+ ((flag & VIS_SAFE) && issafe(c)))) { \
+ *dst++ = c; \
+ break; \
+ } \
+ if (flag & VIS_CSTYLE) { \
+ switch (c) { \
+ case '\n': \
+ *dst++ = '\\'; *dst++ = 'n'; \
+ continue; \
+ case '\r': \
+ *dst++ = '\\'; *dst++ = 'r'; \
+ continue; \
+ case '\b': \
+ *dst++ = '\\'; *dst++ = 'b'; \
+ continue; \
+ case BELL: \
+ *dst++ = '\\'; *dst++ = 'a'; \
+ continue; \
+ case '\v': \
+ *dst++ = '\\'; *dst++ = 'v'; \
+ continue; \
+ case '\t': \
+ *dst++ = '\\'; *dst++ = 't'; \
+ continue; \
+ case '\f': \
+ *dst++ = '\\'; *dst++ = 'f'; \
+ continue; \
+ case ' ': \
+ *dst++ = '\\'; *dst++ = 's'; \
+ continue; \
+ case '\0': \
+ *dst++ = '\\'; *dst++ = '0'; \
+ if (isoctal(nextc)) { \
+ *dst++ = '0'; \
+ *dst++ = '0'; \
+ } \
+ continue; \
+ default: \
+ if (isgraph(c)) { \
+ *dst++ = '\\'; *dst++ = c; \
+ continue; \
+ } \
+ } \
+ } \
+ if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { \
+ *dst++ = '\\'; \
+ *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0'; \
+ *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0'; \
+ *dst++ = (c & 07) + '0'; \
+ } else { \
+ if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; \
+ if (c & 0200) { \
+ c &= 0177; *dst++ = 'M'; \
+ } \
+ if (iscntrl(c)) { \
+ *dst++ = '^'; \
+ if (c == 0177) \
+ *dst++ = '?'; \
+ else \
+ *dst++ = c + '@'; \
+ } else { \
+ *dst++ = '-'; *dst++ = c; \
+ } \
+ } \
+} while (/*CONSTCOND*/0)
+
+
+/*
+ * svis - visually encode characters, also encoding the characters
+ * pointed to by `extra'
+ */
+char *
+svis(char *dst, int c, int flag, int nextc, const char *extra)
+{
+ char *nextra = NULL;
+
+ _DIAGASSERT(dst != NULL);
+ _DIAGASSERT(extra != NULL);
+ MAKEEXTRALIST(flag, nextra, extra);
+ if (!nextra) {
+ *dst = '\0'; /* can't create nextra, return "" */
+ return dst;
+ }
+ if (flag & VIS_HTTPSTYLE)
+ HVIS(dst, c, flag, nextc, nextra);
+ else
+ SVIS(dst, c, flag, nextc, nextra);
+ free(nextra);
+ *dst = '\0';
+ return dst;
+}
+
+
+/*
+ * strsvis, strsvisx - visually encode characters from src into dst
+ *
+ * Extra is a pointer to a \0-terminated list of characters to
+ * be encoded, too. These functions are useful e. g. to
+ * encode strings in such a way so that they are not interpreted
+ * by a shell.
+ *
+ * Dst must be 4 times the size of src to account for possible
+ * expansion. The length of dst, not including the trailing NULL,
+ * is returned.
+ *
+ * Strsvisx encodes exactly len bytes from src into dst.
+ * This is useful for encoding a block of data.
+ */
+int
+strsvis(char *dst, const char *csrc, int flag, const char *extra)
+{
+ int c;
+ char *start;
+ char *nextra = NULL;
+ const unsigned char *src = (const unsigned char *)csrc;
+
+ _DIAGASSERT(dst != NULL);
+ _DIAGASSERT(src != NULL);
+ _DIAGASSERT(extra != NULL);
+ MAKEEXTRALIST(flag, nextra, extra);
+ if (!nextra) {
+ *dst = '\0'; /* can't create nextra, return "" */
+ return 0;
+ }
+ if (flag & VIS_HTTPSTYLE) {
+ for (start = dst; (c = *src++) != '\0'; /* empty */)
+ HVIS(dst, c, flag, *src, nextra);
+ } else {
+ for (start = dst; (c = *src++) != '\0'; /* empty */)
+ SVIS(dst, c, flag, *src, nextra);
+ }
+ free(nextra);
+ *dst = '\0';
+ return (dst - start);
+}
+
+
+int
+strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra)
+{
+ unsigned char c;
+ char *start;
+ char *nextra = NULL;
+ const unsigned char *src = (const unsigned char *)csrc;
+
+ _DIAGASSERT(dst != NULL);
+ _DIAGASSERT(src != NULL);
+ _DIAGASSERT(extra != NULL);
+ MAKEEXTRALIST(flag, nextra, extra);
+ if (! nextra) {
+ *dst = '\0'; /* can't create nextra, return "" */
+ return 0;
+ }
+
+ if (flag & VIS_HTTPSTYLE) {
+ for (start = dst; len > 0; len--) {
+ c = *src++;
+ HVIS(dst, c, flag, len ? *src : '\0', nextra);
+ }
+ } else {
+ for (start = dst; len > 0; len--) {
+ c = *src++;
+ SVIS(dst, c, flag, len ? *src : '\0', nextra);
+ }
+ }
+ free(nextra);
+ *dst = '\0';
+ return (dst - start);
+}
+#endif
+
+#if !HAVE_VIS
+/*
+ * vis - visually encode characters
+ */
+char *
+vis(char *dst, int c, int flag, int nextc)
+{
+ char *extra = NULL;
+ unsigned char uc = (unsigned char)c;
+
+ _DIAGASSERT(dst != NULL);
+
+ MAKEEXTRALIST(flag, extra, "");
+ if (! extra) {
+ *dst = '\0'; /* can't create extra, return "" */
+ return dst;
+ }
+ if (flag & VIS_HTTPSTYLE)
+ HVIS(dst, uc, flag, nextc, extra);
+ else
+ SVIS(dst, uc, flag, nextc, extra);
+ free(extra);
+ *dst = '\0';
+ return dst;
+}
+
+
+/*
+ * strvis, strvisx - visually encode characters from src into dst
+ *
+ * Dst must be 4 times the size of src to account for possible
+ * expansion. The length of dst, not including the trailing NULL,
+ * is returned.
+ *
+ * Strvisx encodes exactly len bytes from src into dst.
+ * This is useful for encoding a block of data.
+ */
+int
+strvis(char *dst, const char *src, int flag)
+{
+ char *extra = NULL;
+ int rv;
+
+ MAKEEXTRALIST(flag, extra, "");
+ if (!extra) {
+ *dst = '\0'; /* can't create extra, return "" */
+ return 0;
+ }
+ rv = strsvis(dst, src, flag, extra);
+ free(extra);
+ return rv;
+}
+
+
+int
+strvisx(char *dst, const char *src, size_t len, int flag)
+{
+ char *extra = NULL;
+ int rv;
+
+ MAKEEXTRALIST(flag, extra, "");
+ if (!extra) {
+ *dst = '\0'; /* can't create extra, return "" */
+ return 0;
+ }
+ rv = strsvisx(dst, src, len, flag, extra);
+ free(extra);
+ return rv;
+}
+#endif
diff --git a/cpukit/libmisc/shell/vis.h b/cpukit/libmisc/shell/vis.h
new file mode 100644
index 0000000000..fb0aa6dc2a
--- /dev/null
+++ b/cpukit/libmisc/shell/vis.h
@@ -0,0 +1,91 @@
+/* $NetBSD: vis.h,v 1.16 2005/09/13 01:44:32 christos Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)vis.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _VIS_H_
+#define _VIS_H_
+
+#include <sys/types.h>
+
+/*
+ * to select alternate encoding format
+ */
+#define VIS_OCTAL 0x01 /* use octal \ddd format */
+#define VIS_CSTYLE 0x02 /* use \[nrft0..] where appropiate */
+
+/*
+ * to alter set of characters encoded (default is to encode all
+ * non-graphic except space, tab, and newline).
+ */
+#define VIS_SP 0x04 /* also encode space */
+#define VIS_TAB 0x08 /* also encode tab */
+#define VIS_NL 0x10 /* also encode newline */
+#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL)
+#define VIS_SAFE 0x20 /* only encode "unsafe" characters */
+
+/*
+ * other
+ */
+#define VIS_NOSLASH 0x40 /* inhibit printing '\' */
+#define VIS_HTTPSTYLE 0x80 /* http-style escape % HEX HEX */
+
+/*
+ * unvis return codes
+ */
+#define UNVIS_VALID 1 /* character valid */
+#define UNVIS_VALIDPUSH 2 /* character valid, push back passed char */
+#define UNVIS_NOCHAR 3 /* valid sequence, no character produced */
+#define UNVIS_SYNBAD -1 /* unrecognized escape sequence */
+#define UNVIS_ERROR -2 /* decoder in unknown state (unrecoverable) */
+
+/*
+ * unvis flags
+ */
+#define UNVIS_END 1 /* no more characters */
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+char *vis(char *, int, int, int);
+char *svis(char *, int, int, int, const char *);
+int strvis(char *, const char *, int);
+int strsvis(char *, const char *, int, const char *);
+int strvisx(char *, const char *, size_t, int);
+int strsvisx(char *, const char *, size_t, int, const char *);
+int strunvis(char *, const char *);
+int strunvisx(char *, const char *, int);
+#ifndef __LIBC12_SOURCE__
+//int unvis(char *, int, int *, int) __RENAME(__unvis13);
+#endif
+__END_DECLS
+
+#endif /* !_VIS_H_ */
diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
index 3822fc3f83..346a2ee921 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -587,7 +587,7 @@ extern rtems_configuration_table Configuration;
#define CONFIGURE_ATA_DRIVER_TASK_PRIORITY ATA_DRIVER_TASK_DEFAULT_PRIORITY
#endif
#ifdef CONFIGURE_INIT
- rtems_task_priority ata_driver_task_priority
+ rtems_task_priority rtems_ata_driver_task_priority
= CONFIGURE_ATA_DRIVER_TASK_PRIORITY;
#endif /* CONFIGURE_INIT */
#endif
@@ -598,13 +598,36 @@ extern rtems_configuration_table Configuration;
#ifdef CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
#include <rtems/bdbuf.h>
/*
- * configure the priority of the bdbuf swapout task
+ * configure the bdbuf cache parameters
*/
+ #ifndef CONFIGURE_BDBUF_MAX_READ_AHEAD_BLOCKS
+ #define CONFIGURE_BDBUF_MAX_READ_AHEAD_BLOCKS \
+ RTEMS_BDBUF_MAX_READ_AHEAD_BLOCKS_DEFAULT
+ #endif
+ #ifndef CONFIGURE_BDBUF_MAX_WRITE_BLOCKS
+ #define CONFIGURE_BDBUF_MAX_WRITE_BLOCKS \
+ RTEMS_BDBUF_MAX_WRITE_BLOCKS_DEFAULT
+ #endif
#ifndef CONFIGURE_SWAPOUT_TASK_PRIORITY
- #define CONFIGURE_SWAPOUT_TASK_PRIORITY SWAPOUT_TASK_DEFAULT_PRIORITY
+ #define CONFIGURE_SWAPOUT_TASK_PRIORITY \
+ RTEMS_BDBUF_SWAPOUT_TASK_PRIORITY_DEFAULT
+ #endif
+ #ifndef CONFIGURE_SWAPOUT_SWAP_PERIOD
+ #define CONFIGURE_SWAPOUT_SWAP_PERIOD \
+ RTEMS_BDBUF_SWAPOUT_TASK_SWAP_PERIOD_DEFAULT
+ #endif
+ #ifndef CONFIGURE_SWAPOUT_BLOCK_HOLD
+ #define CONFIGURE_SWAPOUT_BLOCK_HOLD \
+ RTEMS_BDBUF_SWAPOUT_TASK_BLOCK_HOLD_DEFAULT
#endif
#ifdef CONFIGURE_INIT
- rtems_task_priority swapout_task_priority = CONFIGURE_SWAPOUT_TASK_PRIORITY;
+ rtems_bdbuf_config rtems_bdbuf_configuration = {
+ CONFIGURE_BDBUF_MAX_READ_AHEAD_BLOCKS,
+ CONFIGURE_BDBUF_MAX_WRITE_BLOCKS,
+ CONFIGURE_SWAPOUT_TASK_PRIORITY,
+ CONFIGURE_SWAPOUT_SWAP_PERIOD,
+ CONFIGURE_SWAPOUT_BLOCK_HOLD
+ };
#endif
#ifndef CONFIGURE_HAS_OWN_BDBUF_TABLE
#ifndef CONFIGURE_BDBUF_BUFFER_COUNT
@@ -615,11 +638,12 @@ extern rtems_configuration_table Configuration;
#define CONFIGURE_BDBUF_BUFFER_SIZE 512
#endif
#ifdef CONFIGURE_INIT
- rtems_bdbuf_config rtems_bdbuf_configuration[] = {
+ rtems_bdbuf_pool_config rtems_bdbuf_pool_configuration[] = {
{CONFIGURE_BDBUF_BUFFER_SIZE, CONFIGURE_BDBUF_BUFFER_COUNT, NULL}
};
- int rtems_bdbuf_configuration_size =( sizeof(rtems_bdbuf_configuration)
- /sizeof(rtems_bdbuf_configuration[0]));
+ int rtems_bdbuf_pool_configuration_size =
+ (sizeof(rtems_bdbuf_pool_configuration) /
+ sizeof(rtems_bdbuf_pool_configuration[0]));
#endif /* CONFIGURE_INIT */
#endif /* CONFIGURE_HAS_OWN_BDBUF_TABLE */
#endif /* CONFIGURE_APPLICATION_NEEDS_LIBBLOCK */
diff --git a/cpukit/score/src/coremutex.c b/cpukit/score/src/coremutex.c
index 6e23561f19..60a2995882 100644
--- a/cpukit/score/src/coremutex.c
+++ b/cpukit/score/src/coremutex.c
@@ -66,9 +66,9 @@ void _CORE_mutex_Initialize(
_CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) )
#ifdef __RTEMS_STRICT_ORDER_MUTEX__
- _Chain_Prepend_unprotected( &executing->lock_mutex,
+ _Chain_Prepend_unprotected( &_Thread_Executing->lock_mutex,
&the_mutex->queue.lock_queue );
- the_mutex->queue.priority_before = executing->current_priority;
+ the_mutex->queue.priority_before = _Thread_Executing->current_priority;
#endif
_Thread_Executing->resource_count++;
diff --git a/cpukit/score/src/interr.c b/cpukit/score/src/interr.c
index e904815762..4431c7b313 100644
--- a/cpukit/score/src/interr.c
+++ b/cpukit/score/src/interr.c
@@ -61,4 +61,5 @@ void _Internal_error_Occurred(
_CPU_Fatal_halt( the_error );
/* will not return from this routine */
+ while (TRUE);
}