static unsigned int test_rw(HANDLE hDrive, blk_t last_block, size_t block_size, blk_t first_block, size_t blocks_at_once, int nb_passes) { unsigned char *buffer = NULL, *read_buffer; const unsigned int pattern[] = {0xaa, 0x55, 0xff, 0x00}; int i, pat_idx; unsigned int bb_count = 0; blk_t got, tryout, recover_block = ~0, *blk_id; size_t id_offset; if ((nb_passes < 1) || (nb_passes > 4)) { uprintf("%sInvalid number of passes\n", bb_prefix); cancel_ops = -1; return 0; } buffer = allocate_buffer(2 * blocks_at_once * block_size); read_buffer = buffer + blocks_at_once * block_size; if (!buffer) { uprintf("%sError while allocating buffers\n", bb_prefix); cancel_ops = -1; return 0; } uprintf("%sChecking from block %lu to %lu\n", bb_prefix, (unsigned long) first_block, (unsigned long) last_block - 1); nr_pattern = nb_passes; cur_pattern = 0; for (pat_idx = 0; pat_idx < nb_passes; pat_idx++) { if (cancel_ops) goto out; srand((unsigned int)GetTickCount()); id_offset = rand()* (block_size-sizeof(blk_t)) / RAND_MAX; pattern_fill(buffer, pattern[pat_idx], blocks_at_once * block_size); uprintf("%sBlock ID at offset: %d\n", bb_prefix, id_offset); num_blocks = last_block - 1; currently_testing = first_block; if (s_flag | v_flag) uprintf("%sWriting test pattern 0x%02X\n", bb_prefix, pattern[pat_idx]); cur_op = OP_WRITE; tryout = blocks_at_once; while (currently_testing < last_block) { if (cancel_ops) goto out; if (max_bb && bb_count >= max_bb) { if (s_flag || v_flag) { uprintf(abort_msg); fprintf(log_fd, abort_msg); fflush(log_fd); } cancel_ops = -1; goto out; } if (currently_testing + tryout > last_block) tryout = last_block - currently_testing; if (detect_fakes) { /* Add the block number at a fixed (random) offset during each pass to allow for the detection of 'fake' media (eg. 2GB USB masquerading as 16GB) */ for (i=0; i<(int)blocks_at_once; i++) { blk_id = (blk_t*)(intptr_t)(buffer + id_offset+ i*block_size); *blk_id = (blk_t)(currently_testing + i); } } got = do_write(hDrive, buffer, tryout, block_size, currently_testing); if (v_flag > 1) print_status(); if (got == 0 && tryout == 1) bb_count += bb_output(currently_testing++, WRITE_ERROR); currently_testing += got; if (got != tryout) { tryout = 1; if (recover_block == ~0) recover_block = currently_testing - got + blocks_at_once; continue; } else if (currently_testing == recover_block) { tryout = blocks_at_once; recover_block = ~0; } } num_blocks = 0; if (s_flag | v_flag) uprintf("%sReading and comparing\n", bb_prefix); cur_op = OP_READ; num_blocks = last_block; currently_testing = first_block; tryout = blocks_at_once; while (currently_testing < last_block) { if (cancel_ops) goto out; if (max_bb && bb_count >= max_bb) { if (s_flag || v_flag) { uprintf(abort_msg); fprintf(log_fd, abort_msg); fflush(log_fd); } cancel_ops = -1; goto out; } if (currently_testing + tryout > last_block) tryout = last_block - currently_testing; if (detect_fakes) { for (i=0; i<(int)blocks_at_once; i++) { blk_id = (blk_t*)(intptr_t)(buffer + id_offset+ i*block_size); *blk_id = (blk_t)(currently_testing + i); } } got = do_read(hDrive, read_buffer, tryout, block_size, currently_testing); if (got == 0 && tryout == 1) bb_count += bb_output(currently_testing++, READ_ERROR); currently_testing += got; if (got != tryout) { tryout = 1; if (recover_block == ~0) recover_block = currently_testing - got + blocks_at_once; continue; } else if (currently_testing == recover_block) { tryout = blocks_at_once; recover_block = ~0; } for (i=0; i < got; i++) { if (memcmp(read_buffer + i * block_size, buffer + i * block_size, block_size)) bb_count += bb_output(currently_testing+i-got, CORRUPTION_ERROR); } if (v_flag > 1) print_status(); } num_blocks = 0; } out: free_buffer(buffer); return bb_count; }
static unsigned int test_rw(HANDLE hDrive, blk64_t last_block, size_t block_size, blk64_t first_block, size_t blocks_at_once, int pattern_type, int nb_passes) { const unsigned int pattern[BADLOCKS_PATTERN_TYPES][BADBLOCK_PATTERN_COUNT] = { BADBLOCK_PATTERN_SLC, BADCLOCK_PATTERN_MLC, BADBLOCK_PATTERN_TLC }; unsigned char *buffer = NULL, *read_buffer; int i, pat_idx; unsigned int bb_count = 0; blk64_t got, tryout, recover_block = ~0, *blk_id; size_t id_offset = 0; if ((pattern_type < 0) || (pattern_type >= BADLOCKS_PATTERN_TYPES)) { uprintf("%sInvalid pattern type\n", bb_prefix); cancel_ops = -1; return 0; } if ((nb_passes < 1) || (nb_passes > BADBLOCK_PATTERN_COUNT)) { uprintf("%sInvalid number of passes\n", bb_prefix); cancel_ops = -1; return 0; } buffer = allocate_buffer(2 * blocks_at_once * block_size); read_buffer = buffer + blocks_at_once * block_size; if (!buffer) { uprintf("%sError while allocating buffers\n", bb_prefix); cancel_ops = -1; return 0; } uprintf("%sChecking from block %lu to %lu (1 block = %s)\n", bb_prefix, (unsigned long) first_block, (unsigned long) last_block - 1, SizeToHumanReadable(BADBLOCK_BLOCK_SIZE, FALSE, FALSE)); nr_pattern = nb_passes; cur_pattern = 0; for (pat_idx = 0; pat_idx < nb_passes; pat_idx++) { if (cancel_ops) goto out; if (detect_fakes && (pat_idx == 0)) { srand((unsigned int)GetTickCount64()); id_offset = rand() * (block_size - sizeof(blk64_t)) / RAND_MAX; uprintf("%sUsing offset %d for fake device check\n", bb_prefix, id_offset); } // coverity[dont_call] pattern_fill(buffer, pattern[pattern_type][pat_idx], blocks_at_once * block_size); num_blocks = last_block - 1; currently_testing = first_block; if (s_flag | v_flag) uprintf("%sWriting test pattern 0x%02X\n", bb_prefix, pattern[pattern_type][pat_idx]); cur_op = OP_WRITE; tryout = blocks_at_once; while (currently_testing < last_block) { if (cancel_ops) goto out; if (max_bb && bb_count >= max_bb) { if (s_flag || v_flag) { uprintf(abort_msg); fprintf(log_fd, abort_msg); fflush(log_fd); } cancel_ops = -1; goto out; } if (currently_testing + tryout > last_block) tryout = last_block - currently_testing; if (detect_fakes && (pat_idx == 0)) { /* Add the block number at a fixed (random) offset during each pass to allow for the detection of 'fake' media (eg. 2GB USB masquerading as 16GB) */ for (i=0; i<(int)blocks_at_once; i++) { blk_id = (blk64_t*)(intptr_t)(buffer + id_offset+ i*block_size); *blk_id = (blk64_t)(currently_testing + i); } } got = do_write(hDrive, buffer, tryout, block_size, currently_testing); if (v_flag > 1) print_status(); if (got == 0 && tryout == 1) bb_count += bb_output(currently_testing++, WRITE_ERROR); currently_testing += got; if (got != tryout) { tryout = 1; if (recover_block == ~0) recover_block = currently_testing - got + blocks_at_once; continue; } else if (currently_testing == recover_block) { tryout = blocks_at_once; recover_block = ~0; } } num_blocks = 0; if (s_flag | v_flag) uprintf("%sReading and comparing\n", bb_prefix); cur_op = OP_READ; num_blocks = last_block; currently_testing = first_block; tryout = blocks_at_once; while (currently_testing < last_block) { if (cancel_ops) goto out; if (max_bb && bb_count >= max_bb) { if (s_flag || v_flag) { uprintf(abort_msg); fprintf(log_fd, abort_msg); fflush(log_fd); } cancel_ops = -1; goto out; } if (currently_testing + tryout > last_block) tryout = last_block - currently_testing; if (detect_fakes && (pat_idx == 0)) { for (i=0; i<(int)blocks_at_once; i++) { blk_id = (blk64_t*)(intptr_t)(buffer + id_offset+ i*block_size); *blk_id = (blk64_t)(currently_testing + i); } } got = do_read(hDrive, read_buffer, tryout, block_size, currently_testing); if (got == 0 && tryout == 1) bb_count += bb_output(currently_testing++, READ_ERROR); currently_testing += got; if (got != tryout) { tryout = 1; if (recover_block == ~0) recover_block = currently_testing - got + blocks_at_once; continue; } else if (currently_testing == recover_block) { tryout = blocks_at_once; recover_block = ~0; } for (i=0; i < got; i++) { if (memcmp(read_buffer + i * block_size, buffer + i * block_size, block_size)) bb_count += bb_output(currently_testing+i-got, CORRUPTION_ERROR); } if (v_flag > 1) print_status(); } num_blocks = 0; } out: free_buffer(buffer); return bb_count; }