void test_prout_register_simple(void) { const unsigned long long key = rand_key(); int ret = 0; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test Persistent Reserve IN REGISTER works."); /* register our reservation key with the target */ ret = prout_register_and_ignore(sd, key); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] PERSISTEN RESERVE OUT is not implemented."); CU_PASS("PERSISTENT RESERVE OUT is not implemented."); return; } CU_ASSERT_EQUAL(ret, 0); /* verify we can read the registration */ ret = prin_verify_key_presence(sd, key, 1); CU_ASSERT_EQUAL(ret, 0); /* try to reregister, which should fail */ ret = prout_reregister_key_fails(sd, key+1); CU_ASSERT_EQUAL(ret, 0); /* release from the target */ ret = prout_register_key(sd, 0, key); CU_ASSERT_EQUAL(ret, 0); /* Verify the registration is gone */ ret = prin_verify_key_presence(sd, key, 0); CU_ASSERT_EQUAL(ret, 0); }
void test_prout_reserve_simple(void) { int ret = 0; int i; const unsigned long long key = rand_key(); logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test Persistent Reserve IN RESERVE works."); /* register our reservation key with the target */ ret = prout_register_and_ignore(sd, key); if (ret == -2) { CU_PASS("PERSISTENT RESERVE OUT is not implemented."); return; } CU_ASSERT_EQUAL(ret, 0); /* test each reservatoin type */ for (i = 0; pr_types_to_test[i] != 0; i++) { enum scsi_persistent_out_type pr_type = pr_types_to_test[i]; /* reserve the target */ ret = prout_reserve(sd, key, pr_type); CU_ASSERT_EQUAL(ret, 0); /* verify target reservation */ ret = prin_verify_reserved_as(sd, pr_type_is_all_registrants(pr_type) ? 0 : key, pr_type); CU_ASSERT_EQUAL(ret, 0); /* release our reservation */ ret = prout_release(sd, key, pr_type); CU_ASSERT_EQUAL(ret, 0); } /* remove our key from the target */ ret = prout_register_key(sd, 0, key); CU_ASSERT_EQUAL(ret, 0); }
/************************************************************************* * * * Generate a random record. * * * *************************************************************************/ void gen_rec(struct record *rp) { static int current; char *sptr; static char nxtchar = 'A'; int i, j; rand_key(rp->sortkey) ; // Get 10 byte sort key sprintf(rp->recnum, "%10d", current++); sptr = rp->txtfld ; for( i=0; i < 8; i++) { for( j=0; j < 10; j++ ) *sptr++ = nxtchar ; nxtchar++; if( nxtchar > 'Z' ) nxtchar = 'A'; } sptr[-2] = '\r'; sptr[-1] = '\n'; }
int main (int argc, char **argv) { srand(time(0)); long long num_threads = 1; int c; while (1) { c = getopt_long(argc, argv, "", long_options, &option_index); /* Detect the end of the options. */ if (c == -1) break; switch (c) { case THREADS: num_threads = strtol(optarg, NULL, 10); break; case ITERATIONS: num_iterations = strtol(optarg, NULL, 10); break; case YIELD: { int i; for (i = 0; optarg[i] != 0; i++) { switch(optarg[i]) { case 'i': opt_yield |= INSERT_YIELD; break; case 'd': opt_yield |= DELETE_YIELD; break; case 's': opt_yield |= SEARCH_YIELD; break; default: fprintf(stderr, "Unknown option for --yield\n"); exit(1); } } } break; case SYNC: switch(optarg[0]) { case 's': // printf("set spin locks\n"); using_spinlocks = 1; using_mutexes = 0; insert_func = SortedList_insert_spinlock; delete_func = SortedList_delete_spinlock; lookup_func = SortedList_lookup_spinlock; length_func = SortedList_length_spinlock; break; case 'm': // printf("set mutexes\n"); using_mutexes = 1; using_spinlocks = 0; insert_func = SortedList_insert_mutex; delete_func = SortedList_delete_mutex; lookup_func = SortedList_lookup_mutex; length_func = SortedList_length_mutex; break; default: fprintf(stderr, "Unknown option for --sync\n"); exit(1); } break; case LISTS: num_lists = strtol(optarg, NULL, 10); break; default: /* code for unrecognized options */ break; } } /* check for nonpositive values */ if (num_threads < 1) { fprintf(stderr, "Thread number is less than 1\n"); exit(1); } if (num_iterations < 1) { fprintf(stderr, "Iterations number is less than 1\n"); exit(1); } if (num_lists < 1) { fprintf(stderr, "Lists number is less than 1\n"); exit(1); } sorted_lists = malloc(num_lists * sizeof(SortedList_t*)); int sl; for (sl = 0; sl < num_lists; sl++) { sorted_lists[sl] = SortedList_new_list(); } // Initialize spin locks, mutexes if (using_spinlocks) { spin_locks = malloc(num_lists * sizeof(int)); for (sl = 0; sl < num_lists; sl++) { spin_locks[sl] = 0; } } else if (using_mutexes) { blocking_mutexes = (pthread_mutex_t*)malloc(num_lists * sizeof(pthread_mutex_t)); for (sl = 0; sl < num_lists; sl++) { if (pthread_mutex_init(&blocking_mutexes[sl], NULL)) { perror("pthread_mutex_init"); exit(1); } } } pthread_t threads[num_threads]; list_elements = malloc(num_threads * num_iterations * sizeof(SortedListElement_t*)); keys = (char**)malloc(num_threads * num_iterations * sizeof(char*)); // Create elements with random keys int i; for (i = 0; i < num_threads * num_iterations; i++) { keys[i] = rand_key(); list_elements[i] = SortedList_new_element(keys[i]); } struct timespec start_time; if (clock_gettime(CLOCK_MONOTONIC, &start_time)) { perror("clock_gettime"); exit(1); } long long n; for (n = 0; n < num_threads; n++) { int thread_ret = pthread_create(&threads[n], NULL, thread_func, (void*)n); if (thread_ret) { perror("pthread_create"); exit(1); } } for (n = 0; n < num_threads; n++) { int join_ret = pthread_join(threads[n], NULL); if (join_ret) { perror("pthread_join"); exit(1); } } struct timespec end_time; if (clock_gettime(CLOCK_MONOTONIC, &end_time)) { perror("clock_gettime"); exit(1); } int sorted_list_size = length_func(sorted_lists[0]); float length_per_thread = (float)num_iterations / num_lists; float operations = num_threads * num_iterations * length_per_thread; printf("%lld threads x %lld iterations x (ins + lookup/del) x (%.2f/2 avg len) = %.2f operations\n", num_threads, num_iterations, length_per_thread, operations); int size_err = sorted_list_size != 0; if (size_err) { fprintf(stderr, "ERROR: final count = %d\n", sorted_list_size); } long long elapsed = (end_time.tv_sec * pow(10, 9) + end_time.tv_nsec) - (start_time.tv_sec * pow(10, 9) + start_time.tv_nsec); printf("elapsed time: %lld ns\n", elapsed); printf("per operation: %.2f ns\n", elapsed / operations); for (sl = 0; sl < num_lists; sl++) { SortedList_free(sorted_lists[sl]); } for (i = 0; i < num_threads * num_iterations; i++) { free(keys[i]); } free(keys); free(list_elements); if (using_spinlocks) { free(spin_locks); } if (using_mutexes) { free(blocking_mutexes); } return size_err; }
int T1145_persistent_reserve_access_check_wear(const char *initiator, const char *url) { struct iscsi_context *iscsi = NULL, *iscsi2 = NULL; int ret; int lun, lun2; const unsigned long long key = rand_key(); const unsigned long long key2 = rand_key(); const enum scsi_persistent_out_type pr_type = SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_ALL_REGISTRANTS; const char *pr_type_str = scsi_pr_type_str(pr_type); unsigned char *buf = NULL; printf("1145_persistent_reserve_access_check_wear:\n"); printf("=========================================\n"); if (show_info) { int idx = 1; printf("Test that access constrols are correct for %s Persistent Reservations\n", pr_type_str); printf("%d, %s Reservation Holder Read Access\n", idx++, pr_type_str); printf("%d, %s Reservation Holder Write Access\n", idx++, pr_type_str); printf("%d, non-%s Reservation Holder does not have read access\n", idx++, pr_type_str); printf("%d, non-%s Reservation Holder does not have write access\n", idx++, pr_type_str); return 0; } iscsi = iscsi_context_login(initiator, url, &lun); if (iscsi == NULL) { printf("Failed to login to target\n"); ret = -1; goto finished; } iscsi2 = iscsi_context_login(initiatorname2, url, &lun2); if (iscsi2 == NULL) { printf("Failed to login to target (2nd initiator)\n"); ret = -1; goto finished; } if (!data_loss) { printf("--dataloss flag is not set. Skipping test\n"); ret = -2; goto finished; } /* register our reservation key with the target */ ret = register_and_ignore(iscsi, lun, key); if (ret != 0) goto finished; ret = register_and_ignore(iscsi2, lun2, key2); if (ret != 0) goto finished; /* reserve the target through initiator 1 */ ret = reserve(iscsi, lun, key, pr_type); if (ret != 0) goto finished; /* verify target reservation */ ret = verify_reserved_as(iscsi, lun, pr_type_is_all_registrants(pr_type) ? 0 : key, pr_type); if (ret != 0) goto finished; buf = malloc(512); /* allocate a buffer */ if (buf == NULL) { printf("failed to allocate 512 byes of memory\n"); ret = -1; goto finished; } /* make sure init1 can read */ ret = verify_read_works(iscsi, lun, buf); if (ret != 0) goto finished; /* make sure init1 can write */ ret = verify_write_works(iscsi, lun, buf); if (ret != 0) goto finished; /* make sure init2 does have read access */ ret = verify_read_works(iscsi2, lun2, buf); if (ret != 0) goto finished; /* make sure init2 does have write access */ ret = verify_write_works(iscsi2, lun2, buf); if (ret != 0) goto finished; /* unregister init2 */ ret = register_key(iscsi2, lun2, 0, key); if (ret != 0) { goto finished; } /* make sure init2 does have read access */ ret = verify_read_works(iscsi2, lun2, buf); if (ret != 0) goto finished; /* make sure init2 does not have write access */ ret = verify_write_fails(iscsi2, lun2, buf); if (ret != 0) goto finished; /* release our reservation */ ret = release(iscsi, lun, key, pr_type); if (ret != 0) goto finished; /* remove our key from the target */ ret = register_key(iscsi, lun, 0, key); if (ret != 0) goto finished; finished: /* XXX should we clean up key if needed? */ if (iscsi) { iscsi_logout_sync(iscsi); iscsi_destroy_context(iscsi); } if (iscsi2) { iscsi_logout_sync(iscsi2); iscsi_destroy_context(iscsi2); } if (buf) free(buf); return ret; }
static void verify_persistent_reserve_access(struct scsi_device *sd1, struct scsi_device *sd2, const enum scsi_persistent_out_type pr_type, int reg_i2_can_read, int reg_i2_can_write, int unreg_i2_can_read, int unreg_i2_can_write) { int ret; const unsigned long long key = rand_key(); const unsigned long long key2 = rand_key(); logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Verify access for reservation type: %s", scsi_pr_type_str(pr_type)); /* send TURs to clear possible check conditions */ (void) testunitready_clear_ua(sd1); (void) testunitready_clear_ua(sd2); /* register our reservation key with the target */ ret = prout_register_and_ignore(sd1, key); if (ret == -2) { CU_PASS("PERSISTENT RESERVE OUT is not implemented."); return; } CU_ASSERT_EQUAL(0, ret); ret = prout_register_and_ignore(sd2, key2); CU_ASSERT_EQUAL(0, ret); /* reserve the target through initiator 1 */ ret = prout_reserve(sd1, key, pr_type); CU_ASSERT_EQUAL(0, ret); /* verify target reservation */ ret = prin_verify_reserved_as(sd1, pr_type_is_all_registrants(pr_type) ? 0 : key, pr_type); CU_ASSERT_EQUAL(0, ret); CU_ASSERT_PTR_NOT_NULL_FATAL(scratch); /* make sure init1 can read */ ret = verify_read_works(sd1, scratch); CU_ASSERT_EQUAL(0, ret); /* make sure init1 can write */ ret = verify_write_works(sd1, scratch); CU_ASSERT_EQUAL(0, ret); /* verify registered init2 read access */ if (reg_i2_can_read) ret = verify_read_works(sd2, scratch); else ret = verify_read_fails(sd2, scratch); CU_ASSERT_EQUAL(0, ret); /* verify registered init2 write access */ if (reg_i2_can_write) ret = verify_write_works(sd2, scratch); else ret = verify_write_fails(sd2, scratch); CU_ASSERT_EQUAL(0, ret); /* unregister init2 */ ret = prout_register_key(sd2, 0, key2); CU_ASSERT_EQUAL(0, ret); /* verify unregistered init2 read access */ if (unreg_i2_can_read) ret = verify_read_works(sd2, scratch); else ret = verify_read_fails(sd2, scratch); CU_ASSERT_EQUAL(0, ret); /* verify unregistered init2 write access */ if (unreg_i2_can_write) ret = verify_write_works(sd2, scratch); else ret = verify_write_fails(sd2, scratch); CU_ASSERT_EQUAL(0, ret); /* release our reservation */ ret = prout_release(sd1, key, pr_type); CU_ASSERT_EQUAL(0, ret); /* remove our key from the target */ ret = prout_register_key(sd1, 0, key); CU_ASSERT_EQUAL(0, ret); }
void test_prin_report_caps_simple(void) { int ret = 0; const unsigned long long key = rand_key(); struct scsi_task *tsk; struct scsi_persistent_reserve_in_report_capabilities *rcaps; struct test_prin_report_caps_types *type; CHECK_FOR_DATALOSS; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test Persistent Reserve In REPORT CAPABILITIES works."); /* register our reservation key with the target */ ret = prout_register_and_ignore(sd, key); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] PERSISTENT RESERVE OUT is not implemented."); CU_PASS("PERSISTENT RESERVE OUT is not implemented."); return; } CU_ASSERT_EQUAL(ret, 0); ret = prin_report_caps(sd, &tsk, &rcaps); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Checking PERSISTENT RESERVE IN REPORT CAPABILITIES fields."); CU_ASSERT_EQUAL(rcaps->length, 8); CU_ASSERT_TRUE(rcaps->allow_commands <= 5); CU_ASSERT_EQUAL(rcaps->persistent_reservation_type_mask & ~SCSI_PR_TYPE_MASK_ALL, 0); for (type = &report_caps_types_array[0]; type->mask != 0; type++) { if (!(rcaps->persistent_reservation_type_mask & type->mask)) { logging(LOG_NORMAL, "PERSISTENT RESERVE op 0x%x not supported", type->op); continue; } logging(LOG_VERBOSE, "PERSISTENT RESERVE OUT op 0x%x supported, testing", type->op); /* reserve the target */ ret = prout_reserve(sd, key, type->op); CU_ASSERT_EQUAL(ret, 0); /* verify target reservation */ ret = prin_verify_reserved_as(sd, pr_type_is_all_registrants(type->op) ? 0 : key, type->op); CU_ASSERT_EQUAL(0, ret); /* release the target */ ret = prout_release(sd, key, type->op); CU_ASSERT_EQUAL(ret, 0); } scsi_free_scsi_task(tsk); rcaps = NULL; /* freed with tsk */ /* drop registration */ ret = prout_register_key(sd, 0, key); CU_ASSERT_EQUAL(ret, 0); }
static void verify_persistent_reserve_ownership(struct scsi_device *sd1, struct scsi_device *sd2, const enum scsi_persistent_out_type pr_type, int resvn_is_shared) { int ret; const unsigned long long key1 = rand_key(); const unsigned long long key2 = rand_key(); logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Verify ownership for reservation type: %s", scsi_pr_type_str(pr_type)); /* send TURs to clear possible check conditions */ (void) testunitready_clear_ua(sd1); (void) testunitready_clear_ua(sd2); /* register our reservation key with the target */ ret = prout_register_and_ignore(sd1, key1); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] PERSISTEN RESERVE OUT is not implemented."); CU_PASS("PERSISTENT RESERVE OUT is not implemented."); return; } CU_ASSERT_EQUAL(0, ret); ret = prout_register_and_ignore(sd2, key2); CU_ASSERT_EQUAL(0, ret); /* reserve the target through initiator 1 */ ret = prout_reserve(sd1, key1, pr_type); CU_ASSERT_EQUAL(0, ret); /* verify target reservation */ ret = prin_verify_reserved_as(sd1, pr_type_is_all_registrants(pr_type) ? 0 : key1, pr_type); CU_ASSERT_EQUAL(0, ret); /* unregister init1 */ ret = prout_register_key(sd1, 0, key1); CU_ASSERT_EQUAL(0, ret); /* verify if reservation is still present */ if (resvn_is_shared) { /* verify target reservation */ ret = prin_verify_reserved_as(sd1, pr_type_is_all_registrants(pr_type) ? 0 : key1, pr_type); CU_ASSERT_EQUAL(0, ret); /* release our reservation */ ret = prout_release(sd2, key2, pr_type); CU_ASSERT_EQUAL(0, ret); } else { /* verify target is not reserved now */ ret = prin_verify_not_reserved(sd1); CU_ASSERT_EQUAL(0, ret); /* send TUR to clear possible check condition */ (void) testunitready_clear_ua(sd2); } /* remove our remaining key from the target */ ret = prout_register_key(sd2, 0, key2); CU_ASSERT_EQUAL(0, ret); }
void test_prout_clear_simple(void) { int ret = 0; uint32_t old_gen; const unsigned long long key = rand_key(); struct scsi_task *tsk; struct scsi_persistent_reserve_in_read_keys *rk = NULL; CHECK_FOR_DATALOSS; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test Persistent Reserve OUT CLEAR works."); /* register our reservation key with the target */ ret = prout_register_and_ignore(sd, key); if (ret == -2) { CU_PASS("PERSISTENT RESERVE OUT is not implemented."); return; } CU_ASSERT_EQUAL(ret, 0); ret = prin_read_keys(sd, &tsk, &rk, 16384); CU_ASSERT_EQUAL(ret, 0); CU_ASSERT_NOT_EQUAL(rk, NULL); if (!rk) goto out; CU_ASSERT_NOT_EQUAL(rk->num_keys, 0); /* retain PR generation number to check for increments */ old_gen = rk->prgeneration; scsi_free_scsi_task(tsk); rk = NULL; /* freed with tsk */ /* reserve the target */ ret = prout_reserve(sd, key, SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS); CU_ASSERT_EQUAL(ret, 0); /* verify target reservation */ ret = prin_verify_reserved_as(sd, key, SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS); CU_ASSERT_EQUAL(ret, 0); /* clear reservation and registration */ ret = prout_clear(sd, key); CU_ASSERT_EQUAL(ret, 0); ret = prin_verify_not_reserved(sd); CU_ASSERT_EQUAL(ret, 0); ret = prin_read_keys(sd, &tsk, &rk, 16384); CU_ASSERT_EQUAL(ret, 0); CU_ASSERT_NOT_EQUAL(rk, NULL); if (!rk) goto out; CU_ASSERT_EQUAL(rk->num_keys, 0); /* generation incremented once for CLEAR (not for RESERVE) */ CU_ASSERT_EQUAL(rk->prgeneration, old_gen + 1); out: scsi_free_scsi_task(tsk); rk = NULL; /* freed with tsk */ }