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; }
/* * 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; }
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(); }
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(); }
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; }
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; }
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(); }
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(); }
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_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(); }
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(); }
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; }
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; }
/* 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; }
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); } }
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"); }
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; }
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(); }
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; }
/** * 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; }
/* 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; }