[rtems commit] libblock: Add generic IMFS block device nodes

Joel Sherrill joel at rtems.org
Thu Mar 29 14:14:30 UTC 2012


Module:    rtems
Branch:    master
Commit:    36f742304f1208441f3d1e2087f43500fd8d3cac
Changeset: http://git.rtems.org/rtems/commit/?id=36f742304f1208441f3d1e2087f43500fd8d3cac

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Mon Mar  5 15:06:02 2012 +0100

libblock: Add generic IMFS block device nodes

New functions
 o rtems_blkdev_create(), and
 o rtems_blkdev_create_partition().

New test libtests/block11.

---

 cpukit/libblock/Makefile.am             |    1 +
 cpukit/libblock/include/rtems/blkdev.h  |   50 ++++
 cpukit/libblock/src/blkdev-imfs.c       |  380 +++++++++++++++++++++++++++++
 testsuites/libtests/Makefile.am         |    2 +-
 testsuites/libtests/block11/Makefile.am |   25 ++
 testsuites/libtests/block11/block11.doc |   12 +
 testsuites/libtests/block11/block11.scn |    2 +
 testsuites/libtests/block11/init.c      |  402 +++++++++++++++++++++++++++++++
 testsuites/libtests/configure.ac        |    1 +
 9 files changed, 874 insertions(+), 1 deletions(-)

diff --git a/cpukit/libblock/Makefile.am b/cpukit/libblock/Makefile.am
index 0311319..5cf143d 100644
--- a/cpukit/libblock/Makefile.am
+++ b/cpukit/libblock/Makefile.am
@@ -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 \
diff --git a/cpukit/libblock/include/rtems/blkdev.h b/cpukit/libblock/include/rtems/blkdev.h
index 70259d6..c512380 100644
--- a/cpukit/libblock/include/rtems/blkdev.h
+++ b/cpukit/libblock/include/rtems/blkdev.h
@@ -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
diff --git a/cpukit/libblock/src/blkdev-imfs.c b/cpukit/libblock/src/blkdev-imfs.c
new file mode 100644
index 0000000..080ca21
--- /dev/null
+++ b/cpukit/libblock/src/blkdev-imfs.c
@@ -0,0 +1,380 @@
+/*
+ * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at 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;
+}
diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am
index a399032..0e30a51 100644
--- a/testsuites/libtests/Makefile.am
+++ b/testsuites/libtests/Makefile.am
@@ -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
diff --git a/testsuites/libtests/block11/Makefile.am b/testsuites/libtests/block11/Makefile.am
new file mode 100644
index 0000000..dee51b6
--- /dev/null
+++ b/testsuites/libtests/block11/Makefile.am
@@ -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 at .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
diff --git a/testsuites/libtests/block11/block11.doc b/testsuites/libtests/block11/block11.doc
new file mode 100644
index 0000000..e52b244
--- /dev/null
+++ b/testsuites/libtests/block11/block11.doc
@@ -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
diff --git a/testsuites/libtests/block11/block11.scn b/testsuites/libtests/block11/block11.scn
new file mode 100644
index 0000000..fff48c0
--- /dev/null
+++ b/testsuites/libtests/block11/block11.scn
@@ -0,0 +1,2 @@
+*** TEST BLOCK 11 ***
+*** END OF TEST BLOCK 11 ***
diff --git a/testsuites/libtests/block11/init.c b/testsuites/libtests/block11/init.c
new file mode 100644
index 0000000..3127331
--- /dev/null
+++ b/testsuites/libtests/block11/init.c
@@ -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 at 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>
diff --git a/testsuites/libtests/configure.ac b/testsuites/libtests/configure.ac
index 675f343..b634ff8 100644
--- a/testsuites/libtests/configure.ac
+++ b/testsuites/libtests/configure.ac
@@ -53,6 +53,7 @@ block07/Makefile
 block08/Makefile
 block09/Makefile
 block10/Makefile
+block11/Makefile
 bspcmdline01/Makefile
 cpuuse/Makefile
 devfs01/Makefile




More information about the vc mailing list