// 7.1.219 : Pass context token to different process & do detach/release. int test_detach_diff_proc() { int rc=0; int cstat; struct ctx myctx; struct ctx *p_ctx = &myctx; pid = getpid(); //ctx_init with default flash disk & devno rc = ctx_init(p_ctx); CHECK_RC(rc, "Context init failed"); rc = fork(); if ( rc == -1 ) CHECK_RC(1, "fork() failed"); // child process if ( rc == 0 ) { pid = getpid(); rc = ctx_close(p_ctx); if ( 22 != rc ) CHECK_RC_EXIT(1, "Context detach did not fail"); exit(0); } else { // Probe child's exit status. if ( wait(&cstat) == -1 ) CHECK_RC(1, "Failed while wait() for child"); // We expect child to exit itself if (WIFEXITED(cstat)) { // We expect child to exit with rc 0 only ! if ( WEXITSTATUS(cstat) != 0 ) rc=1; else rc=0; } } rc |= ctx_close(p_ctx); return rc; }
int test_clone_ioctl(int cmd) { struct ctx myctx; int i; pid_t cpid; struct ctx *p_ctx=&myctx; uint64_t nlba; uint64_t st_lba; uint64_t stride=0x1000; int rc=0; uint64_t src_ctx_id; uint64_t src_adap_fd; pthread_t thread; uint64_t resource[MAX_RES_HANDLE]; uint64_t RES_CLOSED=-1; int cl_index[5]={ 1,7,10,12,15 }; pid = getpid(); rc =ctx_init(p_ctx); CHECK_RC(rc, "Context init failed"); pthread_create(&thread, NULL, ctx_rrq_rx, p_ctx); p_ctx->flags = DK_UVF_ALL_PATHS; for (i=0;i<MAX_RES_HANDLE;i++) { p_ctx->lun_size = (i+1)*p_ctx->chunk_size; rc = create_res(p_ctx); CHECK_RC(rc, "create res failed"); resource[i]=p_ctx->rsrc_handle; } for (i=0;i<5;i++) { p_ctx->rsrc_handle= resource[cl_index[i]]; close_res(p_ctx); resource[cl_index[i]]= RES_CLOSED; } for (i=0; i<MAX_RES_HANDLE;i++) { if (RES_CLOSED == resource[i]) continue; nlba = (i+1)*p_ctx->chunk_size; p_ctx->rsrc_handle = resource[i]; p_ctx->res_hndl = p_ctx->rsrc_handle & RES_HNDLR_MASK; for (st_lba=0;st_lba<nlba;st_lba += (NUM_CMDS*stride)) { rc = send_write(p_ctx,st_lba,stride,pid); CHECK_RC(rc, "send write failed\n"); } } //write done cancel thread now pthread_cancel(thread); cpid = fork(); if (cpid == 0) { //child process pid = getpid(); ppid = getppid(); //take backup parent ctx_id src_ctx_id= p_ctx->context_id; src_adap_fd = p_ctx->adap_fd; //do unmap parent mmio 1st rc =munmap((void *)p_ctx->p_host_map, p_ctx->mmio_size); CHECK_RC_EXIT(rc, "munmap failed\n"); //do fresh attach for child rc = ctx_init_internal(p_ctx,DK_AF_ASSIGN_AFU,p_ctx->devno); CHECK_RC_EXIT(rc, "ctx_init_internal failed"); pthread_create(&thread, NULL,ctx_rrq_rx,p_ctx); //do clone rc = ioctl_dk_capi_clone(p_ctx, src_ctx_id,src_adap_fd); CHECK_RC_EXIT(rc, "clone ioctl failed"); //do read data for (i=0; i< MAX_RES_HANDLE;i++) { if (RES_CLOSED == resource[i]) continue; p_ctx->rsrc_handle = resource[i]; p_ctx->res_hndl = p_ctx->rsrc_handle & RES_HNDLR_MASK; nlba = (i+1)*p_ctx->chunk_size; for (st_lba=0;st_lba<nlba; st_lba+=(NUM_CMDS*stride)) { rc = send_read(p_ctx,st_lba,stride); CHECK_RC_EXIT(rc,"send_read failed\n"); rc = rw_cmp_buf_cloned(p_ctx, st_lba); CHECK_RC_EXIT(rc,"rw_cmp_buf_cloned failed\n"); } } sleep(1); //now create closed resources p_ctx->flags = DK_UVF_ALL_PATHS; for (i=0; i < 5;i++) { p_ctx->lun_size = (cl_index[i]+1)*p_ctx->chunk_size; rc = create_res(p_ctx); CHECK_RC_EXIT(rc,"res_create failed\n"); resource[cl_index[i]] = p_ctx->rsrc_handle; } //do io on new resources p_ctx->st_lba = 0; for (i=0;i<5;i++) { p_ctx->last_lba = ((cl_index[i]+1)*p_ctx->chunk_size) -1; p_ctx->res_hndl = resource[cl_index[i]] & RES_HNDLR_MASK; rc = do_io(p_ctx, stride); CHECK_RC_EXIT(rc, "do_io failed\n"); } pthread_cancel(thread); ctx_close(p_ctx); exit(0); } //child process end else { //create pthread sleep(1); //let child process do clone & read written data pthread_create(&thread, NULL, ctx_rrq_rx, p_ctx); //do open closed res //now create closed resources p_ctx->flags = DK_UVF_ALL_PATHS; for (i=0; i < 5;i++) { p_ctx->lun_size = (cl_index[i]+1)*p_ctx->chunk_size; rc = create_res(p_ctx); CHECK_RC_EXIT(rc,"res_create failed\n"); resource[cl_index[i]] = p_ctx->rsrc_handle; } //do resize all resources & IO for (i=0;i<MAX_RES_HANDLE;i++) { p_ctx->req_size = (rand()%MAX_RES_HANDLE +1) * p_ctx->chunk_size; p_ctx->rsrc_handle = resource[i]; p_ctx->res_hndl = p_ctx->rsrc_handle & RES_HNDLR_MASK; rc = ioctl_dk_capi_vlun_resize(p_ctx); CHECK_RC(rc, "dk_capi_resize_ioctl failed\n"); rc = do_io(p_ctx, stride); CHECK_RC(rc, "do_io failed\n"); } //close res for (i=0;i<MAX_RES_HANDLE;i++) { p_ctx->rsrc_handle = resource[i]; rc = close_res(p_ctx); CHECK_RC(rc, "cose_res failed\n"); } pthread_cancel(thread); ctx_close(p_ctx); rc = wait4all(); } return rc; }
// 7.1.218 : Pass context token to different process & do REUSE int test_attach_reuse_diff_proc() { int rc=0; int nDisk; struct flash_disk cfDisk[2]; int cstat; struct ctx myctx; struct ctx *p_ctx = &myctx; pid = getpid(); nDisk = get_flash_disks(cfDisk, FDISKS_SAME_ADPTR); if (nDisk < 2) { fprintf(stderr,"Failed to find 2 flash disks from same adapter..\n"); return -1; } // sanity check for AIX! //#ifdef _AIX // if ( cfDisk[0].devno != cfDisk[1].devno ) return 1; //#endif rc = ctx_init2(p_ctx, cfDisk[0].dev, DK_AF_ASSIGN_AFU, cfDisk[0].devno[0]); CHECK_RC(rc, "p_ctx Context init failed"); rc = fork(); if ( rc == -1 ) CHECK_RC(1, "fork() failed"); // child process if ( rc == 0 ) { pid = getpid(); #ifdef _AIX rc = ctx_init2(p_ctx, cfDisk[1].dev, DK_AF_REUSE_CTX, cfDisk[0].devno[0]); if ( 0 == rc ) CHECK_RC_EXIT(1, "Context init with DK_AF_REUSE_CTX did not fail"); #else rc = ctx_init2(p_ctx, cfDisk[1].dev, DK_CXLFLASH_ATTACH_REUSE_CONTEXT, cfDisk[0].devno[0]); if ( 0 == rc ) CHECK_RC_EXIT(1, "Context init with DK_CXLFLASH_ATTACH_REUSE_CONTEXT did not fail"); #endif exit(0); } else { // Probe child's exit status. if ( wait(&cstat) == -1 ) CHECK_RC(1, "Failed while wait() for child"); // We expect child to exit itself if (WIFEXITED(cstat)) { // We expect child to exit with rc 0 only ! if ( WEXITSTATUS(cstat) != 0 ) rc=1; else rc=0; } } cleanup(p_ctx, -1); return rc; }
// 7.1.201 : Queue up commands, do not wait for completion and // exit w/o detach/close, // and do detach/close while commands in queue int test_spio_exit() { int rc; int isFailed=0; int i, nTimes; pid_t cpid; int cstat; struct ctx myctx; struct ctx *p_ctx = &myctx; pthread_t threadId, ioThreadId; do_io_thread_arg_t ioThreadData; do_io_thread_arg_t * p_ioThreadData=&ioThreadData; __u64 chunk = 0x10; __u64 nlba; __u64 stride= 0x10000; for (i=0, nTimes=50; i<nTimes; i++) { rc = fork(); if ( rc == -1 ) CHECK_RC(1, "fork() failed"); // child process if ( rc == 0 ) { signal(SIGABRT, sig_handle); signal(SIGSEGV, sig_handle); // pid used to create unique data patterns & logging from util ! pid = getpid(); debug("...... Child process: Iteration : %d .....\n",i); //ctx_init with default flash disk & devno rc = ctx_init(p_ctx); CHECK_RC(rc, "Context init failed"); //thread to handle AFU interrupt & events rc = pthread_create(&threadId, NULL, ctx_rrq_rx, p_ctx); CHECK_RC(rc, "pthread_create failed"); // Test with vluns one after another if ( i < nTimes/5 ) { nlba = chunk * p_ctx->chunk_size; //create vlun rc = create_resource(p_ctx,nlba, DK_UVF_ALL_PATHS, LUN_VIRTUAL); CHECK_RC(rc, "create LUN_VIRTUAL failed"); } // Test with pluns one after another else if ( i > nTimes/5 && i < 2*nTimes/5 ) { // Create PLUN rc = create_resource(p_ctx, 0, DK_UDF_ASSIGN_PATH, LUN_DIRECT); CHECK_RC(rc, "create LUN_DIRECT failed"); stride = 0x10000; } // Test with vluns/pluns alternately ! else if ( i % 2 ) { nlba = chunk * p_ctx->chunk_size; //create vlun rc = create_resource(p_ctx,nlba, DK_UVF_ALL_PATHS, LUN_VIRTUAL); CHECK_RC(rc, "create LUN_VIRTUAL failed"); } else { // Create PLUN rc = create_resource(p_ctx, 0, DK_UDF_ASSIGN_PATH, LUN_DIRECT); CHECK_RC(rc, "create LUN_DIRECT failed"); stride = 0x10000; } // Make sure at-least 1 IO is successful before proceeding ! rc = do_io(p_ctx, stride); CHECK_RC_EXIT(rc, "Initial IO attempt failed"); // We wish to do IO in a different thread... Setting up for that ! p_ioThreadData->p_ctx=p_ctx; p_ioThreadData->stride=stride; p_ioThreadData->loopCount=100; rc = pthread_create(&ioThreadId,NULL, do_io_thread, (void *)p_ioThreadData); CHECK_RC_EXIT(rc, "do_io_thread() pthread_create failed"); // Sleep for a sec before exiting sleep(1); if ( i % 2 ) { debug("%d:Exiting w/o detach/close",pid); } else { debug("%d:Exiting after detach/close",pid); cleanup(p_ctx, threadId); } exit(10); } // parent process else { pid = getpid(); cpid = rc; // Probe child's exit status. if ( wait(&cstat) == -1 ) CHECK_RC(1, "Failed while wait() for child"); // We expect child to exit itself if (WIFEXITED(cstat)) { debug("Exiting w/o getting killed %d \n",cpid); // We expect child to exit with rc 10 only ! if ( WEXITSTATUS(cstat) != 10 ) isFailed=1; } else if (WIFSIGNALED(cstat)) { //isFailed=1; debug("%d : killed by %d signal\n", cpid, WTERMSIG(cstat)); if (WCOREDUMP(cstat)) //expected if exiting without cancelling poll thread fprintf(stderr, "%d : was core dupmed ...\n", cpid); } debug("pid %d exited with rc = %d\n", cpid, cstat); } } return isFailed; }
// 7.1.200 : Send signal to kill process when it has cmds queued. int test_spio_killprocess() { int rc; int isFailed=0; int i, nTimes; pid_t cpid; int cstat; struct ctx myctx; struct ctx *p_ctx = &myctx; struct sigaction action; sigset_t sigset; pthread_t threadId; __u64 chunk = 0x10; __u64 nlba; __u64 stride=0x1000; pid = getpid(); sigemptyset(&sigset); sigprocmask(SIG_SETMASK, &sigset, NULL); // Set up the signal handler action.sa_handler = callme; action.sa_flags = 0; sigemptyset(&action.sa_mask); if (sigaction(SIGUSR1, &action, NULL) < 0) CHECK_RC(1, "sigaction() failed"); char *str = getenv("LONG_RUN"); if (str == NULL) nTimes=10; else nTimes=100; for (i=0; i<nTimes; i++) { rc = fork(); if ( rc == -1 ) CHECK_RC(1, "fork() failed"); // child process if ( rc == 0 ) { debug("...... Child process: Iteration : %d .....\n",i); // pid used to create unique data patterns & logging from util ! pid = getpid(); //ctx_init with default flash disk & devno rc = ctx_init(p_ctx); CHECK_RC(rc, "Context init failed"); //thread to handle AFU interrupt & events rc = pthread_create(&threadId, NULL, ctx_rrq_rx, p_ctx); CHECK_RC(rc, "pthread_create failed"); // Test with vluns one after another if ( i < nTimes/5 ) { nlba = chunk * p_ctx->chunk_size; //create vlun rc = create_resource(p_ctx,nlba, DK_UVF_ALL_PATHS, LUN_VIRTUAL); CHECK_RC(rc, "create LUN_VIRTUAL failed"); } // Test with pluns one after another else if ( i > nTimes/5 && i < 2*nTimes/5 ) { // Create PLUN rc = create_resource(p_ctx, 0, DK_UDF_ASSIGN_PATH, LUN_DIRECT); CHECK_RC(rc, "create LUN_DIRECT failed"); stride=0x10000; } // Test with vluns/pluns alternately ! else if ( i % 2 ) { nlba = chunk * p_ctx->chunk_size; //create vlun rc = create_resource(p_ctx,nlba, DK_UVF_ALL_PATHS, LUN_VIRTUAL); CHECK_RC(rc, "create LUN_VIRTUAL failed"); stride=0x1000; } else { // Create PLUN rc = create_resource(p_ctx, 0, DK_UDF_ASSIGN_PATH, LUN_DIRECT); CHECK_RC(rc, "create LUN_DIRECT failed"); stride=0x10000; } rc = do_io(p_ctx, stride); // Signal parent to kill itself after this point. kill(getppid(), SIGUSR1); // Exit at this point if we failed in initial IO CHECK_RC_EXIT(rc, "Initial IO failed"); // Keep driving IO till killed for (;;) do_io(p_ctx, stride); } // parent process else { pid = getpid(); cpid = rc; // Wait for child to complete at-least 1 successful IO. pause(); // Let the child IO go on some more time ! sleep(1); // Send signal 9 - process can't ignore it; kill(cpid, 9); // Probe child's exit status. if ( wait(&cstat) == -1 ) CHECK_RC(1, "Failed while wait() for child"); // We don't expect child to exit itself if (WIFEXITED(cstat)) isFailed = 1; else if (WIFSIGNALED(cstat)) { // We expect this ! debug("%d : killed by %d signal\n", cpid, WTERMSIG(cstat)); if (WCOREDUMP(cstat)) fprintf(stderr, "%d : was core dupmed ...\n", cpid); } debug("pid %d exited with rc = %d\n", cpid, cstat); } } return isFailed; }
int ioctl_7_1_196() { int rc,i,j; struct ctx myctx[21],myctx_1, myctx_2; struct ctx *p_ctx[21],*p_ctx_1,*p_ctx_2; __u64 stride=0x1000,st_lba=0; pthread_t thread[20]; struct flash_disk disks[MAX_FDISK]; char disk1[30]; char disk2[30]; int cfdisk = MAX_FDISK; pid = getpid(); cfdisk = get_flash_disks(disks, FDISKS_SAME_ADPTR); //need to check the number of disks if (cfdisk < 2) { fprintf(stderr,"Must have 2 flash disks..\n"); TESTCASE_SKIP("Need disk from same adapter and each disk multipathed"); return 0; } strcpy(disk1,disks[0].dev); strcpy(disk2,disks[1].dev); // creating first context for (i=0;i<21;i++) { p_ctx[i]=&myctx[i]; } p_ctx_1=&myctx_1; p_ctx_2=&myctx_2; debug("1ST PROCEDURE\n"); // using p_ctx[[0] for LUN direct for firect disk /* rc = ctx_init2(p_ctx[0], disks[0].dev, DK_AF_ASSIGN_AFU, disks[0].devno[0]); pthread_create(&thread[0], NULL, ctx_rrq_rx, p_ctx[0]); */ /* rc = create_resource(p_ctx[0], 0, DK_UDF_ASSIGN_PATH, LUN_DIRECT); CHECK_RC(rc, "create LUN_DIRECT failed"); */ // creating another 19 context LUN VIRTUAL for ( i=2;i<21;i++) { sleep(2); rc = ctx_init2(p_ctx[i], disks[1].dev, DK_AF_ASSIGN_AFU, disks[1].devno[0]); rc=create_resource(p_ctx[i], p_ctx[i]->chunk_size, DK_UVF_ASSIGN_PATH, LUN_VIRTUAL); } // do context reuse for direct LUN strcpy(p_ctx[0]->dev,disks[0].dev); strcpy(p_ctx[1]->dev,disks[1].dev); p_ctx[0]->fd = open_dev(disks[0].dev, O_RDWR); if (p_ctx[0]->fd < 0) { fprintf(stderr, "open() failed: device %s, errno %d\n", disks[0].dev, errno); g_error = -1; return -1; } p_ctx[1]->fd = open_dev(disks[1].dev, O_RDWR); //Hoping to open second disk if (p_ctx[1]->fd < 0) { fprintf(stderr, "open() failed: device %s, errno %d\n", disks[1].dev, errno); g_error = -1; } #ifdef _AIX rc = ioctl_dk_capi_query_path(p_ctx[0]); CHECK_RC(rc, "DK_CAPI_QUERY_PATH failed"); #else //TBD for linux #endif p_ctx[0]->work.num_interrupts = p_ctx[1]->work.num_interrupts = 4; rc=ioctl_dk_capi_attach_reuse(p_ctx[0],p_ctx[1],LUN_DIRECT); // CHECK_RC(rc, "DK_CAPI_ATTACH with reuse flag failed"); if ( rc != 0 ) { fprintf(stderr,"LUN DIRECT got attached to new disk with VLUN, should have succeeded"); return rc; } // initiate I/O on all the LUNs for (i=2;i<21;i++) { pthread_create(&thread[i], NULL, ctx_rrq_rx, p_ctx[i]); rc = do_io(p_ctx[i], stride); } if ( rc != 0 ) { fprintf(stderr,"io on some LUN failed"); return rc; } /* using a goto-label removes the compile warning (-O3 issue) */ i=2; for_loop: pthread_cancel(thread[i]); close_res(p_ctx[i]); if (++i < 21) {goto for_loop;} ctx_close(p_ctx[2]); debug("2nd PROCEDURE\n"); // procedure 2 of the same case debug("%d: ........Phase 1 done.. Starting 2nd Phase........\n",getpid()); memset(p_ctx_1, 0, sizeof(struct ctx)); memset(p_ctx_2, 0, sizeof(struct ctx)); // open the first flash disk in write mode and create a DIRECT LUN // restoring from backup strcpy(disks[0].dev,disk1); p_ctx_1->fd = open_dev(disks[0].dev, O_WRONLY); if (p_ctx_1->fd < 0) { fprintf(stderr, "open() failed: device %s, errno %d\n", disks[0].dev, errno); return -1; } rc = ctx_init2(p_ctx_1, disks[0].dev, DK_AF_ASSIGN_AFU, disks[0].devno[0]); pthread_create(&thread[0], NULL, ctx_rrq_rx, p_ctx_1); CHECK_RC(rc, "create context failed"); rc = create_resource(p_ctx_1, 0, DK_UDF_ASSIGN_PATH, LUN_DIRECT); CHECK_RC(rc, "create LUN_DIRECT failed"); // open the same flash disk in read mode again. p_ctx_2->fd = open_dev(disks[0].dev, O_RDONLY); if (p_ctx_2->fd < 0) { fprintf(stderr, "open() failed: device %s, errno %d\n", disks[0].dev, errno); return -1; } rc = ctx_init2(p_ctx_2, disks[0].dev, DK_AF_ASSIGN_AFU, disks[0].devno[0]); pthread_create(&thread[1], NULL, ctx_rrq_rx, p_ctx_2); CHECK_RC(rc, "create context failed"); rc = create_resource(p_ctx_2, 0, DK_UDF_ASSIGN_PATH, LUN_DIRECT); CHECK_RC(rc, "create LUN_DIRECT failed"); // now write to the disk and then read for (st_lba = 0; st_lba <= p_ctx_1->last_lba; st_lba += (NUM_CMDS*stride)) { rc = send_write(p_ctx_1, st_lba, stride, pid); CHECK_RC(rc, "send_write failed"); rc = send_read(p_ctx_2, st_lba, stride); CHECK_RC(rc, "send_read failed"); /*if (rc !=0 ) { rc = rw_cmp_buf(p_ctx_1, st_lba); if (rc != 0) { fprintf(stderr,"buf cmp failed for lba 0x%lX,rc =%d\n",st_lba,rc); break; } }*/ } if ( rc != 0 ) return rc; for (i=0;i<2;i++) { pthread_cancel(thread[i]); } //close_res(p_ctx_1); ctx_close(p_ctx_1); //close_res(p_ctx_2); ctx_close(p_ctx_2); debug("3rd PROCEDURE\n"); debug("%d: ........Phase 2 done.. Starting 3rd Phase........\n",getpid()); // case 3 of the same case // creating multiple process for LUN_DIRECT creation. for (j=0;j<long_run;j++) { for (i=0; i<20;i++) { if ( 0 == fork()) { rc = ctx_init(p_ctx[i]); CHECK_RC_EXIT(rc, "Context init failed"); // CHECK_RC(rc, "Context init failed"); //thread to handle AFU interrupt & events rc = create_resource(p_ctx[i], 0, DK_UDF_ASSIGN_PATH , LUN_DIRECT); CHECK_RC_EXIT(rc, "create LUN_DIRECT failed"); // do io on context pthread_create(&thread[i], NULL, ctx_rrq_rx, p_ctx[i]); stride=0x1000; sleep(2); //do_io(p_ctx[i], stride); pthread_cancel(thread[i]); close_res(p_ctx[i]); exit(rc); } } wait4all(); } return 0; }