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>
