Subject: analysis of Darwin ufs filesystem differences
To: None <port-macppc@netbsd.org>
From: None <dbj@netbsd.org>
List: port-macppc
Date: 12/13/2001 22:11:59
I have analysed the differences between the ufs filesystem of NetBSD
and that of Darwin.  By appropriately tweaking NetBSD ufs filesystem
and tools, I am now successfully running a -current NetBSD/macppc
system on a root partition that was created by and can be read by
Darwin and Mac OS X.  I am now looking at various possibilities for
accommodating apple's ufs filesystem in NetBSD and plan to discuss some
of the options in a future email.

Apple made two changes to ufs which significantly affect NetBSD's
usage of their filesystem.  I have included patches from NetBSD's
-current source here to demonstrate the nature of the changes,
although I do not recommend that anyone apply or attempt to use them
directly.

The first change is that they changed the value of DIRBLKSIZ as
follows:

Index: dir.h
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/ufs/dir.h,v
retrieving revision 1.11
diff -u -r1.11 dir.h
--- dir.h	2001/11/16 16:09:17	1.11
+++ dir.h	2001/12/14 01:16:27
@@ -76,7 +76,7 @@
  * Entries other than the first in a directory do not normally have
  * dp->d_ino set to 0.
  */
-#define DIRBLKSIZ	DEV_BSIZE
+#define DIRBLKSIZ	1024
 #define	MAXNAMLEN	255
 
 struct	direct {

I suspect that this change was introduced either for performance, or
inadvertently when they first added support for devices with non-512
byte block sizes.  Unfortunately, it presents the most serious
incompatibility.  There is no certain way to tell from the filesystem
which DIRBLKSIZ it is used with.  There exist filesystem instances
that are valid with either value for DIRBLKSIZ as well as instances
that are only valid with DIRBLKSIZ=512 or DIRBLKSIZ=1024.

For example, with DIRBLKSIZ=1024 individual directory entries may
cross a 512 byte boundary and may even have their record length set to
larger than 512 bytes so they would be invalid with tools compiled to
expect DIRBLKSIZ=512.  On the other hand, with DIRBLKSIZ=512,
directories may not be a multiple of 1024 bytes long as would
be expected by tools compiled to use DIRBLKSIZ=1024.

Accommodating this change will require updates to the kernel as well as
filesystem utilities and any other programs that attempt to interpret
directory files themselves.

The second change that affects us is that they inserted an extra four
bytes in the cylinder group block between the free block bit maps and
the available cluster summary count array:

Index: pass5.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/fsck_ffs/pass5.c,v
retrieving revision 1.27
diff -u -r1.27 pass5.c
--- pass5.c	2001/08/17 02:18:47	1.27
+++ pass5.c	2001/12/14 01:16:38
@@ -153,8 +153,7 @@
 		    howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
 		blkmapsize = newcg->cg_nextfreeoff - newcg->cg_freeoff;
 		if (fs->fs_contigsumsize > 0) {
-			newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
-			    sizeof(int32_t);
+			newcg->cg_clustersumoff = newcg->cg_nextfreeoff;
 			newcg->cg_clustersumoff =
 			    roundup(newcg->cg_clustersumoff, sizeof(int32_t));
 			newcg->cg_clusteroff = newcg->cg_clustersumoff +

This change was introduced as a result of apple PR2216969, which
can be found at:
  http://www.opensource.apple.com/bugs/Rhapsody/BSD%20Kernel/2216969.html

According to that bug report, the cluster summary array overlaps with
the free block bit maps.  At first glance of the code, this appears to
be a problem and the change introduced in that PR's fix moves the
array forward by four bytes so they do not overlap.

My analysis is that this bug report is from a misunderstanding of the
ffs code and is not actually a bug.  The cluster summary array is an
array of available clusters indexed by cluster length.  The first
four byte location in the array counts the number of zero length
clusters.  Since the number of zero length clusters is ill-defined,
in practice this position in the array is unused.  It is thus
harmless that it overlaps with the free block bit maps and the
``-sizeof(int32_t)'' in the original code was intentional.

Although the kernel doesn't require any modification to work with this
change, the current implementation of fsck will claim that the cluster
summary and free block bitmaps are corrupted unless fsck is modified
to recognize the changed offset.

In order to get my kernel to work with the Darwin filesystem, I also
had to tweak the disksubr.c to recognize the correct partitions in the
apple partition map.  I also compiled version 0.8a2 of the pdisk
utility for NetBSD.  These required relatively straightforward
changes, although some new decisions will need to be made regarding
the mapping between apple partition maps and NetBSD disklabels.

I am hoping we will be able to gracefully support Darwin UFS
filesystems in NetBSD and I have pondered several approaches to
extending NetBSD in this area.  I hope to write up a couple of
options for discussion so we can determine which is the best
approach on which to proceed.

Darrin