[Bug 213507] [msdosfs] [patch]: Prevent occasional directory corruption while extending it to another cluster
bugzilla-noreply at freebsd.org
bugzilla-noreply at freebsd.org
Sat Oct 15 17:43:56 UTC 2016
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=213507
Bug ID: 213507
Summary: [msdosfs] [patch]: Prevent occasional directory
corruption while extending it to another cluster
Product: Base System
Version: CURRENT
Hardware: Any
OS: Any
Status: New
Keywords: patch
Severity: Affects Some People
Priority: ---
Component: kern
Assignee: freebsd-bugs at FreeBSD.org
Reporter: vladislav.movchan at gmail.com
Keywords: patch
Created attachment 175786
--> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=175786&action=edit
This patch fixes the problem for me
When amount of directory entries grows directory could reach size when it
require one more cluster.
This condition checked at the beginning of createde() inside of
msdosfs_lookup.c
Actual directory extension occurs by extendfile() inside of msdosfs_fat.c
I found that after completion of extendfile() newly allocated cluster consists
of garbage-like data which after completion of "grow to one more cluster" might
be interpreted as phantom/random directory entries.
This bug is sometimes hard to reproduce intentionally as data in newly
allocated cluster often looks the same no matter how many times you retry.
And if this data consists of mostly zeros it won't produce effect noticeable on
the filesystem.
Here is an output when I got lucky to trigger this problem (shell is bash):
# newfs_msdos -F 32 /dev/gpt/sg1-disk-f
/dev/gpt/sg1-disk-f: 315571904 sectors in 4930811 FAT32 clusters (32768
bytes/cluster)
BytesPerSec=512 SecPerClust=64 ResSectors=32 FATs=2 Media=0xf0 SecPerTrack=63
Heads=16 HiddenSecs=0 HugeSectors=315649016 FATsecs=38522 RootCluster=2
FSInfo=1 Backup=2
# mount_msdosfs -o large /dev/gpt/sg1-disk-f /mnt/f
# mkdir /mnt/f/test
# cd /mnt/f/test
# for i in `seq 1 150`; do; head -c $((20000*1000+1)) /dev/random > `echo
{0..9}{a..k} | tr -d ' '`$i; done
# ls -laR /mnt/f/test > /dev/null
ls: .гJ(: No such file or directory
ls: .гM(: No such file or directory
ls: .гP(: No such file or directory
ls: .гS(: No such file or directory
ls: .гV(: No such file or directory
ls: .гY(: No such file or directory
ls: .А?.: Invalid argument
ls: .АB(: No such file or directory
ls: 0?.?????: Invalid argument
ls: 0t,?????.ПМ+: Invalid argument
ls: 0w,?????.?t,: Invalid argument
ls: 0|#?????.0|#: Invalid argument
ls: 0|#?????.0|#: Invalid argument
ls: 0|#?????.0|#: Invalid argument
...
In most cases there is no other way than newfs_msdos to get rid of such
"random" directory entries.
So don't run this on filesystem you care about.
After I tried to intentionally bzero() newly allocated cluster data (only for
directory case) I'm no longer able to reproduce this problem. Patch attached.
System details:
$ uname -a
FreeBSD morgenstern 12.0-CURRENT FreeBSD 12.0-CURRENT #0 r306964: Mon Oct 10
18:17:21 EEST 2016 root at morgenstern:/usr/obj/usr/src/sys/Mephistopheles
amd64
$ diskinfo -v /dev/gpt/sg1-disk-f
/dev/gpt/sg1-disk-f
512 # sectorsize
161612296192 # mediasize in bytes (151G)
315649016 # mediasize in sectors
0 # stripesize
539533312 # stripeoffset
313143 # Cylinders according to firmware.
16 # Heads according to firmware.
63 # Sectors according to firmware.
9WM0NGVRs0 # Disk ident.
$ gpart show -l /dev/ada3
=> 40 3907026976 ada3 GPT (1.8T)
40 23 - free - (12K)
63 105910497 1 sg1-disk-e (51G)
105910560 14680080 - free - (7.0G)
120590640 1572864000 2 sg1-tank-disk3 (750G)
1693454640 39 - free - (20K)
1693454679 1897923321 4 sg1-disk-i (905G)
3591378000 315649016 5 sg1-disk-f (151G)
--
You are receiving this mail because:
You are the assignee for the bug.
More information about the freebsd-bugs
mailing list