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 #define MAX_WRITE_BYTES 262144000 56 57 static void * 58 normal_writer(void *filename) 59 { 60 char *file_path = filename; 61 int fd = -1; 62 ssize_t write_num = 0; 63 int page_size = getpagesize(); 64 65 fd = open(file_path, O_RDWR | O_CREAT, 0777); 66 if (fd == -1) { 67 err(1, "failed to open %s", file_path); 68 } 69 70 char buf = 'z'; 71 off_t bytes_written = 0; 72 73 while (bytes_written < MAX_WRITE_BYTES) { 74 write_num = write(fd, &buf, 1); 75 if (write_num == 0) { 76 err(1, "write failed!"); 77 break; 78 } 79 if ((bytes_written = lseek(fd, page_size, SEEK_CUR)) == -1) { 80 err(1, "lseek failed on %s: %s", file_path, 81 strerror(errno)); 82 break; 83 } 84 } 85 86 if (close(fd) != 0) 87 err(1, "failed to close file"); 88 89 return (NULL); 90 } 91 92 static void * 93 map_writer(void *filename) 94 { 95 int fd = -1; 96 int ret = 0; 97 char *buf = NULL; 98 int page_size = getpagesize(); 99 char *file_path = filename; 100 101 while (1) { 102 fd = open(file_path, O_RDWR); 103 if (fd == -1) { 104 if (errno == ENOENT) { 105 fd = open(file_path, O_RDWR | O_CREAT, 0777); 106 if (fd == -1) { 107 err(1, "open file failed"); 108 } 109 ret = ftruncate(fd, page_size); 110 if (ret == -1) { 111 err(1, "truncate file failed"); 112 } 113 } else { 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