Exemple #1
0
static rtems_task Init(rtems_task_argument argument)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
  rtems_bdbuf_buffer *bd = NULL;
  dev_t dev = 0;
  rtems_disk_device *dd = NULL;

  printk("\n\n*** TEST BLOCK 9 ***\n");

  sc = rtems_disk_io_initialize();
  ASSERT_SC(sc);

  sc = disk_register(BLOCK_SIZE, BLOCK_COUNT, &dev);
  ASSERT_SC(sc);

  dd = rtems_disk_obtain(dev);
  assert(dd != NULL);

  check_read(dd, BLOCK_READ_IO_ERROR, RTEMS_IO_ERROR);
  check_read(dd, BLOCK_READ_UNSATISFIED, RTEMS_UNSATISFIED);
  check_read(dd, BLOCK_READ_SUCCESSFUL, RTEMS_SUCCESSFUL);
  check_read(dd, BLOCK_WRITE_IO_ERROR, RTEMS_SUCCESSFUL);

  /* Check write IO error */

  sc = rtems_bdbuf_read(dd, BLOCK_WRITE_IO_ERROR, &bd);
  ASSERT_SC(sc);

  bd->buffer [0] = 1;

  sc = rtems_bdbuf_sync(bd);
  ASSERT_SC(sc);

  sc = rtems_bdbuf_read(dd, BLOCK_WRITE_IO_ERROR, &bd);
  ASSERT_SC(sc);

  assert(bd->buffer [0] == 0);

  sc = rtems_bdbuf_release(bd);
  ASSERT_SC(sc);

  /* Check write to deleted disk */

  sc = rtems_bdbuf_read(dd, BLOCK_READ_SUCCESSFUL, &bd);
  ASSERT_SC(sc);

  sc = rtems_disk_delete(dev);
  ASSERT_SC(sc);

  sc = rtems_bdbuf_sync(bd);
  ASSERT_SC(sc);

  sc = rtems_disk_release(dd);
  ASSERT_SC(sc);

  printk("*** END OF TEST BLOCK 9 ***\n");

  exit(0);
}
/**
 * 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;
}
Exemple #3
0
/*
 * get_sector --
 *      gets sector from the disk
 *
 * PARAMETERS:
 *      dev        - device number
 *      sector_num - number of sector to read
 *      sector     - returned pointer to pointer to allocated
 *                   sector_data_t structure
 *
 * RETURNS:
 *      RTEMS_SUCCESSFUL, if success;
 *      RTEMS_NO_MEMORY, if canot allocate memory for sector data;
 *      other error codes returned by rtems_bdbuf_read().
 *
 * NOTES:
 *      get_sector() operates with device via bdbuf library,
 *      and does not support devices with sector size other than 512 bytes
 */
static rtems_status_code
get_sector(dev_t dev, uint32_t sector_num, rtems_sector_data_t **sector)
{
    rtems_sector_data_t *s;
    rtems_bdbuf_buffer  *buf;
    rtems_status_code    rc;

    if (sector == NULL)
    {
        return RTEMS_INTERNAL_ERROR;
    }

    s = (rtems_sector_data_t *) malloc(sizeof(rtems_sector_data_t) + RTEMS_IDE_SECTOR_SIZE);
    if (s == NULL)
    {
        return RTEMS_NO_MEMORY;
    }

    rc = rtems_bdbuf_read(dev, sector_num, &buf);
    if (rc != RTEMS_SUCCESSFUL)
    {
        free(s);
        return rc;
    }

    memcpy(s->data, buf->buffer, RTEMS_IDE_SECTOR_SIZE);
    s->sector_num = sector_num;

    *sector = s;

    rtems_bdbuf_release(buf);

    return RTEMS_SUCCESSFUL;
}
Exemple #4
0
static rtems_task
bdbuf_test4_1_thread2(rtems_task_argument arg)
{
    rtems_status_code   rc;
    rtems_bdbuf_buffer *bd = NULL;

    WAIT_MAIN_SYNC(2);

    /*
     * Step 2:
     * In thread #2 call rtems_bdbuf_read(#N).
     * We will block on this call.
     */
    rc = rtems_bdbuf_read(test_dd, TEST_BLK_NUM_N, &bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }

    CONTINUE_MAIN(2);

    /*
     * Release buffer.
     */
    rc = rtems_bdbuf_release(bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }
    THREAD_END();
}
Exemple #5
0
static rtems_task
bdbuf_test4_1_thread1(rtems_task_argument arg)
{
    rtems_status_code   rc;
    rtems_bdbuf_buffer *bd = NULL;

    /*
     * Step 1:
     * Call rtems_bdbuf_read(#N) in thread #1;
     */
    rc = rtems_bdbuf_read(test_dd, TEST_BLK_NUM_N, &bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }

    CONTINUE_MAIN(1);
    
    /*
     * Step 3:
     * Call rtems_bdbuf_sync(#N)
     */
    rc = rtems_bdbuf_sync(bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }

    CONTINUE_MAIN(1);

    THREAD_END();
}
Exemple #6
0
static rtems_task
bdbuf_test1_2_thread2(rtems_task_argument arg)
{
    rtems_status_code   rc;
    rtems_bdbuf_buffer *bd = NULL;

    WAIT_MAIN_SYNC(2);

    /*
     * Step 2:
     * Try to read block #N. Right now thread #1 is waiting
     * on data transfer operation, so we will block here as well.
     *
     * Step 4:
     * Due to the fact that thread #1 failed to read required block
     * number, bdbuf library should ask for re-read data again.
     * But main test task will agin tell device driver to return
     * RTEMS_IO_ERROR data transfer result.
     */
    rc = rtems_bdbuf_read(test_dd, TEST_BLK_NUM, &bd);
    if (rc != RTEMS_IO_ERROR || bd != NULL)
    {
        TEST_FAILED();
    }

    CONTINUE_MAIN(2);

    THREAD_END();
}
int
rtems_rfs_buffer_bdbuf_request (rtems_rfs_file_system*   fs,
                                rtems_rfs_buffer_block   block,
                                bool                     read,
                                rtems_rfs_buffer**       buffer)
{
  rtems_status_code sc;
  int               rc = 0;

  if (read)
    sc = rtems_bdbuf_read (rtems_rfs_fs_device (fs), block, buffer);
  else
    sc = rtems_bdbuf_get (rtems_rfs_fs_device (fs), block, buffer);

  if (sc != RTEMS_SUCCESSFUL)
  {
#if RTEMS_RFS_BUFFER_ERRORS
    printf ("rtems-rfs: buffer-bdbuf-request: block=%lu: bdbuf-%s: %d: %s\n",
            block, read ? "read" : "get", sc, rtems_status_text (sc));
#endif
    rc = EIO;
  }

  return rc;
}
Exemple #8
0
static rtems_status_code rtems_bdpart_read_record(
  rtems_disk_device *dd,
  rtems_blkdev_bnum index,
  rtems_bdbuf_buffer **block
)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;

  /* Release previous block if necessary */
  if (*block != NULL) {
    sc = rtems_bdbuf_release( *block);
    if (sc != RTEMS_SUCCESSFUL) {
      return sc;
    }
  }

  /* Read the record block */
  sc = rtems_bdbuf_read( dd, index, block);
  if (sc != RTEMS_SUCCESSFUL) {
    return sc;
  }

  /* just in case block did not get filled in */
  if ( *block == NULL ) {
    return RTEMS_INVALID_ADDRESS;
  }

  /* Check MBR signature */
  if (!rtems_bdpart_is_valid_record( (*block)->buffer)) {
    return RTEMS_IO_ERROR;
  }

  return RTEMS_SUCCESSFUL;
}
Exemple #9
0
static rtems_task
bdbuf_test3_3_thread1(rtems_task_argument arg)
{
    rtems_status_code   rc;
    rtems_bdbuf_buffer *bd = NULL;

    /*
     * Step 1:
     * Call rtems_bdbuf_read(#N) to get a buffer;
     */
    rc = rtems_bdbuf_read(test_dd, TEST_BLK_NUM_N1, &bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }

    CONTINUE_MAIN(1);

    /*
     * Step 4:
     * Call rtems_bdbuf_release(#N).
     */
    rc = rtems_bdbuf_release(bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }

    THREAD_END();
}
Exemple #10
0
static rtems_task
bdbuf_test1_4_thread2(rtems_task_argument arg)
{
    rtems_status_code   rc;
    rtems_bdbuf_buffer *bd = NULL;

    WAIT_MAIN_SYNC(2);

    /*
     * Step 2:
     * Try to read block #N. Right now thread #1 is waiting
     * on data transfer operation, so we will block here as well.
     *
     * Step 5:
     * On step 4 thread #1 releases buffer and as the result 
     * our read operation should finish with success. 
     */
    rc = rtems_bdbuf_read(test_dd, TEST_BLK_NUM, &bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }
    CONTINUE_MAIN(2);

    /*
     * Step 6:
     * Release buffer returned on the previous step.
     */
    rc = rtems_bdbuf_release(bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }
    THREAD_END();
}
Exemple #11
0
static rtems_task
bdbuf_test1_4_thread1(rtems_task_argument arg)
{
    rtems_status_code   rc;
    rtems_bdbuf_buffer *bd = NULL;

    /*
     * Step 1 - 3:
     * Try to read blk #N on thread #1
     * We will block on this read and meanwhile
     * thread #2 will try to read the same block.
     * After blocking on read in thread #2, device
     * driver will notify successful completion of 
     * date transfer, and as the result this call 
     * will return valid buffer.
     */
    rc = rtems_bdbuf_read(test_dd, TEST_BLK_NUM, &bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }
    CONTINUE_MAIN(1);

    /*
     * Step 4:
     * Release buffer returned on the previous step.
     */
    rc = rtems_bdbuf_release(bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }
    THREAD_END();
}
Exemple #12
0
static rtems_task
bdbuf_test1_2_thread1(rtems_task_argument arg)
{
    rtems_status_code   rc;
    rtems_bdbuf_buffer *bd = NULL;

    /*
     * Step 1 - 3:
     * Try to read blk #N on thread #1
     * We will block on this read and meanwhile
     * thread #2 will try to read the same block.
     * After blocking on read in thread #2, device
     * driver will notify about an error, and as the
     * result this call will return an error.
     */
    rc = rtems_bdbuf_read(test_dd, TEST_BLK_NUM, &bd);
    if (rc != RTEMS_IO_ERROR || bd != NULL)
    {
        TEST_FAILED();
    }

    CONTINUE_MAIN(1);

    THREAD_END();
}
Exemple #13
0
static rtems_task
bdbuf_test3_3_thread3(rtems_task_argument arg)
{
    rtems_status_code   rc;
    rtems_bdbuf_buffer *bd = NULL;

    WAIT_MAIN_SYNC(3);

    /*
     * Step 3:
     * In thread #3 call read(#N3)
     */
    rc = rtems_bdbuf_read(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(bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }

    THREAD_END();
}
Exemple #14
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;
}
Exemple #15
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();
}
static rtems_bdbuf_buffer *do_read(char task)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
  rtems_bdbuf_buffer *bd = NULL;

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

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

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

  return bd;
}
Exemple #17
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;
}
Exemple #18
0
static void check_read(
  rtems_disk_device *dd,
  rtems_blkdev_bnum block,
  rtems_status_code expected_sc
)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
  rtems_bdbuf_buffer *bd = NULL;

  sc = rtems_bdbuf_read(dd, block, &bd);
  assert(sc == expected_sc);

  if (sc == RTEMS_SUCCESSFUL) {
    sc = rtems_bdbuf_release(bd);
    ASSERT_SC(sc);
  }
}
Exemple #19
0
static void test_read_ahead(rtems_disk_device *dd)
{
  int i;

  for (i = 0; i < READ_COUNT; ++i) {
    int action = action_sequence [i];

    if (action != RESET_CACHE) {
      rtems_blkdev_bnum block = (rtems_blkdev_bnum) action;
      rtems_status_code sc;
      rtems_bdbuf_buffer *bd;

      printf("%i ", action);

      sc = rtems_bdbuf_read(dd, block, &bd);
      rtems_test_assert(sc == RTEMS_SUCCESSFUL);

      sc = rtems_bdbuf_release(bd);
      rtems_test_assert(sc == RTEMS_SUCCESSFUL);

      rtems_test_assert(
        memcmp(
          block_access_counts,
          expected_block_access_counts [i],
          sizeof(block_access_counts)
        ) == 0
      );
    } else {
      printf("\nreset\n");

      rtems_bdbuf_purge_dev(dd);
      memset(&block_access_counts, 0, sizeof(block_access_counts));
    }

    rtems_test_assert(trigger [i] == dd->read_ahead.trigger);
    rtems_test_assert(next [i] == dd->read_ahead.next);
  }

  printf("\n");
}
Exemple #20
0
static rtems_status_code rtems_bdpart_new_record(
  rtems_disk_device *dd,
  rtems_blkdev_bnum index,
  rtems_bdbuf_buffer **block
)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;

  /* Synchronize previous block if necessary */
  if (*block != NULL) {
    sc = rtems_bdbuf_sync( *block);
    if (sc != RTEMS_SUCCESSFUL) {
      return sc;
    }
  }

  /* Read the new record block (this accounts for disk block sizes > 512) */
  sc = rtems_bdbuf_read( dd, index, block);
  if (sc != RTEMS_SUCCESSFUL) {
    return sc;
  }

  /* just in case block did not get filled in */
  if ( *block == NULL ) {
    return RTEMS_INVALID_ADDRESS;
  }

  /* Clear record */
  memset( (*block)->buffer, 0, RTEMS_BDPART_BLOCK_SIZE);

  /* Write signature */
  (*block)->buffer [RTEMS_BDPART_MBR_OFFSET_SIGNATURE_0] =
    RTEMS_BDPART_MBR_SIGNATURE_0;
  (*block)->buffer [RTEMS_BDPART_MBR_OFFSET_SIGNATURE_1] =
    RTEMS_BDPART_MBR_SIGNATURE_1;

  return RTEMS_SUCCESSFUL;
}
Exemple #21
0
static rtems_task
bdbuf_test1_3_thread2(rtems_task_argument arg)
{
    rtems_status_code   rc;
    rtems_bdbuf_buffer *bd = NULL;

    WAIT_MAIN_SYNC(2);

    /*
     * Step 2:
     * Try to read block #N. Right now thread #1 is waiting
     * on data transfer operation, so we will block here as well.
     *
     * Step 4-5:
     * Due to the fact that thread #1 failed to read required block
     * number, bdbuf library should ask for re-read data again.
     * Time time main task will tell driver to report success.
     */
    rc = rtems_bdbuf_read(test_dd, TEST_BLK_NUM, &bd);
    if (rc != RTEMS_SUCCESSFUL || bd == NULL)
    {
        TEST_FAILED();
    }
    CONTINUE_MAIN(2);

    /*
     * Step 6:
     * Release buffer.
     */
    rc = rtems_bdbuf_release(bd);
    if (rc != RTEMS_SUCCESSFUL)
    {
        TEST_FAILED();
    }
    THREAD_END();
}
Exemple #22
0
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;
}
Exemple #23
0
/**
 * 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;
}
Exemple #24
0
/* fat_init_volume_info --
 *     Get inforamtion about volume on which filesystem is mounted on
 *
 * PARAMETERS:
 *     mt_entry - mount table entry
 *
 * RETURNS:
 *     RC_OK on success, or -1 if error occured
 *     and errno set appropriately
 */
int
fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
{
    rtems_status_code   sc = RTEMS_SUCCESSFUL;
    int                 rc = RC_OK;
    fat_fs_info_t      *fs_info = mt_entry->fs_info;
    register fat_vol_t *vol = &fs_info->vol;
    uint32_t            data_secs = 0;
    char                boot_rec[FAT_MAX_BPB_SIZE];
    char                fs_info_sector[FAT_USEFUL_INFO_SIZE];
    ssize_t             ret = 0;
    struct stat         stat_buf;
    int                 i = 0;
    rtems_bdbuf_buffer *block = NULL;

    vol->fd = open(mt_entry->dev, O_RDWR);
    if (vol->fd < 0)
    {
        rtems_set_errno_and_return_minus_one(ENXIO);
    }

    rc = fstat(vol->fd, &stat_buf);
    if (rc != 0)
    {
        close(vol->fd);
        rtems_set_errno_and_return_minus_one(ENXIO);
    }

    /* Must be a block device. */
    if (!S_ISBLK(stat_buf.st_mode))
    {
        close(vol->fd);
        rtems_set_errno_and_return_minus_one(ENXIO);
    }

    /* check that device is registred as block device and lock it */
    rc = rtems_disk_fd_get_disk_device(vol->fd, &vol->dd);
    if (rc != 0) {
        close(vol->fd);
        rtems_set_errno_and_return_minus_one(ENXIO);
    }

    /* Read boot record */
    /* FIXME: Asserts FAT_MAX_BPB_SIZE < bdbuf block size */
    sc = rtems_bdbuf_read( vol->dd, 0, &block);
    if (sc != RTEMS_SUCCESSFUL)
    {
        close(vol->fd);
        rtems_set_errno_and_return_minus_one( EIO);
    }

    memcpy( boot_rec, block->buffer, FAT_MAX_BPB_SIZE);

    sc = rtems_bdbuf_release( block);
    if (sc != RTEMS_SUCCESSFUL)
    {
        close(vol->fd);
        rtems_set_errno_and_return_minus_one( EIO );
    }

    /* Evaluate boot record */
    vol->bps = FAT_GET_BR_BYTES_PER_SECTOR(boot_rec);

    if ( (vol->bps != 512)  &&
         (vol->bps != 1024) &&
         (vol->bps != 2048) &&
         (vol->bps != 4096))
    {
        close(vol->fd);
        rtems_set_errno_and_return_minus_one( EINVAL );
    }

    for (vol->sec_mul = 0, i = (vol->bps >> FAT_SECTOR512_BITS); (i & 1) == 0;
         i >>= 1, vol->sec_mul++);
    for (vol->sec_log2 = 0, i = vol->bps; (i & 1) == 0;
         i >>= 1, vol->sec_log2++);

    vol->spc = FAT_GET_BR_SECTORS_PER_CLUSTER(boot_rec);
    /*
     * "sectors per cluster" of zero is invalid
     * (and would hang the following loop)
     */
    if (vol->spc == 0)
    {
        close(vol->fd);
        rtems_set_errno_and_return_minus_one(EINVAL);
    }

    for (vol->spc_log2 = 0, i = vol->spc; (i & 1) == 0;
         i >>= 1, vol->spc_log2++);

    /*
     * "bytes per cluster" value greater than 32K is invalid
     */
    if ((vol->bpc = vol->bps << vol->spc_log2) > MS_BYTES_PER_CLUSTER_LIMIT)
    {
        close(vol->fd);
        rtems_set_errno_and_return_minus_one(EINVAL);
    }

    for (vol->bpc_log2 = 0, i = vol->bpc; (i & 1) == 0;
         i >>= 1, vol->bpc_log2++);

    vol->fats = FAT_GET_BR_FAT_NUM(boot_rec);
    vol->fat_loc = FAT_GET_BR_RESERVED_SECTORS_NUM(boot_rec);

    vol->rdir_entrs = FAT_GET_BR_FILES_PER_ROOT_DIR(boot_rec);

    /* calculate the count of sectors occupied by the root directory */
    vol->rdir_secs = ((vol->rdir_entrs * FAT_DIRENTRY_SIZE) + (vol->bps - 1)) /
                     vol->bps;

    vol->rdir_size = vol->rdir_secs << vol->sec_log2;

    if ( (FAT_GET_BR_SECTORS_PER_FAT(boot_rec)) != 0)
        vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT(boot_rec);
    else
        vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT32(boot_rec);

    vol->data_fsec = vol->fat_loc + vol->fats * vol->fat_length +
                     vol->rdir_secs;

    /* for  FAT12/16 root dir starts at(sector) */
    vol->rdir_loc = vol->fat_loc + vol->fats * vol->fat_length;

    if ( (FAT_GET_BR_TOTAL_SECTORS_NUM16(boot_rec)) != 0)
        vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM16(boot_rec);
    else
        vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM32(boot_rec);

    data_secs = vol->tot_secs - vol->data_fsec;

    vol->data_cls = data_secs / vol->spc;

    /* determine FAT type at least */
    if ( vol->data_cls < FAT_FAT12_MAX_CLN)
    {
        vol->type = FAT_FAT12;
        vol->mask = FAT_FAT12_MASK;
        vol->eoc_val = FAT_FAT12_EOC;
    }
    else
    {
        if ( vol->data_cls < FAT_FAT16_MAX_CLN)
        {
            vol->type = FAT_FAT16;
            vol->mask = FAT_FAT16_MASK;
            vol->eoc_val = FAT_FAT16_EOC;
        }
        else
        {
            vol->type = FAT_FAT32;
            vol->mask = FAT_FAT32_MASK;
            vol->eoc_val = FAT_FAT32_EOC;
        }
    }

    if (vol->type == FAT_FAT32)
    {
        vol->rdir_cl = FAT_GET_BR_FAT32_ROOT_CLUSTER(boot_rec);

        vol->mirror = FAT_GET_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_MIRROR;
        if (vol->mirror)
            vol->afat = FAT_GET_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_FAT_NUM;
        else
            vol->afat = 0;

        vol->info_sec = FAT_GET_BR_FAT32_FS_INFO_SECTOR(boot_rec);
        if( vol->info_sec == 0 )
        {
            close(vol->fd);
            rtems_set_errno_and_return_minus_one( EINVAL );
        }
        else
        {
            ret = _fat_block_read(mt_entry, vol->info_sec , 0,
                                  FAT_FSI_LEADSIG_SIZE, fs_info_sector);
            if ( ret < 0 )
            {
                close(vol->fd);
                return -1;
            }

            if (FAT_GET_FSINFO_LEAD_SIGNATURE(fs_info_sector) !=
                FAT_FSINFO_LEAD_SIGNATURE_VALUE)
            {
                _fat_block_release(mt_entry);
                close(vol->fd);
                rtems_set_errno_and_return_minus_one( EINVAL );
            }
            else
            {
                ret = _fat_block_read(mt_entry, vol->info_sec , FAT_FSI_INFO,
                                      FAT_USEFUL_INFO_SIZE, fs_info_sector);
                if ( ret < 0 )
                {
                    _fat_block_release(mt_entry);
                    close(vol->fd);
                    return -1;
                }

                vol->free_cls = FAT_GET_FSINFO_FREE_CLUSTER_COUNT(fs_info_sector);
                vol->next_cl = FAT_GET_FSINFO_NEXT_FREE_CLUSTER(fs_info_sector);
                rc = fat_fat32_update_fsinfo_sector(mt_entry, 0xFFFFFFFF,
                                                    0xFFFFFFFF);
                if ( rc != RC_OK )
                {
                    _fat_block_release(mt_entry);
                    close(vol->fd);
                    return rc;
                }
            }
        }
    }
    else
    {
        vol->rdir_cl = 0;
        vol->mirror = 0;
        vol->afat = 0;
        vol->free_cls = 0xFFFFFFFF;
        vol->next_cl = 0xFFFFFFFF;
    }

    _fat_block_release(mt_entry);

    vol->afat_loc = vol->fat_loc + vol->fat_length * vol->afat;

    /* set up collection of fat-files fd */
    fs_info->vhash = calloc(FAT_HASH_SIZE, sizeof(rtems_chain_control));
    if ( fs_info->vhash == NULL )
    {
        close(vol->fd);
        rtems_set_errno_and_return_minus_one( ENOMEM );
    }

    for (i = 0; i < FAT_HASH_SIZE; i++)
        rtems_chain_initialize_empty(fs_info->vhash + i);

    fs_info->rhash = calloc(FAT_HASH_SIZE, sizeof(rtems_chain_control));
    if ( fs_info->rhash == NULL )
    {
        close(vol->fd);
        free(fs_info->vhash);
        rtems_set_errno_and_return_minus_one( ENOMEM );
    }
    for (i = 0; i < FAT_HASH_SIZE; i++)
        rtems_chain_initialize_empty(fs_info->rhash + i);

    fs_info->uino_pool_size = FAT_UINO_POOL_INIT_SIZE;
    fs_info->uino_base = (vol->tot_secs << vol->sec_mul) << 4;
    fs_info->index = 0;
    fs_info->uino = (char *)calloc(fs_info->uino_pool_size, sizeof(char));
    if ( fs_info->uino == NULL )
    {
        close(vol->fd);
        free(fs_info->vhash);
        free(fs_info->rhash);
        rtems_set_errno_and_return_minus_one( ENOMEM );
    }
    fs_info->sec_buf = (uint8_t *)calloc(vol->bps, sizeof(uint8_t));
    if (fs_info->sec_buf == NULL)
    {
        close(vol->fd);
        free(fs_info->vhash);
        free(fs_info->rhash);
        free(fs_info->uino);
        rtems_set_errno_and_return_minus_one( ENOMEM );
    }

    return RC_OK;
}