2 # Routines for populating a scratch fs, and helpers to exercise an FS
3 # once it's been fuzzed.
4 #-----------------------------------------------------------------------
5 # Copyright (c) 2015 Oracle. All Rights Reserved.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 # Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
22 # Mountain View, CA 94043, USA, or: http://www.sgi.com
23 #-----------------------------------------------------------------------
25 _require_populate_commands() {
26 _require_xfs_io_command "falloc"
27 _require_xfs_io_command "fpunch"
28 _require_test_program "punch-alternating"
29 _require_command "$XFS_DB_PROG" "xfs_db"
32 _require_xfs_db_blocktrash_z_command() {
33 test "${FSTYP}" = "xfs" || _notrun "cannot run xfs_db on ${FSTYP}"
34 $XFS_DB_PROG -x -f -c 'blocktrash -z' "${TEST_DEV}" | grep -q 'nothing on stack' || _notrun "blocktrash -z not supported"
37 # Attempt to make files of "every" format for data, dirs, attrs etc.
38 # (with apologies to Eric Sandeen for mutating xfser.sh)
40 # Create a large directory
41 __populate_create_dir() {
47 seq 0 "${nr}" | while read d; do
49 test "$((d % 20))" -eq 0 && creat=touch
50 $creat "${name}/$(printf "%.08d" "$d")"
53 test -z "${missing}" && return
54 seq 1 2 "${nr}" | while read d; do
55 rm -rf "${name}/$(printf "%.08d" "$d")"
59 # Add a bunch of attrs to a file
60 __populate_create_attr() {
66 seq 0 "${nr}" | while read d; do
67 setfattr -n "user.$(printf "%.08d" "$d")" -v "$(printf "%.08d" "$d")" "${name}"
70 test -z "${missing}" && return
71 seq 1 2 "${nr}" | while read d; do
72 setfattr -x "user.$(printf "%.08d" "$d")" "${name}"
76 # Fill up some percentage of the remaining free space
77 __populate_fill_fs() {
80 test -z "${pct}" && pct=60
82 mkdir -p "${dir}/test/1"
83 cp -pRdu "${dir}"/S_IFREG* "${dir}/test/1/"
85 SRC_SZ="$(du -ks "${dir}/test/1" | cut -f 1)"
86 FS_SZ="$(( $(stat -f "${dir}" -c '%a * %S') / 1024 ))"
88 NR="$(( (FS_SZ * ${pct} / 100) / SRC_SZ ))"
91 echo "src_sz $SRC_SZ fs_sz $FS_SZ nr $NR"
92 seq 2 "${NR}" | while read nr; do
93 cp -pRdu "${dir}/test/1" "${dir}/test/${nr}"
97 # Populate an XFS on the scratch device with (we hope) all known
98 # types of metadata block
99 _scratch_xfs_populate() {
110 blksz="$(stat -f -c '%s' "${SCRATCH_MNT}")"
111 dblksz="$(xfs_info "${SCRATCH_MNT}" | grep naming.*bsize | sed -e 's/^.*bsize=//g' -e 's/\([0-9]*\).*$/\1/g')"
112 leaf_lblk="$((32 * 1073741824 / blksz))"
113 node_lblk="$((64 * 1073741824 / blksz))"
117 # Fill up the root inode chunk
118 echo "+ fill root ino chunk"
119 seq 1 64 | while read f; do
120 $XFS_IO_PROG -f -c "truncate 0" "${SCRATCH_MNT}/dummy${f}"
125 echo "+ extents file"
126 $XFS_IO_PROG -f -c "pwrite -S 0x61 0 ${blksz}" "${SCRATCH_MNT}/S_IFREG.FMT_EXTENTS"
129 echo "+ btree extents file"
130 nr="$((blksz * 2 / 16))"
131 $XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/S_IFREG.FMT_BTREE"
132 ./src/punch-alternating "${SCRATCH_MNT}/S_IFREG.FMT_BTREE"
137 __populate_create_dir "${SCRATCH_MNT}/S_IFDIR.FMT_INLINE" 1
141 __populate_create_dir "${SCRATCH_MNT}/S_IFDIR.FMT_BLOCK" "$((dblksz / 40))"
145 __populate_create_dir "${SCRATCH_MNT}/S_IFDIR.FMT_LEAF" "$((dblksz / 12))"
149 __populate_create_dir "${SCRATCH_MNT}/S_IFDIR.FMT_NODE" "$((16 * dblksz / 40))" true
153 __populate_create_dir "${SCRATCH_MNT}/S_IFDIR.FMT_BTREE" "$((128 * dblksz / 40))" true
157 echo "+ inline symlink"
158 ln -s target "${SCRATCH_MNT}/S_IFLNK.FMT_LOCAL"
161 echo "+ extents symlink"
162 ln -s "$(perl -e 'print "x" x 1023;')" "${SCRATCH_MNT}/S_IFLNK.FMT_EXTENTS"
166 mknod "${SCRATCH_MNT}/S_IFCHR" c 1 1
167 mknod "${SCRATCH_MNT}/S_IFBLK" c 1 1
169 # special file with an xattr
170 setfacl -P -m u:nobody:r ${SCRATCH_MNT}/S_IFCHR
175 __populate_create_attr "${SCRATCH_MNT}/ATTR.FMT_LOCAL" 1
179 __populate_create_attr "${SCRATCH_MNT}/ATTR.FMT_LEAF" "$((blksz / 40))"
183 __populate_create_attr "${SCRATCH_MNT}/ATTR.FMT_NODE" "$((8 * blksz / 40))"
187 __populate_create_attr "${SCRATCH_MNT}/ATTR.FMT_BTREE" "$((64 * blksz / 40))" true
190 touch ${SCRATCH_MNT}/ATTR.TRUSTED
191 setfattr -n trusted.moo -v urk ${SCRATCH_MNT}/ATTR.TRUSTED
194 touch ${SCRATCH_MNT}/ATTR.SECURITY
195 setfattr -n security.foo -v bar ${SCRATCH_MNT}/ATTR.SECURITY
198 touch ${SCRATCH_MNT}/ATTR.SYSTEM
199 setfacl -m u:root:r ${SCRATCH_MNT}/ATTR.SYSTEM
201 # FMT_EXTENTS with a remote less-than-a-block value
202 echo "+ attr extents with a remote less-than-a-block value"
203 touch "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE3K"
204 $XFS_IO_PROG -f -c "pwrite -S 0x43 0 $((blksz - 300))" "${SCRATCH_MNT}/attrvalfile" > /dev/null
205 attr -q -s user.remotebtreeattrname "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE3K" < "${SCRATCH_MNT}/attrvalfile"
207 # FMT_EXTENTS with a remote block-size value
208 echo "+ attr extents with a remote one-block value"
209 touch "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE4K"
210 $XFS_IO_PROG -f -c "pwrite -S 0x44 0 ${blksz}" "${SCRATCH_MNT}/attrvalfile" > /dev/null
211 attr -q -s user.remotebtreeattrname "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE4K" < "${SCRATCH_MNT}/attrvalfile"
212 rm -rf "${SCRATCH_MNT}/attrvalfile"
214 # Make an unused inode
216 touch "${SCRATCH_MNT}/unused"
217 $XFS_IO_PROG -f -c 'fsync' "${SCRATCH_MNT}/unused"
218 rm -rf "${SCRATCH_MNT}/unused"
221 echo "+ freesp btree"
222 nr="$((blksz * 2 / 8))"
223 $XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/BNOBT"
224 ./src/punch-alternating "${SCRATCH_MNT}/BNOBT"
226 # Reverse-mapping btree
227 is_rmapbt="$(xfs_info "${SCRATCH_MNT}" | grep -c 'rmapbt=1')"
228 if [ $is_rmapbt -gt 0 ]; then
229 echo "+ rmapbt btree"
230 nr="$((blksz * 2 / 24))"
231 $XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/RMAPBT"
232 ./src/punch-alternating "${SCRATCH_MNT}/RMAPBT"
235 # Realtime Reverse-mapping btree
236 is_rt="$(xfs_info "${SCRATCH_MNT}" | grep -c 'rtextents=[1-9]')"
237 if [ $is_rmapbt -gt 0 ] && [ $is_rt -gt 0 ]; then
238 echo "+ rtrmapbt btree"
239 nr="$((blksz * 2 / 32))"
240 $XFS_IO_PROG -f -R -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/RTRMAPBT"
241 ./src/punch-alternating "${SCRATCH_MNT}/RTRMAPBT"
244 # Reference-count btree
245 is_reflink="$(xfs_info "${SCRATCH_MNT}" | grep -c 'reflink=1')"
246 if [ $is_reflink -gt 0 ]; then
247 echo "+ reflink btree"
248 nr="$((blksz * 2 / 12))"
249 $XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/REFCOUNTBT"
250 cp --reflink=always "${SCRATCH_MNT}/REFCOUNTBT" "${SCRATCH_MNT}/REFCOUNTBT2"
251 ./src/punch-alternating "${SCRATCH_MNT}/REFCOUNTBT"
254 # Copy some real files (xfs tests, I guess...)
256 test $fill -ne 0 && __populate_fill_fs "${SCRATCH_MNT}" 5
258 umount "${SCRATCH_MNT}"
261 # Populate an ext4 on the scratch device with (we hope) all known
262 # types of metadata block
263 _scratch_ext4_populate() {
274 blksz="$(stat -f -c '%s' "${SCRATCH_MNT}")"
276 leaf_lblk="$((32 * 1073741824 / blksz))"
277 node_lblk="$((64 * 1073741824 / blksz))"
284 $XFS_IO_PROG -f -c "pwrite -S 0x61 0 1" "${SCRATCH_MNT}/S_IFREG.FMT_INLINE"
287 echo "+ extents file"
288 $XFS_IO_PROG -f -c "pwrite -S 0x61 0 ${blksz}" "${SCRATCH_MNT}/S_IFREG.FMT_EXTENTS"
291 echo "+ extent tree file"
292 nr="$((blksz * 2 / 12))"
293 $XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/S_IFREG.FMT_ETREE"
294 ./src/punch-alternating "${SCRATCH_MNT}/S_IFREG.FMT_ETREE"
299 __populate_create_dir "${SCRATCH_MNT}/S_IFDIR.FMT_INLINE" 1
303 __populate_create_dir "${SCRATCH_MNT}/S_IFDIR.FMT_BLOCK" "$((dblksz / 24))"
307 __populate_create_dir "${SCRATCH_MNT}/S_IFDIR.FMT_HTREE" "$((4 * dblksz / 24))"
311 echo "+ inline symlink"
312 ln -s target "${SCRATCH_MNT}/S_IFLNK.FMT_LOCAL"
315 echo "+ extents symlink"
316 ln -s "$(perl -e 'print "x" x 1023;')" "${SCRATCH_MNT}/S_IFLNK.FMT_EXTENTS"
320 mknod "${SCRATCH_MNT}/S_IFCHR" c 1 1
321 mknod "${SCRATCH_MNT}/S_IFBLK" c 1 1
323 # special file with an xattr
324 setfacl -P -m u:nobody:r ${SCRATCH_MNT}/S_IFCHR
329 __populate_create_attr "${SCRATCH_MNT}/ATTR.FMT_LOCAL" 1
333 __populate_create_attr "${SCRATCH_MNT}/ATTR.FMT_BLOCK" "$((blksz / 40))"
336 touch ${SCRATCH_MNT}/ATTR.TRUSTED
337 setfattr -n trusted.moo -v urk ${SCRATCH_MNT}/ATTR.TRUSTED
340 touch ${SCRATCH_MNT}/ATTR.SECURITY
341 setfattr -n security.foo -v bar ${SCRATCH_MNT}/ATTR.SECURITY
344 touch ${SCRATCH_MNT}/ATTR.SYSTEM
345 setfacl -m u:root:r ${SCRATCH_MNT}/ATTR.SYSTEM
347 # Make an unused inode
349 touch "${SCRATCH_MNT}/unused"
350 $XFS_IO_PROG -f -c 'fsync' "${SCRATCH_MNT}/unused"
351 rm -rf "${SCRATCH_MNT}/unused"
353 # Copy some real files (xfs tests, I guess...)
355 test $fill -ne 0 && __populate_fill_fs "${SCRATCH_MNT}" 5
357 umount "${SCRATCH_MNT}"
360 # Find the inode number of a file
361 __populate_find_inode() {
363 inode="$(stat -c '%i' "${name}")"
367 # Check data fork format of XFS file
368 __populate_check_xfs_dformat() {
372 fmt="$(_scratch_xfs_db -c "inode ${inode}" -c 'p core.format' | sed -e 's/^.*(\([a-z]*\)).*$/\1/g')"
373 test "${format}" = "${fmt}" || _fail "failed to create ino ${inode} dformat expected ${format} saw ${fmt}"
376 # Check attr fork format of XFS file
377 __populate_check_xfs_aformat() {
381 fmt="$(_scratch_xfs_db -c "inode ${inode}" -c 'p core.aformat' | sed -e 's/^.*(\([a-z]*\)).*$/\1/g')"
382 test "${format}" = "${fmt}" || _fail "failed to create ino ${inode} aformat expected ${format} saw ${fmt}"
385 # Check structure of XFS directory
386 __populate_check_xfs_dir() {
390 (test -n "${leaf_lblk}" && test -n "${node_lblk}") || _fail "must define leaf_lblk and node_lblk before calling __populate_check_xfs_dir"
394 #echo "== check dir ${inode} type ${dtype}" ; _scratch_xfs_db -x -c "inode ${inode}" -c "bmap"
395 _scratch_xfs_db -x -c "inode ${inode}" -c "dblock 0" -c "stack" | grep -q 'file data block is unmapped' || datab=1
396 _scratch_xfs_db -x -c "inode ${inode}" -c "dblock ${leaf_lblk}" -c "stack" | grep -q 'file data block is unmapped' || leafb=1
397 _scratch_xfs_db -x -c "inode ${inode}" -c "dblock ${node_lblk}" -c "stack" | grep -q 'file data block is unmapped' || freeb=1
400 "shortform"|"inline"|"local")
401 (test "${datab}" -eq 0 && test "${leafb}" -eq 0 && test "${freeb}" -eq 0) || _fail "failed to create ${dtype} dir ino ${inode} datab ${datab} leafb ${leafb} freeb ${freeb}"
404 (test "${datab}" -eq 1 && test "${leafb}" -eq 0 && test "${freeb}" -eq 0) || _fail "failed to create ${dtype} dir ino ${inode} datab ${datab} leafb ${leafb} freeb ${freeb}"
407 (test "${datab}" -eq 1 && test "${leafb}" -eq 1 && test "${freeb}" -eq 0) || _fail "failed to create ${dtype} dir ino ${inode} datab ${datab} leafb ${leafb} freeb ${freeb}"
410 (test "${datab}" -eq 1 && test "${leafb}" -eq 1 && test "${freeb}" -eq 1) || _fail "failed to create ${dtype} dir ino ${inode} datab ${datab} leafb ${leafb} freeb ${freeb}"
413 _fail "Unknown directory type ${dtype}"
417 # Check structure of XFS attr
418 __populate_check_xfs_attr() {
424 #echo "== check attr ${inode} type ${dtype}" ; _scratch_xfs_db -x -c "inode ${inode}" -c "bmap -a"
425 _scratch_xfs_db -x -c "inode ${inode}" -c "ablock 0" -c "stack" | grep -q 'file attr block is unmapped' || datab=1
426 _scratch_xfs_db -x -c "inode ${inode}" -c "ablock 1" -c "stack" | grep -q 'file attr block is unmapped' || leafb=1
429 "shortform"|"inline"|"local")
430 (test "${datab}" -eq 0 && test "${leafb}" -eq 0) || _fail "failed to create ${atype} attr ino ${inode} datab ${datab} leafb ${leafb}"
433 (test "${datab}" -eq 1 && test "${leafb}" -eq 0) || _fail "failed to create ${atype} attr ino ${inode} datab ${datab} leafb ${leafb}"
436 (test "${datab}" -eq 1 && test "${leafb}" -eq 1) || _fail "failed to create ${atype} attr ino ${inode} datab ${datab} leafb ${leafb}"
439 _fail "Unknown attribute type ${atype}"
443 # Check that there's at least one per-AG btree with multiple levels
444 __populate_check_xfs_agbtree_height() {
446 nr_ags=$(_scratch_xfs_db -c 'sb 0' -c 'p agcount' | awk '{print $3}')
449 "bno"|"cnt"|"rmap"|"refcnt")
451 bt_prefix="${bt_type}"
462 _fail "Don't know about AG btree ${bt_type}"
466 seq 0 $((nr_ags - 1)) | while read ag; do
467 bt_level=$(_scratch_xfs_db -c "${hdr} ${ag}" -c "p ${bt_prefix}level" | awk '{print $3}')
468 if [ "${bt_level}" -gt 1 ]; then
472 test $? -eq 100 || _fail "Failed to create ${bt_type} of sufficient height!"
476 # Check that populate created all the types of files we wanted
477 _scratch_xfs_populate_check() {
479 extents_file="$(__populate_find_inode "${SCRATCH_MNT}/S_IFREG.FMT_EXTENTS")"
480 btree_file="$(__populate_find_inode "${SCRATCH_MNT}/S_IFREG.FMT_BTREE")"
481 inline_dir="$(__populate_find_inode "${SCRATCH_MNT}/S_IFDIR.FMT_INLINE")"
482 block_dir="$(__populate_find_inode "${SCRATCH_MNT}/S_IFDIR.FMT_BLOCK")"
483 leaf_dir="$(__populate_find_inode "${SCRATCH_MNT}/S_IFDIR.FMT_LEAF")"
484 node_dir="$(__populate_find_inode "${SCRATCH_MNT}/S_IFDIR.FMT_NODE")"
485 btree_dir="$(__populate_find_inode "${SCRATCH_MNT}/S_IFDIR.FMT_BTREE")"
486 local_slink="$(__populate_find_inode "${SCRATCH_MNT}/S_IFLNK.FMT_LOCAL")"
487 extents_slink="$(__populate_find_inode "${SCRATCH_MNT}/S_IFLNK.FMT_EXTENTS")"
488 bdev="$(__populate_find_inode "${SCRATCH_MNT}/S_IFBLK")"
489 cdev="$(__populate_find_inode "${SCRATCH_MNT}/S_IFCHR")"
490 local_attr="$(__populate_find_inode "${SCRATCH_MNT}/ATTR.FMT_LOCAL")"
491 leaf_attr="$(__populate_find_inode "${SCRATCH_MNT}/ATTR.FMT_LEAF")"
492 node_attr="$(__populate_find_inode "${SCRATCH_MNT}/ATTR.FMT_NODE")"
493 btree_attr="$(__populate_find_inode "${SCRATCH_MNT}/ATTR.FMT_BTREE")"
494 is_finobt=$(xfs_info "${SCRATCH_MNT}" | grep -c 'finobt=1')
495 is_rmapbt=$(xfs_info "${SCRATCH_MNT}" | grep -c 'rmapbt=1')
496 is_reflink=$(xfs_info "${SCRATCH_MNT}" | grep -c 'reflink=1')
498 blksz="$(stat -f -c '%s' "${SCRATCH_MNT}")"
499 dblksz="$(xfs_info "${SCRATCH_MNT}" | grep naming.*bsize | sed -e 's/^.*bsize=//g' -e 's/\([0-9]*\).*$/\1/g')"
500 leaf_lblk="$((32 * 1073741824 / blksz))"
501 node_lblk="$((64 * 1073741824 / blksz))"
502 umount "${SCRATCH_MNT}"
504 __populate_check_xfs_dformat "${extents_file}" "extents"
505 __populate_check_xfs_dformat "${btree_file}" "btree"
506 __populate_check_xfs_dir "${inline_dir}" "inline"
507 __populate_check_xfs_dir "${block_dir}" "block"
508 __populate_check_xfs_dir "${leaf_dir}" "leaf"
509 __populate_check_xfs_dir "${node_dir}" "node"
510 __populate_check_xfs_dir "${btree_dir}" "btree"
511 __populate_check_xfs_dformat "${btree_dir}" "btree"
512 __populate_check_xfs_dformat "${bdev}" "dev"
513 __populate_check_xfs_dformat "${cdev}" "dev"
514 __populate_check_xfs_attr "${local_attr}" "local"
515 __populate_check_xfs_attr "${leaf_attr}" "leaf"
516 __populate_check_xfs_attr "${node_attr}" "node"
517 __populate_check_xfs_attr "${btree_attr}" "btree"
518 __populate_check_xfs_aformat "${btree_attr}" "btree"
519 __populate_check_xfs_agbtree_height "bno"
520 __populate_check_xfs_agbtree_height "cnt"
521 test $is_rmapbt -ne 0 && __populate_check_xfs_agbtree_height "rmap"
522 test $is_reflink -ne 0 && __populate_check_xfs_agbtree_height "refcnt"
525 # Check data fork format of ext4 file
526 __populate_check_ext4_dformat() {
533 debugfs -R "stat <${inode}>" "${dev}" 2> /dev/null | grep 'ETB[0-9]' -q && etree=1
534 iflags="$(debugfs -R "stat <${inode}>" "${dev}" 2> /dev/null | grep 'Flags:' | sed -e 's/^.*Flags: \([0-9a-fx]*\).*$/\1/g')"
535 test "$(echo "${iflags}" | awk '{print and(strtonum($1), 0x80000);}')" -gt 0 && extents=1
539 test "${extents}" -eq 0 || _fail "failed to create ino ${inode} with blockmap"
542 test "${extents}" -eq 1 || _fail "failed to create ino ${inode} with extents"
545 (test "${extents}" -eq 1 && test "${etree}" -eq 1) || _fail "failed to create ino ${inode} with extent tree"
548 _fail "Unknown dformat ${format}"
552 # Check attr fork format of ext4 file
553 __populate_check_ext4_aformat() {
559 debugfs -R "stat <${inode}>" "${dev}" 2> /dev/null | grep 'File ACL: 0' -q && ablock=0
563 test "${ablock}" -eq 0 || _fail "failed to create inode ${inode} with ${format} xattr"
566 test "${extents}" -eq 1 || _fail "failed to create inode ${inode} with ${format} xattr"
569 _fail "Unknown aformat ${format}"
573 # Check structure of ext4 dir
574 __populate_check_ext4_dir() {
581 iflags="$(debugfs -R "stat <${inode}>" "${dev}" 2> /dev/null | grep 'Flags:' | sed -e 's/^.*Flags: \([0-9a-fx]*\).*$/\1/g')"
582 test "$(echo "${iflags}" | awk '{print and(strtonum($1), 0x1000);}')" -gt 0 && htree=1
583 test "$(echo "${iflags}" | awk '{print and(strtonum($1), 0x10000000);}')" -gt 0 && inline=1
587 (test "${inline}" -eq 1 && test "${htree}" -eq 0) || _fail "failed to create ${dtype} dir ino ${inode} htree ${htree} inline ${inline}"
590 (test "${inline}" -eq 0 && test "${htree}" -eq 0) || _fail "failed to create ${dtype} dir ino ${inode} htree ${htree} inline ${inline}"
593 (test "${inline}" -eq 0 && test "${htree}" -eq 1) || _fail "failed to create ${dtype} dir ino ${inode} htree ${htree} inline ${inline}"
596 _fail "Unknown directory type ${dtype}"
601 # Check that populate created all the types of files we wanted
602 _scratch_ext4_populate_check() {
604 extents_file="$(__populate_find_inode "${SCRATCH_MNT}/S_IFREG.FMT_EXTENTS")"
605 etree_file="$(__populate_find_inode "${SCRATCH_MNT}/S_IFREG.FMT_ETREE")"
606 block_dir="$(__populate_find_inode "${SCRATCH_MNT}/S_IFDIR.FMT_BLOCK")"
607 htree_dir="$(__populate_find_inode "${SCRATCH_MNT}/S_IFDIR.FMT_HTREE")"
608 extents_slink="$(__populate_find_inode "${SCRATCH_MNT}/S_IFLNK.FMT_EXTENTS")"
609 local_attr="$(__populate_find_inode "${SCRATCH_MNT}/ATTR.FMT_LOCAL")"
610 block_attr="$(__populate_find_inode "${SCRATCH_MNT}/ATTR.FMT_BLOCK")"
611 umount "${SCRATCH_MNT}"
613 __populate_check_ext4_dformat "${extents_file}" "extents"
614 __populate_check_ext4_dformat "${etree_file}" "etree"
615 __populate_check_ext4_dir "${block_dir}" "block"
616 __populate_check_ext4_dir "${htree_dir}" "htree"
617 __populate_check_ext4_dformat "${extents_slink}" "extents"
618 __populate_check_ext4_aformat "${local_attr}" "local"
619 __populate_check_ext4_aformat "${block_attr}" "block"
622 # Populate a scratch FS and check the contents to make sure we got that
623 _scratch_populate() {
626 _scratch_xfs_populate
627 _scratch_xfs_populate_check
629 "ext2"|"ext3"|"ext4")
630 _scratch_ext4_populate
631 _scratch_ext4_populate_check
634 _fail "Don't know how to populate a ${FSTYP} filesystem."
639 # Fill a file system by repeatedly creating files in the given folder
640 # starting with the given file size. Files are reduced in size when
641 # they can no longer fit until no more files can be created.
649 local bytes_written=0
652 if [ $# -ne 4 ]; then
653 echo "Usage: _fill_fs filesize dir blocksize switch_user"
657 if [ $switch_user -eq 0 ]; then
660 _user_do "mkdir -p $dir"
662 if [ ! -d $dir ]; then
666 testio=`$XFS_IO_PROG -F -fc "falloc 0 $block_size" $dir/$$.xfs_io 2>&1`
667 echo $testio | grep -q "not found" && use_falloc=0
668 echo $testio | grep -q "Operation not supported" && use_falloc=0
670 if [ $file_size -lt $block_size ]; then
671 $file_size = $block_size
674 while [ $file_size -ge $block_size ]; do
676 if [ $switch_user -eq 0 ]; then
677 if [ $use_falloc -eq 0 ]; then
678 $XFS_IO_PROG -fc "pwrite -b 8388608 0 $file_size" \
681 $XFS_IO_PROG -fc "falloc 0 $file_size" \
685 if [ $use_falloc -eq 0 ]; then
686 _user_do "$XFS_IO_PROG -f -c \"pwrite -b 8388608 0 \
687 $file_size\" $dir/$file_count"
689 _user_do "$XFS_IO_PROG -f -c \"falloc 0 \
690 $file_size\" $dir/$file_count"
694 if [ -f $dir/$file_count ]; then
695 bytes_written=$(stat -c '%s' $dir/$file_count)
698 # If there was no room to make the file, then divide it in
699 # half, and keep going
700 if [ $bytes_written -lt $file_size ]; then
701 file_size=$((file_size / 2))
703 file_count=$((file_count + 1))
707 # Populate a scratch FS from scratch or from a cached image.
708 _scratch_populate_cached() {
709 POPULATE_METADUMP="${TEST_DIR}/__populate.${FSTYP}"
710 POPULATE_METADUMP_DESCR="${TEST_DIR}/__populate.${FSTYP}.txt"
712 # Don't keep metadata images cached for more 48 hours...
713 rm -rf "$(find "${POPULATE_METADUMP}" -mtime +2 2>/dev/null)"
715 # Throw away cached image if it doesn't match our spec.
716 meta_descr="FSTYP ${FSTYP} MKFS_OPTIONS ${MKFS_OPTIONS} SIZE $(blockdev --getsz "${SCRATCH_DEV}") ARGS $@"
717 cmp -s "${POPULATE_METADUMP_DESCR}" <(echo "${meta_descr}") || rm -rf "${POPULATE_METADUMP}"
719 # Do we have a cached image?
720 if [ -r "${POPULATE_METADUMP}" ]; then
723 xfs_mdrestore "${POPULATE_METADUMP}" "${SCRATCH_DEV}" && return
725 "ext2"|"ext3"|"ext4")
726 e2image -r "${POPULATE_METADUMP}" "${SCRATCH_DEV}" && return
731 # Oh well, just create one from scratch
733 echo "${meta_descr}" > "${POPULATE_METADUMP_DESCR}"
736 _scratch_xfs_populate $@
737 _scratch_xfs_populate_check
738 _scratch_metadump "${POPULATE_METADUMP}" -a -o
740 "ext2"|"ext3"|"ext4")
741 _scratch_ext4_populate $@
742 _scratch_ext4_populate_check
743 e2image -Q "${SCRATCH_DEV}" "${POPULATE_METADUMP}"
746 _fail "Don't know how to populate a ${FSTYP} filesystem."