Painful speed for copying to fat32 partitions with small cluster size.

Bruce Evans bde at zeta.org.au
Sat Feb 7 14:37:56 PST 2004


On Sat, 7 Feb 2004, Ion-Mihai Tetcu wrote:

> Does anyone know why this happens or what to do ?
>
> Setup: UDMA133 primary master, UFS2; UDMA100 secondary master, FAT32.
>
> Copying to FAT32 partitions is very slow with small cluster sizes (I was
> copying some 300 - 700MB files):
>
> FAT32 clustersize=4K	500KB/s
> FAT32 clustersize=32K	3.5MB/s
> FAT32 clustersize=64K	6.2MB/s
> FAT32 clustersize=128K	6.4MB/s
> FAT16			6.5MB/s
>
> Reading speed is the same.

Lots of things are suboptimal, including your disk apparently not liking
small writes (or reads?).

Try this patch:

%%%
Index: msdosfs_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/fs/msdosfs/msdosfs_vnops.c,v
retrieving revision 1.147
diff -u -2 -r1.147 msdosfs_vnops.c
--- msdosfs_vnops.c	4 Feb 2004 21:52:53 -0000	1.147
+++ msdosfs_vnops.c	5 Feb 2004 08:11:38 -0000
@@ -771,5 +791,9 @@
 			(void) bwrite(bp);
 		else if (n + croffset == pmp->pm_bpcluster)
+#if 0
 			bawrite(bp);
+#else
+			bdwrite(bp);
+#endif
 		else
 			bdwrite(bp);
%%%

With it, I get 3+ MB/sec from iozone with a write size of 4K to a file
system with a cluster size of 4K on an old 6.3GB drive with 9MB/sec max
transfer speed, and writing 512-blocks is not much slower.  Without it,
writing 4K blocks goes fast enough but writing 2K blocks is 10 times
slower.

It won't help reads.

See ffs_write() for a more complete version of this.   ffs_write()
normally uses cluster_write() for the full-block case where the original
version of the above uses foot-shooting; both ffs_write() and
msdosfs_write() use bdwrite() for partial blocks and ffs_write() also
sets B_CLUSTEROK for this and most other cases.  As fair as I understand,
bdwrite() with B_CLUSTEROK is just as good as, if not better than
cluster_write() (the former gives a delayed clustered write and the
latter gives an immediate clustered write if the cluster is full and
is no different otherwise; the advantage of cluster_write() is that it
gives a better hint to vfs_bio that the write should be done soon).

> Newfs_msdos on a 30G partition:
>
> itetcu at it> /home/itetcu [16:31:40] 1
> # newfs_msdos -F32 -b65536 /dev/ad2s1
> /dev/ad2s1: 167746176 sectors in 1310517 FAT32 clusters (65536 bytes/cluster)
> bps=512 spc=128 res=32 nft=2 mid=0xf0 spt=63 hds=16 hid=0 bsec=167766732 bspf=10239 rdcl=2 infs=1 bkbs=2
> itetcu at it> /home/itetcu [16:34:48] 0
> #
>
> The same with 4K clusters takes about 50 minutes !

Your disk apparently doesn't like writing 4K-blocks and mine apparently
doesn't like writing 2K-blocks.  Write caching probably helps a lot here.
My old drive doesn't have it.  Read ahead on the disk certainly helps for
reads with too-small block sizes.

Bruce


More information about the freebsd-fs mailing list