void test_wait_for_threads_finish( const object_t* threads, unsigned int num_threads ) { unsigned int i; bool waiting = true; while( waiting ) { waiting = false; atomic_thread_fence_acquire(); for( i = 0; i < num_threads; ++i ) { if( thread_is_running( threads[i] ) ) { waiting = true; break; } } } }
int main_run(void* main_arg) { #if !BUILD_MONOLITHIC string_const_t pattern; string_t* exe_paths = 0; size_t iexe, exesize; process_t* process = 0; string_t process_path = { 0, 0 }; unsigned int* exe_flags = 0; #else void* test_result; #endif #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID || FOUNDATION_PLATFORM_PNACL int remain_counter = 0; #endif #if BUILD_DEBUG const string_const_t build_name = string_const(STRING_CONST("debug")); #elif BUILD_RELEASE const string_const_t build_name = string_const(STRING_CONST("release")); #elif BUILD_PROFILE const string_const_t build_name = string_const(STRING_CONST("profile")); #elif BUILD_DEPLOY const string_const_t build_name = string_const(STRING_CONST("deploy")); #endif #if BUILD_MONOLITHIC const string_const_t build_type = string_const(STRING_CONST(" monolithic")); #else const string_const_t build_type = string_empty(); #endif char* pathbuf; int process_result = 0; thread_t event_thread; FOUNDATION_UNUSED(main_arg); FOUNDATION_UNUSED(build_name); log_set_suppress(HASH_TEST, ERRORLEVEL_DEBUG); log_infof(HASH_TEST, STRING_CONST("Task library v%s built for %s using %s (%.*s%.*s)"), string_from_version_static(task_module_version()).str, FOUNDATION_PLATFORM_DESCRIPTION, FOUNDATION_COMPILER_DESCRIPTION, STRING_FORMAT(build_name), STRING_FORMAT(build_type)); thread_initialize(&event_thread, event_loop, 0, STRING_CONST("event_thread"), THREAD_PRIORITY_NORMAL, 0); thread_start(&event_thread); pathbuf = memory_allocate(HASH_STRING, BUILD_MAX_PATHLEN, 0, MEMORY_PERSISTENT); while (!thread_is_running(&event_thread)) thread_sleep(10); #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID || FOUNDATION_PLATFORM_PNACL while (!_test_should_start) { #if FOUNDATION_PLATFORM_ANDROID system_process_events(); #endif thread_sleep(100); } #endif fs_remove_directory(STRING_ARGS(environment_temporary_directory())); #if BUILD_MONOLITHIC test_run_fn tests[] = { test_task_run, 0 }; #if FOUNDATION_PLATFORM_ANDROID thread_t test_thread; thread_initialize(&test_thread, test_runner, tests, STRING_CONST("test_runner"), THREAD_PRIORITY_NORMAL, 0); thread_start(&test_thread); log_debug(HASH_TEST, STRING_CONST("Starting test runner thread")); while (!thread_is_running(&test_thread)) { system_process_events(); thread_sleep(10); } while (thread_is_running(&test_thread)) { system_process_events(); thread_sleep(10); } test_result = thread_join(&test_thread); process_result = (int)(intptr_t)test_result; thread_finalize(&test_thread); #else test_result = test_runner(tests); process_result = (int)(intptr_t)test_result; #endif if (process_result != 0) log_warnf(HASH_TEST, WARNING_SUSPICIOUS, STRING_CONST("Tests failed with exit code %d"), process_result); #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID || FOUNDATION_PLATFORM_PNACL while (!_test_should_terminate && _test_have_focus && (remain_counter < 50)) { system_process_events(); thread_sleep(100); ++remain_counter; } #endif log_debug(HASH_TEST, STRING_CONST("Exiting main loop")); #else // !BUILD_MONOLITHIC //Find all test executables in the current executable directory #if FOUNDATION_PLATFORM_WINDOWS pattern = string_const(STRING_CONST("^test-.*\\.exe$")); #elif FOUNDATION_PLATFORM_MACOSX pattern = string_const(STRING_CONST("^test-.*$")); #elif FOUNDATION_PLATFORM_POSIX pattern = string_const(STRING_CONST("^test-.*$")); #else # error Not implemented #endif exe_paths = fs_matching_files(STRING_ARGS(environment_executable_directory()), STRING_ARGS(pattern), false); array_resize(exe_flags, array_size(exe_paths)); memset(exe_flags, 0, sizeof(unsigned int) * array_size(exe_flags)); #if FOUNDATION_PLATFORM_MACOSX //Also search for test applications string_const_t app_pattern = string_const(STRING_CONST("^test-.*\\.app$")); regex_t* app_regex = regex_compile(app_pattern.str, app_pattern.length); string_t* subdirs = fs_subdirs(STRING_ARGS(environment_executable_directory())); for (size_t idir = 0, dirsize = array_size(subdirs); idir < dirsize; ++idir) { if (regex_match(app_regex, subdirs[idir].str, subdirs[idir].length, 0, 0)) { string_t exe_path = { subdirs[idir].str, subdirs[idir].length - 4 }; array_push(exe_paths, exe_path); array_push(exe_flags, PROCESS_MACOSX_USE_OPENAPPLICATION); } } string_array_deallocate(subdirs); regex_deallocate(app_regex); #endif for (iexe = 0, exesize = array_size(exe_paths); iexe < exesize; ++iexe) { string_const_t* process_args = 0; string_const_t exe_file_name = path_base_file_name(STRING_ARGS(exe_paths[iexe])); if (string_equal(STRING_ARGS(exe_file_name), STRING_ARGS(environment_executable_name()))) continue; //Don't run self process_path = path_concat(pathbuf, BUILD_MAX_PATHLEN, STRING_ARGS(environment_executable_directory()), STRING_ARGS(exe_paths[iexe])); process = process_allocate(); process_set_executable_path(process, STRING_ARGS(process_path)); process_set_working_directory(process, STRING_ARGS(environment_executable_directory())); process_set_flags(process, PROCESS_ATTACHED | exe_flags[iexe]); if (!_test_memory_tracker) array_push(process_args, string_const(STRING_CONST("--no-memory-tracker"))); process_set_arguments(process, process_args, array_size(process_args)); log_infof(HASH_TEST, STRING_CONST("Running test executable: %.*s"), STRING_FORMAT(exe_paths[iexe])); process_result = process_spawn(process); while (process_result == PROCESS_WAIT_INTERRUPTED) { thread_sleep(10); process_result = process_wait(process); } process_deallocate(process); array_deallocate(process_args); if (process_result != 0) { if (process_result >= PROCESS_INVALID_ARGS) log_warnf(HASH_TEST, WARNING_SUSPICIOUS, STRING_CONST("Tests failed, process terminated with error %x"), process_result); else log_warnf(HASH_TEST, WARNING_SUSPICIOUS, STRING_CONST("Tests failed with exit code %d"), process_result); process_set_exit_code(-1); goto exit; } log_infof(HASH_TEST, STRING_CONST("All tests from %.*s passed (%d)"), STRING_FORMAT(exe_paths[iexe]), process_result); } log_info(HASH_TEST, STRING_CONST("All tests passed")); exit: if (exe_paths) string_array_deallocate(exe_paths); array_deallocate(exe_flags); #endif _test_should_terminate = true; thread_signal(&event_thread); thread_finalize(&event_thread); memory_deallocate(pathbuf); log_infof(HASH_TEST, STRING_CONST("Tests exiting: %s (%d)"), process_result ? "FAILED" : "PASSED", process_result); if (process_result) memory_set_tracker(memory_tracker_none()); return process_result; }
int main_run( void* main_arg ) { #if !BUILD_MONOLITHIC const char* pattern = 0; char** exe_paths = 0; unsigned int iexe, exesize; process_t* process = 0; char* process_path = 0; unsigned int* exe_flags = 0; #endif #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID || FOUNDATION_PLATFORM_PNACL int remain_counter = 0; #endif #if BUILD_DEBUG const char* build_name = "debug"; #elif BUILD_RELEASE const char* build_name = "release"; #elif BUILD_PROFILE const char* build_name = "profile"; #elif BUILD_DEPLOY const char* build_name = "deploy"; #endif int process_result = 0; object_t thread = 0; FOUNDATION_UNUSED( main_arg ); FOUNDATION_UNUSED( build_name ); log_set_suppress( HASH_TEST, ERRORLEVEL_DEBUG ); log_infof( HASH_TEST, "Foundation library v%s built for %s using %s (%s)", string_from_version_static( foundation_version() ), FOUNDATION_PLATFORM_DESCRIPTION, FOUNDATION_COMPILER_DESCRIPTION, build_name ); thread = thread_create( event_thread, "event_thread", THREAD_PRIORITY_NORMAL, 0 ); thread_start( thread, 0 ); while( !thread_is_running( thread ) ) thread_sleep( 10 ); #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID while( !_test_should_start ) { #if FOUNDATION_PLATFORM_ANDROID system_process_events(); #endif thread_sleep( 100 ); } #endif fs_remove_directory( environment_temporary_directory() ); #if BUILD_MONOLITHIC test_run_fn tests[] = { test_app_run, test_array_run, test_atomic_run, test_base64_run, test_bitbuffer_run, test_blowfish_run, test_bufferstream_run, test_config_run, test_crash_run, test_environment_run, test_error_run, test_event_run, test_fs_run, test_hash_run, test_hashmap_run, test_hashtable_run, test_library_run, test_math_run, test_md5_run, test_mutex_run, test_objectmap_run, test_path_run, test_pipe_run, test_process_run, test_profile_run, test_radixsort_run, test_random_run, test_regex_run, test_ringbuffer_run, test_semaphore_run, test_stacktrace_run, test_stream_run, //stream test closes stdin test_string_run, test_system_run, test_time_run, test_uuid_run, 0 }; #if FOUNDATION_PLATFORM_ANDROID object_t test_thread = thread_create( test_runner, "test_runner", THREAD_PRIORITY_NORMAL, 0 ); thread_start( test_thread, tests ); log_debug( HASH_TEST, "Starting test runner thread" ); while( !thread_is_running( test_thread ) ) { system_process_events(); thread_sleep( 10 ); } while( thread_is_running( test_thread ) ) { system_process_events(); thread_sleep( 10 ); } process_result = (int)(intptr_t)thread_result( test_thread ); thread_destroy( test_thread ); while( thread_is_thread( test_thread ) ) { system_process_events(); thread_sleep( 10 ); } #else process_result = (int)(intptr_t)test_runner( 0, tests ); #endif if( process_result != 0 ) log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed with exit code %d", process_result ); #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID || FOUNDATION_PLATFORM_PNACL while( !_test_should_terminate && _test_have_focus && ( remain_counter < 50 ) ) { system_process_events(); thread_sleep( 100 ); ++remain_counter; } #endif log_debug( HASH_TEST, "Exiting main loop" ); #else // !BUILD_MONOLITHIC //Find all test executables in the current executable directory #if FOUNDATION_PLATFORM_WINDOWS pattern = "^test-.*\\.exe$"; #elif FOUNDATION_PLATFORM_MACOSX pattern = "^test-.*$"; #elif FOUNDATION_PLATFORM_POSIX pattern = "^test-.*$"; #else # error Not implemented #endif exe_paths = fs_matching_files( environment_executable_directory(), pattern, false ); array_resize( exe_flags, array_size( exe_paths ) ); memset( exe_flags, 0, sizeof( unsigned int ) * array_size( exe_flags ) ); #if FOUNDATION_PLATFORM_MACOSX //Also search for test applications const char* app_pattern = "^test-.*\\.app$"; regex_t* app_regex = regex_compile( app_pattern ); char** subdirs = fs_subdirs( environment_executable_directory() ); for( int idir = 0, dirsize = array_size( subdirs ); idir < dirsize; ++idir ) { if( regex_match( app_regex, subdirs[idir], string_length( subdirs[idir] ), 0, 0 ) ) { array_push( exe_paths, string_substr( subdirs[idir], 0, string_length( subdirs[idir] ) - 4 ) ); array_push( exe_flags, PROCESS_MACOSX_USE_OPENAPPLICATION ); } } string_array_deallocate( subdirs ); regex_deallocate( app_regex ); #endif for( iexe = 0, exesize = array_size( exe_paths ); iexe < exesize; ++iexe ) { bool is_self = false; char* exe_file_name = path_base_file_name( exe_paths[iexe] ); if( string_equal( exe_file_name, environment_executable_name() ) ) is_self = true; string_deallocate( exe_file_name ); if( is_self ) continue; //Don't run self process_path = path_merge( environment_executable_directory(), exe_paths[iexe] ); process = process_allocate(); process_set_executable_path( process, process_path ); process_set_working_directory( process, environment_executable_directory() ); process_set_flags( process, PROCESS_ATTACHED | exe_flags[iexe] ); log_infof( HASH_TEST, "Running test executable: %s", exe_paths[iexe] ); process_result = process_spawn( process ); while( process_result == PROCESS_WAIT_INTERRUPTED ) { thread_sleep( 10 ); process_result = process_wait( process ); } process_deallocate( process ); string_deallocate( process_path ); if( process_result != 0 ) { if( process_result >= PROCESS_INVALID_ARGS ) log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed, process terminated with error %x", process_result ); else log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed with exit code %d", process_result ); process_set_exit_code( -1 ); goto exit; } log_infof( HASH_TEST, "All tests from %s passed (%d)", exe_paths[iexe], process_result ); } log_info( HASH_TEST, "All tests passed" ); exit: if( exe_paths ) string_array_deallocate( exe_paths ); array_deallocate( exe_flags ); #endif thread_terminate( thread ); thread_destroy( thread ); while( thread_is_running( thread ) ) thread_sleep( 10 ); while( thread_is_thread( thread ) ) thread_sleep( 10 ); log_infof( HASH_TEST, "Tests exiting: %d", process_result ); return process_result; }
/** * Verification thread to check parent FID consistency. * * Kernel thread to check consistency of parent FID for any * new item added for checking by ofd_add_inconsistency_item(). * * \param[in] args OFD device * * \retval 0 on successful thread termination * \retval negative value if thread can't start */ static int ofd_inconsistency_verification_main(void *args) { struct lu_env env; struct ofd_device *ofd = args; struct ptlrpc_thread *thread = &ofd->ofd_inconsistency_thread; struct ofd_inconsistency_item *oii; struct lfsck_request *lr = NULL; struct l_wait_info lwi = { 0 }; int rc; ENTRY; rc = lu_env_init(&env, LCT_DT_THREAD); spin_lock(&ofd->ofd_inconsistency_lock); thread_set_flags(thread, rc != 0 ? SVC_STOPPED : SVC_RUNNING); wake_up_all(&thread->t_ctl_waitq); spin_unlock(&ofd->ofd_inconsistency_lock); if (rc != 0) RETURN(rc); OBD_ALLOC_PTR(lr); if (unlikely(lr == NULL)) GOTO(out_unlocked, rc = -ENOMEM); lr->lr_event = LE_PAIRS_VERIFY; lr->lr_active = LFSCK_TYPE_LAYOUT; spin_lock(&ofd->ofd_inconsistency_lock); while (1) { if (unlikely(!thread_is_running(thread))) break; while (!list_empty(&ofd->ofd_inconsistency_list)) { oii = list_entry(ofd->ofd_inconsistency_list.next, struct ofd_inconsistency_item, oii_list); list_del_init(&oii->oii_list); spin_unlock(&ofd->ofd_inconsistency_lock); ofd_inconsistency_verify_one(&env, ofd, oii, lr); spin_lock(&ofd->ofd_inconsistency_lock); } spin_unlock(&ofd->ofd_inconsistency_lock); l_wait_event(thread->t_ctl_waitq, !list_empty(&ofd->ofd_inconsistency_list) || !thread_is_running(thread), &lwi); spin_lock(&ofd->ofd_inconsistency_lock); } while (!list_empty(&ofd->ofd_inconsistency_list)) { struct ofd_object *fo; oii = list_entry(ofd->ofd_inconsistency_list.next, struct ofd_inconsistency_item, oii_list); list_del_init(&oii->oii_list); fo = oii->oii_obj; spin_unlock(&ofd->ofd_inconsistency_lock); ofd_write_lock(&env, fo); fo->ofo_pfid_checking = 0; ofd_write_unlock(&env, fo); lu_object_put(&env, &fo->ofo_obj.do_lu); OBD_FREE_PTR(oii); spin_lock(&ofd->ofd_inconsistency_lock); } OBD_FREE_PTR(lr); GOTO(out, rc = 0); out_unlocked: spin_lock(&ofd->ofd_inconsistency_lock); out: thread_set_flags(thread, SVC_STOPPED); wake_up_all(&thread->t_ctl_waitq); spin_unlock(&ofd->ofd_inconsistency_lock); lu_env_fini(&env); return rc; }
DECLARE_TEST( ringbufferstream, threadedio ) { ringbufferstream_test_t test = {0}; uint32_t* srcbuffer; unsigned int si; unsigned int loop, loops; real elapsed, throughput; unsigned int mbytes; #if FOUNDATION_PLATFORM_ANDROID || FOUNDATION_PLATFORM_IOS mbytes = 16; loops = 32; #else mbytes = 256; loops = 16; #endif test.buffer_size = mbytes * 1024 * 1024; srcbuffer = memory_allocate( test.buffer_size, 0, MEMORY_PERSISTENT ); test.source_buffer = (void*)srcbuffer; test.dest_buffer = memory_allocate_zero( test.buffer_size, 0, MEMORY_PERSISTENT ); for( si = 0; si < ( test.buffer_size / 4 ); ++si ) srcbuffer[si] = random32(); elapsed = 0; for( loop = 0; loop < loops; ++loop ) { test.stream = ringbuffer_stream_allocate( 23477, test.buffer_size ); test.read_thread = thread_create( read_thread, "reader", THREAD_PRIORITY_NORMAL, 0 ); test.write_thread = thread_create( write_thread, "writer", THREAD_PRIORITY_NORMAL, 0 ); thread_start( test.read_thread, &test ); thread_start( test.write_thread, &test ); thread_sleep( 100 ); while( thread_is_running( test.read_thread ) || thread_is_running( test.write_thread ) ) thread_sleep( 10 ); thread_destroy( test.read_thread ); thread_destroy( test.write_thread ); for( si = 0; si < test.buffer_size; ++si ) EXPECT_EQ( test.source_buffer[si], test.dest_buffer[si] ); stream_deallocate( test.stream ); elapsed += time_ticks_to_seconds( time_diff( test.start_time, test.end_time ) ); } throughput = (real)( (float64_t)( mbytes * loops ) / (float64_t)elapsed ); log_infof( HASH_TEST, "Ringbuffer throughput: %d MiB in %.2f sec -> %.2f MiB/sec", ( loops * mbytes ), (float32_t)elapsed, (float32_t)throughput ); elapsed = 0; for( loop = 0; loop < loops; ++loop ) { test.start_time = time_current(); memcpy( test.dest_buffer, test.source_buffer, test.buffer_size ); test.end_time = time_current(); for( si = 0; si < test.buffer_size; ++si ) EXPECT_EQ( test.source_buffer[si], test.dest_buffer[si] ); elapsed += time_ticks_to_seconds( time_diff( test.start_time, test.end_time ) ); } throughput = (real)( (float64_t)( mbytes * loops ) / (float64_t)elapsed ); log_infof( HASH_TEST, "Memcpy throughput: %d MiB in %.2f sec -> %.2f MiB/sec", ( loops * mbytes ), (float32_t)elapsed, (float32_t)throughput ); memory_deallocate( test.source_buffer ); memory_deallocate( test.dest_buffer ); return 0; }
int lfsck_master_engine(void *args) { struct lfsck_thread_args *lta = args; struct lu_env *env = <a->lta_env; struct lfsck_instance *lfsck = lta->lta_lfsck; struct ptlrpc_thread *thread = &lfsck->li_thread; struct dt_object *oit_obj = lfsck->li_obj_oit; const struct dt_it_ops *oit_iops = &oit_obj->do_index_ops->dio_it; struct dt_it *oit_di; struct l_wait_info lwi = { 0 }; int rc; ENTRY; oit_di = oit_iops->init(env, oit_obj, lfsck->li_args_oit, BYPASS_CAPA); if (IS_ERR(oit_di)) { rc = PTR_ERR(oit_di); CERROR("%s: LFSCK, fail to init iteration: rc = %d\n", lfsck_lfsck2name(lfsck), rc); GOTO(fini_args, rc); } spin_lock(&lfsck->li_lock); lfsck->li_di_oit = oit_di; spin_unlock(&lfsck->li_lock); rc = lfsck_prep(env, lfsck, lta->lta_lsp); if (rc != 0) GOTO(fini_oit, rc); CDEBUG(D_LFSCK, "LFSCK entry: oit_flags = %#x, dir_flags = %#x, " "oit_cookie = "LPU64", dir_cookie = "LPU64", parent = "DFID ", pid = %d\n", lfsck->li_args_oit, lfsck->li_args_dir, lfsck->li_pos_current.lp_oit_cookie, lfsck->li_pos_current.lp_dir_cookie, PFID(&lfsck->li_pos_current.lp_dir_parent), current_pid()); spin_lock(&lfsck->li_lock); thread_set_flags(thread, SVC_RUNNING); spin_unlock(&lfsck->li_lock); wake_up_all(&thread->t_ctl_waitq); l_wait_event(thread->t_ctl_waitq, lfsck->li_start_unplug || !thread_is_running(thread), &lwi); if (!thread_is_running(thread)) GOTO(fini_oit, rc = 0); if (!cfs_list_empty(&lfsck->li_list_scan) || cfs_list_empty(&lfsck->li_list_double_scan)) rc = lfsck_master_oit_engine(env, lfsck); else rc = 1; CDEBUG(D_LFSCK, "LFSCK exit: oit_flags = %#x, dir_flags = %#x, " "oit_cookie = "LPU64", dir_cookie = "LPU64", parent = "DFID ", pid = %d, rc = %d\n", lfsck->li_args_oit, lfsck->li_args_dir, lfsck->li_pos_current.lp_oit_cookie, lfsck->li_pos_current.lp_dir_cookie, PFID(&lfsck->li_pos_current.lp_dir_parent), current_pid(), rc); if (!OBD_FAIL_CHECK(OBD_FAIL_LFSCK_CRASH)) rc = lfsck_post(env, lfsck, rc); if (lfsck->li_di_dir != NULL) lfsck_close_dir(env, lfsck); fini_oit: lfsck_di_oit_put(env, lfsck); oit_iops->fini(env, oit_di); if (rc == 1) { if (!cfs_list_empty(&lfsck->li_list_double_scan)) rc = lfsck_double_scan(env, lfsck); else rc = 0; } else { lfsck_quit(env, lfsck); } /* XXX: Purge the pinned objects in the future. */ fini_args: spin_lock(&lfsck->li_lock); thread_set_flags(thread, SVC_STOPPED); spin_unlock(&lfsck->li_lock); wake_up_all(&thread->t_ctl_waitq); lfsck_thread_args_fini(lta); return rc; }
static int lfsck_master_oit_engine(const struct lu_env *env, struct lfsck_instance *lfsck) { struct lfsck_thread_info *info = lfsck_env_info(env); const struct dt_it_ops *iops = &lfsck->li_obj_oit->do_index_ops->dio_it; struct dt_it *di = lfsck->li_di_oit; struct lu_fid *fid = &info->lti_fid; struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram; struct ptlrpc_thread *thread = &lfsck->li_thread; __u32 idx = lfsck_dev_idx(lfsck->li_bottom); int rc; ENTRY; do { struct dt_object *target; bool update_lma = false; if (lfsck->li_di_dir != NULL) { rc = lfsck_master_dir_engine(env, lfsck); if (rc <= 0) RETURN(rc); } if (unlikely(lfsck->li_oit_over)) RETURN(1); if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_DELAY1) && cfs_fail_val > 0) { struct l_wait_info lwi; lwi = LWI_TIMEOUT(cfs_time_seconds(cfs_fail_val), NULL, NULL); l_wait_event(thread->t_ctl_waitq, !thread_is_running(thread), &lwi); } if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_CRASH)) RETURN(0); lfsck->li_current_oit_processed = 1; lfsck->li_new_scanned++; rc = iops->rec(env, di, (struct dt_rec *)fid, 0); if (rc != 0) { lfsck_fail(env, lfsck, true); if (rc < 0 && bk->lb_param & LPF_FAILOUT) RETURN(rc); else goto checkpoint; } if (fid_is_idif(fid)) { __u32 idx1 = fid_idif_ost_idx(fid); LASSERT(!lfsck->li_master); /* It is an old format device, update the LMA. */ if (idx != idx1) { struct ost_id *oi = &info->lti_oi; fid_to_ostid(fid, oi); ostid_to_fid(fid, oi, idx); update_lma = true; } } else if (!fid_is_norm(fid) && !fid_is_igif(fid) && !fid_is_last_id(fid) && !fid_is_root(fid) && !fid_seq_is_dot(fid_seq(fid))) { /* If the FID/object is only used locally and invisible * to external nodes, then LFSCK will not handle it. */ goto checkpoint; } target = lfsck_object_find(env, lfsck, fid); if (target == NULL) { goto checkpoint; } else if (IS_ERR(target)) { lfsck_fail(env, lfsck, true); if (bk->lb_param & LPF_FAILOUT) RETURN(PTR_ERR(target)); else goto checkpoint; } /* XXX: Currently, skip remote object, the consistency for * remote object will be processed in LFSCK phase III. */ if (dt_object_exists(target) && !dt_object_remote(target)) { if (update_lma) rc = lfsck_update_lma(env, lfsck, target); if (rc == 0) rc = lfsck_exec_oit(env, lfsck, target); } lfsck_object_put(env, target); if (rc != 0 && bk->lb_param & LPF_FAILOUT) RETURN(rc); checkpoint: rc = lfsck_checkpoint(env, lfsck); if (rc != 0 && bk->lb_param & LPF_FAILOUT) RETURN(rc); /* Rate control. */ lfsck_control_speed(lfsck); if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_FATAL1)) { spin_lock(&lfsck->li_lock); thread_set_flags(thread, SVC_STOPPING); spin_unlock(&lfsck->li_lock); RETURN(-EINVAL); } rc = iops->next(env, di); if (unlikely(rc > 0)) lfsck->li_oit_over = 1; else if (likely(rc == 0)) lfsck->li_current_oit_processed = 0; if (unlikely(!thread_is_running(thread))) RETURN(0); } while (rc == 0 || lfsck->li_di_dir != NULL); RETURN(rc); }
static int lfsck_master_dir_engine(const struct lu_env *env, struct lfsck_instance *lfsck) { struct lfsck_thread_info *info = lfsck_env_info(env); const struct dt_it_ops *iops = &lfsck->li_obj_dir->do_index_ops->dio_it; struct dt_it *di = lfsck->li_di_dir; struct lu_dirent *ent = &info->lti_ent; struct lu_fid *fid = &info->lti_fid; struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram; struct ptlrpc_thread *thread = &lfsck->li_thread; int rc; ENTRY; do { struct dt_object *child; if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_DELAY2) && cfs_fail_val > 0) { struct l_wait_info lwi; lwi = LWI_TIMEOUT(cfs_time_seconds(cfs_fail_val), NULL, NULL); l_wait_event(thread->t_ctl_waitq, !thread_is_running(thread), &lwi); } lfsck->li_new_scanned++; rc = iops->rec(env, di, (struct dt_rec *)ent, lfsck->li_args_dir); lfsck_unpack_ent(ent, &lfsck->li_cookie_dir); if (rc != 0) { lfsck_fail(env, lfsck, true); if (bk->lb_param & LPF_FAILOUT) RETURN(rc); else goto checkpoint; } if (ent->lde_attrs & LUDA_IGNORE) goto checkpoint; *fid = ent->lde_fid; child = lfsck_object_find(env, lfsck, fid); if (child == NULL) { goto checkpoint; } else if (IS_ERR(child)) { lfsck_fail(env, lfsck, true); if (bk->lb_param & LPF_FAILOUT) RETURN(PTR_ERR(child)); else goto checkpoint; } /* XXX: Currently, skip remote object, the consistency for * remote object will be processed in LFSCK phase III. */ if (dt_object_exists(child) && !dt_object_remote(child)) rc = lfsck_exec_dir(env, lfsck, child, ent); lfsck_object_put(env, child); if (rc != 0 && bk->lb_param & LPF_FAILOUT) RETURN(rc); checkpoint: rc = lfsck_checkpoint(env, lfsck); if (rc != 0 && bk->lb_param & LPF_FAILOUT) RETURN(rc); /* Rate control. */ lfsck_control_speed(lfsck); if (unlikely(!thread_is_running(thread))) RETURN(0); if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_FATAL2)) { spin_lock(&lfsck->li_lock); thread_set_flags(thread, SVC_STOPPING); spin_unlock(&lfsck->li_lock); RETURN(-EINVAL); } rc = iops->next(env, di); } while (rc == 0); if (rc > 0 && !lfsck->li_oit_over) lfsck_close_dir(env, lfsck); RETURN(rc); }
DECLARE_TEST( event, delay_threaded ) { object_t thread[32]; producer_thread_arg_t args[32] = {0}; event_stream_t* stream; event_block_t* block; event_t* event; tick_t endtime, curtime, payloadtime, begintime, prevtime; unsigned int read[32]; int i; bool running = true; int num_threads = math_clamp( system_hardware_threads() * 4, 4, 32 ); stream = event_stream_allocate( 0 ); begintime = time_current(); for( i = 0; i < num_threads; ++i ) { args[i].stream = stream; args[i].end_time = time_current() + ( time_ticks_per_second() * 5 ); args[i].max_delay = time_ticks_per_second() * 5; args[i].sleep_time = 50; args[i].id = i; read[i] = 0; thread[i] = thread_create( producer_thread, "event_producer", THREAD_PRIORITY_NORMAL, 0 ); thread_start( thread[i], &args[i] ); } test_wait_for_threads_startup( thread, num_threads ); while( running ) { running = false; for( i = 0; i < num_threads; ++i ) { if( thread_is_running( thread[i] ) ) { running = true; break; } } thread_yield(); prevtime = begintime; begintime = time_current(); block = event_stream_process( stream ); event = event_next( block, 0 ); curtime = time_current(); while( event ) { running = true; ++read[ event->object ]; memcpy( &payloadtime, event->payload, sizeof( tick_t ) ); EXPECT_GE( event_payload_size( event ), 8 ); EXPECT_LE( event_payload_size( event ), 256 ); EXPECT_GE( payloadtime, prevtime ); EXPECT_GE( curtime, payloadtime ); event = event_next( block, event ); curtime = time_current(); } } endtime = time_current() + ( time_ticks_per_second() * 6 ); do { prevtime = begintime; begintime = time_current(); block = event_stream_process( stream ); event = event_next( block, 0 ); curtime = time_current(); while( event ) { ++read[ event->object ]; memcpy( &payloadtime, event->payload, sizeof( tick_t ) ); EXPECT_GE( event_payload_size( event ), 8 ); EXPECT_LE( event_payload_size( event ), 256 ); EXPECT_GE( payloadtime, prevtime ); EXPECT_GE( curtime, payloadtime ); event = event_next( block, event ); curtime = time_current(); } thread_sleep( 10 ); } while( time_current() < endtime ); for( i = 0; i < num_threads; ++i ) { unsigned int should_have_read = (unsigned int)((uintptr_t)thread_result( thread[i] )); EXPECT_EQ( read[i], should_have_read ); thread_terminate( thread[i] ); thread_destroy( thread[i] ); } test_wait_for_threads_exit( thread, num_threads ); event_stream_deallocate( stream ); return 0; }
int main_run( void* main_arg ) { const char* pattern = 0; char** exe_paths = 0; unsigned int iexe, exesize; process_t* process = 0; char* process_path = 0; int process_result = 0; object_t thread = 0; thread = thread_create( event_thread, "event_thread", THREAD_PRIORITY_NORMAL, 0 ); thread_start( thread, 0 ); #if FOUNDATION_PLATFORM_ANDROID int test_fn = 0; test_run_fn tests[] = { //test_app_run test_array_run, test_atomic_run, test_base64_run, test_bitbuffer_run, test_blowfish_run, test_bufferstream_run, test_config_run, test_crash_run, test_environment_run, test_error_run, test_event_run, test_fs_run, test_hash_run, test_hashmap_run, test_hashtable_run, test_library_run, test_math_run, test_md5_run, test_mutex_run, test_objectmap_run, test_path_run, test_pipe_run, test_profile_run, test_radixsort_run, test_random_run, test_ringbuffer_run, test_semaphore_run, //test_stacktrace_run, test_string_run, test_uuid_run, 0 }; do { if( process_result >= 0 ) { if( ( process_result = tests[test_fn]() ) >= 0 ) log_infof( HASH_TEST, "All tests passed (%d)", process_result ); } ++test_fn; } while( tests[test_fn] && ( process_result >= 0 ) ); if( process_result != 0 ) { log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed with exit code %d", process_result ); } #else //Find all test executables in the current executable directory #if FOUNDATION_PLATFORM_WINDOWS pattern = "test-*.exe"; #elif FOUNDATION_PLATFORM_MACOSX || FOUNDATION_PLATFORM_IOS pattern = "test-*"; #elif FOUNDATION_PLATFORM_POSIX pattern = "test-*"; #else # error Not implemented #endif exe_paths = fs_matching_files( environment_executable_directory(), pattern, true ); for( iexe = 0, exesize = array_size( exe_paths ); iexe < exesize; ++iexe ) { bool is_self = false; char* exe_file_name = path_base_file_name( exe_paths[iexe] ); if( string_equal( exe_file_name, environment_executable_name() ) ) is_self = true; string_deallocate( exe_file_name ); if( is_self ) continue; //Don't run self process_path = path_merge( environment_executable_directory(), exe_paths[iexe] ); process = process_allocate(); process_set_executable_path( process, process_path ); process_set_working_directory( process, environment_executable_directory() ); process_set_flags( process, PROCESS_ATTACHED ); log_infof( HASH_TEST, "Running test executable: %s", exe_paths[iexe] ); process_result = process_spawn( process ); while( process_result == PROCESS_WAIT_INTERRUPTED ) { thread_sleep( 10 ); process_result = process_wait( process ); } process_deallocate( process ); string_deallocate( process_path ); if( process_result != 0 ) { if( process_result >= PROCESS_INVALID_ARGS ) log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed, process terminated with error %x", process_result ); else log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed with exit code %d", process_result ); process_set_exit_code( -1 ); goto exit; } log_infof( HASH_TEST, "All tests from %s passed (%d)", exe_paths[iexe], process_result ); } log_info( HASH_TEST, "All tests passed" ); exit: if( exe_paths ) string_array_deallocate( exe_paths ); #endif thread_terminate( thread ); thread_destroy( thread ); while( thread_is_running( thread ) ) thread_sleep( 10 ); return process_result; }
static int lfsck_namespace_double_scan_main(void *args) { struct lfsck_thread_args *lta = args; const struct lu_env *env = <a->lta_env; struct lfsck_component *com = lta->lta_com; struct lfsck_instance *lfsck = com->lc_lfsck; struct ptlrpc_thread *thread = &lfsck->li_thread; struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram; struct lfsck_namespace *ns = com->lc_file_ram; struct dt_object *obj = com->lc_obj; const struct dt_it_ops *iops = &obj->do_index_ops->dio_it; struct dt_object *target; struct dt_it *di; struct dt_key *key; struct lu_fid fid; int rc; __u8 flags = 0; ENTRY; com->lc_new_checked = 0; com->lc_new_scanned = 0; com->lc_time_last_checkpoint = cfs_time_current(); com->lc_time_next_checkpoint = com->lc_time_last_checkpoint + cfs_time_seconds(LFSCK_CHECKPOINT_INTERVAL); di = iops->init(env, obj, 0, BYPASS_CAPA); if (IS_ERR(di)) GOTO(out, rc = PTR_ERR(di)); fid_cpu_to_be(&fid, &ns->ln_fid_latest_scanned_phase2); rc = iops->get(env, di, (const struct dt_key *)&fid); if (rc < 0) GOTO(fini, rc); /* Skip the start one, which either has been processed or non-exist. */ rc = iops->next(env, di); if (rc != 0) GOTO(put, rc); if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_NO_DOUBLESCAN)) GOTO(put, rc = 0); do { if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_DELAY3) && cfs_fail_val > 0) { struct l_wait_info lwi; lwi = LWI_TIMEOUT(cfs_time_seconds(cfs_fail_val), NULL, NULL); l_wait_event(thread->t_ctl_waitq, !thread_is_running(thread), &lwi); } key = iops->key(env, di); fid_be_to_cpu(&fid, (const struct lu_fid *)key); target = lfsck_object_find(env, lfsck, &fid); down_write(&com->lc_sem); if (target == NULL) { rc = 0; goto checkpoint; } else if (IS_ERR(target)) { rc = PTR_ERR(target); goto checkpoint; } /* XXX: Currently, skip remote object, the consistency for * remote object will be processed in LFSCK phase III. */ if (dt_object_exists(target) && !dt_object_remote(target)) { rc = iops->rec(env, di, (struct dt_rec *)&flags, 0); if (rc == 0) rc = lfsck_namespace_double_scan_one(env, com, target, flags); } lfsck_object_put(env, target); checkpoint: com->lc_new_checked++; com->lc_new_scanned++; ns->ln_fid_latest_scanned_phase2 = fid; if (rc > 0) ns->ln_objs_repaired_phase2++; else if (rc < 0) ns->ln_objs_failed_phase2++; up_write(&com->lc_sem); if ((rc == 0) || ((rc > 0) && !(bk->lb_param & LPF_DRYRUN))) { lfsck_namespace_delete(env, com, &fid); } else if (rc < 0) { flags |= LLF_REPAIR_FAILED; lfsck_namespace_update(env, com, &fid, flags, true); } if (rc < 0 && bk->lb_param & LPF_FAILOUT) GOTO(put, rc); if (unlikely(cfs_time_beforeq(com->lc_time_next_checkpoint, cfs_time_current())) && com->lc_new_checked != 0) { down_write(&com->lc_sem); ns->ln_run_time_phase2 += cfs_duration_sec(cfs_time_current() + HALF_SEC - com->lc_time_last_checkpoint); ns->ln_time_last_checkpoint = cfs_time_current_sec(); ns->ln_objs_checked_phase2 += com->lc_new_checked; com->lc_new_checked = 0; rc = lfsck_namespace_store(env, com, false); up_write(&com->lc_sem); if (rc != 0) GOTO(put, rc); com->lc_time_last_checkpoint = cfs_time_current(); com->lc_time_next_checkpoint = com->lc_time_last_checkpoint + cfs_time_seconds(LFSCK_CHECKPOINT_INTERVAL); } lfsck_control_speed_by_self(com); if (unlikely(!thread_is_running(thread))) GOTO(put, rc = 0); rc = iops->next(env, di); } while (rc == 0); GOTO(put, rc); put: iops->put(env, di); fini: iops->fini(env, di); out: down_write(&com->lc_sem); ns->ln_run_time_phase2 += cfs_duration_sec(cfs_time_current() + HALF_SEC - lfsck->li_time_last_checkpoint); ns->ln_time_last_checkpoint = cfs_time_current_sec(); ns->ln_objs_checked_phase2 += com->lc_new_checked; com->lc_new_checked = 0; if (rc > 0) { com->lc_journal = 0; ns->ln_status = LS_COMPLETED; if (!(bk->lb_param & LPF_DRYRUN)) ns->ln_flags &= ~(LF_SCANNED_ONCE | LF_INCONSISTENT); ns->ln_time_last_complete = ns->ln_time_last_checkpoint; ns->ln_success_count++; } else if (rc == 0) { ns->ln_status = lfsck->li_status; if (ns->ln_status == 0) ns->ln_status = LS_STOPPED; } else { ns->ln_status = LS_FAILED; } if (ns->ln_status != LS_PAUSED) { spin_lock(&lfsck->li_lock); cfs_list_del_init(&com->lc_link); cfs_list_add_tail(&com->lc_link, &lfsck->li_list_idle); spin_unlock(&lfsck->li_lock); } rc = lfsck_namespace_store(env, com, false); up_write(&com->lc_sem); if (atomic_dec_and_test(&lfsck->li_double_scan_count)) wake_up_all(&thread->t_ctl_waitq); lfsck_thread_args_fini(lta); return rc; }
int main_run( void* main_arg ) { #if !FOUNDATION_PLATFORM_IOS && !FOUNDATION_PLATFORM_ANDROID const char* pattern = 0; char** exe_paths = 0; unsigned int iexe, exesize; process_t* process = 0; char* process_path = 0; unsigned int* exe_flags = 0; #endif int process_result = 0; object_t thread = 0; log_set_suppress( HASH_TEST, ERRORLEVEL_DEBUG ); thread = thread_create( event_thread, "event_thread", THREAD_PRIORITY_NORMAL, 0 ); thread_start( thread, 0 ); while( !thread_is_running( thread ) ) thread_sleep( 10 ); #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID while( !_test_should_start ) thread_sleep( 10 ); test_run_fn tests[] = { //test_app_run test_array_run, test_atomic_run, test_base64_run, test_bitbuffer_run, test_blowfish_run, test_bufferstream_run, test_config_run, test_crash_run, test_environment_run, test_error_run, test_event_run, test_fs_run, test_hash_run, test_hashmap_run, test_hashtable_run, test_library_run, test_math_run, test_md5_run, test_mutex_run, test_objectmap_run, test_path_run, test_pipe_run, test_profile_run, test_radixsort_run, test_random_run, test_ringbuffer_run, test_semaphore_run, test_stacktrace_run, test_string_run, test_uuid_run, 0 }; #if FOUNDATION_PLATFORM_ANDROID object_t test_thread = thread_create( test_runner, "test_runner", THREAD_PRIORITY_NORMAL, 0 ); thread_start( test_thread, tests ); while( !thread_is_running( test_thread ) ) { system_process_events(); thread_sleep( 10 ); } while( thread_is_running( test_thread ) ) { system_process_events(); thread_sleep( 10 ); } process_result = (int)(intptr_t)thread_result( test_thread ); thread_destroy( test_thread ); while( thread_is_thread( test_thread ) ) { system_process_events(); thread_sleep( 10 ); } #else process_result = (int)(intptr_t)test_runner( 0, tests ); #endif if( process_result != 0 ) log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed with exit code %d", process_result ); while( !_test_should_terminate ) { system_process_events(); thread_sleep( 100 ); } log_debug( HASH_TEST, "Exiting main loop" ); #else //Find all test executables in the current executable directory #if FOUNDATION_PLATFORM_WINDOWS pattern = "test-*.exe"; #elif FOUNDATION_PLATFORM_MACOSX pattern = "test-*"; #elif FOUNDATION_PLATFORM_POSIX pattern = "test-*"; #else # error Not implemented #endif exe_paths = fs_matching_files( environment_executable_directory(), pattern, false ); array_resize( exe_flags, array_size( exe_paths ) ); memset( exe_flags, 0, sizeof( unsigned int ) * array_size( exe_flags ) ); #if FOUNDATION_PLATFORM_MACOSX //Also search for test-*.app const char* app_pattern = "test-*.app"; char** subdirs = fs_subdirs( environment_executable_directory() ); for( int idir = 0, dirsize = array_size( subdirs ); idir < dirsize; ++idir ) { if( string_match_pattern( subdirs[idir], app_pattern ) ) { array_push( exe_paths, string_substr( subdirs[idir], 0, string_length( subdirs[idir] ) - 4 ) ); array_push( exe_flags, PROCESS_OSX_USE_OPENAPPLICATION ); } } string_array_deallocate( subdirs ); #endif for( iexe = 0, exesize = array_size( exe_paths ); iexe < exesize; ++iexe ) { bool is_self = false; char* exe_file_name = path_base_file_name( exe_paths[iexe] ); if( string_equal( exe_file_name, environment_executable_name() ) ) is_self = true; string_deallocate( exe_file_name ); if( is_self ) continue; //Don't run self process_path = path_merge( environment_executable_directory(), exe_paths[iexe] ); process = process_allocate(); process_set_executable_path( process, process_path ); process_set_working_directory( process, environment_executable_directory() ); process_set_flags( process, PROCESS_ATTACHED | exe_flags[iexe] ); log_infof( HASH_TEST, "Running test executable: %s", exe_paths[iexe] ); process_result = process_spawn( process ); while( process_result == PROCESS_WAIT_INTERRUPTED ) { thread_sleep( 10 ); process_result = process_wait( process ); } process_deallocate( process ); string_deallocate( process_path ); if( process_result != 0 ) { if( process_result >= PROCESS_INVALID_ARGS ) log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed, process terminated with error %x", process_result ); else log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed with exit code %d", process_result ); process_set_exit_code( -1 ); goto exit; } log_infof( HASH_TEST, "All tests from %s passed (%d)", exe_paths[iexe], process_result ); } log_info( HASH_TEST, "All tests passed" ); exit: if( exe_paths ) string_array_deallocate( exe_paths ); array_deallocate( exe_flags ); #endif thread_terminate( thread ); thread_destroy( thread ); while( thread_is_running( thread ) ) thread_sleep( 10 ); while( thread_is_thread( thread ) ) thread_sleep( 10 ); return process_result; }