static void do_child(void) { int fd, offset; char buf[FS_BLOCKSIZE]; char *addr = NULL; /* * We have changed SIGBUS' handler in parent process by calling * tst_sig(FORK, DEF_HANDLER, NULL), so here just restore it. */ if (signal(SIGBUS, SIG_DFL) == SIG_ERR) tst_brkm(TBROK | TERRNO, NULL, "signal(SIGBUS) failed"); memset(buf, 'a', FS_BLOCKSIZE); fd = SAFE_OPEN(NULL, "testfilec", O_RDWR); SAFE_PWRITE(NULL, 1, fd, buf, FS_BLOCKSIZE, 0); /* * In case mremap() may fail because that memory area can not be * expanded at current virtual address(MREMAP_MAYMOVE is not set), * we first do a mmap(page_size * 2) operation to reserve some * free address space. */ addr = SAFE_MMAP(NULL, NULL, page_size * 2, PROT_WRITE | PROT_READ, MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, -1, 0); SAFE_MUNMAP(NULL, addr, page_size * 2); addr = SAFE_MMAP(NULL, addr, FS_BLOCKSIZE, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0); addr[0] = 'a'; SAFE_FTRUNCATE(NULL, fd, page_size * 2); addr = mremap(addr, FS_BLOCKSIZE, 2 * page_size, 0); if (addr == MAP_FAILED) tst_brkm(TBROK | TERRNO, NULL, "mremap failed unexpectedly"); /* * Let parent process consume FS free blocks as many as possible, then * there'll be no free blocks allocated for this new file mmaping for * offset starting at 1024, 2048, or 3072. If this above kernel bug * has been fixed, usually child process will killed by SIGBUS signal, * if not, the data 'A', 'B', 'C' will be silently discarded later when * kernel writepage is called, that means data corruption. */ TST_SAFE_CHECKPOINT_WAKE(NULL, 0); TST_SAFE_CHECKPOINT_WAIT(NULL, 0); for (offset = FS_BLOCKSIZE; offset < page_size; offset += FS_BLOCKSIZE) addr[offset] = 'a'; SAFE_MUNMAP(NULL, addr, 2 * page_size); SAFE_CLOSE(NULL, fd); exit(TFAIL); }
static void verify_pwritev2(unsigned int n) { int i; char preadbuf[CHUNK]; struct tcase *tc = &tcases[n]; SAFE_PWRITE(1, fd, initbuf, sizeof(initbuf), 0); SAFE_LSEEK(fd, tc->seek_off, SEEK_SET); TEST(pwritev2(fd, wr_iovec, tc->count, tc->write_off, 0)); if (TST_RET < 0) { tst_res(TFAIL | TTERRNO, "pwritev2() failed"); return; } if (TST_RET != tc->size) { tst_res(TFAIL, "pwritev2() wrote %li bytes, expected %zi", TST_RET, tc->size); return; } if (SAFE_LSEEK(fd, 0, SEEK_CUR) != tc->exp_off) { tst_res(TFAIL, "pwritev2() had changed file offset"); return; } memset(preadbuf, 0, CHUNK); if (tc->write_off != -1) SAFE_PREAD(1, fd, preadbuf, tc->size, tc->write_off); else SAFE_PREAD(1, fd, preadbuf, tc->size, tc->seek_off); for (i = 0; i < tc->size; i++) { if (preadbuf[i] != 0x61) break; } if (i != tc->size) { tst_res(TFAIL, "buffer wrong at %i have %c expected 'a'", i, preadbuf[i]); return; } tst_res(TPASS, "pwritev2() wrote %zi bytes successfully " "with content 'a' expectedly ", tc->size); }