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