xref: /freebsd/tools/test/stress2/misc/mapwrite.sh (revision 81b7ebe32edd4be705fe2d50c8d061191ba41573)
1*81b7ebe3SPeter Holm#!/bin/sh
2*81b7ebe3SPeter Holm
3*81b7ebe3SPeter Holm# File corruption scenario
4*81b7ebe3SPeter Holm
5*81b7ebe3SPeter Holm# Test program by Rob Norris <rob norris klarasystems com>
6*81b7ebe3SPeter Holm# Test program obtained from: https://gist.github.com/robn/9804c60cd0275086d26893d73e7af35c
7*81b7ebe3SPeter Holm# https://github.com/openzfs/zfs/issues/15654
8*81b7ebe3SPeter Holm
9*81b7ebe3SPeter Holm[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
10*81b7ebe3SPeter Holm
11*81b7ebe3SPeter Holm. ../default.cfg
12*81b7ebe3SPeter Holm
13*81b7ebe3SPeter Holmset -u
14*81b7ebe3SPeter Holmprog=$(basename "$0" .sh)
15*81b7ebe3SPeter Holmcat > /tmp/$prog.c <<EOF
16*81b7ebe3SPeter Holm/*
17*81b7ebe3SPeter Holm * Some kind of clone-related crasher. Not sure if legit or just outdated
18*81b7ebe3SPeter Holm * assertion.
19*81b7ebe3SPeter Holm *
20*81b7ebe3SPeter Holm * Creates clone, maps it, writes from map back into itself.
21*81b7ebe3SPeter Holm *
22*81b7ebe3SPeter Holm * Compile a recent (2.2+) ZFS with --enable-debug.
23*81b7ebe3SPeter Holm *
24*81b7ebe3SPeter Holm * cc -o mapwrite mapwrite.c
25*81b7ebe3SPeter Holm *
26*81b7ebe3SPeter Holm * echo 1 > /sys/modules/zfs/parameters/zfs_bclone_enabled
27*81b7ebe3SPeter Holm * zpool create tank ...
28*81b7ebe3SPeter Holm * cd /tank
29*81b7ebe3SPeter Holm * mapwrite
30*81b7ebe3SPeter Holm *
31*81b7ebe3SPeter Holm * [    7.666305] VERIFY(arc_released(db->db_buf)) failed
32*81b7ebe3SPeter Holm * [    7.666443] PANIC at dbuf.c:2150:dbuf_redirty()
33*81b7ebe3SPeter Holm * [    7.666489] Showing stack for process 608
34*81b7ebe3SPeter Holm * [    7.666534] CPU: 1 PID: 608 Comm: mapwrite Tainted: P           O      5.10.170 #3
35*81b7ebe3SPeter Holm * [    7.666610] Call Trace:
36*81b7ebe3SPeter Holm * [    7.666646]  dump_stack+0x57/0x6e
37*81b7ebe3SPeter Holm * [    7.666717]  spl_panic+0xd3/0xfb [spl]
38*81b7ebe3SPeter Holm * [    7.667113]  ? zfs_btree_find+0x16a/0x300 [zfs]
39*81b7ebe3SPeter Holm * [    7.667278]  ? range_tree_find_impl+0x55/0xa0 [zfs]
40*81b7ebe3SPeter Holm * [    7.667333]  ? _cond_resched+0x1a/0x50
41*81b7ebe3SPeter Holm * [    7.667371]  ? __kmalloc_node+0x14a/0x2b0
42*81b7ebe3SPeter Holm * [    7.667415]  ? spl_kmem_alloc_impl+0xb0/0xd0 [spl]
43*81b7ebe3SPeter Holm * [    7.667555]  ? __list_add+0x12/0x30 [zfs]
44*81b7ebe3SPeter Holm * [    7.667681]  spl_assert+0x17/0x20 [zfs]
45*81b7ebe3SPeter Holm * [    7.667807]  dbuf_redirty+0xad/0xb0 [zfs]
46*81b7ebe3SPeter Holm * [    7.667963]  dbuf_dirty+0xe76/0x1310 [zfs]
47*81b7ebe3SPeter Holm * [    7.668011]  ? mutex_lock+0xe/0x30
48*81b7ebe3SPeter Holm * [    7.668133]  ? dbuf_noread+0x112/0x240 [zfs]
49*81b7ebe3SPeter Holm * [    7.668271]  dmu_write_uio_dnode+0x101/0x1b0 [zfs]
50*81b7ebe3SPeter Holm * [    7.668411]  dmu_write_uio_dbuf+0x4a/0x70 [zfs]
51*81b7ebe3SPeter Holm * [    7.668555]  zfs_write+0x500/0xc80 [zfs]
52*81b7ebe3SPeter Holm * [    7.668610]  ? page_add_file_rmap+0xe/0xb0
53*81b7ebe3SPeter Holm * [    7.668740]  zpl_iter_write+0xe4/0x130 [zfs]
54*81b7ebe3SPeter Holm * [    7.668803]  new_sync_write+0x119/0x1b0
55*81b7ebe3SPeter Holm * [    7.668843]  vfs_write+0x1ce/0x260
56*81b7ebe3SPeter Holm * [    7.668880]  __x64_sys_pwrite64+0x91/0xc0
57*81b7ebe3SPeter Holm * [    7.668918]  do_syscall_64+0x30/0x40
58*81b7ebe3SPeter Holm * [    7.668957]  entry_SYSCALL_64_after_hwframe+0x61/0xc6
59*81b7ebe3SPeter Holm */
60*81b7ebe3SPeter Holm
61*81b7ebe3SPeter Holm#define	_GNU_SOURCE
62*81b7ebe3SPeter Holm
63*81b7ebe3SPeter Holm#include <fcntl.h>
64*81b7ebe3SPeter Holm#include <string.h>
65*81b7ebe3SPeter Holm#include <stdio.h>
66*81b7ebe3SPeter Holm#include <stdlib.h>
67*81b7ebe3SPeter Holm#include <unistd.h>
68*81b7ebe3SPeter Holm#include <errno.h>
69*81b7ebe3SPeter Holm#include <sys/stat.h>
70*81b7ebe3SPeter Holm#include <sys/mman.h>
71*81b7ebe3SPeter Holm
72*81b7ebe3SPeter Holm#define	DATASIZE	(1024*1024)
73*81b7ebe3SPeter Holmchar data[DATASIZE];
74*81b7ebe3SPeter Holm
75*81b7ebe3SPeter Holm#define NDATA		(512)
76*81b7ebe3SPeter Holm
77*81b7ebe3SPeter Holm#define FILE_NAME	"file"
78*81b7ebe3SPeter Holm#define CLONE_NAME	"clone"
79*81b7ebe3SPeter Holm
80*81b7ebe3SPeter Holmstatic int
81*81b7ebe3SPeter Holm_create_file(void)
82*81b7ebe3SPeter Holm{
83*81b7ebe3SPeter Holm	memset(data, 0x5a, DATASIZE);
84*81b7ebe3SPeter Holm
85*81b7ebe3SPeter Holm	int fd;
86*81b7ebe3SPeter Holm	if ((fd = open(FILE_NAME, O_RDWR | O_CREAT | O_APPEND,
87*81b7ebe3SPeter Holm	    S_IRUSR | S_IWUSR)) < 0) {
88*81b7ebe3SPeter Holm		perror("open '" FILE_NAME "'");
89*81b7ebe3SPeter Holm		abort();
90*81b7ebe3SPeter Holm	}
91*81b7ebe3SPeter Holm
92*81b7ebe3SPeter Holm	for (int i = 0; i < NDATA; i++) {
93*81b7ebe3SPeter Holm		int nwr = write(fd, data, DATASIZE);
94*81b7ebe3SPeter Holm		if (nwr < 0) {
95*81b7ebe3SPeter Holm			perror("write");
96*81b7ebe3SPeter Holm			abort();
97*81b7ebe3SPeter Holm		}
98*81b7ebe3SPeter Holm		if (nwr < DATASIZE) {
99*81b7ebe3SPeter Holm			fprintf(stderr, "short write\n");
100*81b7ebe3SPeter Holm			abort();
101*81b7ebe3SPeter Holm		}
102*81b7ebe3SPeter Holm	}
103*81b7ebe3SPeter Holm
104*81b7ebe3SPeter Holm	if (lseek(fd, 0, SEEK_SET) < 0) {
105*81b7ebe3SPeter Holm		perror("lseek");
106*81b7ebe3SPeter Holm		abort();
107*81b7ebe3SPeter Holm	}
108*81b7ebe3SPeter Holm
109*81b7ebe3SPeter Holm	sync();
110*81b7ebe3SPeter Holm
111*81b7ebe3SPeter Holm	return (fd);
112*81b7ebe3SPeter Holm}
113*81b7ebe3SPeter Holm
114*81b7ebe3SPeter Holmstatic int
115*81b7ebe3SPeter Holm_clone_file(int sfd)
116*81b7ebe3SPeter Holm{
117*81b7ebe3SPeter Holm	int dfd;
118*81b7ebe3SPeter Holm	if ((dfd = open(CLONE_NAME, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
119*81b7ebe3SPeter Holm		perror("open '" CLONE_NAME "'");
120*81b7ebe3SPeter Holm		abort();
121*81b7ebe3SPeter Holm	}
122*81b7ebe3SPeter Holm
123*81b7ebe3SPeter Holm	if (copy_file_range(sfd, 0, dfd, 0, DATASIZE * NDATA, 0) < 0) {
124*81b7ebe3SPeter Holm		perror("copy_file_range");
125*81b7ebe3SPeter Holm		abort();
126*81b7ebe3SPeter Holm	}
127*81b7ebe3SPeter Holm
128*81b7ebe3SPeter Holm	return (dfd);
129*81b7ebe3SPeter Holm}
130*81b7ebe3SPeter Holm
131*81b7ebe3SPeter Holmstatic void *
132*81b7ebe3SPeter Holm_map_file(int fd)
133*81b7ebe3SPeter Holm{
134*81b7ebe3SPeter Holm	void *p = mmap(NULL, DATASIZE*NDATA, PROT_READ, MAP_SHARED, fd, 0);
135*81b7ebe3SPeter Holm	if (p == MAP_FAILED) {
136*81b7ebe3SPeter Holm		perror("mmap");
137*81b7ebe3SPeter Holm		abort();
138*81b7ebe3SPeter Holm	}
139*81b7ebe3SPeter Holm
140*81b7ebe3SPeter Holm	return (p);
141*81b7ebe3SPeter Holm}
142*81b7ebe3SPeter Holm
143*81b7ebe3SPeter Holmstatic void
144*81b7ebe3SPeter Holm_map_write(void *p, int fd)
145*81b7ebe3SPeter Holm{
146*81b7ebe3SPeter Holm	if (pwrite(fd, p, DATASIZE, 0) < 0) {
147*81b7ebe3SPeter Holm		perror("pwrite");
148*81b7ebe3SPeter Holm		abort();
149*81b7ebe3SPeter Holm	}
150*81b7ebe3SPeter Holm}
151*81b7ebe3SPeter Holm
152*81b7ebe3SPeter Holmint
153*81b7ebe3SPeter Holmmain(void)
154*81b7ebe3SPeter Holm{
155*81b7ebe3SPeter Holm	int sfd = _create_file();
156*81b7ebe3SPeter Holm	int dfd = _clone_file(sfd);
157*81b7ebe3SPeter Holm	void *p = _map_file(dfd);
158*81b7ebe3SPeter Holm	_map_write(p, dfd);
159*81b7ebe3SPeter Holm	return (0);
160*81b7ebe3SPeter Holm}
161*81b7ebe3SPeter HolmEOF
162*81b7ebe3SPeter Holmmycc -o /tmp/$prog -Wall -Wextra -O2 /tmp/$prog.c || exit 1
163*81b7ebe3SPeter Holm
164*81b7ebe3SPeter Holmmount | grep -q "on $mntpoint " && umount -f $mntpoint
165*81b7ebe3SPeter Holmmdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart
166*81b7ebe3SPeter Holmmdconfig -s 5g -u $mdstart
167*81b7ebe3SPeter Holm
168*81b7ebe3SPeter Holmnewfs -n $newfs_flags /dev/md$mdstart > /dev/null
169*81b7ebe3SPeter Holmmount /dev/md$mdstart $mntpoint
170*81b7ebe3SPeter Holm
171*81b7ebe3SPeter Holmmycc -o /tmp/swap -Wall -Wextra -O0 ../tools/swap.c || exit 1
172*81b7ebe3SPeter Holmtimeout -k 90 60 /tmp/swap -d 100 &
173*81b7ebe3SPeter Holmfor i in `jot 10`; do
174*81b7ebe3SPeter Holm	capacity=`swapinfo | tail -1 | sed 's/.* //; s/%//'`
175*81b7ebe3SPeter Holm	[ $capacity -gt 1 ] && break
176*81b7ebe3SPeter Holm	sleep 2	# Wait for swapping
177*81b7ebe3SPeter Holmdone
178*81b7ebe3SPeter Holm
179*81b7ebe3SPeter Holmcd $mntpoint
180*81b7ebe3SPeter Holm/tmp/$prog; s=$?
181*81b7ebe3SPeter Holmpkill swap
182*81b7ebe3SPeter Holmwait
183*81b7ebe3SPeter Holmcmp $mntpoint/file $mntpoint/clone || { echo Fail; s=1; }
184*81b7ebe3SPeter Holmcd -
185*81b7ebe3SPeter Holm
186*81b7ebe3SPeter Holmumount $mntpoint
187*81b7ebe3SPeter Holmmdconfig -d -u $mdstart
188*81b7ebe3SPeter Holmrm /tmp/$prog /tmp/$prog.c
189*81b7ebe3SPeter Holmexit $s
190