#!/bin/ksh

# Simple test to demonstrate that ZFS ARC caching severely hinders
# read performance if the file has been read before, but its data has
# since been purged from the ARC by subsequent reads.

# Needs to be run as 'root' since it creates a pool filesystem and
# unmounts and mounts it.  This should be safe since data is never
# destroyed.

# The first time the script is executed, it creates a new zfs
# filesystem and populates it with files.  Additional executions use
# the existing filesystem and files.

# Written by Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

######## Start Of Tunables ########

# Pool name (may be specified as first script argument)
if [ $# -eq 1 ] ; then
  POOL=$1
else
  POOL=rpool
fi

# Subordinate filesystem name (will be created/mounted/umounted)
FS=zfscachetest

# File size (in 1024 byte blocks)
FILESIZE=8000

# Number of 8.2MB files to create.  Total file data should exceed the
# maximum ARC size but should also fit in the storage pool.
integer numfiles=3000

######## End Of Tunables ########


FILESYS="${POOL}/${FS}"
FILESYSPATH="/${FILESYS}"
PATHFORMAT="${FILESYSPATH}/file-%05d.dat"

# Identify the system
/usr/sbin/prtdiag | head -1
echo "System architecture: `/sbin/uname -p`"
echo "System release level: `/sbin/uname -r` `/sbin/uname -v`"
echo "CPU ISA list: `/usr/bin/isalist`"

# Dump the pool configuration
echo
echo "Pool configuration:"
/usr/sbin/zpool status ${POOL}
echo

# Try to mount the filesystem in case it already exists but is not
# currently mounted
zfs mount ${FILESYS} 2> /dev/null

set -e # Exit on any error

if [ ! -d "${FILESYSPATH}" ] ; then
    echo "zfs create ${FILESYS}"
    zfs create "${FILESYS}"
fi

basefile=`printf "$PATHFORMAT" 0`

if [ ! -f "${basefile}" ] ; then
  echo "Creating data file set (${numfiles} files of `echo ${FILESIZE}\*1024 | bc` bytes) under ${FILESYSPATH} ..."
  dd if=/dev/urandom of="${basefile}" bs=1024 count=${FILESIZE} 2> /dev/null
  integer i=1
  while [ $i -lt $numfiles ]
  do 
    destfile=`printf "$PATHFORMAT" $i`
    #echo cp "${basefile}" "${destfile}"
    cp "${basefile}" "${destfile}"
    i=$(($i+1))
  done
  echo "Done!"
fi

echo "zfs unmount ${FILESYS}"
zfs unmount "${FILESYS}"
sleep 1
echo "zfs mount ${FILESYS}"
zfs mount "${FILESYS}"
sleep 1
echo
echo "Doing initial (unmount/mount) 'cpio -C 131072 -o > /dev/null'"
(cd ${FILESYSPATH} && time (find . | cpio -C 131072 -o > /dev/null))

echo
echo "Doing second 'cpio -C 131072 -o > /dev/null'"
(cd ${FILESYSPATH} && time (find . | cpio -C 131072 -o > /dev/null))
echo
echo "Feel free to clean up with 'zfs destroy ${FILESYS}'."
