[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