Date: Sun, 22 Jun 1997 09:00:02 -0700 (PDT) From: Tor Egge <Tor.Egge@idi.ntnu.no> To: freebsd-bugs Subject: Re: kern/3688: fsck -p gets transient unexpected inconsistensies Message-ID: <199706221600.JAA08995@hub.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/3688; it has been noted by GNATS. From: Tor Egge <Tor.Egge@idi.ntnu.no> To: Tor.Egge@idi.ntnu.no Cc: FreeBSD-gnats-submit@FreeBSD.ORG Subject: Re: kern/3688: fsck -p gets transient unexpected inconsistensies Date: Sun, 22 Jun 1997 17:56:39 +0200 I wrote: > When recovering from a system crash, `fsck -p' in /etc/rc complained about > unexpected inconsistencies on 3 different filesystems. When running fsck > manually on each of these filesystems, only the clean flag needed to be set in > the superblock. The three filesystems were all located on ccd devices. This is caused by a superblock for a different filesystem being present in memory when comparing the superblock with the alternate superblock. :-( Under some circumstances, copy-on-write handling is broken. How-To-Repeat: Compile the appended program, using the `-static' option. Run this program on a machine with a recent 3.0-current SMP kernel and only one CPU enabled (sysctl -w kern.smp_active=1). ---------- #include <sys/types.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/errno.h> #include <errno.h> #include <assert.h> #include <fcntl.h> #include <fstab.h> #include <string.h> #ifndef NUMCHILD #define NUMCHILD 3 #endif struct child { pid_t pid; int fd; } children[NUMCHILD]; char okbuf[1]; char childbuf[1]; void touchbuf(char *buf); int main(int argc,char **argv) { int i; pid_t pid; int pipefd[2]; char *buf; int exitcode; exitcode = 0; buf = malloc(8*1024); for (i=0;i<NUMCHILD;i++) { if (pipe(pipefd)) { perror("pipe"); exit(1); } fflush(stdout); fflush(stderr); fflush(stdin); pid = fork(); if (pid<0) { perror("fork"); exit(1); } if (pid == 0) { /* child */ close(pipefd[0]); touchbuf(buf); if (read(pipefd[1],buf,1)!=1) { perror("child read"); exit(1); } memcpy(okbuf,buf,1); sleep(1); if (write(pipefd[1],buf,1)!=1) { perror("child write"); exit(1); } if (memcmp(okbuf,buf,1)) printf("Child %d (pid %d) broken\n",i,getpid()); exit(0); } /* parent */ close(pipefd[1]); children[i].fd = pipefd[0]; children[i].pid = pid; } for (i=0;i<NUMCHILD;i++) { memset(childbuf,i+1,sizeof(childbuf)); if (write(children[i].fd,childbuf,1)!=1) { perror("parent write"); exit(1); } } sleep(3); for (i=0;i<NUMCHILD;i++) { memset(okbuf,i+1,sizeof(okbuf)); printf("Verifying child %d (pid %d)\n",i, children[i].pid); if (read(children[i].fd,childbuf,1)!=1) { perror("parent piperead"); } if (memcmp(childbuf,okbuf,1)) { printf("BAD "); exitcode=1; } else printf("GOOD"); printf(" (got %d, expected %d)\n",childbuf[0],okbuf[0]); } exit(exitcode); } char ___xxx; void touchbuf(char *buf) { ___xxx = * buf; } ---------- The result might be something like: ------ ikke:/amd/kamelia/home/kamelia/a/tegge$ ./bad2 Child 1 (pid 553) broken Child 0 (pid 552) broken Verifying child 0 (pid 552) BAD (got 3, expected 1) Verifying child 1 (pid 553) BAD (got 3, expected 2) Verifying child 2 (pid 554) GOOD (got 3, expected 3) ------ When using gdb on the kernel and looking at the page tables, the virtual page pointed to by the `buf' variable is read-only and located on the same physical page for all three child processes. - Tor Egge
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199706221600.JAA08995>