Date: Wed, 27 Aug 2008 20:14:47 +0000 (UTC) From: Tor Egge <Tor.Egge@cvsup.no.freebsd.org> To: freebsd-gnats-submit@freebsd.org Cc: freebsd-bugs@freebsd.org, kib@freebsd.org, bde@freebsd.org Subject: Re: kern/47628: msdosfs file corruption fix Message-ID: <20080827.201447.28785684.Tor.Egge@cvsup.no.freebsd.org> In-Reply-To: <200312060548.hB65mNlr075759@freefall.freebsd.org> References: <200312060548.hB65mNlr075759@freefall.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
----Next_Part(Wed_Aug_27_20_14_47_2008_639)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit I recently stumbled onto the same issue when setting up a backup disk with a msdosfs scratch area for transfer of files. I used rsync with the 'S' option to copy the files to the FAT32 file system, resulting in corrupted blocks. The cluster size was 32K. Looking at the badness in a file, blocks 5 and 6 contained NULs instead of the correct file data. Those were the only blocks where the first byte should be a NUL. A few extra debug messages in the file system code (e.g. in msdosfs_strategy) when reproducing the problem showed that blocks 5 and 6 were correctly written, but later blocks 320 and 384 were written to the same location with NULs. The file was 319488 bytes long, and should only have blocks in the range [0..9]. This problem seems to have been introduced in revision 1.17 of src/sys/fs/msdosfs/msdosfs_fat.c, where file relative cluster numbers were replaced by file relative sector numbers as the buffer block number when zero-padding a file during extension. With the enclosed patch applied, I no longer got corrupted files, but I only tested with clustering disabled, using mount -t msdosfs -o large -o noclusterr -o noclusterw /dev/da6s1 /mnt to mount the file system. As an alternative to initializing nvp->v_bufobj.bo_bsize to the cluster size for regular files, mp->mnt_stat.f_iosize could be initialized to the cluster size in mountmsdosfs(). The cluster size would then be copied to new vnodes in getnewvnode(). - Tor Egge ----Next_Part(Wed_Aug_27_20_14_47_2008_639)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="msdosfs.diff2" Index: sys/fs/msdosfs/msdosfs_denode.c =================================================================== RCS file: /home/ncvs/src/sys/fs/msdosfs/msdosfs_denode.c,v retrieving revision 1.99 diff -u -r1.99 msdosfs_denode.c --- sys/fs/msdosfs/msdosfs_denode.c 24 Jan 2008 12:34:26 -0000 1.99 +++ sys/fs/msdosfs/msdosfs_denode.c 26 Aug 2008 04:52:06 -0000 @@ -163,6 +163,8 @@ } bzero((caddr_t)ldep, sizeof *ldep); nvp->v_data = ldep; + if ((ldep->de_Attributes & ATTR_DIRECTORY) == 0) + nvp->v_bufobj.bo_bsize = pmp->pm_bpcluster; ldep->de_vnode = nvp; ldep->de_flag = 0; ldep->de_dirclust = dirclust; Index: sys/fs/msdosfs/msdosfs_fat.c =================================================================== RCS file: /home/ncvs/src/sys/fs/msdosfs/msdosfs_fat.c,v retrieving revision 1.49 diff -u -r1.49 msdosfs_fat.c --- sys/fs/msdosfs/msdosfs_fat.c 25 Oct 2007 08:23:08 -0000 1.49 +++ sys/fs/msdosfs/msdosfs_fat.c 26 Aug 2008 04:09:26 -0000 @@ -1065,13 +1065,13 @@ pmp->pm_bpcluster, 0, 0, 0); else { bp = getblk(DETOV(dep), - de_cn2bn(pmp, frcn++), + frcn++, pmp->pm_bpcluster, 0, 0, 0); /* * Do the bmap now, as in msdosfs_write */ if (pcbmap(dep, - de_bn2cn(pmp, bp->b_lblkno), + bp->b_lblkno, &blkno, 0, 0)) bp->b_blkno = -1; if (bp->b_blkno == -1) ----Next_Part(Wed_Aug_27_20_14_47_2008_639)----
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20080827.201447.28785684.Tor.Egge>