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