Skip site navigation (1)Skip section navigation (2)
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>