Commit 4a28274227d085d77d46709dc94ccc3d69610f53

Authored by Stephen Warren
Committed by Tom Rini
1 parent 7861204c9a

test: fat: add test of non-contiguous file reads

In my patch series to replace fs/fat with "ff.c", I enhanced ff.c to
optimize file reading, so that reads of contiguous clusters are submitted
to the IO device as a single read. This test attempts to torture-test
edge-cases of that enhancement.

BTW, the only way I found to validate that this script actually does
create non-contiguous files was to manually inspect the FAT bitmap in a
hex dump of the FAT image. hdparm --fibmap doesn't work on loop-mounted
filesystems. filefrag -v -e seems to lie about files being contiguous
when they aren't.

Signed-off-by: Stephen Warren <swarren@wwwdotorg.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>

Showing 1 changed file with 113 additions and 0 deletions Side-by-side Diff

test/fs/fat-noncontig-test.sh
  1 +#!/bin/bash
  2 +
  3 +# (C) Copyright 2015 Stephen Warren
  4 +#
  5 +# SPDX-License-Identifier: GPL-2.0+
  6 +
  7 +# This script tests U-Boot's FAT filesystem code's ability to read non-
  8 +# contiguous files.
  9 +
  10 +# When porting the ff.c FAT parsing code into U-Boot, it was found that ff.c
  11 +# always reads files cluster-by-cluster, which results in poor performance.
  12 +# This was solved by adding a patch to ff.c to coalesce reads of adjacent
  13 +# clusters. Since this patch needed to correctly handle non-contiguous files,
  14 +# this test was written to validate that.
  15 +#
  16 +# To execute the test, simply run it from the U-Boot source root directory:
  17 +#
  18 +# cd u-boot
  19 +# ./test/fs/fat-noncontig-test.sh
  20 +#
  21 +# The test will create a FAT filesystem image, record the CRC of a randomly
  22 +# generated file in the image, build U-Boot sandbox, invoke U-Boot sandbox to
  23 +# read the file and validate that the CRCs match. Expected output is shown
  24 +# below. The important part of the log is the penultimate line that contains
  25 +# either "PASS" or "FAILURE".
  26 +#
  27 +# mkfs.fat 3.0.26 (2014-03-07)
  28 +#
  29 +#
  30 +# U-Boot 2015.10-rc4-00018-g4b22a3e5513f (Oct 03 2015 - 13:49:23 -0600)
  31 +#
  32 +# DRAM: 128 MiB
  33 +# Using default environment
  34 +#
  35 +# In: serial
  36 +# Out: lcd
  37 +# Err: lcd
  38 +# Net: No ethernet found.
  39 +# => host bind 0 sandbox/fat-noncontig.img
  40 +# => load host 0:0 1000 noncontig.img
  41 +# 33584964 bytes read in 18 ms (1.7 GiB/s)
  42 +# => crc32 1000 $filesize 0
  43 +# crc32 for 00001000 ... 02008743 ==> 6a080523
  44 +# => if itest.l *0 != 2305086a; then echo FAILURE; else echo PASS; fi
  45 +# PASS
  46 +# => reset
  47 +#
  48 +# All temporary files used by this script are created in ./sandbox to avoid
  49 +# polluting the source tree. test/fs/fs-test.sh also uses this directory for
  50 +# the same purpose.
  51 +#
  52 +# TODO: Integrate this (and many other corner-cases e.g. different types of
  53 +# FAT) with fs-test.sh so that a single script tests everything filesystem-
  54 +# related.
  55 +
  56 +odir=sandbox
  57 +img=${odir}/fat-noncontig.img
  58 +mnt=${odir}/mnt
  59 +fill=/dev/urandom
  60 +testfn=noncontig.img
  61 +mnttestfn=${mnt}/${testfn}
  62 +crcaddr=0
  63 +loadaddr=1000
  64 +
  65 +for prereq in fallocate mkfs.fat dd crc32; do
  66 + if [ ! -x "`which $prereq`" ]; then
  67 + echo "Missing $prereq binary. Exiting!"
  68 + exit 1
  69 + fi
  70 +done
  71 +
  72 +make O=${odir} -s sandbox_defconfig && make O=${odir} -s -j8
  73 +
  74 +mkdir -p ${mnt}
  75 +if [ ! -f ${img} ]; then
  76 + fallocate -l 40M ${img}
  77 + mkfs.fat ${img}
  78 +
  79 + sudo mount -o loop,uid=$(id -u) ${img} ${mnt}
  80 +
  81 + for ((sects=8; sects < 512; sects += 8)); do
  82 + fn=${mnt}/keep-${sects}.img
  83 + dd if=${fill} of=${fn} bs=512 count=${sects} >/dev/null 2>&1
  84 + fn=${mnt}/remove-${sects}.img
  85 + dd if=${fill} of=${fn} bs=512 count=${sects} >/dev/null 2>&1
  86 + done
  87 +
  88 + rm -f ${mnt}/remove-*.img
  89 +
  90 + # 511 deliberately to trigger a file size that's not a multiple of the
  91 + # sector size (ignoring sizes that are multiples of both).
  92 + dd if=${fill} of=${mnttestfn} bs=511 >/dev/null 2>&1
  93 +
  94 + sudo umount ${mnt}
  95 +fi
  96 +
  97 +sudo mount -o ro,loop,uid=$(id -u) ${img} ${mnt}
  98 +crc=0x`crc32 ${mnttestfn}`
  99 +sudo umount ${mnt}
  100 +
  101 +crc=`printf %02x%02x%02x%02x \
  102 + $((${crc} & 0xff)) \
  103 + $(((${crc} >> 8) & 0xff)) \
  104 + $(((${crc} >> 16) & 0xff)) \
  105 + $((${crc} >> 24))`
  106 +
  107 +./sandbox/u-boot << EOF
  108 +host bind 0 ${img}
  109 +load host 0:0 ${loadaddr} ${testfn}
  110 +crc32 ${loadaddr} \$filesize ${crcaddr}
  111 +if itest.l *${crcaddr} != ${crc}; then echo FAILURE; else echo PASS; fi
  112 +reset
  113 +EOF