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