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(); }
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_dev, 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(); }
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); }
static void do_rel(char task, rtems_bdbuf_buffer *bd) { rtems_status_code sc = RTEMS_SUCCESSFUL; printk("%c: release\n", task); sc = rtems_bdbuf_release(bd); ASSERT_SC(sc); printk("%c: release 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; }
static void task_high(rtems_task_argument arg) { rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_bdbuf_buffer *bd = NULL; rtems_test_assert(!sync_done); printk("H: try access: A0\n"); sc = rtems_bdbuf_get(dd_a, 0, &bd); ASSERT_SC(sc); rtems_test_assert(sync_done); printk("H: access: A0\n"); printk("H: release: A0\n"); sc = rtems_bdbuf_release(bd); ASSERT_SC(sc); printk("H: release done: A0\n"); printk("H: try access: B0\n"); sc = rtems_bdbuf_get(dd_b, 0, &bd); ASSERT_SC(sc); printk("H: access: B0\n"); /* If we reach this code, we have likely a bug */ printk("H: release: B0\n"); sc = rtems_bdbuf_release(bd); ASSERT_SC(sc); printk("H: release done: B0\n"); rtems_task_delete(RTEMS_SELF); }
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 ssize_t rtems_blkdev_imfs_read( rtems_libio_t *iop, 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); char *dst = buffer; while (remaining > 0) { rtems_bdbuf_buffer *bd; rtems_status_code sc = rtems_bdbuf_read(dd, block, &bd); if (sc == RTEMS_SUCCESSFUL) { ssize_t copy = block_size - block_offset; if (copy > remaining) { copy = remaining; } memcpy(dst, (char *) bd->buffer + block_offset, (size_t) copy); sc = rtems_bdbuf_release(bd); if (sc == RTEMS_SUCCESSFUL) { block_offset = 0; remaining -= copy; dst += copy; ++block; } else { remaining = -1; } } else { remaining = -1; } } if (remaining >= 0) { iop->offset += count; rv = (ssize_t) count; } else { errno = EIO; rv = -1; } return rv; }
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; }
/** * Get the blocks 0 -> 4 and release them. Task 0 should be holding * each one. */ static void bdbuf_tests_ranged_get_release (bdbuf_task_control* tc, bool wake_master, int lower, int upper) { rtems_status_code sc; bool passed; int i; rtems_bdbuf_buffer* bd; /* * Set task control's passed to false to handle a timeout. */ tc->passed = false; passed = true; for (i = lower; (i < upper) && passed; i++) { dev_t device = rtems_filesystem_make_dev_t (tc->major, tc->minor); bdbuf_test_printf ("%s: rtems_bdbuf_get[%d]: blocking ...\n", tc->name, i); sc = rtems_bdbuf_get (device, i, &bd); bdbuf_test_printf ("%s: rtems_bdbuf_get[%d]: ", tc->name, i); if (!bdbuf_test_print_sc (sc, true)) { passed = false; break; } bdbuf_test_printf ("%s: rtems_bdbuf_release[%d]: ", tc->name, i); sc = rtems_bdbuf_release (bd); if (!bdbuf_test_print_sc (sc, true)) { passed = false; break; } /* * Wake the master to tell it we have finished. */ if (wake_master) bdbuf_send_wait_event (tc->name, "wake master", tc->master); } tc->passed = passed; tc->test = 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); } }
/* rtems_blkdev_generic_read -- * Generic block device read primitive. Implemented using block device * buffer management primitives. */ rtems_device_driver rtems_blkdev_generic_read( 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; rc = rtems_bdbuf_read(dd, block, &diskbuf); if (rc != RTEMS_SUCCESSFUL) break; copy = block_size - blkofs; if (copy > count) copy = count; memcpy(buf, (char *)diskbuf->buffer + blkofs, copy); rc = rtems_bdbuf_release(diskbuf); args->bytes_moved += copy; if (rc != RTEMS_SUCCESSFUL) break; count -= copy; buf += copy; blkofs = 0; block++; } return rc; }
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"); }
/** * Get the block 0 buffer twice. The first time it is requested it * will be taken from the empty list and returned to the LRU list. * The second time it will be removed from the LRU list. */ static void bdbuf_tests_task_0_test_1 (bdbuf_task_control* tc) { rtems_status_code sc; bool passed; int i; rtems_bdbuf_buffer* bd; /* * Set task control's passed to false to handle a timeout. */ tc->passed = false; passed = true; for (i = 0; (i < 2) && passed; i++) { dev_t device = rtems_filesystem_make_dev_t (tc->major, tc->minor); bdbuf_test_printf ("%s: rtems_bdbuf_get[0]: ", tc->name); sc = rtems_bdbuf_get (device, 0, &bd); if (!bdbuf_test_print_sc (sc, true)) { passed = false; break; } bdbuf_test_printf ("%s: rtems_bdbuf_release[0]: ", tc->name); sc = rtems_bdbuf_release (bd); if (!bdbuf_test_print_sc (sc, true)) { passed = false; break; } } tc->passed = passed; tc->test = 0; }
static void task_mid(rtems_task_argument arg) { rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_bdbuf_buffer *bd = NULL; printk("M: try access: 0\n"); sc = rtems_bdbuf_get(dd, 0, &bd); ASSERT_SC(sc); printk("M: access: 0\n"); rtems_test_assert(bd->group->bds_per_group == 1); printk("M: release: 0\n"); sc = rtems_bdbuf_release(bd); ASSERT_SC(sc); printk("M: release done: 0\n"); rtems_task_delete(RTEMS_SELF); }
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(); }
static void execute_test(unsigned i) { rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_bdbuf_buffer *bd = NULL; bool suspend = false; print( 1, "[%05u]T(%c,%c,%s,%c)L(%c,%s,%c)H(%c,%s,%c)\n", i, trig_style_desc [trig], get_type_desc [trig_get], blk_kind_desc [trig_blk], rel_type_desc [trig_rel], get_type_desc [low_get], blk_kind_desc [low_blk], rel_type_desc [low_rel], get_type_desc [high_get], blk_kind_desc [high_blk], rel_type_desc [high_rel] ); set_task_prio(task_id_low, PRIORITY_LOW); finish_low = false; finish_high = false; sc = rtems_task_resume(task_id_low); ASSERT_SC(sc); sc = rtems_task_resume(task_id_high); ASSERT_SC(sc); sc = rtems_bdbuf_get(dd_b, 0, &bd); rtems_test_assert(sc == RTEMS_SUCCESSFUL && bd->dd == dd_b && bd->block == 0); sc = rtems_bdbuf_release(bd); ASSERT_SC(sc); switch (trig) { case SUSP: suspend = true; break; case CONT: suspend = false; break; default: rtems_test_assert(false); break; } print(2, "TG\n"); bd = get(trig_get, trig_blk); if (suspend) { print(2, "S\n"); resume = RESUME_IMMEDIATE; sc = rtems_task_suspend(RTEMS_SELF); ASSERT_SC(sc); } resume = RESUME_FINISH; print(2, "TR\n"); rel(bd, trig_rel); sc = rtems_task_suspend(RTEMS_SELF); ASSERT_SC(sc); print(2, "F\n"); sc = rtems_bdbuf_syncdev(dd_a); ASSERT_SC(sc); sc = rtems_bdbuf_syncdev(dd_b); ASSERT_SC(sc); }
rtems_status_code rtems_bdpart_read( const char *disk_name, rtems_bdpart_format *format, rtems_bdpart_partition *pt, size_t *count ) { rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_status_code esc = RTEMS_SUCCESSFUL; rtems_bdbuf_buffer *block = NULL; rtems_bdpart_partition *p = pt - 1; const rtems_bdpart_partition *p_end = pt + (count != NULL ? *count : 0); rtems_blkdev_bnum ep_begin = 0; /* Extended partition begin */ rtems_blkdev_bnum ebr = 0; /* Extended boot record block index */ rtems_blkdev_bnum disk_end = 0; size_t i = 0; const uint8_t *data = NULL; int fd = -1; rtems_disk_device *dd = NULL; /* Check parameter */ if (format == NULL || pt == NULL || count == NULL) { return RTEMS_INVALID_ADDRESS; } /* Set count to a save value */ *count = 0; /* Get disk data */ sc = rtems_bdpart_get_disk_data( disk_name, &fd, &dd, &disk_end); if (sc != RTEMS_SUCCESSFUL) { return sc; } /* Read MBR */ sc = rtems_bdpart_read_record( dd, 0, &block); if (sc != RTEMS_SUCCESSFUL) { esc = sc; goto cleanup; } /* Read the first partition entry */ data = block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_0; sc = rtems_bdpart_read_mbr_partition( data, &p, p_end, &ep_begin); if (sc != RTEMS_SUCCESSFUL) { esc = sc; goto cleanup; } /* Determine if we have a MBR or GPT format */ if (rtems_bdpart_mbr_partition_type( p->type) == RTEMS_BDPART_MBR_GPT) { esc = RTEMS_NOT_IMPLEMENTED; goto cleanup; } /* Set format */ format->type = RTEMS_BDPART_FORMAT_MBR; format->mbr.disk_id = rtems_uint32_from_little_endian( block->buffer + RTEMS_BDPART_MBR_OFFSET_DISK_ID ); format->mbr.dos_compatibility = true; /* Iterate through the rest of the primary partition table */ for (i = 1; i < 4; ++i) { data += RTEMS_BDPART_MBR_TABLE_ENTRY_SIZE; sc = rtems_bdpart_read_mbr_partition( data, &p, p_end, &ep_begin); if (sc != RTEMS_SUCCESSFUL) { esc = sc; goto cleanup; } } /* Iterate through the logical partitions within the extended partition */ ebr = ep_begin; while (ebr != 0) { rtems_blkdev_bnum tmp = 0; /* Read EBR */ sc = rtems_bdpart_read_record( dd, ebr, &block); if (sc != RTEMS_SUCCESSFUL) { esc = sc; goto cleanup; } /* Read first partition entry */ sc = rtems_bdpart_read_mbr_partition( block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_0, &p, p_end, NULL ); if (sc != RTEMS_SUCCESSFUL) { esc = sc; goto cleanup; } /* Adjust partition begin */ tmp = p->begin + ebr; if (tmp > p->begin) { p->begin = tmp; } else { esc = RTEMS_IO_ERROR; goto cleanup; } /* Adjust partition end */ tmp = p->end + ebr; if (tmp > p->end) { p->end = tmp; } else { esc = RTEMS_IO_ERROR; goto cleanup; } /* Read second partition entry for next EBR block */ ebr = rtems_bdpart_next_ebr( block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_1 ); if (ebr != 0) { /* Adjust partition EBR block index */ tmp = ebr + ep_begin; if (tmp > ebr) { ebr = tmp; } else { esc = RTEMS_IO_ERROR; goto cleanup; } } } /* Return partition count */ *count = (size_t) (p - pt + 1); cleanup: if (fd >= 0) { close( fd); } if (block != NULL) { rtems_bdbuf_release( block); } return esc; }
static rtems_task Init(rtems_task_argument argument) { rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_task_priority cur_prio = 0; rtems_bdbuf_buffer *bd = NULL; dev_t dev = 0; rtems_test_begink(); sc = rtems_disk_io_initialize(); ASSERT_SC(sc); sc = ramdisk_register(BLOCK_SIZE_A, BLOCK_COUNT, false, "/dev/rda", &dev); ASSERT_SC(sc); dd = rtems_disk_obtain(dev); rtems_test_assert(dd != NULL); sc = rtems_task_create( rtems_build_name(' ', 'L', 'O', 'W'), PRIORITY_LOW, 0, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &task_id_low ); ASSERT_SC(sc); sc = rtems_task_start(task_id_low, task_low, 0); ASSERT_SC(sc); sc = rtems_task_create( rtems_build_name(' ', 'M', 'I', 'D'), PRIORITY_MID, 0, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &task_id_mid ); ASSERT_SC(sc); sc = rtems_task_start(task_id_mid, task_mid, 0); ASSERT_SC(sc); sc = rtems_task_create( rtems_build_name('H', 'I', 'G', 'H'), PRIORITY_HIGH, 0, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &task_id_high ); ASSERT_SC(sc); sc = rtems_task_start(task_id_high, task_high, 0); ASSERT_SC(sc); sc = rtems_task_suspend(task_id_mid); ASSERT_SC(sc); sc = rtems_task_suspend(task_id_high); ASSERT_SC(sc); sc = rtems_bdbuf_get(dd, 1, &bd); ASSERT_SC(sc); sc = rtems_bdbuf_release(bd); ASSERT_SC(sc); printk("I: try access: 0\n"); sc = rtems_bdbuf_get(dd, 0, &bd); ASSERT_SC(sc); printk("I: access: 0\n"); sc = rtems_task_set_priority(RTEMS_SELF, PRIORITY_IDLE, &cur_prio); ASSERT_SC(sc); sc = rtems_task_resume(task_id_high); ASSERT_SC(sc); sc = rtems_task_resume(task_id_mid); ASSERT_SC(sc); sc = rtems_task_set_priority(RTEMS_SELF, PRIORITY_INIT, &cur_prio); ASSERT_SC(sc); printk("I: release: 0\n"); sc = rtems_bdbuf_release(bd); ASSERT_SC(sc); printk("I: release done: 0\n"); rtems_task_delete(RTEMS_SELF); }
/** * Get the blocks 0 -> 4 and hold them. Wake the master to tell it was have the * buffers then wait for the master to tell us to release a single buffer. * Task 1 will be block waiting for each buffer. It is a higher priority. */ static void bdbuf_tests_task_0_test_2 (bdbuf_task_control* tc) { rtems_status_code sc; bool passed; int i; rtems_bdbuf_buffer* bd; rtems_chain_control buffers; /* * Set task control's passed to false to handle a timeout. */ tc->passed = false; passed = true; /* * 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_get[%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); } /* * Wake the master to tell it we have the buffers. */ bdbuf_send_wait_event (tc->name, "wake master", tc->master); if (passed) { /* * For each buffer we hold wait until the master wakes us * and then return it. Task 2 will block waiting for this * buffer. It is a higher priority task. */ for (i = 0; (i < 5) && passed; i++) { sc = bdbuf_wait (tc->name, BDBUF_SECONDS (5)); if (sc != RTEMS_SUCCESSFUL) { bdbuf_test_printf ("%s: wait failed: ", tc->name); bdbuf_test_print_sc (sc, true); passed = false; break; } else { bdbuf_test_printf ("%s: rtems_bdbuf_release[%d]: unblocks task 1\n", tc->name, i); bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers); sc = rtems_bdbuf_release (bd); bdbuf_test_printf ("%s: rtems_bdbuf_release[%d]: ", tc->name, i); if (!bdbuf_test_print_sc (sc, true)) { passed = false; break; } } } } tc->passed = passed; tc->test = 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; }
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; }