*BSD News Article 61618


Return to BSD News archive

Newsgroups: comp.bugs.2bsd
Path: euryale.cc.adfa.oz.au!newshost.anu.edu.au!harbinger.cc.monash.edu.au!nntp.coast.net!news.kei.com!newsfeed.internetmci.com!in1.uu.net!news.new-york.net!wlbr!sms
From: sms@wlv.iipo.gtegsc.com (Steven M. Schultz)
Subject: Parallel fsck runs conflict with each other (#302)
Sender: news@wlbr.iipo.gtegsc.com (Steven M. Schultz)
Organization: GTE Government Systems, Thousand Oaks CA USA
Message-ID: <DMFwM5.CIn@wlbr.iipo.gtegsc.com>
X-Nntp-Posting-Host: wlv.iipo.gtegsc.com
Date: Thu, 8 Feb 1996 04:32:29 GMT
Lines: 176

Subject: Parallel fsck runs conflict with each other (#302)
Index:	etc/fsck/{setup,main}.c 2.11BSD

Description:
	Parallel fsck runs (filesystems with the same 'passno' value
	in /etc/fstab) will use the same tempfile name for their work
	file resulting in total chaos.

Repeat-By:
	Have more than one entry in /etc/fstab with the same sixth field:

		/dev/ra1g /usr ufs rw 1 4
		/dev/ra0g /u1  ufs rw 1 4

	Fsck will prompt _once_ for a tmp file name but _both_ (parallel)
	instances of fsck will use the name.

Fix:
	Although fsck unlinks the tmp file after creating it there is a 
	race condition which can result in multiple fsck processes using
	the same intermediate file.  The results are not pretty.

	The fix is to append ".XXXXX" to the filename provided by the
	user and then call the 'mkstemp(3)' routine to generate a unique
	temporary file.

	Cut where indicated, saving to a file (/tmp/302) and then:

		patch -p0 < /tmp/301
		cd /usr/src/etc/fsck
		make
		make install
		make clean

===========================cut here===================
*** /usr/src/etc/fsck/setup.c.old	Wed Jun 13 08:45:47 1990
--- /usr/src/etc/fsck/setup.c	Sat Feb  3 21:46:25 1996
***************
*** 5,11 ****
   */
  
  #if	!defined(lint) && defined(DOSCCS)
! static char sccsid[] = "@(#)setup.c	5.3 (Berkeley) 5/15/86";
  #endif not lint
  
  #include <stdio.h>
--- 5,11 ----
   */
  
  #if	!defined(lint) && defined(DOSCCS)
! static char sccsid[] = "@(#)setup.c	5.3.1 (2.11BSD) 1996/2/3";
  #endif not lint
  
  #include <stdio.h>
***************
*** 28,33 ****
--- 28,34 ----
  	int i, j, n;
  	long size;
  	BUFAREA *bp;
+ 	char junk[80 + sizeof (".XXXXX") + 1];
  
  	if (stat("/", &statb) < 0)
  		errexit("Can't stat root\n");
***************
*** 112,136 ****
  			pfatal("\nNEED SCRATCH FILE (%ld BLKS)\n",nscrblk);
  			do {
  				printf("ENTER FILENAME:  ");
! 				if((n = getline(stdin,scrfile,sizeof(scrfile))) == EOF)
  					errexit("\n");
- 				if(stat(scrfile,&statb) == 0 &&
- 					(statb.st_mode & S_IFMT) != S_IFREG)
- 					errexit("Not a good scratch filename");
  			} while(n == 0);
  		}
! 		sfile.wfdes=open(scrfile, O_CREAT|O_TRUNC|O_WRONLY, 0666);
  		if ((sfile.wfdes < 0)
! 		    || ((sfile.rfdes = open(scrfile,0)) < 0)) {
! 			printf("Can't create %s\n",scrfile);
  			ckfini();
  			return(0);
  		}
! 		unlink(scrfile);	/* make it invisible incase we exit */
! 		if (hotroot && (stat(scrfile,&statb)==0)
  		    && ((statb.st_mode & S_IFMT) == S_IFREG)
  		    && (statb.st_dev==rootdev))
! 		     pfatal("TMP FILE (%s) ON ROOT WHEN CHECKING ROOT",scrfile);
  		bp = &((BUFAREA *)mbase)[(msize/sizeof(BUFAREA))];
  		poolhead = NULL;
  		while(--bp >= (BUFAREA *)mbase) {
--- 113,137 ----
  			pfatal("\nNEED SCRATCH FILE (%ld BLKS)\n",nscrblk);
  			do {
  				printf("ENTER FILENAME:  ");
! 				if((n = getline(stdin, scrfile, 
! 						sizeof(scrfile) - 6)) == EOF)
  					errexit("\n");
  			} while(n == 0);
  		}
! 		strcpy(junk, scrfile);
! 		strcat(junk, ".XXXXX");
! 		sfile.wfdes = mkstemp(junk);
  		if ((sfile.wfdes < 0)
! 		    || ((sfile.rfdes = open(junk,0)) < 0)) {
! 			printf("Can't create %s\n", junk);
  			ckfini();
  			return(0);
  		}
! 		unlink(junk);	/* make it invisible incase we exit */
! 		if (hotroot && (fstat(sfile.wfdes,&statb)==0)
  		    && ((statb.st_mode & S_IFMT) == S_IFREG)
  		    && (statb.st_dev==rootdev))
! 		     pfatal("TMP FILE (%s) ON ROOT WHEN CHECKING ROOT", junk);
  		bp = &((BUFAREA *)mbase)[(msize/sizeof(BUFAREA))];
  		poolhead = NULL;
  		while(--bp >= (BUFAREA *)mbase) {
*** /usr/src/etc/fsck/main.c.old	Wed Jun 13 08:42:32 1990
--- /usr/src/etc/fsck/main.c	Sat Feb  3 21:42:38 1996
***************
*** 9,15 ****
  "@(#) Copyright (c) 1980 Regents of the University of California.\n\
   All rights reserved.\n";
  
! static char sccsid[] = "@(#)main.c	5.4 (Berkeley) 3/5/86";
  #endif not lint
  
  #include <sys/param.h>
--- 9,15 ----
  "@(#) Copyright (c) 1980 Regents of the University of California.\n\
   All rights reserved.\n";
  
! static char sccsid[] = "@(#)main.c	5.4.1 (2.11BSD) 1996/2/3";
  #endif not lint
  
  #include <sys/param.h>
***************
*** 114,124 ****
  	do {
  		anygtr = 0;
  		if (setfsent() == 0)
! 			errexit("Can't open checklist file: %s\n", FSTAB);
  		while ((fsp = getfsent()) != 0) {
! 			if (strcmp(fsp->fs_type, FSTAB_RW) &&
  			    strcmp(fsp->fs_type, FSTAB_RO) &&
! 			    strcmp(fsp->fs_type, FSTAB_RQ))
  				continue;
  			if (preen == 0 ||
  			    passno == 1 && fsp->fs_passno == passno) {
--- 114,126 ----
  	do {
  		anygtr = 0;
  		if (setfsent() == 0)
! 			errexit("Can't open %s\n", FSTAB);
  		while ((fsp = getfsent()) != 0) {
! 			if (strcmp(fsp->fs_vfstype, "ufs") ||
! 			    (strcmp(fsp->fs_type, FSTAB_RW) &&
  			    strcmp(fsp->fs_type, FSTAB_RO) &&
! 			    strcmp(fsp->fs_type, FSTAB_RQ)) ||
! 			    fsp->fs_passno == 0)
  				continue;
  			if (preen == 0 ||
  			    passno == 1 && fsp->fs_passno == passno) {
*** /VERSION.old	Wed Feb  7 19:51:21 1996
--- /VERSION	Wed Feb  7 20:16:05 1996
***************
*** 1,4 ****
! Current Patch Level: 301
  
  2.11 BSD
  ============
--- 1,4 ----
! Current Patch Level: 302
  
  2.11 BSD
  ============