mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-22 19:11:44 +08:00
libblock: Add generic IMFS block device nodes
New functions o rtems_blkdev_create(), and o rtems_blkdev_create_partition(). New test libtests/block11.
This commit is contained in:
@@ -8,6 +8,7 @@ include $(top_srcdir)/automake/compile.am
|
||||
noinst_LIBRARIES = libblock.a
|
||||
libblock_a_SOURCES = src/bdbuf.c \
|
||||
src/blkdev.c \
|
||||
src/blkdev-imfs.c \
|
||||
src/blkdev-ioctl.c \
|
||||
src/blkdev-ops.c \
|
||||
src/diskdevs.c \
|
||||
|
||||
@@ -307,6 +307,56 @@ rtems_blkdev_ioctl(rtems_disk_device *dd, uint32_t req, void *argp);
|
||||
*/
|
||||
extern const rtems_driver_address_table rtems_blkdev_generic_ops;
|
||||
|
||||
/**
|
||||
* @brief Creates a block device.
|
||||
*
|
||||
* @param[in] device The path for the new block device.
|
||||
* @param[in] block_size The block size. Must be positive.
|
||||
* @param[in] block_count The block count. Must be positive.
|
||||
* @param[in] handler The block device IO control handler. Must not be @c NULL.
|
||||
* @param[in] driver_data The block device driver data.
|
||||
*
|
||||
* @retval RTEMS_SUCCESSFUL Successful operation.
|
||||
* @retval RTEMS_INVALID_NUMBER Block size or block count is not positive.
|
||||
* @retval RTEMS_NO_MEMORY Not enough memory.
|
||||
* @retval RTEMS_UNSATISFIED Cannot create generic device node.
|
||||
*/
|
||||
rtems_status_code rtems_blkdev_create(
|
||||
const char *device,
|
||||
uint32_t block_size,
|
||||
rtems_blkdev_bnum block_count,
|
||||
rtems_block_device_ioctl handler,
|
||||
void *driver_data
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Creates a partition within a block device.
|
||||
*
|
||||
* A partition manages a subset of consecutive blocks contained in a block
|
||||
* device. The blocks must be within the range of blocks managed by the
|
||||
* associated block device. The media block size, block size, and IO control
|
||||
* handler are inherited by the block device.
|
||||
*
|
||||
* @param[in] partition The path for the new partition device.
|
||||
* @param[in] device The block device path.
|
||||
* @param[in] block_begin The block begin of the partition.
|
||||
* @param[in] block_count The block count of the partition.
|
||||
*
|
||||
* @retval RTEMS_SUCCESSFUL Successful operation.
|
||||
* @retval RTEMS_INVALID_ID Block device node does not exist.
|
||||
* @retval RTEMS_INVALID_NODE File system node is not a block device.
|
||||
* @retval RTEMS_NOT_IMPLEMENTED Block device implementation is incomplete.
|
||||
* @retval RTEMS_INVALID_NUMBER Block begin or block count is invalid.
|
||||
* @retval RTEMS_NO_MEMORY Not enough memory.
|
||||
* @retval RTEMS_UNSATISFIED Cannot create generic device node.
|
||||
*/
|
||||
rtems_status_code rtems_blkdev_create_partition(
|
||||
const char *partition,
|
||||
const char *device,
|
||||
rtems_blkdev_bnum block_begin,
|
||||
rtems_blkdev_bnum block_count
|
||||
);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright (c) 2012 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rtems/blkdev.h>
|
||||
#include <rtems/bdbuf.h>
|
||||
#include <rtems/imfs.h>
|
||||
|
||||
typedef struct {
|
||||
rtems_disk_device dd;
|
||||
int fd;
|
||||
} rtems_blkdev_imfs_context;
|
||||
|
||||
static ssize_t rtems_blkdev_imfs_read(
|
||||
rtems_libio_t *iop,
|
||||
void *buffer,
|
||||
size_t count
|
||||
)
|
||||
{
|
||||
int rv;
|
||||
const rtems_blkdev_imfs_context *ctx = IMFS_generic_get_context_by_iop(iop);
|
||||
const rtems_disk_device *dd = &ctx->dd;
|
||||
ssize_t remaining = (ssize_t) count;
|
||||
off_t offset = iop->offset;
|
||||
ssize_t block_size = (ssize_t) rtems_disk_get_block_size(dd);
|
||||
rtems_blkdev_bnum block = (rtems_blkdev_bnum) (offset / block_size);
|
||||
ssize_t block_offset = (ssize_t) (offset % block_size);
|
||||
char *dst = buffer;
|
||||
|
||||
while (remaining > 0) {
|
||||
rtems_bdbuf_buffer *bd;
|
||||
rtems_status_code sc = rtems_bdbuf_read(dd, block, &bd);
|
||||
|
||||
if (sc == RTEMS_SUCCESSFUL) {
|
||||
ssize_t copy = block_size - block_offset;
|
||||
|
||||
if (copy > remaining) {
|
||||
copy = remaining;
|
||||
}
|
||||
|
||||
memcpy(dst, (char *) bd->buffer + block_offset, (size_t) copy);
|
||||
|
||||
sc = rtems_bdbuf_release(bd);
|
||||
if (sc == RTEMS_SUCCESSFUL) {
|
||||
block_offset = 0;
|
||||
remaining -= copy;
|
||||
dst += copy;
|
||||
++block;
|
||||
} else {
|
||||
remaining = -1;
|
||||
}
|
||||
} else {
|
||||
remaining = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (remaining >= 0) {
|
||||
rv = (ssize_t) count;
|
||||
} else {
|
||||
errno = EIO;
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static ssize_t rtems_blkdev_imfs_write(
|
||||
rtems_libio_t *iop,
|
||||
const void *buffer,
|
||||
size_t count
|
||||
)
|
||||
{
|
||||
int rv;
|
||||
const rtems_blkdev_imfs_context *ctx = IMFS_generic_get_context_by_iop(iop);
|
||||
const rtems_disk_device *dd = &ctx->dd;
|
||||
ssize_t remaining = (ssize_t) count;
|
||||
off_t offset = iop->offset;
|
||||
ssize_t block_size = (ssize_t) rtems_disk_get_block_size(dd);
|
||||
rtems_blkdev_bnum block = (rtems_blkdev_bnum) (offset / block_size);
|
||||
ssize_t block_offset = (ssize_t) (offset % block_size);
|
||||
const char *src = buffer;
|
||||
|
||||
while (remaining > 0) {
|
||||
rtems_status_code sc;
|
||||
rtems_bdbuf_buffer *bd;
|
||||
|
||||
if (block_offset == 0 && remaining >= block_size) {
|
||||
sc = rtems_bdbuf_get(dd, block, &bd);
|
||||
} else {
|
||||
sc = rtems_bdbuf_read(dd, block, &bd);
|
||||
}
|
||||
|
||||
if (sc == RTEMS_SUCCESSFUL) {
|
||||
ssize_t copy = block_size - block_offset;
|
||||
|
||||
if (copy > remaining) {
|
||||
copy = remaining;
|
||||
}
|
||||
|
||||
memcpy((char *) bd->buffer + block_offset, src, (size_t) copy);
|
||||
|
||||
sc = rtems_bdbuf_release_modified(bd);
|
||||
if (sc == RTEMS_SUCCESSFUL) {
|
||||
block_offset = 0;
|
||||
remaining -= copy;
|
||||
src += copy;
|
||||
++block;
|
||||
} else {
|
||||
remaining = -1;
|
||||
}
|
||||
} else {
|
||||
remaining = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (remaining >= 0) {
|
||||
rv = (ssize_t) count;
|
||||
} else {
|
||||
errno = EIO;
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int rtems_blkdev_imfs_ioctl(
|
||||
rtems_libio_t *iop,
|
||||
uint32_t request,
|
||||
void *buffer
|
||||
)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
if (request != RTEMS_BLKIO_REQUEST) {
|
||||
rtems_blkdev_imfs_context *ctx = IMFS_generic_get_context_by_iop(iop);
|
||||
rtems_disk_device *dd = &ctx->dd;
|
||||
|
||||
rv = (*dd->ioctl)(dd, request, buffer);
|
||||
} else {
|
||||
/*
|
||||
* It is not allowed to directly access the driver circumventing the cache.
|
||||
*/
|
||||
errno = EINVAL;
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int rtems_blkdev_imfs_fstat(
|
||||
const rtems_filesystem_location_info_t *loc,
|
||||
struct stat *buf
|
||||
)
|
||||
{
|
||||
const rtems_blkdev_imfs_context *ctx =
|
||||
IMFS_generic_get_context_by_location(loc);
|
||||
const rtems_disk_device *dd = &ctx->dd;
|
||||
|
||||
buf->st_rdev = rtems_disk_get_device_identifier(dd);
|
||||
buf->st_blksize = rtems_disk_get_block_size(dd);
|
||||
buf->st_blocks = rtems_disk_get_block_count(dd);
|
||||
|
||||
return IMFS_stat(loc, buf);
|
||||
}
|
||||
|
||||
static int rtems_blkdev_imfs_fsync_or_fdatasync(
|
||||
rtems_libio_t *iop
|
||||
)
|
||||
{
|
||||
int rv = 0;
|
||||
const rtems_blkdev_imfs_context *ctx = IMFS_generic_get_context_by_iop(iop);
|
||||
const rtems_disk_device *dd = &ctx->dd;
|
||||
rtems_status_code sc = rtems_bdbuf_syncdev(dd);
|
||||
|
||||
if (sc != RTEMS_SUCCESSFUL) {
|
||||
errno = EIO;
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static const rtems_filesystem_file_handlers_r rtems_blkdev_imfs_node = {
|
||||
.open_h = rtems_filesystem_default_open,
|
||||
.close_h = rtems_filesystem_default_close,
|
||||
.read_h = rtems_blkdev_imfs_read,
|
||||
.write_h = rtems_blkdev_imfs_write,
|
||||
.ioctl_h = rtems_blkdev_imfs_ioctl,
|
||||
.lseek_h = rtems_filesystem_default_lseek_success,
|
||||
.fstat_h = rtems_blkdev_imfs_fstat,
|
||||
.ftruncate_h = rtems_filesystem_default_ftruncate,
|
||||
.fsync_h = rtems_blkdev_imfs_fsync_or_fdatasync,
|
||||
.fdatasync_h = rtems_blkdev_imfs_fsync_or_fdatasync,
|
||||
.fcntl_h = rtems_filesystem_default_fcntl
|
||||
};
|
||||
|
||||
static IMFS_jnode_t *rtems_blkdev_imfs_initialize(
|
||||
IMFS_jnode_t *node,
|
||||
const IMFS_types_union *info
|
||||
)
|
||||
{
|
||||
rtems_blkdev_imfs_context *ctx;
|
||||
rtems_disk_device *dd;
|
||||
|
||||
node = IMFS_node_initialize_generic(node, info);
|
||||
|
||||
ctx = IMFS_generic_get_context_by_node(node);
|
||||
dd = &ctx->dd;
|
||||
dd->dev = IMFS_generic_get_device_identifier_by_node(node);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static IMFS_jnode_t *rtems_blkdev_imfs_destroy(IMFS_jnode_t *node)
|
||||
{
|
||||
rtems_blkdev_imfs_context *ctx = IMFS_generic_get_context_by_node(node);
|
||||
rtems_disk_device *dd = &ctx->dd;
|
||||
|
||||
rtems_bdbuf_syncdev(dd);
|
||||
rtems_bdbuf_purge_dev(dd);
|
||||
|
||||
if (ctx->fd >= 0) {
|
||||
close(ctx->fd);
|
||||
} else {
|
||||
(*dd->ioctl)(dd, RTEMS_BLKIO_DELETED, NULL);
|
||||
}
|
||||
|
||||
free(ctx);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static const IMFS_node_control rtems_blkdev_imfs_control = {
|
||||
.imfs_type = IMFS_GENERIC,
|
||||
.handlers = &rtems_blkdev_imfs_node,
|
||||
.node_initialize = rtems_blkdev_imfs_initialize,
|
||||
.node_remove = IMFS_node_remove_default,
|
||||
.node_destroy = rtems_blkdev_imfs_destroy
|
||||
};
|
||||
|
||||
rtems_status_code rtems_blkdev_create(
|
||||
const char *device,
|
||||
uint32_t block_size,
|
||||
rtems_blkdev_bnum block_count,
|
||||
rtems_block_device_ioctl handler,
|
||||
void *driver_data
|
||||
)
|
||||
{
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
|
||||
if (block_size > 0 && block_count > 0) {
|
||||
rtems_blkdev_imfs_context *ctx = calloc(1, sizeof(*ctx));
|
||||
|
||||
if (ctx != NULL) {
|
||||
rtems_disk_device *dd = &ctx->dd;
|
||||
int rv;
|
||||
|
||||
ctx->fd = -1;
|
||||
|
||||
dd->phys_dev = dd;
|
||||
dd->size = block_count;
|
||||
dd->media_block_size = block_size;
|
||||
dd->block_size = block_size;
|
||||
dd->ioctl = handler;
|
||||
dd->driver_data = driver_data;
|
||||
|
||||
if ((*handler)(dd, RTEMS_BLKIO_CAPABILITIES, &dd->capabilities) != 0) {
|
||||
dd->capabilities = 0;
|
||||
}
|
||||
|
||||
rv = IMFS_make_generic_node(
|
||||
device,
|
||||
S_IFBLK | S_IRWXU | S_IRWXG | S_IRWXO,
|
||||
&rtems_blkdev_imfs_control,
|
||||
ctx
|
||||
);
|
||||
|
||||
if (rv != 0) {
|
||||
free(ctx);
|
||||
sc = RTEMS_UNSATISFIED;
|
||||
}
|
||||
} else {
|
||||
sc = RTEMS_NO_MEMORY;
|
||||
}
|
||||
} else {
|
||||
sc = RTEMS_INVALID_NUMBER;
|
||||
}
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
rtems_status_code rtems_blkdev_create_partition(
|
||||
const char *partition,
|
||||
const char *device,
|
||||
rtems_blkdev_bnum block_begin,
|
||||
rtems_blkdev_bnum block_count
|
||||
)
|
||||
{
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
int fd = open(device, O_RDWR);
|
||||
|
||||
if (fd >= 0) {
|
||||
int rv;
|
||||
struct stat st;
|
||||
|
||||
rv = fstat(fd, &st);
|
||||
if (rv == 0 && S_ISBLK(st.st_mode)) {
|
||||
rtems_disk_device *dd;
|
||||
|
||||
rv = ioctl(fd, RTEMS_BLKIO_GETDISKDEV, &dd);
|
||||
if (rv == 0) {
|
||||
rtems_blkdev_bnum device_block_count = rtems_disk_get_block_count(dd);
|
||||
|
||||
if (
|
||||
block_begin < device_block_count
|
||||
&& block_count > 0
|
||||
&& block_count <= device_block_count - block_begin
|
||||
) {
|
||||
rtems_blkdev_imfs_context *ctx = malloc(sizeof(*ctx));
|
||||
|
||||
if (ctx != NULL) {
|
||||
memcpy(&ctx->dd, dd, sizeof(ctx->dd));
|
||||
|
||||
ctx->dd.start = block_begin;
|
||||
ctx->dd.size = block_count;
|
||||
ctx->fd = fd;
|
||||
|
||||
rv = IMFS_make_generic_node(
|
||||
partition,
|
||||
S_IFBLK | S_IRWXU | S_IRWXG | S_IRWXO,
|
||||
&rtems_blkdev_imfs_control,
|
||||
ctx
|
||||
);
|
||||
|
||||
if (rv != 0) {
|
||||
free(ctx);
|
||||
sc = RTEMS_UNSATISFIED;
|
||||
}
|
||||
} else {
|
||||
sc = RTEMS_NO_MEMORY;
|
||||
}
|
||||
} else {
|
||||
sc = RTEMS_INVALID_NUMBER;
|
||||
}
|
||||
} else {
|
||||
sc = RTEMS_NOT_IMPLEMENTED;
|
||||
}
|
||||
} else {
|
||||
sc = RTEMS_INVALID_NODE;
|
||||
}
|
||||
|
||||
if (sc != RTEMS_SUCCESSFUL) {
|
||||
close(fd);
|
||||
}
|
||||
} else {
|
||||
sc = RTEMS_INVALID_ID;
|
||||
}
|
||||
|
||||
return sc;
|
||||
}
|
||||
@@ -13,7 +13,7 @@ SUBDIRS += bspcmdline01 cpuuse devfs01 devfs02 devfs03 devfs04 \
|
||||
termios termios01 termios02 termios03 termios04 termios05 \
|
||||
termios06 termios07 termios08 \
|
||||
rtems++ tztest block01 block02 block03 block04 block05 block06 block07 \
|
||||
block08 block09 block10 stringto01 \
|
||||
block08 block09 block10 block11 stringto01 \
|
||||
tar01 tar02 tar03 \
|
||||
math mathf mathl complex \
|
||||
mouse01
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
##
|
||||
## $Id$
|
||||
##
|
||||
|
||||
|
||||
rtems_tests_PROGRAMS = block11
|
||||
block11_SOURCES = init.c
|
||||
|
||||
dist_rtems_tests_DATA = block11.scn block11.doc
|
||||
|
||||
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||
include $(top_srcdir)/../automake/compile.am
|
||||
include $(top_srcdir)/../automake/leaf.am
|
||||
|
||||
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/../support/include
|
||||
|
||||
LINK_OBJS = $(block11_OBJECTS)
|
||||
LINK_LIBS = $(block11_LDLIBS)
|
||||
|
||||
block11$(EXEEXT): $(block11_OBJECTS) $(block11_DEPENDENCIES)
|
||||
@rm -f block11$(EXEEXT)
|
||||
$(make-exe)
|
||||
|
||||
include $(top_srcdir)/../automake/local.am
|
||||
@@ -0,0 +1,12 @@
|
||||
This file describes the directives and concepts tested by this test set.
|
||||
|
||||
test set name: block11
|
||||
|
||||
directives:
|
||||
|
||||
rtems_blkdev_create
|
||||
rtems_blkdev_create_partition
|
||||
|
||||
concepts:
|
||||
|
||||
TBD
|
||||
@@ -0,0 +1,2 @@
|
||||
*** TEST BLOCK 11 ***
|
||||
*** END OF TEST BLOCK 11 ***
|
||||
@@ -0,0 +1,402 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup tests
|
||||
*
|
||||
* @brief Block device tests.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "tmacros.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/ramdisk.h>
|
||||
#include <rtems/diskdevs.h>
|
||||
#include <rtems/malloc.h>
|
||||
|
||||
#define ASSERT_SC(sc) rtems_test_assert((sc) == RTEMS_SUCCESSFUL)
|
||||
|
||||
#define CHUNK_MAX 32U
|
||||
|
||||
#define AREA_SIZE ((CHUNK_MAX * (CHUNK_MAX + 1U)) / 2U)
|
||||
|
||||
#define BLOCK_SIZE 4U
|
||||
|
||||
#define BLOCK_COUNT (AREA_SIZE / BLOCK_SIZE)
|
||||
|
||||
static const char rda [] = "/dev/rda";
|
||||
|
||||
static const char rda1 [] = "/dev/rda1";
|
||||
|
||||
static const char not_exist [] = "not_exist";
|
||||
|
||||
static const char not_blkdev [] = "not_blkdev";
|
||||
|
||||
static const char invalid_blkdev [] = "invalid_blkdev";
|
||||
|
||||
static long area_a [AREA_SIZE / sizeof(long)];
|
||||
|
||||
static long area_b [AREA_SIZE / sizeof(long)];
|
||||
|
||||
static void area_init(long *area)
|
||||
{
|
||||
size_t i;
|
||||
size_t n = AREA_SIZE / sizeof(long);
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
area [i] = mrand48();
|
||||
}
|
||||
}
|
||||
|
||||
static void area_read(int fd, long *area)
|
||||
{
|
||||
size_t i;
|
||||
size_t n = CHUNK_MAX;
|
||||
char *dst = (char *) area;
|
||||
|
||||
for (i = 0; i <= n; ++i) {
|
||||
ssize_t m = read(fd, dst, i);
|
||||
rtems_test_assert(m == (ssize_t) i);
|
||||
dst += i;
|
||||
}
|
||||
}
|
||||
|
||||
static void area_write(int fd, const long *area)
|
||||
{
|
||||
size_t i;
|
||||
size_t n = CHUNK_MAX;
|
||||
const char *src = (const char *) area;
|
||||
|
||||
for (i = 0; i <= n; ++i) {
|
||||
ssize_t m = write(fd, src, i);
|
||||
rtems_test_assert(m == (ssize_t) i);
|
||||
src += i;
|
||||
}
|
||||
}
|
||||
|
||||
static void area_compare(const long *area_a, const long *area_b, bool equal)
|
||||
{
|
||||
bool actual_equal = memcmp(area_a, area_b, AREA_SIZE) == 0;
|
||||
rtems_test_assert(actual_equal == equal);
|
||||
}
|
||||
|
||||
static void test_blkdev_imfs_read_and_write(void)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
int rv;
|
||||
ramdisk *rd;
|
||||
int fd;
|
||||
off_t off;
|
||||
|
||||
rd = ramdisk_allocate(area_a, BLOCK_SIZE, BLOCK_COUNT, false);
|
||||
rtems_test_assert(rd != NULL);
|
||||
|
||||
ramdisk_enable_free_at_delete_request(rd);
|
||||
|
||||
sc = rtems_blkdev_create(
|
||||
rda,
|
||||
BLOCK_SIZE,
|
||||
BLOCK_COUNT,
|
||||
ramdisk_ioctl,
|
||||
rd
|
||||
);
|
||||
ASSERT_SC(sc);
|
||||
|
||||
fd = open(rda, O_RDWR);
|
||||
rtems_test_assert(fd >= 0);
|
||||
|
||||
area_init(area_a);
|
||||
area_read(fd, area_b);
|
||||
area_compare(area_a, area_b, true);
|
||||
|
||||
off = lseek(fd, 0, SEEK_SET);
|
||||
rtems_test_assert(off == 0);
|
||||
|
||||
area_init(area_b);
|
||||
area_write(fd, area_b);
|
||||
area_compare(area_a, area_b, false);
|
||||
|
||||
rv = close(fd);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
rv = unlink(rda);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
area_compare(area_a, area_b, true);
|
||||
}
|
||||
|
||||
static void test_blkdev_imfs_parameters(void)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
int rv;
|
||||
ramdisk *rd;
|
||||
int fd;
|
||||
const rtems_disk_device *dd;
|
||||
struct stat st;
|
||||
|
||||
rd = ramdisk_allocate(NULL, BLOCK_SIZE, BLOCK_COUNT, false);
|
||||
rtems_test_assert(rd != NULL);
|
||||
|
||||
ramdisk_enable_free_at_delete_request(rd);
|
||||
|
||||
sc = rtems_blkdev_create(
|
||||
rda,
|
||||
BLOCK_SIZE,
|
||||
BLOCK_COUNT,
|
||||
ramdisk_ioctl,
|
||||
rd
|
||||
);
|
||||
ASSERT_SC(sc);
|
||||
|
||||
sc = rtems_blkdev_create_partition(
|
||||
rda1,
|
||||
rda,
|
||||
1,
|
||||
BLOCK_COUNT - 1
|
||||
);
|
||||
ASSERT_SC(sc);
|
||||
|
||||
fd = open(rda, O_RDWR);
|
||||
rtems_test_assert(fd >= 0);
|
||||
|
||||
rv = fstat(fd, &st);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
rv = rtems_disk_fd_get_disk_device(fd, &dd);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
rtems_test_assert(rtems_disk_get_driver_data(dd) == rd);
|
||||
rtems_test_assert(rtems_disk_get_device_identifier(dd) == st.st_rdev);
|
||||
rtems_test_assert(rtems_disk_get_media_block_size(dd) == BLOCK_SIZE);
|
||||
rtems_test_assert(rtems_disk_get_block_size(dd) == BLOCK_SIZE);
|
||||
rtems_test_assert(rtems_disk_get_block_begin(dd) == 0);
|
||||
rtems_test_assert(rtems_disk_get_block_count(dd) == BLOCK_COUNT);
|
||||
|
||||
rv = close(fd);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
fd = open(rda1, O_RDWR);
|
||||
rtems_test_assert(fd >= 0);
|
||||
|
||||
rv = fstat(fd, &st);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
rv = rtems_disk_fd_get_disk_device(fd, &dd);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
rtems_test_assert(rtems_disk_get_driver_data(dd) == rd);
|
||||
rtems_test_assert(rtems_disk_get_device_identifier(dd) == st.st_rdev);
|
||||
rtems_test_assert(rtems_disk_get_media_block_size(dd) == BLOCK_SIZE);
|
||||
rtems_test_assert(rtems_disk_get_block_size(dd) == BLOCK_SIZE);
|
||||
rtems_test_assert(rtems_disk_get_block_begin(dd) == 1);
|
||||
rtems_test_assert(rtems_disk_get_block_count(dd) == BLOCK_COUNT - 1);
|
||||
|
||||
rv = close(fd);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
rv = unlink(rda1);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
rv = unlink(rda);
|
||||
rtems_test_assert(rv == 0);
|
||||
}
|
||||
|
||||
static void test_blkdev_imfs_errors(void)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
int rv;
|
||||
ramdisk *rd;
|
||||
void *opaque;
|
||||
|
||||
rd = ramdisk_allocate(NULL, BLOCK_SIZE, BLOCK_COUNT, false);
|
||||
rtems_test_assert(rd != NULL);
|
||||
|
||||
ramdisk_enable_free_at_delete_request(rd);
|
||||
|
||||
sc = rtems_blkdev_create(
|
||||
rda,
|
||||
0,
|
||||
BLOCK_COUNT,
|
||||
ramdisk_ioctl,
|
||||
rd
|
||||
);
|
||||
rtems_test_assert(sc == RTEMS_INVALID_NUMBER);
|
||||
|
||||
sc = rtems_blkdev_create(
|
||||
rda,
|
||||
BLOCK_SIZE,
|
||||
0,
|
||||
ramdisk_ioctl,
|
||||
rd
|
||||
);
|
||||
rtems_test_assert(sc == RTEMS_INVALID_NUMBER);
|
||||
|
||||
opaque = rtems_heap_greedy_allocate(0);
|
||||
sc = rtems_blkdev_create(
|
||||
rda,
|
||||
BLOCK_SIZE,
|
||||
BLOCK_COUNT,
|
||||
ramdisk_ioctl,
|
||||
rd
|
||||
);
|
||||
rtems_test_assert(sc == RTEMS_NO_MEMORY);
|
||||
rtems_heap_greedy_free(opaque);
|
||||
|
||||
opaque = rtems_heap_greedy_allocate(sizeof(rtems_disk_device) + sizeof(int));
|
||||
sc = rtems_blkdev_create(
|
||||
rda,
|
||||
BLOCK_SIZE,
|
||||
BLOCK_COUNT,
|
||||
ramdisk_ioctl,
|
||||
rd
|
||||
);
|
||||
rtems_test_assert(sc == RTEMS_UNSATISFIED);
|
||||
rtems_heap_greedy_free(opaque);
|
||||
|
||||
sc = rtems_blkdev_create(
|
||||
rda,
|
||||
BLOCK_SIZE,
|
||||
BLOCK_COUNT,
|
||||
ramdisk_ioctl,
|
||||
rd
|
||||
);
|
||||
ASSERT_SC(sc);
|
||||
|
||||
sc = rtems_blkdev_create_partition(
|
||||
rda1,
|
||||
not_exist,
|
||||
0,
|
||||
BLOCK_COUNT
|
||||
);
|
||||
rtems_test_assert(sc == RTEMS_INVALID_ID);
|
||||
|
||||
rv = mknod(not_blkdev, S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO, 0);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
sc = rtems_blkdev_create_partition(
|
||||
rda1,
|
||||
not_blkdev,
|
||||
0,
|
||||
BLOCK_COUNT
|
||||
);
|
||||
rtems_test_assert(sc == RTEMS_INVALID_NODE);
|
||||
|
||||
rv = mknod(invalid_blkdev, S_IFBLK | S_IRWXU | S_IRWXG | S_IRWXO, 0);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
sc = rtems_blkdev_create_partition(
|
||||
rda1,
|
||||
invalid_blkdev,
|
||||
0,
|
||||
BLOCK_COUNT
|
||||
);
|
||||
rtems_test_assert(sc == RTEMS_NOT_IMPLEMENTED);
|
||||
|
||||
sc = rtems_blkdev_create_partition(
|
||||
rda1,
|
||||
rda,
|
||||
0,
|
||||
0
|
||||
);
|
||||
rtems_test_assert(sc == RTEMS_INVALID_NUMBER);
|
||||
|
||||
sc = rtems_blkdev_create_partition(
|
||||
rda1,
|
||||
rda,
|
||||
BLOCK_COUNT,
|
||||
BLOCK_COUNT
|
||||
);
|
||||
rtems_test_assert(sc == RTEMS_INVALID_NUMBER);
|
||||
|
||||
sc = rtems_blkdev_create_partition(
|
||||
rda1,
|
||||
rda,
|
||||
0,
|
||||
BLOCK_COUNT + 1
|
||||
);
|
||||
rtems_test_assert(sc == RTEMS_INVALID_NUMBER);
|
||||
|
||||
opaque = rtems_heap_greedy_allocate(0);
|
||||
sc = rtems_blkdev_create_partition(
|
||||
rda1,
|
||||
rda,
|
||||
0,
|
||||
BLOCK_COUNT
|
||||
);
|
||||
rtems_test_assert(sc == RTEMS_NO_MEMORY);
|
||||
rtems_heap_greedy_free(opaque);
|
||||
|
||||
opaque = rtems_heap_greedy_allocate(sizeof(rtems_disk_device) + sizeof(int));
|
||||
sc = rtems_blkdev_create_partition(
|
||||
rda1,
|
||||
rda,
|
||||
0,
|
||||
BLOCK_COUNT
|
||||
);
|
||||
rtems_test_assert(sc == RTEMS_UNSATISFIED);
|
||||
rtems_heap_greedy_free(opaque);
|
||||
|
||||
rv = unlink(rda);
|
||||
rtems_test_assert(rv == 0);
|
||||
}
|
||||
|
||||
static rtems_task Init(rtems_task_argument argument)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
|
||||
puts("\n\n*** TEST BLOCK 11 ***");
|
||||
|
||||
sc = rtems_disk_io_initialize();
|
||||
ASSERT_SC(sc);
|
||||
|
||||
test_blkdev_imfs_read_and_write();
|
||||
test_blkdev_imfs_parameters();
|
||||
test_blkdev_imfs_errors();
|
||||
|
||||
sc = rtems_disk_io_done();
|
||||
ASSERT_SC(sc);
|
||||
|
||||
puts("*** END OF TEST BLOCK 11 ***");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#define CONFIGURE_INIT
|
||||
|
||||
#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
|
||||
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
|
||||
#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
|
||||
|
||||
#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
|
||||
#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 5
|
||||
|
||||
#define CONFIGURE_MAXIMUM_TASKS 2
|
||||
#define CONFIGURE_MAXIMUM_DRIVERS 2
|
||||
#define CONFIGURE_EXTRA_TASK_STACKS (8 * 1024)
|
||||
|
||||
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
|
||||
|
||||
#include <rtems/confdefs.h>
|
||||
@@ -53,6 +53,7 @@ block07/Makefile
|
||||
block08/Makefile
|
||||
block09/Makefile
|
||||
block10/Makefile
|
||||
block11/Makefile
|
||||
bspcmdline01/Makefile
|
||||
cpuuse/Makefile
|
||||
devfs01/Makefile
|
||||
|
||||
Reference in New Issue
Block a user