From: paulp@uts.amdahl.com (Paul Popelka)
Newsgroups: comp.unix.bsd
Subject: [386bsd] patches for pcfs to support hard disk filesystems
Date: 23 Nov 92 17:35:09 GMT
Organization: Amdahl Corporation, Sunnyvale CA


Hi,

Here are some patches to make pcfs work with dos filesystems
on hard disks.  Don't use an unpatched pcfs on hard disks.

To mount a hard disk dos filesystem:
- use disklabel to define a 386bsd partition that covers the
  area occupied by the dos filesystem.  Set this partition's
  type to MSDOS with disklabel.  When you use disklabel in
  this way it will write a 386bsd bootblock on the
  first block of the disk.  This wipes out the dos partition
  table.  I don't know of a way to prevent
  it from doing this.  So, I just used dd to save a copy of
  the dos bootblock, and restored it after disklabel was done.
- Then, mount the filesystem.  Example:
	mount -t pcfs /dev/sd0b /mnt

Don't put a dos filesystem in partition "a" of your hard disk.
This will corrupt that dos filesystem.  This is because the kernel
thinks partition "a" covers the disk label and attempts to write
in the area where the label is thought to be are disallowed.
Unfortunately the first block of the fat in a hard disk dos
filesystem lives in this spot where the label might be.

There is a problem with moving directories in pcfs.  It does
NOT corrupt your filesystem.  Here's a description of how to
see the problem.

	Assume there are 3 directories on the filesystem.  One
	called abc and under it is one called def.  Under def
	is one called 123.

	mount -t pcfs /dev/fd0a /mnt
	cd /mnt
	mv abc/def def
	cd def/123
	pwd
		/mnt/def/123
	cd /mnt
	mv def abc
	cd abc/def
	pwd

	At this pointed the diagnostic "pwd: No such file or directory"
	will appear.  At this point we are(?) in directory /mnt/abc/def.

	cd ..
	pwd
		/mnt

	So, the cd .. moved us up 2 levels to def's old parent.

Once the vnode cache is flushed of the related vnodes this
works ok.  I'm looking at this problem.

Paul

--------------------------cut here-----------------------------------
*** 0.0/pcfs_fat.c	Sun Nov 22 20:14:33 1992
--- pcfs_fat.c	Fri Nov 20 20:06:05 1992
***************
*** 204,211 ****
  			if (bn != bp0_bn) {
  				if (bp0)
  					brelse(bp0);
! 				if (error = bread(pmp->pm_devvp, bn,
! 				    pmp->pm_BytesPerSec, NOCRED, &bp0)) {
  					brelse(bp0);
  					return error;
  				}
--- 204,212 ----
  			if (bn != bp0_bn) {
  				if (bp0)
  					brelse(bp0);
! 				error = bread(pmp->pm_devvp, bn,
! 				    pmp->pm_BytesPerSec, NOCRED, &bp0);
! 				if (error) {
  					brelse(bp0);
  					return error;
  				}
***************
*** 571,577 ****
  				whichbyte));
  		}
  		if (function & FAT_SET) {
! 			*(u_short *)(bp0->b_un.b_addr+whichbyte) = newcontents;
  			updateotherfats(pmp, bp0, 0, whichblk);
  			if (pmp->pm_waitonfat)
  				bwrite(bp0);	/* write out blk from the 1st fat */
--- 572,578 ----
  				whichbyte));
  		}
  		if (function & FAT_SET) {
! 			*((u_short *)(bp0->b_un.b_addr+whichbyte)) = newcontents;
  			updateotherfats(pmp, bp0, 0, whichblk);
  			if (pmp->pm_waitonfat)
  				bwrite(bp0);	/* write out blk from the 1st fat */
*** 0.0/pcfs_lookup.c	Sun Nov 22 20:14:24 1992
--- pcfs_lookup.c	Sat Nov 21 20:49:24 1992
***************
*** 488,494 ****
   */
  	if (ndp->ni_pcfs.pcfs_cluster == PCFSROOT) {
  		bn = pmp->pm_rootdirblk +
! 			(ndp->ni_pcfs.pcfs_offset / pmp->pm_depclust);
  		theoff = ndp->ni_pcfs.pcfs_offset % pmp->pm_depclust;
  	} else {
  		bn = cntobn(pmp, ndp->ni_pcfs.pcfs_cluster);
--- 488,495 ----
   */
  	if (ndp->ni_pcfs.pcfs_cluster == PCFSROOT) {
  		bn = pmp->pm_rootdirblk +
! 			((ndp->ni_pcfs.pcfs_offset / pmp->pm_depclust) *
! 			pmp->pm_SectPerClust);
  		theoff = ndp->ni_pcfs.pcfs_offset % pmp->pm_depclust;
  	} else {
  		bn = cntobn(pmp, ndp->ni_pcfs.pcfs_cluster);
***************
*** 534,540 ****
  	struct buf *bp;
  
  	if (dirclust == PCFSROOT) {
! 		bn = pmp->pm_rootdirblk + (diroffset / pmp->pm_depclust);
  		offset = diroffset % pmp->pm_depclust;
  	} else {
  		bn = cntobn(pmp, dirclust);
--- 535,542 ----
  	struct buf *bp;
  
  	if (dirclust == PCFSROOT) {
! 		bn = pmp->pm_rootdirblk + ((diroffset / pmp->pm_depclust) *
! 			pmp->pm_SectPerClust);
  		offset = diroffset % pmp->pm_depclust;
  	} else {
  		bn = cntobn(pmp, dirclust);
***************
*** 753,759 ****
  
  	if (dep->de_dirclust == PCFSROOT) {
  		bn = pmp->pm_rootdirblk +
! 			(dep->de_diroffset / pmp->pm_depclust);
  		theoff = dep->de_diroffset % pmp->pm_depclust;
  	} else {
  		bn = cntobn(pmp, dep->de_dirclust);
--- 755,762 ----
  
  	if (dep->de_dirclust == PCFSROOT) {
  		bn = pmp->pm_rootdirblk +
! 			((dep->de_diroffset / pmp->pm_depclust) *
! 			pmp->pm_SectPerClust);
  		theoff = dep->de_diroffset % pmp->pm_depclust;
  	} else {
  		bn = cntobn(pmp, dep->de_dirclust);
*** 0.0/pcfs_vnops.c	Wed Nov 18 21:46:28 1992
--- pcfs_vnops.c	Sat Nov 21 20:18:45 1992
***************
*** 991,996 ****
--- 991,997 ----
   *  tdep is unlocked and unreferenced
   */
  	} else {
+ 		unsigned long dirsize;
  /*
   *  If the source and destination are in different
   *  directories, then mark the entry in the source
***************
*** 1000,1009 ****
   *  the filesystem.  And, if we moved a directory,
   *  then update its .. entry to point to the new
   *  parent directory.
   */
  		DELOCK(fdep);
  		bcopy(toname, fdep->de_Name, 11);	/* update denode */
! 		if (error = createde(fdep, tndp, (struct denode **)0)) {
  			/* should put back filename */
  			DEUNLOCK(fdep);
  			goto bad;
--- 1001,1021 ----
   *  the filesystem.  And, if we moved a directory,
   *  then update its .. entry to point to the new
   *  parent directory.
+  *  If we moved a directory will also insure that
+  *  the directory entry on disk has a filesize of
+  *  zero.
   */
  		DELOCK(fdep);
  		bcopy(toname, fdep->de_Name, 11);	/* update denode */
! 		if (fdep->de_Attributes & ATTR_DIRECTORY) {
! 			dirsize = fdep->de_FileSize;
! 			fdep->de_FileSize = 0;
! 		}
! 		error = createde(fdep, tndp, (struct denode **)0);
! 		if (fdep->de_Attributes & ATTR_DIRECTORY) {
! 			fdep->de_FileSize = dirsize;
! 		}
! 		if (error) {
  			/* should put back filename */
  			DEUNLOCK(fdep);
  			goto bad;
***************
*** 1294,1299 ****
--- 1306,1312 ----
  {
  	int error = 0;
  	int diff;
+ 	char pushout;
  	long n;
  	long on;
  	long lost;
***************
*** 1380,1389 ****
  /*
   *  code to convert from dos directory entries to ufs directory entries
   */
! 		dentp = (struct direntry *)bp->b_un.b_addr + on;
  		prev = 0;
  		crnt = (struct dirent *)dirbuf;
! 		while ((char *)dentp < bp->b_un.b_addr + n) {
  /*printf("rd: dentp %08x prev %08x crnt %08x deName %02x attr %02x\n",
  	dentp, prev, crnt, dentp->deName[0], dentp->deAttributes);*/
  /*
--- 1393,1403 ----
  /*
   *  code to convert from dos directory entries to ufs directory entries
   */
! 		pushout = 0;
! 		dentp = (struct direntry *)(bp->b_un.b_addr + on);
  		prev = 0;
  		crnt = (struct dirent *)dirbuf;
! 		while ((char *)dentp < bp->b_un.b_addr + on + n) {
  /*printf("rd: dentp %08x prev %08x crnt %08x deName %02x attr %02x\n",
  	dentp, prev, crnt, dentp->deName[0], dentp->deAttributes);*/
  /*
***************
*** 1392,1401 ****
   *  space onto the end of the previous entry or,
   *  manufacture an empty entry if there is no previous
   *  entry.
-  *  If the entry is empty then set a flag saying finish
-  *  out the block but signal an end of file since empty
-  *  slots mean there are no further entries of interest
-  *  in the directory.
   */
  			if (dentp->deName[0] == SLOT_EMPTY  ||
  			    dentp->deName[0] == SLOT_DELETED  ||
--- 1406,1411 ----
***************
*** 1432,1437 ****
--- 1442,1448 ----
  				prev = crnt;
  			}
  			crnt = (struct dirent *)((char *)crnt + sizeof(struct direntry));
+ 			pushout = 1;
  
  /*
   *  If our intermediate buffer is full then copy
***************
*** 1443,1449 ****
   *  the buffer before brelse()'ing it.
   */
  			if ((unsigned char *)crnt >= &dirbuf[sizeof dirbuf]) {
! 				error = uiomove(dirbuf, n, uio);
  				if (error)
  					break;
  				prev = 0;
--- 1454,1461 ----
   *  the buffer before brelse()'ing it.
   */
  			if ((unsigned char *)crnt >= &dirbuf[sizeof dirbuf]) {
! 				pushout = 0;
! 				error = uiomove(dirbuf, sizeof(dirbuf), uio);
  				if (error)
  					break;
  				prev = 0;
***************
*** 1451,1456 ****
--- 1463,1473 ----
  			}
  			dentp++;
  		}
+ 		if (pushout) {
+ 			pushout = 0;
+ 			error = uiomove(dirbuf, (char *)crnt - (char *)dirbuf,
+ 				uio);
+ 		}
  
  /*
   *  If we have read everything from this block or
***************
*** 1572,1580 ****
   *  holes, so we shouldn't ever see this.
   */
  	if (bp->b_blkno == bp->b_lblkno) {
! 		if (error = pcbmap(dep,
! 			bp->b_lblkno << (pmp->pm_cnshift - pmp->pm_bnshift),
! 			&bp->b_blkno, 0))
  			return error;
  		if ((long)bp->b_blkno == -1)
  			clrbuf(bp);
--- 1589,1595 ----
   *  holes, so we shouldn't ever see this.
   */
  	if (bp->b_blkno == bp->b_lblkno) {
! 		if (error = pcbmap(dep, bp->b_lblkno, &bp->b_blkno, 0))
  			return error;
  		if ((long)bp->b_blkno == -1)
  			clrbuf(bp);
--------------------------you've got the complete patch---------------------