From time to time I need to test things related to disk fragmentation, like the performance of fragmented versus unfragmented disks, or how well a disk defragmenter works. Rather than trying to find machines with fragmented disks I decided to generate fragmentation on my own.
It’s actually quite easy to generate a fragmented disk on NTFS or ext3 filesystems. Fragmentation happens when you don’t have much free space on disk and a filesystem is forced to use non-contiguous blocks to fulfill requests. So we just encourage that behavior by filling the drive with a bunch of small files, then freeing some space by truncating those files to a smaller size. Then we fill the free space again by growing those files. Wash. Rinse. Repeat. Do this a few times and we end up with decent amounts of fragmentation.
I use the following short bash shell script under Linux natively, and on Windows with cygwin installed. This is probably easily done in PowerShell using something like dd for Windows but I will leave that to someone who knows more PowerShell than I do.
You’ll want to adjust the numbers below, particularly the “2217” in the loop. I adjust that by taking the amount of space I have on disk, in megabytes, subtract 32 MB for working space, and divide the result by 32. Then I round down. So if I have 71000 MB free it would be:
(71000 MB – 32 MB)/ 32 MB = 2217.75
#!/bin/bash for size in 30 31 32 30 32 do for i in {0..2217} do dd if=/dev/zero of=$i bs=1M count=$size done done
You can also vary the block size (the “bs=” parameter) if you desire larger files initially. That can be helpful if your volume is bigger. For example, on an 80 GB ext3 filesystem I get 33% fragmentation with a block size of 1 MB, but I get 56% if I increase that to 2 MB (bs=2M). You’ll need to do the math for 64 MB files, though, so you get the number of iterations right.
As for measuring the fragmentation, on Windows there is a myriad of programs, including free ones, that will measure the fragmentation (and then defragment if you would like). Some of my favorites beyond the Disk Defragmenter shipped with Windows (Programs->Accessories->System Tools) include Piriform’s Defraggler and MyDefrag.
On Linux you have a couple of options. First, the fsck utility will report the percentage of non-contiguous files when it checks your filesystems:
$ sudo e2fsck -f /dev/Volume00/test_lv e2fsck 1.39 (29-May-2006) Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information /dev/Volume00/test_lv: 1110/9175040 files (55.7% non-contiguous), 18344624/18350080 blocks
Normally this requires the filesystem to be unmounted, which is what I recommend, but you can walk on the wild side and ask e2fsck to do a read-only check with “-n”. If you try it on a live filesystem you will likely get errors – do not act on them! A mounted, functioning filesystem will always look like it has errors.
$ sudo e2fsck -n -f /dev/Volume00/LogVol00 e2fsck 1.39 (29-May-2006) Warning! /dev/Volume00/LogVol00 is mounted. Warning: skipping journal recovery because doing a read-only filesystem check. Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information Free inodes count wrong (124627, counted=124626). Fix? no /dev/Volume00/LogVol00: ********** WARNING: Filesystem still has errors ********** /dev/Volume00/LogVol00: 6445/131072 files (7.0% non-contiguous), 401060/524288 blocks
Alternately, you can use the ‘filefrag’ utility to report on the individual fragmentation of files. Using it in conjunction with the ‘find’ and ‘sort’ commands might be handy:
$ sudo find /mnt -type f -exec /usr/sbin/filefrag {} ; | sort -k 2 –n /mnt/649: 28 extents found, perfection would be 1 extent /mnt/449: 29 extents found, perfection would be 1 extent /mnt/876: 29 extents found, perfection would be 1 extent /mnt/1032: 31 extents found, perfection would be 1 extent /mnt/507: 31 extents found, perfection would be 1 extent /mnt/821: 33 extents found, perfection would be 1 extent /mnt/313: 40 extents found, perfection would be 1 extent
Replace /mnt with the path you’d like to search.