1*716fd348SMartin Matuska /* 2*716fd348SMartin Matuska * CDDL HEADER START 3*716fd348SMartin Matuska * 4*716fd348SMartin Matuska * The contents of this file are subject to the terms of the 5*716fd348SMartin Matuska * Common Development and Distribution License (the "License"). 6*716fd348SMartin Matuska * You may not use this file except in compliance with the License. 7*716fd348SMartin Matuska * 8*716fd348SMartin Matuska * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*716fd348SMartin Matuska * or http://www.opensolaris.org/os/licensing. 10*716fd348SMartin Matuska * See the License for the specific language governing permissions 11*716fd348SMartin Matuska * and limitations under the License. 12*716fd348SMartin Matuska * 13*716fd348SMartin Matuska * When distributing Covered Code, include this CDDL HEADER in each 14*716fd348SMartin Matuska * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*716fd348SMartin Matuska * If applicable, add the following below this CDDL HEADER, with the 16*716fd348SMartin Matuska * fields enclosed by brackets "[]" replaced with your own identifying 17*716fd348SMartin Matuska * information: Portions Copyright [yyyy] [name of copyright owner] 18*716fd348SMartin Matuska * 19*716fd348SMartin Matuska * CDDL HEADER END 20*716fd348SMartin Matuska */ 21*716fd348SMartin Matuska 22*716fd348SMartin Matuska /* 23*716fd348SMartin Matuska * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24*716fd348SMartin Matuska * Use is subject to license terms. 25*716fd348SMartin Matuska */ 26*716fd348SMartin Matuska 27*716fd348SMartin Matuska #include <unistd.h> 28*716fd348SMartin Matuska #include <fcntl.h> 29*716fd348SMartin Matuska #include <stdio.h> 30*716fd348SMartin Matuska #include <stdlib.h> 31*716fd348SMartin Matuska #include <string.h> 32*716fd348SMartin Matuska #include <sys/mman.h> 33*716fd348SMartin Matuska #include <pthread.h> 34*716fd348SMartin Matuska #include <errno.h> 35*716fd348SMartin Matuska #include <err.h> 36*716fd348SMartin Matuska 37*716fd348SMartin Matuska /* 38*716fd348SMartin Matuska * -------------------------------------------------------------------- 39*716fd348SMartin Matuska * Bug Issue Id: #7512 40*716fd348SMartin Matuska * The bug time sequence: 41*716fd348SMartin Matuska * 1. context #1, zfs_write assign a txg "n". 42*716fd348SMartin Matuska * 2. In the same process, context #2, mmap page fault (which means the mm_sem 43*716fd348SMartin Matuska * is hold) occurred, zfs_dirty_inode open a txg failed, and wait previous 44*716fd348SMartin Matuska * txg "n" completed. 45*716fd348SMartin Matuska * 3. context #1 call zfs_uiomove to write, however page fault is occurred in 46*716fd348SMartin Matuska * zfs_uiomove, which means it needs mm_sem, but mm_sem is hold by 47*716fd348SMartin Matuska * context #2, so it stuck and can't complete, then txg "n" will not 48*716fd348SMartin Matuska * complete. 49*716fd348SMartin Matuska * 50*716fd348SMartin Matuska * So context #1 and context #2 trap into the "dead lock". 51*716fd348SMartin Matuska * -------------------------------------------------------------------- 52*716fd348SMartin Matuska */ 53*716fd348SMartin Matuska 54*716fd348SMartin Matuska #define NORMAL_WRITE_TH_NUM 2 55*716fd348SMartin Matuska 56*716fd348SMartin Matuska static void * 57*716fd348SMartin Matuska normal_writer(void *filename) 58*716fd348SMartin Matuska { 59*716fd348SMartin Matuska char *file_path = filename; 60*716fd348SMartin Matuska int fd = -1; 61*716fd348SMartin Matuska ssize_t write_num = 0; 62*716fd348SMartin Matuska int page_size = getpagesize(); 63*716fd348SMartin Matuska 64*716fd348SMartin Matuska fd = open(file_path, O_RDWR | O_CREAT, 0777); 65*716fd348SMartin Matuska if (fd == -1) { 66*716fd348SMartin Matuska err(1, "failed to open %s", file_path); 67*716fd348SMartin Matuska } 68*716fd348SMartin Matuska 69*716fd348SMartin Matuska char buf; 70*716fd348SMartin Matuska while (1) { 71*716fd348SMartin Matuska write_num = write(fd, &buf, 1); 72*716fd348SMartin Matuska if (write_num == 0) { 73*716fd348SMartin Matuska err(1, "write failed!"); 74*716fd348SMartin Matuska break; 75*716fd348SMartin Matuska } 76*716fd348SMartin Matuska lseek(fd, page_size, SEEK_CUR); 77*716fd348SMartin Matuska } 78*716fd348SMartin Matuska } 79*716fd348SMartin Matuska 80*716fd348SMartin Matuska static void * 81*716fd348SMartin Matuska map_writer(void *filename) 82*716fd348SMartin Matuska { 83*716fd348SMartin Matuska int fd = -1; 84*716fd348SMartin Matuska int ret = 0; 85*716fd348SMartin Matuska char *buf = NULL; 86*716fd348SMartin Matuska int page_size = getpagesize(); 87*716fd348SMartin Matuska int op_errno = 0; 88*716fd348SMartin Matuska char *file_path = filename; 89*716fd348SMartin Matuska 90*716fd348SMartin Matuska while (1) { 91*716fd348SMartin Matuska ret = access(file_path, F_OK); 92*716fd348SMartin Matuska if (ret) { 93*716fd348SMartin Matuska op_errno = errno; 94*716fd348SMartin Matuska if (op_errno == ENOENT) { 95*716fd348SMartin Matuska fd = open(file_path, O_RDWR | O_CREAT, 0777); 96*716fd348SMartin Matuska if (fd == -1) { 97*716fd348SMartin Matuska err(1, "open file failed"); 98*716fd348SMartin Matuska } 99*716fd348SMartin Matuska 100*716fd348SMartin Matuska ret = ftruncate(fd, page_size); 101*716fd348SMartin Matuska if (ret == -1) { 102*716fd348SMartin Matuska err(1, "truncate file failed"); 103*716fd348SMartin Matuska } 104*716fd348SMartin Matuska } else { 105*716fd348SMartin Matuska err(1, "access file failed!"); 106*716fd348SMartin Matuska } 107*716fd348SMartin Matuska } else { 108*716fd348SMartin Matuska fd = open(file_path, O_RDWR, 0777); 109*716fd348SMartin Matuska if (fd == -1) { 110*716fd348SMartin Matuska err(1, "open file failed"); 111*716fd348SMartin Matuska } 112*716fd348SMartin Matuska } 113*716fd348SMartin Matuska 114*716fd348SMartin Matuska if ((buf = mmap(NULL, page_size, PROT_READ | PROT_WRITE, 115*716fd348SMartin Matuska MAP_SHARED, fd, 0)) == MAP_FAILED) { 116*716fd348SMartin Matuska err(1, "map file failed"); 117*716fd348SMartin Matuska } 118*716fd348SMartin Matuska 119*716fd348SMartin Matuska if (fd != -1) 120*716fd348SMartin Matuska close(fd); 121*716fd348SMartin Matuska 122*716fd348SMartin Matuska char s[10] = {0, }; 123*716fd348SMartin Matuska memcpy(buf, s, 10); 124*716fd348SMartin Matuska ret = munmap(buf, page_size); 125*716fd348SMartin Matuska if (ret != 0) { 126*716fd348SMartin Matuska err(1, "unmap file failed"); 127*716fd348SMartin Matuska } 128*716fd348SMartin Matuska } 129*716fd348SMartin Matuska } 130*716fd348SMartin Matuska 131*716fd348SMartin Matuska int 132*716fd348SMartin Matuska main(int argc, char **argv) 133*716fd348SMartin Matuska { 134*716fd348SMartin Matuska pthread_t map_write_tid; 135*716fd348SMartin Matuska pthread_t normal_write_tid[NORMAL_WRITE_TH_NUM]; 136*716fd348SMartin Matuska int i = 0; 137*716fd348SMartin Matuska 138*716fd348SMartin Matuska if (argc != 3) { 139*716fd348SMartin Matuska (void) printf("usage: %s <normal write file name> " 140*716fd348SMartin Matuska "<map write file name>\n", argv[0]); 141*716fd348SMartin Matuska exit(1); 142*716fd348SMartin Matuska } 143*716fd348SMartin Matuska 144*716fd348SMartin Matuska for (i = 0; i < NORMAL_WRITE_TH_NUM; i++) { 145*716fd348SMartin Matuska if (pthread_create(&normal_write_tid[i], NULL, normal_writer, 146*716fd348SMartin Matuska argv[1])) { 147*716fd348SMartin Matuska err(1, "pthread_create normal_writer failed."); 148*716fd348SMartin Matuska } 149*716fd348SMartin Matuska } 150*716fd348SMartin Matuska 151*716fd348SMartin Matuska if (pthread_create(&map_write_tid, NULL, map_writer, argv[2])) { 152*716fd348SMartin Matuska err(1, "pthread_create map_writer failed."); 153*716fd348SMartin Matuska } 154*716fd348SMartin Matuska 155*716fd348SMartin Matuska pthread_join(map_write_tid, NULL); 156*716fd348SMartin Matuska return (0); 157*716fd348SMartin Matuska } 158