示例#1
0
文件: fat.c 项目: kptran/rtems
int
fat_buf_release(fat_fs_info_t *fs_info)
{
    rtems_status_code sc = RTEMS_SUCCESSFUL;
    uint8_t           i;
    bool              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.dd,
                                     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;
}
示例#2
0
static rtems_task
bdbuf_test3_1_thread2(rtems_task_argument arg)
{
    rtems_status_code   rc;
    rtems_bdbuf_buffer *bd = NULL;

    WAIT_MAIN_SYNC(2);

    /*
     * Step 4:
     * In thread #2 call read/get(#M)
     * [We ask for block number #M - there is no such entry in AVL,
     * and all the lists are empty (ready, lru, modified), as a result
     * this thread blocks on 
     * rtems_bdbuf_wait(pool, &pool->waiting, &pool->wait_waiters)]
     */
    rc = rtems_bdbuf_get(test_dev, TEST_BLK_NUM_M, &bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }

    CONTINUE_MAIN(2);

    /*
     * Release buffer.
     */
    rc = rtems_bdbuf_release_modified(bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }
    THREAD_END();
}
示例#3
0
static rtems_task
bdbuf_test3_2_thread3(rtems_task_argument arg)
{
    rtems_status_code   rc;
    rtems_bdbuf_buffer *bd = NULL;

    WAIT_MAIN_SYNC(3);

    /*
     * Step 3:
     * In thread #3 call get(#N3)
     */
    rc = rtems_bdbuf_get(test_dd, TEST_BLK_NUM_N3, &bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }

    printk("Thread #3 DEBLOCK\n");

    CONTINUE_MAIN(3);
    
    rc = rtems_bdbuf_release_modified(bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }

    THREAD_END();
}
int
rtems_rfs_buffer_bdbuf_release (rtems_rfs_buffer* buffer,
                                bool              modified)
{
  rtems_status_code sc;
  int               rc = 0;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_RELEASE))
    printf ("rtems-rfs: bdbuf-release: block=%" PRIuPTR " bdbuf=%" PRIu32 " %s\n",
            ((intptr_t) buffer->user),
            buffer->block, modified ? "(modified)" : "");

  if (modified)
    sc = rtems_bdbuf_release_modified (buffer);
  else
    sc = rtems_bdbuf_release (buffer);

  if (sc != RTEMS_SUCCESSFUL)
  {
#if RTEMS_RFS_BUFFER_ERRORS
    printf ("rtems-rfs: buffer-release: bdbuf-%s: %s(%d)\n",
            modified ? "modified" : "not-modified",
            rtems_status_text (sc), sc);
#endif
    rc = EIO;
  }

  return rc;
}
static void
bdbuf_tests_task_0_test_7 (bdbuf_task_control* tc)
{
  rtems_status_code   sc;
  bool                passed;
  int                 i;
  rtems_bdbuf_buffer* bd;
  rtems_chain_control buffers;
  dev_t               device;

  /*
   * Set task control's passed to false to handle a timeout.
   */
  tc->passed = false;
  passed = true;

  /*
   * Clear any disk settings.
   */
  bdbuf_clear_disk_driver_watch (tc);
  bdbuf_set_disk_driver_action (tc, BDBUF_DISK_NOOP);

  device = rtems_filesystem_make_dev_t (tc->major, tc->minor);

  /*
   * Get the blocks 0 -> 4 and hold them.
   */
  rtems_chain_initialize_empty (&buffers);

  for (i = 0; (i < 5) && passed; i++)
  {
    bdbuf_test_printf ("%s: rtems_bdbuf_read[%d]: ", tc->name, i);
    sc = rtems_bdbuf_get (device, i, &bd);
    if (!bdbuf_test_print_sc (sc, true))
      passed = false;

    rtems_chain_append (&buffers, &bd->link);
  }

  for (i = 0; (i < 5) && passed; i++)
  {
    bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[%d]: ",
                       tc->name, i);
    bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers);
    passed = bdbuf_test_print_sc (rtems_bdbuf_release_modified (bd),
                                  true);
  }

  if (passed)
  {
    bdbuf_test_printf ("%s: rtems_bdbuf_syncdev[%d:%d]: ",
                       tc->name, i,
                       rtems_filesystem_dev_major_t (device),
                       rtems_filesystem_dev_minor_t (device));
    passed = bdbuf_test_print_sc (rtems_bdbuf_syncdev (device), true);
  }

  tc->passed = passed;
  tc->test = 0;
}
示例#6
0
static ssize_t rtems_blkdev_imfs_write(
  rtems_libio_t *iop,
  const void *buffer,
  size_t count
)
{
  int rv;
  rtems_blkdev_imfs_context *ctx = IMFS_generic_get_context_by_iop(iop);
  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) {
    iop->offset += count;
    rv = (ssize_t) count;
  } else {
    errno = EIO;
    rv = -1;
  }

  return rv;
}
void do_rel_mod(char task, rtems_bdbuf_buffer *bd)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;

  printk("%c: release modified\n", task);

  sc = rtems_bdbuf_release_modified(bd);
  ASSERT_SC(sc);

  printk("%c: release modified done\n", task);
}
/**
 * Read the block 5 from the disk modify it then release it modified.
 */
static void
bdbuf_tests_task_0_test_3 (bdbuf_task_control* tc)
{
  rtems_status_code   sc;
  bool                passed;
  rtems_bdbuf_buffer* bd;
  dev_t               device;

  /*
   * Set task control's passed to false to handle a timeout.
   */
  tc->passed = false;
  passed = true;

  device = rtems_filesystem_make_dev_t (tc->major, tc->minor);

  bdbuf_disk_lock (&bdbuf_disks[tc->minor]);
  bdbuf_disks[tc->minor].driver_action = BDBUF_DISK_NOOP;
  bdbuf_disk_unlock (&bdbuf_disks[tc->minor]);

  /*
   * Read the buffer and then release it.
   */
  bdbuf_test_printf ("%s: rtems_bdbuf_read[5]: ", tc->name);
  sc = rtems_bdbuf_read (device, 5, &bd);
  if ((passed = bdbuf_test_print_sc (sc, true)))
  {
    bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[5]: ", tc->name);
    sc = rtems_bdbuf_release_modified (bd);
    passed = bdbuf_test_print_sc (sc, true);
  }

  /*
   * Read the buffer again and then just release. The buffer should
   * be maintained as modified.
   */
  bdbuf_test_printf ("%s: rtems_bdbuf_read[5]: ", tc->name);
  sc = rtems_bdbuf_read (device, 5, &bd);
  if ((passed = bdbuf_test_print_sc (sc, true)))
  {
    bdbuf_test_printf ("%s: rtems_bdbuf_release[5]: ", tc->name);
    sc = rtems_bdbuf_release (bd);
    passed = bdbuf_test_print_sc (sc, true);
  }

  /*
   * Set up a disk watch and wait for the write to happen.
   */
  bdbuf_set_disk_driver_watch (tc, 1);
  passed = bdbuf_disk_driver_watch_wait (tc, BDBUF_SECONDS (5));

  tc->passed = passed;
  tc->test = 0;
}
示例#9
0
static rtems_task
bdbuf_test3_1_thread1(rtems_task_argument arg)
{
    rtems_status_code   rc;
    rtems_bdbuf_buffer *bd = NULL;

    /*
     * Step 1:
     * Call rtems_bdbuf_get(#N) to get an empty block db;
     * [this call will remove a buffer from ready list and insert
     * it in AVL tree with ACCESS state.
     * Step 2:
     * Call release_modified(bd);
     * [Now we have one entry in modified list and it is still 
     * in AVL tree with MODIFIED state]
     * Step 3: 
     * Call read(#N) to get the same buffer.
     * [An entry is found in AVL tree, removed from modified list and 
     * returned with state ACCESS_MODIFIED]
     */
    rc = rtems_bdbuf_get(test_dev, TEST_BLK_NUM_N, &bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }
    
    rc = rtems_bdbuf_release_modified(bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }

    rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM_N, &bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }

    CONTINUE_MAIN(1);

    /* Step 5:
     * Call rtems_bdbuf_release(#N).
     * As the result buffer will be used by bdbuf to get 
     * buffer #M for thread #2.
     */
    rc = rtems_bdbuf_release(bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }

    THREAD_END();
}
示例#10
0
/* rtems_blkdev_generic_write --
 *     Generic block device write primitive. Implemented using block device
 *     buffer management primitives.
 */
rtems_device_driver
rtems_blkdev_generic_write(
    rtems_device_major_number major __attribute__((unused)),
    rtems_device_minor_number minor __attribute__((unused)),
    void                    * arg)
{
    rtems_status_code rc = RTEMS_SUCCESSFUL;
    rtems_libio_rw_args_t *args = arg;
    rtems_libio_t *iop = args->iop;
    rtems_disk_device *dd = iop->data1;
    uint32_t block_size = dd->block_size;
    char *buf = args->buffer;
    uint32_t count = args->count;
    rtems_blkdev_bnum block = (rtems_blkdev_bnum) (args->offset / block_size);
    uint32_t blkofs = (uint32_t) (args->offset % block_size);

    args->bytes_moved = 0;

    while (count > 0)
    {
        rtems_bdbuf_buffer *diskbuf;
        uint32_t            copy;

        if ((blkofs == 0) && (count >= block_size))
            rc = rtems_bdbuf_get(dd, block, &diskbuf);
        else
            rc = rtems_bdbuf_read(dd, block, &diskbuf);
        if (rc != RTEMS_SUCCESSFUL)
            break;

        copy = block_size - blkofs;
        if (copy > count)
            copy = count;
        memcpy((char *)diskbuf->buffer + blkofs, buf, copy);
        args->bytes_moved += copy;

        rc = rtems_bdbuf_release_modified(diskbuf);
        if (rc != RTEMS_SUCCESSFUL)
            break;

        count -= copy;
        buf += copy;
        blkofs = 0;
        block++;
    }

    return rc;
}
示例#11
0
static rtems_bdbuf_buffer *do_get_mod(char task)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
  rtems_bdbuf_buffer *bd = NULL;

  printk("%c: try get modified\n", task);

  sc = rtems_bdbuf_get(dev, 0, &bd);
  ASSERT_SC(sc);

  sc = rtems_bdbuf_release_modified(bd);
  ASSERT_SC(sc);

  sc = rtems_bdbuf_get(dev, 0, &bd);
  ASSERT_SC(sc);

  printk("%c: get modified\n", task);

  return bd;
}
示例#12
0
文件: init.c 项目: lanzhongheng/rtems
/**
 * Get all the blocks in the pool and hold them. Wake the master to tell it was
 * have the buffers then wait for the master to tell us to release them.
 */
static void
bdbuf_tests_task_0_test_4 (bdbuf_task_control* tc)
{
  rtems_status_code   sc;
  bool                passed;
  size_t              i;
  rtems_bdbuf_buffer* bd;
  rtems_chain_control buffers;
  size_t              num = bdbuf_test_buffer_count ();

  /*
   * Set task control's passed to false to handle a timeout.
   */
  tc->passed = false;
  passed = true;

  /*
   * Clear any disk settings.
   */
  bdbuf_clear_disk_driver_watch (tc);
  bdbuf_set_disk_driver_action (tc, BDBUF_DISK_NOOP);

  /*
   * Get the blocks 0 -> 4 and hold them.
   */
  rtems_chain_initialize_empty (&buffers);

  for (i = 0; (i < num) && passed; i++)
  {
    bdbuf_test_printf ("%s: rtems_bdbuf_read[%d]: ", tc->name, i);
    sc = rtems_bdbuf_read (tc->dd, i, &bd);
    if (!bdbuf_test_print_sc (sc, true))
      passed = false;

    rtems_chain_append (&buffers, &bd->link);
  }

  /*
   * Wake the master to tell it we have the buffers.
   */
  bdbuf_send_wait_event (tc->name, "wake master", tc->master);

  if (passed)
  {
    bdbuf_sleep (250);

    bdbuf_set_disk_driver_watch (tc, num / 2);

    /*
     * Release half the buffers, wait 500msecs then release the
     * remainder. This tests the swap out timer on each buffer.
     */
    bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[0]: unblocks task 1\n",
                       tc->name);
    bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers);
    sc = rtems_bdbuf_release_modified (bd);
    bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[0]: ", tc->name);
    passed = bdbuf_test_print_sc (sc, true);
    if (passed)
    {
      for (i = 1; (i < (num / 2)) && passed; i++)
      {
        bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[%d]: " \
                           "unblocks task 1\n", tc->name, i);
        bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers);
        sc = rtems_bdbuf_release_modified (bd);
        bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[%d]: ",
                           tc->name, i);
        passed = bdbuf_test_print_sc (sc, true);
        if (!passed)
          break;
      }

      if (passed)
      {
        passed = bdbuf_disk_driver_watch_wait (tc, BDBUF_SECONDS (5));

        if (passed)
        {
          bdbuf_sleep (500);

          bdbuf_set_disk_driver_watch (tc, num / 2);

          for (i = 0; (i < (num / 2)) && passed; i++)
          {
            bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[%d]: ",
                               tc->name, i + (num / 2));
            bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers);
            passed = bdbuf_test_print_sc (rtems_bdbuf_release_modified (bd),
                                          true);
            if (!passed)
              break;
          }

          passed = bdbuf_disk_driver_watch_wait (tc, BDBUF_SECONDS (5));

          if (passed)
          {
            if (!rtems_chain_is_empty (&buffers))
            {
              passed = false;
              bdbuf_test_printf ("%s: buffer chain not empty\n", tc->name);
            }
          }
        }
      }
    }
  }

  tc->passed = passed;
  tc->test = 0;
}
示例#13
0
文件: init.c 项目: lanzhongheng/rtems
static void
bdbuf_tests_task_0_test_8 (bdbuf_task_control* tc)
{
  rtems_status_code   sc;
  bool                passed;
  int                 i;
  rtems_bdbuf_buffer* bd;
  rtems_chain_control buffers;
  rtems_chain_node*   node;
  rtems_chain_node*   pnode;

  /*
   * Set task control's passed to false to handle a timeout.
   */
  tc->passed = false;
  passed = true;

  /*
   * Clear any disk settings.
   */
  bdbuf_clear_disk_driver_watch (tc);
  bdbuf_set_disk_driver_action (tc, BDBUF_DISK_NOOP);

  /*
   * Get the blocks 0 -> 4 and hold them.
   */
  rtems_chain_initialize_empty (&buffers);

  for (i = 0; (i < 5) && passed; i++)
  {
    bdbuf_test_printf ("%s: rtems_bdbuf_read[%d]: ", tc->name, i);
    sc = rtems_bdbuf_get (tc->dd, i, &bd);
    if (!bdbuf_test_print_sc (sc, true))
      passed = false;

    rtems_chain_append (&buffers, &bd->link);
  }

  node = rtems_chain_tail (&buffers);
  node = node->previous;

  bd = (rtems_bdbuf_buffer*) node;
  pnode = node->previous;
  rtems_chain_extract (node);
  node = pnode;
  bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[4]: ", tc->name);
  passed = bdbuf_test_print_sc (rtems_bdbuf_release_modified (bd), true);

  bd = (rtems_bdbuf_buffer*) node;
  pnode = node->previous;
  rtems_chain_extract (node);
  node = pnode;
  bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[3]: ", tc->name);
  passed = bdbuf_test_print_sc (rtems_bdbuf_release_modified (bd), true);

  for (i = 0; (i < 3) && passed; i++)
  {
    bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[%d]: ",
                       tc->name, i);
    bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers);
    passed = bdbuf_test_print_sc (rtems_bdbuf_release_modified (bd),
                                  true);
  }

  if (passed)
  {
    /*
     * Check the block order.
     */
    bdbuf_set_disk_driver_action (tc, BDBUF_DISK_BLOCKS_INORDER);

    bdbuf_test_printf ("%s: rtems_bdbuf_syncdev[%d:%d]: checking order\n",
                       tc->name, i,
                       tc->major,
                       tc->minor);
    sc = rtems_bdbuf_syncdev (tc->dd);
    bdbuf_test_printf ("%s: rtems_bdbuf_syncdev[%d:%d]: ",
                       tc->name, i,
                       tc->major,
                       tc->minor);
    passed = bdbuf_test_print_sc (sc, true);
  }

  tc->passed = passed;
  tc->test = 0;
}
示例#14
0
文件: fat.c 项目: kptran/rtems
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;
    bool              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.dd, blk, &fs_info->c.buf);
        else
            sc = rtems_bdbuf_get(fs_info->vol.dd, 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.dd,
                                         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.dd, blk, &fs_info->c.buf);
        else
            sc = rtems_bdbuf_get(fs_info->vol.dd, 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;
}