Path: blob/main/sys/contrib/openzfs/tests/zfs-tests/cmd/mmapwrite.c
48529 views
// SPDX-License-Identifier: CDDL-1.01/*2* CDDL HEADER START3*4* The contents of this file are subject to the terms of the5* 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.LICENSE9* or https://opensource.org/licenses/CDDL-1.0.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/2122/*23* Copyright 2007 Sun Microsystems, Inc. All rights reserved.24* Use is subject to license terms.25*/2627#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>3637/*38* --------------------------------------------------------------------39* Bug Issue Id: #751240* 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_sem43* is hold) occurred, zfs_dirty_inode open a txg failed, and wait previous44* txg "n" completed.45* 3. context #1 call zfs_uiomove to write, however page fault is occurred in46* zfs_uiomove, which means it needs mm_sem, but mm_sem is hold by47* context #2, so it stuck and can't complete, then txg "n" will not48* complete.49*50* So context #1 and context #2 trap into the "dead lock".51* --------------------------------------------------------------------52*/5354#define NORMAL_WRITE_TH_NUM 255#define MAX_WRITE_BYTES 2621440005657static void *58normal_writer(void *filename)59{60char *file_path = filename;61int fd;62ssize_t write_num = 0;63int page_size = getpagesize();6465fd = open(file_path, O_RDWR | O_CREAT, 0777);66if (fd == -1) {67err(1, "failed to open %s", file_path);68}6970char buf = 'z';71off_t bytes_written = 0;7273while (bytes_written < MAX_WRITE_BYTES) {74write_num = write(fd, &buf, 1);75if (write_num == 0) {76err(1, "write failed!");77break;78}79if ((bytes_written = lseek(fd, page_size, SEEK_CUR)) == -1) {80err(1, "lseek failed on %s: %s", file_path,81strerror(errno));82break;83}84}8586if (close(fd) != 0)87err(1, "failed to close file");8889return (NULL);90}9192static void *93map_writer(void *filename)94{95int fd;96int ret = 0;97char *buf = NULL;98int page_size = getpagesize();99char *file_path = filename;100101while (1) {102fd = open(file_path, O_RDWR);103if (fd == -1) {104if (errno == ENOENT) {105fd = open(file_path, O_RDWR | O_CREAT, 0777);106if (fd == -1) {107err(1, "open file failed");108}109ret = ftruncate(fd, page_size);110if (ret == -1) {111err(1, "truncate file failed");112}113} else {114err(1, "open file failed");115}116}117118if ((buf = mmap(NULL, page_size, PROT_READ | PROT_WRITE,119MAP_SHARED, fd, 0)) == MAP_FAILED) {120err(1, "map file failed");121}122123if (fd != -1)124close(fd);125126char s[10] = {0, };127memcpy(buf, s, 10);128ret = munmap(buf, page_size);129if (ret != 0) {130err(1, "unmap file failed");131}132}133}134135int136main(int argc, char **argv)137{138pthread_t map_write_tid;139pthread_t normal_write_tid[NORMAL_WRITE_TH_NUM];140int i = 0;141142if (argc != 3) {143(void) printf("usage: %s <normal write file name> "144"<map write file name>\n", argv[0]);145exit(1);146}147148for (i = 0; i < NORMAL_WRITE_TH_NUM; i++) {149if (pthread_create(&normal_write_tid[i], NULL, normal_writer,150argv[1])) {151err(1, "pthread_create normal_writer failed.");152}153}154155if (pthread_create(&map_write_tid, NULL, map_writer, argv[2])) {156err(1, "pthread_create map_writer failed.");157}158159pthread_join(map_write_tid, NULL);160return (0);161}162163164