<br><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Nov 29, 2012 at 9:32 AM, Ralf Kirchner <span dir="ltr"><<a href="mailto:ralf.kirchner@embedded-brains.de" target="_blank">ralf.kirchner@embedded-brains.de</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">---<br>
 cpukit/Makefile.am                                |    1 +<br>
 cpukit/libblock/Makefile.am                       |    1 +<br>
 cpukit/libblock/include/rtems/sparse-disk.h       |  139 +++++++<br>
 cpukit/libblock/src/sparse-disk.c                 |  372 +++++++++++++++++<br>
 cpukit/<a href="http://preinstall.am" target="_blank">preinstall.am</a>                              |    4 +<br>
 testsuites/libtests/Makefile.am                   |    1 +<br>
 testsuites/libtests/<a href="http://configure.ac" target="_blank">configure.ac</a>                  |    1 +<br>
 testsuites/libtests/sparsedisk01/Makefile.am      |   19 +<br>
 testsuites/libtests/sparsedisk01/init.c           |  439 +++++++++++++++++++++<br>
 testsuites/libtests/sparsedisk01/sparsedisk01.doc |   11 +<br>
 10 Dateien geändert, 988 Zeilen hinzugefügt(+)<br>
 create mode 100644 cpukit/libblock/include/rtems/sparse-disk.h<br>
 create mode 100644 cpukit/libblock/src/sparse-disk.c<br>
 create mode 100644 testsuites/libtests/sparsedisk01/Makefile.am<br>
 create mode 100644 testsuites/libtests/sparsedisk01/init.c<br>
 create mode 100644 testsuites/libtests/sparsedisk01/sparsedisk01.doc<br>
 create mode 100644 testsuites/libtests/sparsedisk01/sparsedisk01.scn<br>
<br>
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am<br>
index b5569fa..5b11e7e 100644<br>
--- a/cpukit/Makefile.am<br>
+++ b/cpukit/Makefile.am<br>
@@ -124,6 +124,7 @@ include_rtems_HEADERS += libblock/include/rtems/flashdisk.h<br>
 include_rtems_HEADERS += libblock/include/rtems/ramdisk.h<br>
 include_rtems_HEADERS += libblock/include/rtems/nvdisk.h<br>
 include_rtems_HEADERS += libblock/include/rtems/nvdisk-sram.h<br>
+include_rtems_HEADERS += libblock/include/rtems/sparse-disk.h<br>
 include_rtems_HEADERS += libblock/include/rtems/ide_part_table.h<br>
 include_rtems_HEADERS += libblock/include/rtems/bdpart.h<br>
 include_rtems_HEADERS += libblock/include/rtems/media.h<br>
diff --git a/cpukit/libblock/Makefile.am b/cpukit/libblock/Makefile.am<br>
index d07eb5e..0f720f2 100644<br>
--- a/cpukit/libblock/Makefile.am<br>
+++ b/cpukit/libblock/Makefile.am<br>
@@ -31,6 +31,7 @@ libblock_a_SOURCES = src/bdbuf.c \<br>
     src/media-server.c \<br>
     src/media-desc.c \<br>
     src/media-dev-ident.c \<br>
+    src/sparse-disk.c \<br>
     include/rtems/bdbuf.h include/rtems/blkdev.h \<br>
     include/rtems/diskdevs.h include/rtems/flashdisk.h \<br>
     include/rtems/ramdisk.h include/rtems/nvdisk.h include/rtems/nvdisk-sram.h \<br>
diff --git a/cpukit/libblock/include/rtems/sparse-disk.h b/cpukit/libblock/include/rtems/sparse-disk.h<br>
new file mode 100644<br>
index 0000000..54e3fe9<br>
--- /dev/null<br>
+++ b/cpukit/libblock/include/rtems/sparse-disk.h<br>
@@ -0,0 +1,139 @@<br>
+/**<br>
+ * @file<br>
+ *<br>
+ * @ingroup rtems_sparse_disk<br>
+ *<br>
+ * @brief Sparse disk block device API.<br>
+ */<br>
+<br>
+/*<br>
+ * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.<br>
+ *<br>
+ *  embedded brains GmbH<br>
+ *  Obere Lagerstr. 30<br>
+ *  82178 Puchheim<br>
+ *  Germany<br>
+ *  <<a href="mailto:rtems@embedded-brains.de">rtems@embedded-brains.de</a>><br>
+ *<br>
+ * The license and distribution terms for this file may be<br>
+ * found in the file LICENSE in this distribution or at<br>
+ * <a href="http://www.rtems.com/license/LICENSE" target="_blank">http://www.rtems.com/license/LICENSE</a>.<br>
+ */<br>
+<br>
+#ifndef SPARSE_DISK_H<br>
+#define SPARSE_DISK_H<br>
+<br>
+#include <stddef.h><br>
+#include <stdint.h><br>
+#include <rtems.h><br>
+#include <rtems/diskdevs.h><br>
+<br>
+#ifdef __cplusplus<br>
+extern "C" {<br>
+#endif /* __cplusplus */<br>
+<br>
+<br></blockquote><div>only leave one blank line anywhere. fix here, and in other places.<br> <br></div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

+/**<br>
+ * @defgroup rtems_sparse_disk Sparse Disk Device<br>
+ *<br>
+ * @ingroup rtems_blkdev<br>
+ *<br>
+ * @{<br>
+ */<br>
+<br>
+<br>
+<br>
+typedef struct {<br>
+  rtems_blkdev_bnum  block;<br>
+  void              *data;<br>
+} rtems_sparse_disk_key;<br>
+<br>
+typedef struct rtems_sparse_disk *sparse_disk_ptr;<br></blockquote><div>we don't normally obscure pointers behind typedefs. this should be considered more carefully. I'm not even sure this type gets used anywhere... I see the same name used as a variable, which is confusing.<br>
 <br></div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+<br>
+typedef struct {<br>
+  rtems_id                       mutex;<br>
+  rtems_blkdev_bnum              blocks_allocated;<br>
+  size_t                         used_count;<br>
+  uint32_t                       block_size;<br>
+  void                          *delete_hdlr;<br></blockquote><div>eliminate abbreviation.. don't know what hdlr means.<br> <br></div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

+  uint8_t                        fill_pattern;<br>
+  rtems_sparse_disk_key         *key_table;<br>
+} rtems_sparse_disk;<br>
+<br>
+typedef void (*rtems_sparse_disk_delete_hdlr)(rtems_sparse_disk *sparse_disk);<br>
+<br>
+<br>
+<br>
+/**<br>
+ * @brief Allocates a sparse disk.<br>
+ *<br>
+ * The block size will be @a block_size.<br>
+ * The disk storage will be allocated. The number of actually<br>
+ * allocated blocks will be @a blocks_allocated.<br>
+ * The disk will get allocated to the address pointed to by<br>
+ * @a sparse_disk<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Successful operation.<br>
+ * @retval RTEMS_INVALID_NUMBER Block size or block count is not positive.<br>
+ * @retval RTEMS_INVALID_ADDRESS Invalid sparse disk address.<br>
+ * @retval RTEMS_NO_MEMORY Not enough memory.<br>
+ */<br>
+rtems_status_code rtems_sparse_disk_create(<br>
+  uint32_t            block_size,<br>
+  rtems_blkdev_bnum   blocks_allocated,<br>
+  rtems_sparse_disk **sparse_disk<br>
+  );<br>
+<br>
+/**<br>
+ * @brief Deallocates a sparse disk.<br>
+ *<br>
+ * A disk created with rtems_sparse_disk_create() and pointed to<br>
+ * by @a sparse_disk will get deallocated<br>
+ */<br>
+void rtems_sparse_disk_delete(<br>
+  rtems_sparse_disk *sparse_disk<br>
+ );<br>
+<br>
+<br>
+<br>
+<br></blockquote><div>delete extra blanks.<br> <br></div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+/**<br>
+ * @brief Initializes and registers a sparse disk.<br>
+ *<br>
+ * Registers a device node with disk name path @a device_file_name.<br>
+ * Initialization and registration will be done with the structure<br>
+ * pointed to by @a sparse_disk.<br>
+ * The block size will be @a block_size. The block count will be<br>
+ * @a block_count. The number of actually allocated blocks will<br>
+ * be @a blocks_allocated.<br>
+ * The data in the allocated blocks will get initialized with @a fill_pattern.<br>
+ * @a sparse_disk_delete is a pointer to a method to be called<br>
+ * for deleting the sparse disk. If the sparse disk was allocated<br>
+ * with method rtems_sparse_disk_create() you can pass rtems_sparse_disk_delete().<br>
+ * Alternatively you can pass your own delete method.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Successful operation.<br>
+ * @retval RTEMS_INVALID_NUMBER Block size or block count is not positive.<br>
+ * @retval RTEMS_INVALID_ADDRESS Invalid sparse disk address.<br>
+ * @retval RTEMS_TOO_MANY Can not create semaphore<br>
+ * @retval RTEMS_UNSATISFIED Cannot create generic device node.<br>
+ */<br>
+rtems_status_code rtems_sparse_disk_register(<br>
+  const char                    *device_file_name,<br>
+  rtems_sparse_disk             *sparse_disk,<br>
+  uint32_t                       block_size,<br>
+  rtems_blkdev_bnum              block_count,<br>
+  rtems_blkdev_bnum              blocks_allocated,<br>
+  rtems_sparse_disk_delete_hdlr  sparse_disk_delete,<br>
+  uint8_t                        fill_pattern<br>
+);<br>
+<br>
+<br>
+/** @} */<br>
+<br>
+#ifdef __cplusplus<br>
+}<br>
+#endif /* __cplusplus */<br>
+<br>
+#endif /* SPARSE_DISK_H */<br>
diff --git a/cpukit/libblock/src/sparse-disk.c b/cpukit/libblock/src/sparse-disk.c<br>
new file mode 100644<br>
index 0000000..f6038e9<br>
--- /dev/null<br>
+++ b/cpukit/libblock/src/sparse-disk.c<br>
@@ -0,0 +1,372 @@<br>
+/**<br>
+ * @file<br>
+ *<br>
+ * @ingroup rtems_sparse_disk<br>
+ *<br>
+ * @brief Sparse disk block device implementation.<br>
+ */<br>
+<br>
+/*<br>
+ * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.<br>
+ *<br>
+ *  embedded brains GmbH<br>
+ *  Obere Lagerstr. 30<br>
+ *  82178 Puchheim<br>
+ *  Germany<br>
+ *  <<a href="mailto:rtems@embedded-brains.de">rtems@embedded-brains.de</a>><br>
+ *<br>
+ * The license and distribution terms for this file may be<br>
+ * found in the file LICENSE in this distribution or at<br>
+ * <a href="http://www.rtems.com/license/LICENSE" target="_blank">http://www.rtems.com/license/LICENSE</a>.<br>
+ */<br>
+<br>
+#include <stdlib.h><br>
+#include <errno.h><br>
+#include <string.h><br>
+<br>
+#include <rtems.h><br>
+#include <rtems/blkdev.h><br>
+#include <rtems/fatal.h><br>
+<br>
+#include "rtems/sparse-disk.h"<br>
+<br>
+<br>
+/*<br>
+ * Allocate RAM for sparse disk<br>
+ */<br>
+static rtems_sparse_disk*<br>
+ sparse_disk_allocate(<br>
+  const uint32_t block_size,<br>
+  const rtems_blkdev_bnum blocks_allocated<br>
+)<br>
+{<br>
+  size_t const key_table_size = blocks_allocated * sizeof(rtems_sparse_disk_key);<br>
+  size_t const data_size = blocks_allocated * block_size;<br>
+  size_t const alloc_size = sizeof(rtems_sparse_disk) + key_table_size + data_size;<br>
+<br>
+  uint8_t* data = malloc(alloc_size);<br>
+  rtems_sparse_disk *const sd = (rtems_sparse_disk *) data;<br></blockquote><div>why not just allocate directly into sd? i don't see a reason for the extra variable 'data' here. <br></div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

+<br>
+  if (data == NULL) {<br>
+    return NULL;<br>
+  }<br>
+<br>
+  return sd;<br>
+}<br>
+<br>
+/*<br>
+ * Initialize sparse disk data<br>
+ */<br>
+static rtems_status_code<br>
+ sparse_disk_initialize (rtems_sparse_disk* sd,<br>
+                         const uint32_t block_size,<br>
+                         const rtems_blkdev_bnum blocks_allocated,<br>
+                         const rtems_sparse_disk_delete_hdlr sparse_disk_delete,<br>
+                         const uint8_t fill_pattern)<br>
+{<br>
+  rtems_status_code sc;<br>
+  size_t i;<br></blockquote><div>why size_t?<br> <br></div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+  if (NULL == sd)<br>
+    return RTEMS_INVALID_ADDRESS;<br>
+<br>
+  uint8_t *data = (uint8_t *) sd;<br></blockquote><div>again why the extra variable? <br></div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+  size_t const key_table_size = blocks_allocated * sizeof(rtems_sparse_disk_key);<br>
+  size_t const data_size = blocks_allocated * block_size;<br>
+<br>
+  memset(data, 0, sizeof(rtems_sparse_disk) + key_table_size);<br>
+<br>
+  sd->fill_pattern = fill_pattern;<br>
+  memset((uint8_t*)(data + sizeof(rtems_sparse_disk) + key_table_size), sd->fill_pattern, data_size);<br>
+<br>
+<br>
+  sd->delete_hdlr = sparse_disk_delete;<br>
+<br>
+  sc = rtems_semaphore_create(<br>
+    rtems_build_name('S', 'P', 'A', 'R'),<br>
+    1,<br>
+    RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY,<br>
+    0,<br>
+    &sd->mutex<br>
+  );<br></blockquote><div>This semaphore should be accounted in application configuration requirements, either explicitly by applications that use the rtems_sparse_disk, or with some macro that detects it..<br> </div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

+  if (sc != RTEMS_SUCCESSFUL) {<br>
+    return sc;<br>
+  }<br>
+<br>
+  data += sizeof(rtems_sparse_disk);<br>
+<br>
+  sd->blocks_allocated = blocks_allocated;<br>
+  sd->key_table = (rtems_sparse_disk_key *) data;<br>
+<br>
+  data += key_table_size;<br>
+<br>
+  for (i = 0; i < blocks_allocated; ++i, data += block_size) {<br>
+    sd->key_table [i].data = data;<br>
+  }<br>
+  sd->block_size = block_size;<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+<br>
+<br>
+/*<br>
+ * Block comparison<br>
+ */<br>
+static int<br>
+ sparse_disk_compare(const void *aa, const void *bb)<br>
+{<br>
+  const rtems_sparse_disk_key *a = aa;<br>
+  const rtems_sparse_disk_key *b = bb;<br>
+<br>
+  if (a->block < b->block) {<br>
+    return -1;<br>
+  } else if (a->block == b->block) {<br>
+    return 0;<br>
+  } else {<br>
+    return 1;<br>
+  }<br>
+}<br>
+<br>
+static rtems_sparse_disk_key *<br>
+ sparse_disk_get_new_block(<br>
+  rtems_sparse_disk *sparse_disk,<br>
+  const rtems_blkdev_bnum block<br>
+)<br>
+{<br>
+  rtems_sparse_disk_key *key;<br>
+<br>
+  if (sparse_disk->used_count < sparse_disk->blocks_allocated) {<br>
+    key = &sparse_disk->key_table [sparse_disk->used_count];<br>
+    key->block = block;<br>
+    ++sparse_disk->used_count;<br>
+    qsort(sparse_disk->key_table, sparse_disk->used_count, sizeof(rtems_sparse_disk_key), sparse_disk_compare);<br></blockquote><div>is quicksort every time OK here? is a sorted array the best structure to use, or should a tree be used? Just wondering out loud.<br>
<br></div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+  } else<br>
+    return NULL;<br>
+<br>
+  return key;<br>
+}<br>
+<br>
+static int<br>
+ sparse_disk_read_block(<br>
+  const rtems_sparse_disk *sparse_disk,<br>
+  const rtems_blkdev_bnum block,<br>
+  uint8_t *buffer,<br>
+  const size_t buffer_size<br>
+)<br>
+{<br>
+  rtems_sparse_disk_key *key;<br>
+  rtems_sparse_disk_key block_key = {<br>
+    .block = block,<br>
+    .data = NULL<br>
+  };<br>
+  size_t bytes_to_copy = sparse_disk->block_size;<br>
+<br>
+  if (buffer_size < bytes_to_copy)<br>
+    bytes_to_copy = buffer_size;<br>
+<br>
+  key = bsearch(<br>
+    &block_key,<br>
+    sparse_disk->key_table,<br>
+    sparse_disk->used_count,<br>
+    sizeof(rtems_sparse_disk_key),<br>
+    sparse_disk_compare<br>
+  );<br>
+<br>
+  if (NULL != key)<br>
+    memcpy (buffer, key->data, bytes_to_copy);<br>
+  else<br>
+    memset (buffer, sparse_disk->fill_pattern, buffer_size);<br></blockquote><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+  return bytes_to_copy;<br>
+}<br>
+<br>
+static int<br>
+ sparse_disk_write_block(<br>
+  rtems_sparse_disk *sparse_disk,<br>
+  const rtems_blkdev_bnum block,<br>
+  const uint8_t *buffer,<br>
+  const size_t buffer_size<br>
+)<br>
+{<br>
+  unsigned int i;<br>
+  bool block_needs_writing = false;<br>
+  rtems_sparse_disk_key *key;<br>
+  rtems_sparse_disk_key block_key = {<br>
+    .block = block,<br>
+    .data = NULL<br>
+  };<br>
+  size_t bytes_to_copy = sparse_disk->block_size;<br>
+<br>
+  if (buffer_size < bytes_to_copy)<br>
+    bytes_to_copy = buffer_size;<br>
+<br>
+  /* we only need to write the block if it is different from the fill pattern.<br>
+   * If the read method does not find a block it will deliver the fill pattern anyway.<br>
+   */<br>
+<br>
+  key = bsearch(<br>
+    &block_key,<br>
+    sparse_disk->key_table,<br>
+    sparse_disk->used_count,<br>
+    sizeof(rtems_sparse_disk_key),<br>
+    sparse_disk_compare<br>
+  );<br>
+<br>
+  if (NULL == key) {<br>
+    for (i = 0; (! block_needs_writing) && (i < bytes_to_copy); ++i) {<br>
+      if (buffer[i] != sparse_disk->fill_pattern)<br>
+        block_needs_writing = true;<br>
+    }<br>
+    if (block_needs_writing) {<br>
+      key = sparse_disk_get_new_block (sparse_disk, block);<br>
+    }<br>
+  }<br>
+  if (NULL != key)<br>
+    memcpy (key->data, buffer, bytes_to_copy);<br>
+  else if (block_needs_writing)<br>
+    return -1;<br>
+<br>
+  return bytes_to_copy;<br>
+}<br>
+<br>
+/*<br>
+ * Read/write handling<br>
+ */<br>
+static int<br>
+ sparse_disk_read_write(<br>
+  rtems_sparse_disk *sparse_disk,<br>
+  rtems_blkdev_request *req,<br>
+  const bool read)<br>
+{<br>
+  int rv = 0;<br>
+  uint32_t req_buffer;<br>
+  rtems_blkdev_sg_buffer *scatter_gather;<br>
+  rtems_blkdev_bnum block;<br>
+  uint8_t *buff;<br>
+  size_t buff_size;<br>
+  unsigned int bytes_handled;<br>
+<br>
+  rtems_semaphore_obtain(sparse_disk->mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);<br>
+<br>
+  for (req_buffer = 0; (0 <= rv) && (req_buffer < req->bufnum); ++req_buffer) {<br>
+    scatter_gather = &req->bufs [req_buffer];<br>
+<br>
+    bytes_handled = 0;<br>
+    buff = (uint8_t*)scatter_gather->buffer;<br>
+    block = scatter_gather->block;<br>
+    buff_size = scatter_gather->length;<br>
+<br>
+    while ((0 <= rv) && (0 < buff_size))<br>
+    {<br>
+      if (read)<br>
+        rv = sparse_disk_read_block (sparse_disk, block, &buff[bytes_handled], buff_size);<br>
+      else<br>
+        rv = sparse_disk_write_block (sparse_disk, block, &buff[bytes_handled], buff_size);<br>
+      ++block;<br>
+      bytes_handled += rv;<br>
+      buff_size -= rv;<br>
+    }<br>
+  }<br>
+<br>
+  rtems_semaphore_release(sparse_disk->mutex);<br>
+<br>
+  if (0 > rv)<br>
+    rtems_blkdev_request_done (req, RTEMS_IO_ERROR);<br>
+  else<br>
+    rtems_blkdev_request_done (req, RTEMS_SUCCESSFUL);<br>
+<br>
+  return 0;<br>
+}<br>
+<br>
+/*<br>
+ * ioctl handler to be passed to the block device handler<br>
+ */<br>
+static int<br>
+ sparse_disk_ioctl(rtems_disk_device *dd, uint32_t req, void *argp)<br>
+{<br>
+  rtems_status_code sc;<br>
+  rtems_sparse_disk *sd = rtems_disk_get_driver_data(dd);<br>
+<br>
+  if (RTEMS_BLKIO_REQUEST == req) {<br>
+    rtems_blkdev_request *r = argp;<br>
+<br>
+    switch (r->req) {<br>
+      case RTEMS_BLKDEV_REQ_READ:<br>
+      case RTEMS_BLKDEV_REQ_WRITE:<br>
+        return sparse_disk_read_write(sd, r, r->req == RTEMS_BLKDEV_REQ_READ);<br>
+      default:<br>
+        break;<br>
+    }<br>
+  } else if (RTEMS_BLKIO_DELETED == req) {<br>
+    sc = rtems_semaphore_delete(sd->mutex);<br>
+    if (RTEMS_SUCCESSFUL != sc)<br>
+      rtems_fatal_error_occurred(0xdeadbeef);<br>
+    sd->mutex = RTEMS_ID_NONE;<br>
+    if (NULL != sd->delete_hdlr)<br>
+      ((rtems_sparse_disk_delete_hdlr)sd->delete_hdlr)(sd);<br>
+    return 0;<br>
+  }else {<br>
+    return rtems_blkdev_ioctl(dd, req, argp);<br>
+  }<br>
+<br>
+  errno = EINVAL;<br>
+  return -1;<br>
+}<br>
+<br>
+/*<br>
+ * De-allocate the sparse disk<br>
+ */<br>
+void<br>
+ rtems_sparse_disk_delete(rtems_sparse_disk *sd)<br>
+{<br>
+  if (NULL != sd)<br>
+    free(sd);<br>
+}<br>
+<br>
+rtems_status_code rtems_sparse_disk_create(<br>
+  const uint32_t block_size,<br>
+  const rtems_blkdev_bnum blocks_allocated,<br>
+  rtems_sparse_disk **sparse_disk<br>
+)<br>
+{<br>
+  *sparse_disk = sparse_disk_allocate(<br>
+    block_size,<br>
+    blocks_allocated<br>
+  );<br>
+  if (NULL == *sparse_disk)<br>
+    return RTEMS_NO_MEMORY;<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+rtems_status_code rtems_sparse_disk_register(<br>
+  const char *device_file_name,<br>
+  rtems_sparse_disk *sparse_disk,<br>
+  const uint32_t block_size,<br>
+  const rtems_blkdev_bnum block_count,<br>
+  const rtems_blkdev_bnum blocks_allocated,<br>
+  const rtems_sparse_disk_delete_hdlr sparse_disk_delete,<br>
+  const uint8_t fill_pattern<br>
+)<br>
+{<br>
+  rtems_status_code sc;<br>
+<br>
+    sc = sparse_disk_initialize(<br>
+    sparse_disk,<br>
+    block_size,<br>
+    blocks_allocated,<br>
+    sparse_disk_delete,<br>
+    fill_pattern<br>
+  );<br>
+  if (RTEMS_SUCCESSFUL != sc) {<br>
+    return sc;<br>
+  }<br>
+<br>
+  sc = rtems_blkdev_create(<br>
+    device_file_name,<br>
+    block_size,<br>
+    block_count,<br>
+    sparse_disk_ioctl,<br>
+    sparse_disk<br>
+  );<br>
+  return sc;<br>
+}<br>
diff --git a/cpukit/<a href="http://preinstall.am" target="_blank">preinstall.am</a> b/cpukit/<a href="http://preinstall.am" target="_blank">preinstall.am</a><br>
index f6d24bb..26b90ec 100644<br>
--- a/cpukit/<a href="http://preinstall.am" target="_blank">preinstall.am</a><br>
+++ b/cpukit/<a href="http://preinstall.am" target="_blank">preinstall.am</a><br>
@@ -272,6 +272,10 @@ $(PROJECT_INCLUDE)/rtems/nvdisk-sram.h: libblock/include/rtems/nvdisk-sram.h $(P<br>
        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/nvdisk-sram.h<br>
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/nvdisk-sram.h<br>
<br>
+$(PROJECT_INCLUDE)/rtems/sparse-disk.h: libblock/include/rtems/sparse-disk.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)<br>
+       $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/sparse-disk.h<br>
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/sparse-disk.h<br>
+<br>
 $(PROJECT_INCLUDE)/rtems/ide_part_table.h: libblock/include/rtems/ide_part_table.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)<br>
        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/ide_part_table.h<br>
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/ide_part_table.h<br>
diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am<br>
index afd8605..1197742 100644<br>
--- a/testsuites/libtests/Makefile.am<br>
+++ b/testsuites/libtests/Makefile.am<br>
@@ -1,6 +1,7 @@<br>
 ACLOCAL_AMFLAGS = -I ../aclocal<br>
<br>
 SUBDIRS = POSIX<br>
+SUBDIRS += sparsedisk01<br>
 SUBDIRS += block16<br>
 SUBDIRS += block15<br>
 SUBDIRS += block14<br>
diff --git a/testsuites/libtests/<a href="http://configure.ac" target="_blank">configure.ac</a> b/testsuites/libtests/<a href="http://configure.ac" target="_blank">configure.ac</a><br>
index 83e22ed..b8be927 100644<br>
--- a/testsuites/libtests/<a href="http://configure.ac" target="_blank">configure.ac</a><br>
+++ b/testsuites/libtests/<a href="http://configure.ac" target="_blank">configure.ac</a><br>
@@ -43,6 +43,7 @@ AM_CONDITIONAL(HAS_POSIX,test x"${rtems_cv_RTEMS_POSIX_API}" = x"yes")<br>
<br>
 # Explicitly list all Makefiles here<br>
 AC_CONFIG_FILES([Makefile<br>
+sparsedisk01/Makefile<br>
 block16/Makefile<br>
 mghttpd01/Makefile<br>
 block15/Makefile<br>
diff --git a/testsuites/libtests/sparsedisk01/Makefile.am b/testsuites/libtests/sparsedisk01/Makefile.am<br>
new file mode 100644<br>
index 0000000..3a836c8<br>
--- /dev/null<br>
+++ b/testsuites/libtests/sparsedisk01/Makefile.am<br>
@@ -0,0 +1,19 @@<br>
+rtems_tests_PROGRAMS = sparsedisk01<br>
+sparsedisk01_SOURCES = init.c<br>
+<br>
+dist_rtems_tests_DATA = sparsedisk01.scn sparsedisk01.doc<br>
+<br>
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg<br>
+include $(top_srcdir)/../automake/<a href="http://compile.am" target="_blank">compile.am</a><br>
+include $(top_srcdir)/../automake/<a href="http://leaf.am" target="_blank">leaf.am</a><br>
+<br>
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include<br>
+<br>
+LINK_OBJS = $(sparsedisk01_OBJECTS)<br>
+LINK_LIBS = $(sparsedisk01_LDLIBS)<br>
+<br>
+sparsedisk01$(EXEEXT): $(sparsedisk01_OBJECTS) $(sparsedisk01_DEPENDENCIES)<br>
+       @rm -f sparsedisk01$(EXEEXT)<br>
+       $(make-exe)<br>
+<br>
+include $(top_srcdir)/../automake/<a href="http://local.am" target="_blank">local.am</a><br>
diff --git a/testsuites/libtests/sparsedisk01/init.c b/testsuites/libtests/sparsedisk01/init.c<br>
new file mode 100644<br>
index 0000000..a76738f<br>
--- /dev/null<br>
+++ b/testsuites/libtests/sparsedisk01/init.c<br>
@@ -0,0 +1,439 @@<br>
+/*<br>
+ * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.<br>
+ *<br>
+ *  embedded brains GmbH<br>
+ *  Obere Lagerstr. 30<br>
+ *  82178 Puchheim<br>
+ *  Germany<br>
+ *  <<a href="mailto:rtems@embedded-brains.de">rtems@embedded-brains.de</a>><br>
+ *<br>
+ * The license and distribution terms for this file may be<br>
+ * found in the file LICENSE in this distribution or at<br>
+ * <a href="http://www.rtems.com/license/LICENSE" target="_blank">http://www.rtems.com/license/LICENSE</a>.<br>
+ */<br>
+<br>
+#ifdef HAVE_CONFIG_H<br>
+  #include "config.h"<br>
+#endif<br>
+<br>
+#include <fcntl.h><br>
+#include <rtems/blkdev.h><br>
+#include "rtems/sparse-disk.h"<br>
+<br>
+#include "tmacros.h"<br>
+<br>
+/* Number of bytes for test pattern within a sparse disk container */<br>
+#define STATIC_PATTERN_SIZE           4096<br>
+/* Block size used for the sparse disk in a sparse disk container */<br>
+#define STATIC_BLOCK_SIZE             4096<br>
+/* Number of block allocated for the sparse disk in a sparse disk container */<br>
+#define STATIC_ALLOCATED_BLOCK_COUNT     1<br>
+/* Blocks simulated by the sparse disk in a disk container */<br>
+#define STATIC_SIMULATED_BLOCK_COUNT  4096<br>
+<br>
+/*<br>
+ * Container which cotains a sparse disk + memory for key table and data as would get<br>
+ * allocated by rtems_sparse_disk_create() + memory for a memory test pattern<br>
+ * By using this container white box testing of a sparse disk becomes possible<br>
+ */<br>
+typedef struct {<br>
+  rtems_sparse_disk       sparse_disk;<br>
+  rtems_sparse_disk_key   keytable[STATIC_ALLOCATED_BLOCK_COUNT];<br>
+  uint8_t                 data[STATIC_BLOCK_SIZE * STATIC_ALLOCATED_BLOCK_COUNT];<br>
+  uint8_t                 pattern[STATIC_PATTERN_SIZE];<br>
+} sparse_disk_container;<br>
+<br>
+/*<br>
+ * Black box test the disk parameters of a sparse disk<br>
+ */<br>
+static void<br>
+ test_disk_params(<br>
+   const int file_descriptor,<br>
+   const uint32_t block_size,<br>
+   const uint32_t media_block_size,<br>
+   const rtems_blkdev_bnum block_number<br>
+)<br>
+{<br>
+  int rv;<br>
+  uint32_t value = 0;<br>
+  rtems_disk_device *fd_dd = NULL;<br>
+  rtems_blkdev_bnum block_count = 0;<br>
+<br>
+  rv = rtems_disk_fd_get_media_block_size(file_descriptor, &value);<br>
+  rtems_test_assert(0 == rv);<br>
+  rtems_test_assert(media_block_size == value);<br>
+<br>
+  value = 0;<br>
+  rv = rtems_disk_fd_get_block_size(file_descriptor, &value);<br>
+  rtems_test_assert(0 == rv);<br>
+  rtems_test_assert(block_size == value);<br>
+<br>
+  block_count = 0;<br>
+  rv = rtems_disk_fd_get_block_count(file_descriptor, &block_count);<br>
+  rtems_test_assert(0 == rv);<br>
+  rtems_test_assert(block_number == block_count);<br>
+<br>
+  rv = rtems_disk_fd_get_disk_device(file_descriptor, &fd_dd);<br>
+  rtems_test_assert(0 == rv);<br>
+  rtems_test_assert(NULL != fd_dd);<br>
+}<br>
+<br>
+/*<br>
+ * Verify that writing to a sparse disk delivers expected results<br>
+ */<br>
+static void<br>
+ test_writing(<br>
+  const int file_descriptor,<br>
+  const uint32_t block_size,<br>
+  const rtems_blkdev_bnum blocks_allocated<br>
+)<br>
+{<br>
+  int rv;<br>
+  rtems_blkdev_bnum block_count = 0;<br>
+  unsigned int byte_count;<br>
+  off_t file_pos;<br>
+  uint8_t buff[block_size];<br>
+<br>
+  // Write a pattern to all allocated blocks<br>
+  for (block_count = 0; block_count < blocks_allocated; block_count++) {<br>
+    file_pos = (off_t)block_count * block_size;<br>
+    rv = lseek(file_descriptor, file_pos, SEEK_SET);<br>
+    rtems_test_assert(file_pos == rv);<br>
+<br>
+    rv = read(file_descriptor, buff, block_size);<br>
+    rtems_test_assert(block_size == rv);<br>
+<br>
+    for (byte_count = 0; byte_count < (block_size / sizeof(byte_count)); byte_count++) {<br>
+      memcpy (buff + (byte_count * sizeof(byte_count)), &byte_count, sizeof(byte_count));<br>
+    }<br>
+<br>
+    rv = lseek(file_descriptor, file_pos, SEEK_SET);<br>
+    rtems_test_assert(file_pos == rv);<br>
+<br>
+    rv = write(file_descriptor, buff, block_size);<br>
+    rtems_test_assert(block_size == rv);<br>
+  }<br>
+}<br>
+<br>
+/*<br>
+ * Verify that black box reading for a sparse disk delivers expected results<br>
+ */<br>
+static void<br>
+ test_reading(<br>
+  const int file_descriptor,<br>
+  const uint32_t block_size,<br>
+  const rtems_blkdev_bnum blocks_allocated,<br>
+  const uint8_t fill_pattern<br>
+)<br>
+{<br>
+  int rv;<br>
+  rtems_blkdev_bnum block_count = 0;<br>
+  unsigned int byte_count;<br>
+  off_t file_pos;<br>
+  uint8_t buff[block_size];<br>
+  uint32_t value = 0;<br>
+<br>
+  rv = fsync(file_descriptor);<br>
+  rtems_test_assert(0 == rv);<br>
+<br>
+<br>
+  // Read back the patterns<br>
+  for (block_count = 0; block_count < blocks_allocated; block_count++) {<br>
+    file_pos = (off_t)block_count * block_size;<br>
+    value = lseek (file_descriptor, file_pos,  SEEK_SET);<br>
+    rtems_test_assert(file_pos == value);<br>
+<br>
+    rv = read (file_descriptor, &buff, block_size);<br>
+    rtems_test_assert(block_size <= rv);<br>
+<br>
+    for (byte_count = 0; byte_count < (block_size / sizeof(byte_count)); byte_count++) {<br>
+      rv = memcmp(buff + (byte_count * sizeof(byte_count)), &byte_count, sizeof(byte_count));<br>
+      rtems_test_assert(0 == rv);<br>
+    }<br>
+  }<br>
+  // Try to read from unallocated block<br>
+  file_pos = (off_t)block_count * block_size;<br>
+  rv = lseek(file_descriptor, file_pos, SEEK_SET);<br>
+  rtems_test_assert(file_pos == rv);<br>
+<br>
+  rv = read(file_descriptor, buff, block_size);<br>
+  rtems_test_assert(block_size == rv);<br>
+<br>
+  for (byte_count = 0; byte_count < block_size; ++byte_count)<br>
+    rtems_test_assert(fill_pattern == buff[byte_count]);<br>
+}<br>
+<br>
+/*<br>
+ * Do black box io testing on a sparse disk<br>
+ */<br>
+static void<br>
+ test_device_io (const char *device_name,<br>
+                 const uint32_t block_size,<br>
+                 const uint32_t media_block_size,<br>
+                 const rtems_blkdev_bnum block_number,<br>
+                 const rtems_blkdev_bnum blocks_allocated,<br>
+                 const uint8_t fill_pattern)<br>
+{<br>
+  int rv;<br>
+  int file_descriptor;<br>
+<br>
+  file_descriptor = open (device_name, O_RDWR);<br>
+  rtems_test_assert(0 <= file_descriptor);<br>
+<br>
+  test_disk_params (<br>
+    file_descriptor,<br>
+    block_size,<br>
+    media_block_size,<br>
+    block_number<br>
+  );<br>
+<br>
+<br>
+  test_writing (<br>
+    file_descriptor,<br>
+    block_size,<br>
+    blocks_allocated<br>
+  );<br>
+<br>
+  test_reading(<br>
+    file_descriptor,<br>
+    block_size,<br>
+    blocks_allocated,<br>
+    fill_pattern<br>
+  );<br>
+<br>
+  rv = close (file_descriptor);<br>
+  rtems_test_assert(0 == rv);<br>
+}<br>
+<br>
+/*<br>
+ * In white box testing verify the key table of the sparse disk is correct<br>
+ */<br>
+static void<br>
+ test_static_key_table(<br>
+  const sparse_disk_container *disk_container,<br>
+  const  rtems_blkdev_bnum blocks_allocated,<br>
+  const uint32_t block_size<br>
+)<br>
+{<br>
+  unsigned int i;<br>
+<br>
+  for (i = 0; i < blocks_allocated; ++i)<br>
+  {<br>
+    rtems_test_assert(i == disk_container->keytable[i].block);<br>
+    rtems_test_assert(&disk_container->data[i * block_size] == disk_container->keytable[i].data);<br>
+  }<br>
+<br>
+}<br>
+<br>
+/*<br>
+ * Verify the test pattern used in white box testing is as expected<br>
+ */<br>
+static void<br>
+ test_static_pattern(<br>
+  const unsigned int pattern_size,<br>
+  const uint8_t *pattern<br>
+)<br>
+{<br>
+  unsigned int i;<br>
+<br>
+  for (i = 0; i < pattern_size; ++i)<br>
+    rtems_test_assert(((uint8_t)(pattern_size -1 - i)) == pattern[i]);<br>
+}<br>
+<br>
+/*<br>
+ * Read write testing with a statically allocated disk. Thus white box testing can be done<br>
+ */<br>
+static void<br>
+ test_with_whitebox(const char *device_name)<br>
+{<br>
+  rtems_status_code sc;<br>
+  int rv;<br>
+  unsigned int i;<br>
+  sparse_disk_container disk_container;<br>
+  int file_descriptor;<br>
+  rtems_blkdev_bnum block_count = 0;<br>
+  unsigned int byte_count;<br>
+  uint8_t fill_pattern = 0;<br>
+<br>
+  memset (&disk_container.data, 0, sizeof(disk_container.data));<br>
+  memset (&disk_container.keytable, 0, sizeof(disk_container.keytable));<br>
+  for (i = 0; i < STATIC_PATTERN_SIZE; ++i)<br>
+    disk_container.pattern[i] = (uint8_t)(STATIC_PATTERN_SIZE -1 - i);<br>
+<br>
+  sc = rtems_sparse_disk_register(<br>
+    "/dev/sda1",<br>
+    &disk_container.sparse_disk,<br>
+    STATIC_BLOCK_SIZE,<br>
+    STATIC_SIMULATED_BLOCK_COUNT,<br>
+    STATIC_ALLOCATED_BLOCK_COUNT,<br>
+    NULL,<br>
+    fill_pattern<br>
+  );<br>
+  rtems_test_assert(RTEMS_SUCCESSFUL == sc);<br>
+<br>
+  test_static_key_table(<br>
+    &disk_container,<br>
+    STATIC_ALLOCATED_BLOCK_COUNT,<br>
+    STATIC_BLOCK_SIZE<br>
+   );<br>
+<br>
+  for (i = 0; i < (STATIC_BLOCK_SIZE * STATIC_ALLOCATED_BLOCK_COUNT); ++i)<br>
+    rtems_test_assert(0 == disk_container.data[i]);<br>
+<br>
+  test_static_pattern(<br>
+    STATIC_PATTERN_SIZE,<br>
+    &disk_container.pattern[0]<br>
+  );<br>
+<br>
+  file_descriptor = open (device_name, O_RDWR);<br>
+  rtems_test_assert(0 <= file_descriptor);<br>
+<br>
+  test_disk_params (<br>
+    file_descriptor,<br>
+    STATIC_BLOCK_SIZE,<br>
+    STATIC_BLOCK_SIZE,<br>
+    STATIC_SIMULATED_BLOCK_COUNT<br>
+  );<br>
+<br>
+  test_writing (<br>
+    file_descriptor,<br>
+    STATIC_BLOCK_SIZE,<br>
+    STATIC_ALLOCATED_BLOCK_COUNT<br>
+  );<br>
+<br>
+  test_reading(<br>
+    file_descriptor,<br>
+    STATIC_BLOCK_SIZE,<br>
+    STATIC_ALLOCATED_BLOCK_COUNT,<br>
+    fill_pattern<br>
+  );<br>
+<br>
+  rv = close (file_descriptor);<br>
+  rtems_test_assert(0 == rv);<br>
+<br>
+  test_static_key_table(<br>
+    &disk_container,<br>
+    STATIC_ALLOCATED_BLOCK_COUNT,<br>
+    STATIC_BLOCK_SIZE<br>
+   );<br>
+<br>
+  for (block_count = 0; block_count < STATIC_ALLOCATED_BLOCK_COUNT; block_count++) {<br>
+    for (byte_count = 0; byte_count < (STATIC_BLOCK_SIZE / sizeof(byte_count)); byte_count++) {<br>
+      rv = memcmp(&disk_container.data[byte_count * sizeof(byte_count)], &byte_count, sizeof(byte_count));<br>
+      rtems_test_assert(0 == rv);<br>
+    }<br>
+  }<br>
+<br>
+  test_static_pattern(<br>
+    STATIC_PATTERN_SIZE,<br>
+    &disk_container.pattern[0]<br>
+  );<br>
+<br>
+}<br>
+<br>
+<br>
+/*<br>
+ * The test sequence<br>
+ */<br>
+static<br>
+ void test(void)<br>
+{<br>
+  rtems_status_code sc;<br>
+  int rv;<br>
+  char device_name[] = "/dev/sda1";<br>
+  uint32_t block_size;<br>
+  rtems_blkdev_bnum block_number;<br>
+  rtems_blkdev_bnum blocks_allocated;<br>
+  rtems_sparse_disk *sparse_disk_ptr = NULL;<br>
+  int file_descriptor;<br>
+  uint8_t fill_pattern = 0;<br>
+<br>
+  sc = rtems_disk_io_initialize();<br>
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);<br>
+<br>
+  block_size = 512;<br>
+  block_number = 4 * 2 * 1024;<br>
+  blocks_allocated = 8;<br>
+  sc = rtems_sparse_disk_create(<br>
+    block_size,<br>
+    blocks_allocated,<br>
+    &sparse_disk_ptr<br>
+  );<br>
+  rtems_test_assert(RTEMS_SUCCESSFUL == sc);<br>
+  sc = rtems_sparse_disk_register(<br>
+    "/dev/sda1",<br>
+    sparse_disk_ptr,<br>
+    block_size,<br>
+    block_number,<br>
+    blocks_allocated,<br>
+    rtems_sparse_disk_delete,<br>
+    fill_pattern<br>
+  );<br>
+  rtems_test_assert(RTEMS_SUCCESSFUL == sc);<br>
+<br>
+  // Test reading and writing with sector size 512 and 8 such sectors allocated. Block size will default to 512<br>
+  test_device_io (<br>
+    device_name,<br>
+    block_size,<br>
+    block_size,<br>
+    block_number,<br>
+    blocks_allocated,<br>
+    fill_pattern<br>
+  );<br>
+<br>
+  file_descriptor = open (device_name, O_RDWR);<br>
+  rtems_test_assert(0 <= file_descriptor);<br>
+<br>
+  rv = rtems_disk_fd_set_block_size(file_descriptor, blocks_allocated * block_size);<br>
+  rtems_test_assert(0 == rv);<br>
+<br>
+  rv = close (file_descriptor);<br>
+  rtems_test_assert(0 == rv);<br>
+<br>
+  // Block size was increased to 4k. Thus all to allocated disk space corresponds to one block. Repeat the read write tests<br>
+  test_device_io (<br>
+    device_name,<br>
+    block_size * blocks_allocated,<br>
+    block_size,<br>
+    block_number,<br>
+    1,<br>
+    fill_pattern<br>
+  );<br>
+<br>
+  rv = unlink (device_name);<br>
+  rtems_test_assert(0 == rv);<br>
+<br>
+  // Do testing with a statically allocated disk. This permits white box testing<br>
+  test_with_whitebox(device_name);<br>
+<br>
+}<br>
+<br>
+static void Init(rtems_task_argument arg)<br>
+{<br>
+  (void) arg;<br>
+  puts("\n\n*** TEST sparsedisk01 ***");<br>
+<br>
+  test();<br>
+<br>
+  puts("*** END OF TEST sparsedisk01 ***");<br>
+<br>
+  rtems_test_exit(0);<br>
+}<br>
+<br>
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER<br>
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER<br>
+#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK<br>
+<br>
+#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM<br>
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 4<br>
+<br>
+#define CONFIGURE_UNLIMITED_OBJECTS<br>
+#define CONFIGURE_UNIFIED_WORK_AREAS<br>
+<br>
+#define CONFIGURE_INIT_TASK_STACK_SIZE (16 * 1024)<br>
+<br>
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE<br>
+<br>
+#define CONFIGURE_INIT<br>
+<br>
+#include <rtems/confdefs.h><br>
diff --git a/testsuites/libtests/sparsedisk01/sparsedisk01.doc b/testsuites/libtests/sparsedisk01/sparsedisk01.doc<br>
new file mode 100644<br>
index 0000000..e73746a<br>
--- /dev/null<br>
+++ b/testsuites/libtests/sparsedisk01/sparsedisk01.doc<br>
@@ -0,0 +1,11 @@<br>
+This file describes the directives and concepts tested by this test set.<br>
+<br>
+test set name: sparsedisk01<br>
+<br>
+directives:<br>
+<br>
+  TBD<br>
+<br>
+concepts:<br>
+<br>
+  TBD<br>
diff --git a/testsuites/libtests/sparsedisk01/sparsedisk01.scn b/testsuites/libtests/sparsedisk01/sparsedisk01.scn<br>
new file mode 100644<br>
index 0000000..e69de29<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.7.10.4<br>
<br>
_______________________________________________<br>
rtems-devel mailing list<br>
<a href="mailto:rtems-devel@rtems.org">rtems-devel@rtems.org</a><br>
<a href="http://www.rtems.org/mailman/listinfo/rtems-devel" target="_blank">http://www.rtems.org/mailman/listinfo/rtems-devel</a><br>
</font></span></blockquote></div><br></div>