From 9ed7c9b6adcb586282b44a107dcdd7736f8582cf Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Fri, 5 Dec 2008 11:32:34 -0800 Subject: [PATCH 01/45] Refresh linux-zpios --- .topdeps | 4 +- .topmsg | 17 +- configure.ac | 2 + scripts/profile-zpios-disk.sh | 128 ++ scripts/profile-zpios-pids.sh | 130 +++ scripts/profile-zpios-post.sh | 67 ++ scripts/profile-zpios-pre.sh | 69 ++ scripts/profile-zpios.sh | 222 ++++ scripts/survey.sh | 102 ++ scripts/zpios.sh | 133 +++ zfs/lib/Makefile.in | 2 + zfs/lib/libzpios/Makefile.in | 17 + zfs/lib/libzpios/include/Makefile.in | 1 + zfs/lib/libzpios/include/kpios-ctl.h | 120 ++ zfs/lib/libzpios/include/kpios-internal.h | 137 +++ zfs/lib/libzpios/kpios.c | 1295 +++++++++++++++++++++ zfs/zcmd/Makefile.in | 1 + zfs/zcmd/zpios/Makefile.in | 13 + zfs/zcmd/zpios/zpios.h | 117 ++ zfs/zcmd/zpios/zpios_main.c | 619 ++++++++++ zfs/zcmd/zpios/zpios_util.c | 440 +++++++ 21 files changed, 3618 insertions(+), 18 deletions(-) create mode 100644 scripts/profile-zpios-disk.sh create mode 100644 scripts/profile-zpios-pids.sh create mode 100644 scripts/profile-zpios-post.sh create mode 100644 scripts/profile-zpios-pre.sh create mode 100644 scripts/profile-zpios.sh create mode 100644 scripts/survey.sh create mode 100644 scripts/zpios.sh create mode 100644 zfs/lib/libzpios/Makefile.in create mode 100644 zfs/lib/libzpios/include/Makefile.in create mode 100644 zfs/lib/libzpios/include/kpios-ctl.h create mode 100644 zfs/lib/libzpios/include/kpios-internal.h create mode 100644 zfs/lib/libzpios/kpios.c create mode 100644 zfs/zcmd/zpios/Makefile.in create mode 100644 zfs/zcmd/zpios/zpios.h create mode 100644 zfs/zcmd/zpios/zpios_main.c create mode 100644 zfs/zcmd/zpios/zpios_util.c diff --git a/.topdeps b/.topdeps index 607c231780..7f16cbcdd5 100644 --- a/.topdeps +++ b/.topdeps @@ -1,3 +1 @@ -gcc-branch -fix-branch -feature-branch +zfs-branch diff --git a/.topmsg b/.topmsg index e9722e1075..bd665f5422 100644 --- a/.topmsg +++ b/.topmsg @@ -1,19 +1,6 @@ From: Brian Behlendorf -Subject: [PATCH] zfs branch +Subject: [PATCH] linux zpios -Merged result of all changes which are relevant to both Solaris -and Linux builds of the ZFS code. These are changes where there -is a reasonable chance they will be accepted upstream. - -Additionally, since this is effectively the root of the linux -ZFS tree the core linux build system is added here. This -includes autogen.sh, configure.ac, m4 macros, some scripts/*, -and makefiles for all the core ZFS components. Linux-only -features which require tweaks to the build system should appear -on the relevant topic branches. All autotools products which -result from autogen.sh are commited to the linux-configure-branch. - -This branch also contains the META, ChangeLog, AUTHORS, -README, and GIT files. +Linux kernel implementation of PIOS test app. Signed-off-by: Brian Behlendorf diff --git a/configure.ac b/configure.ac index 15db501914..3dd1cb0812 100644 --- a/configure.ac +++ b/configure.ac @@ -130,6 +130,7 @@ AC_CONFIG_FILES([ Makefile zfs/lib/libspl/include/sys/Makefile zfs/lib/libspl/include/Makefile zfs/lib/libspl/Makefile + zfs/lib/libzpios/Makefile zfs/zcmd/ztest/Makefile zfs/zcmd/Makefile zfs/zcmd/zfs/Makefile @@ -137,5 +138,6 @@ AC_CONFIG_FILES([ Makefile zfs/zcmd/zinject/Makefile zfs/zcmd/zdump/Makefile zfs/zcmd/zpool/Makefile + zfs/zcmd/zpios/Makefile ]) AC_OUTPUT diff --git a/scripts/profile-zpios-disk.sh b/scripts/profile-zpios-disk.sh new file mode 100644 index 0000000000..38607a5492 --- /dev/null +++ b/scripts/profile-zpios-disk.sh @@ -0,0 +1,128 @@ +#!/bin/bash +# profile-zpios-disk.sh +# +# /proc/diskinfo +# Field 1 -- device name +# Field 2 -- # of reads issued +# Field 3 -- # of reads merged +# Field 4 -- # of sectors read +# Field 5 -- # of milliseconds spent reading +# Field 6 -- # of writes completed +# Field 7 -- # of writes merged +# Field 8 -- # of sectors written +# Field 9 -- # of milliseconds spent writing +# Field 10 -- # of I/Os currently in progress +# Field 11 -- # of milliseconds spent doing I/Os +# Field 12 -- weighted # of milliseconds spent doing I/Os + +RUN_PIDS=${0} +RUN_LOG_DIR=${1} +RUN_ID=${2} + +create_table() { + local FIELD=$1 + local ROW_M=() + local ROW_N=() + local HEADER=1 + local STEP=1 + + for DISK_FILE in `ls -r --sort=time --time=ctime ${RUN_LOG_DIR}/${RUN_ID}/disk-[0-9]*`; do + ROW_M=( ${ROW_N[@]} ) + ROW_N=( `cat ${DISK_FILE} | grep sd | cut -c11- | cut -f${FIELD} -d' ' | tr "\n" "\t"` ) + + if [ $HEADER -eq 1 ]; then + echo -n "step, " + cat ${DISK_FILE} | grep sd | cut -c11- | cut -f1 -d' ' | tr "\n" ", " + echo "total" + HEADER=0 + fi + + if [ ${#ROW_M[@]} -eq 0 ]; then + continue + fi + + if [ ${#ROW_M[@]} -ne ${#ROW_N[@]} ]; then + echo "Badly formatted profile data in ${DISK_FILE}" + break + fi + + TOTAL=0 + echo -n "${STEP}, " + for (( i=0; i<${#ROW_N[@]}; i++ )); do + DELTA=`echo "${ROW_N[${i}]}-${ROW_M[${i}]}" | bc` + let TOTAL=${TOTAL}+${DELTA} + echo -n "${DELTA}, " + done + echo "${TOTAL}, " + + let STEP=${STEP}+1 + done +} + +create_table_mbs() { + local FIELD=$1 + local TIME=$2 + local ROW_M=() + local ROW_N=() + local HEADER=1 + local STEP=1 + + for DISK_FILE in `ls -r --sort=time --time=ctime ${RUN_LOG_DIR}/${RUN_ID}/disk-[0-9]*`; do + ROW_M=( ${ROW_N[@]} ) + ROW_N=( `cat ${DISK_FILE} | grep sd | cut -c11- | cut -f${FIELD} -d' ' | tr "\n" "\t"` ) + + if [ $HEADER -eq 1 ]; then + echo -n "step, " + cat ${DISK_FILE} | grep sd | cut -c11- | cut -f1 -d' ' | tr "\n" ", " + echo "total" + HEADER=0 + fi + + if [ ${#ROW_M[@]} -eq 0 ]; then + continue + fi + + if [ ${#ROW_M[@]} -ne ${#ROW_N[@]} ]; then + echo "Badly formatted profile data in ${DISK_FILE}" + break + fi + + TOTAL=0 + echo -n "${STEP}, " + for (( i=0; i<${#ROW_N[@]}; i++ )); do + DELTA=`echo "${ROW_N[${i}]}-${ROW_M[${i}]}" | bc` + MBS=`echo "scale=2; ((${DELTA}*512)/${TIME})/(1024*1024)" | bc` + TOTAL=`echo "scale=2; ${TOTAL}+${MBS}" | bc` + echo -n "${MBS}, " + done + echo "${TOTAL}, " + + let STEP=${STEP}+1 + done +} + +echo +echo "Reads issued per device" +create_table 2 +echo +echo "Reads merged per device" +create_table 3 +echo +echo "Sectors read per device" +create_table 4 +echo "MB/s per device" +create_table_mbs 4 3 + +echo +echo "Writes issued per device" +create_table 6 +echo +echo "Writes merged per device" +create_table 7 +echo +echo "Sectors written per device" +create_table 8 +echo "MB/s per device" +create_table_mbs 8 3 + +exit 0 diff --git a/scripts/profile-zpios-pids.sh b/scripts/profile-zpios-pids.sh new file mode 100644 index 0000000000..4d8adb1a15 --- /dev/null +++ b/scripts/profile-zpios-pids.sh @@ -0,0 +1,130 @@ +#!/bin/bash +# profile-zpios-pids.sh + +RUN_PIDS=${0} +RUN_LOG_DIR=${1} +RUN_ID=${2} + +ROW_M=() +ROW_N=() +ROW_N_SCHED=() +ROW_N_WAIT=() + +HEADER=1 +STEP=1 + +for PID_FILE in `ls -r --sort=time --time=ctime ${RUN_LOG_DIR}/${RUN_ID}/pids-[0-9]*`; do + ROW_M=( ${ROW_N[@]} ) + ROW_N=( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ROW_N_SCHED=( `cat ${PID_FILE} | cut -f15 -d' ' | tr "\n" "\t"` ) + ROW_N_WAIT=( `cat ${PID_FILE} | cut -f17 -d' ' | tr "\n" "\t"` ) + ROW_N_NAMES=( `cat ${PID_FILE} | cut -f2 -d' ' | cut -f2 -d'(' | + cut -f1 -d')' | cut -f1 -d'/' | tr "\n" "\t"` ) + + for (( i=0; i<${#ROW_N_SCHED[@]}; i++ )); do + SUM=`echo "${ROW_N_WAIT[${i}]}+${ROW_N_SCHED[${i}]}" | bc` + + case ${ROW_N_NAMES[${i}]} in + zio_taskq) IDX=0;; + zio_req_nul) IDX=1;; + zio_irq_nul) IDX=2;; + zio_req_rd) IDX=3;; + zio_irq_rd) IDX=4;; + zio_req_wr) IDX=5;; + zio_irq_wr) IDX=6;; + zio_req_fr) IDX=7;; + zio_irq_fr) IDX=8;; + zio_req_cm) IDX=9;; + zio_irq_cm) IDX=10;; + zio_req_ctl) IDX=11;; + zio_irq_ctl) IDX=12;; + txg_quiesce) IDX=13;; + txg_sync) IDX=14;; + txg_timelimit) IDX=15;; + arc_reclaim) IDX=16;; + l2arc_feed) IDX=17;; + kpios_io) IDX=18;; + *) continue;; + esac + + let ROW_N[${IDX}]=${ROW_N[${IDX}]}+${SUM} + done + + if [ $HEADER -eq 1 ]; then + echo "step, zio_taskq, zio_req_nul, zio_irq_nul, " \ + "zio_req_rd, zio_irq_rd, zio_req_wr, zio_irq_wr, " \ + "zio_req_fr, zio_irq_fr, zio_req_cm, zio_irq_cm, " \ + "zio_req_ctl, zio_irq_ctl, txg_quiesce, txg_sync, " \ + "txg_timelimit, arc_reclaim, l2arc_feed, kpios_io, " \ + "idle" + HEADER=0 + fi + + if [ ${#ROW_M[@]} -eq 0 ]; then + continue + fi + + if [ ${#ROW_M[@]} -ne ${#ROW_N[@]} ]; then + echo "Badly formatted profile data in ${PID_FILE}" + break + fi + + # Original values are in jiffies and we expect HZ to be 1000 + # on most 2.6 systems thus we divide by 10 to get a percentage. + IDLE=1000 + echo -n "${STEP}, " + for (( i=0; i<${#ROW_N[@]}; i++ )); do + DELTA=`echo "${ROW_N[${i}]}-${ROW_M[${i}]}" | bc` + DELTA_PERCENT=`echo "scale=1; ${DELTA}/10" | bc` + let IDLE=${IDLE}-${DELTA} + echo -n "${DELTA_PERCENT}, " + done + ILDE_PERCENT=`echo "scale=1; ${IDLE}/10" | bc` + echo "${ILDE_PERCENT}" + + let STEP=${STEP}+1 +done + +exit + +echo +echo "Percent of total system time per pid" +for PID_FILE in `ls -r --sort=time --time=ctime ${RUN_LOG_DIR}/${RUN_ID}/pids-[0-9]*`; do + ROW_M=( ${ROW_N[@]} ) + ROW_N_SCHED=( `cat ${PID_FILE} | cut -f15 -d' ' | tr "\n" "\t"` ) + ROW_N_WAIT=( `cat ${PID_FILE} | cut -f17 -d' ' | tr "\n" "\t"` ) + + for (( i=0; i<${#ROW_N_SCHED[@]}; i++ )); do + ROW_N[${i}]=`echo "${ROW_N_WAIT[${i}]}+${ROW_N_SCHED[${i}]}" | bc` + done + + if [ $HEADER -eq 1 ]; then + echo -n "step, " + cat ${PID_FILE} | cut -f2 -d' ' | tr "\n" ", " + echo + HEADER=0 + fi + + if [ ${#ROW_M[@]} -eq 0 ]; then + continue + fi + + if [ ${#ROW_M[@]} -ne ${#ROW_N[@]} ]; then + echo "Badly formatted profile data in ${PID_FILE}" + break + fi + + # Original values are in jiffies and we expect HZ to be 1000 + # on most 2.6 systems thus we divide by 10 to get a percentage. + echo -n "${STEP}, " + for (( i=0; i<${#ROW_N[@]}; i++ )); do + DELTA=`echo "scale=1; (${ROW_N[${i}]}-${ROW_M[${i}]})/10" | bc` + echo -n "${DELTA}, " + done + + echo + let STEP=${STEP}+1 +done + + +exit 0 diff --git a/scripts/profile-zpios-post.sh b/scripts/profile-zpios-post.sh new file mode 100644 index 0000000000..16bc590f80 --- /dev/null +++ b/scripts/profile-zpios-post.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +prog=profile-zpios-post.sh +. ../.script-config + +RUN_POST=${0} +RUN_PHASE=${1} +RUN_LOG_DIR=${2} +RUN_ID=${3} +RUN_POOL=${4} +RUN_CHUNK_SIZE=${5} +RUN_REGION_SIZE=${6} +RUN_THREAD_COUNT=${7} +RUN_REGION_COUNT=${8} +RUN_OFFSET=${9} +RUN_REGION_NOISE=${10} +RUN_CHUNK_NOISE=${11} +RUN_THREAD_DELAY=${12} +RUN_FLAGS=${13} +RUN_RESULT=${14} + +PROFILE_ZPIOS_PIDS_BIN=/home/behlendo/src/zfs/scripts/profile-zpios-pids.sh +PROFILE_ZPIOS_PIDS_LOG=${RUN_LOG_DIR}/${RUN_ID}/pids-summary.csv + +PROFILE_ZPIOS_DISK_BIN=/home/behlendo/src/zfs/scripts/profile-zpios-disk.sh +PROFILE_ZPIOS_DISK_LOG=${RUN_LOG_DIR}/${RUN_ID}/disk-summary.csv + +PROFILE_ZPIOS_ARC_LOG=${RUN_LOG_DIR}/${RUN_ID}/arcstats +PROFILE_ZPIOS_VDEV_LOG=${RUN_LOG_DIR}/${RUN_ID}/vdev_cache_stats + +KERNEL_BIN="/lib/modules/`uname -r`/kernel/" +SPL_BIN="${SPLBUILD}/modules/spl/" +ZFS_BIN="${ZFSBUILD}/lib/" + +OPROFILE_SHORT_ARGS="-a -g -l -p ${KERNEL_BIN},${SPL_BIN},${ZFS_BIN}" +OPROFILE_LONG_ARGS="-d -a -g -l -p ${KERNEL_BIN},${SPL_BIN},${ZFS_BIN}" + +OPROFILE_LOG=${RUN_LOG_DIR}/${RUN_ID}/oprofile.txt +OPROFILE_SHORT_LOG=${RUN_LOG_DIR}/${RUN_ID}/oprofile-short.txt +OPROFILE_LONG_LOG=${RUN_LOG_DIR}/${RUN_ID}/oprofile-long.txt +PROFILE_PID=${RUN_LOG_DIR}/${RUN_ID}/pid + +if [ "${RUN_PHASE}" != "post" ]; then + exit 1 +fi + +# opcontrol --stop >>${OPROFILE_LOG} 2>&1 +# opcontrol --dump >>${OPROFILE_LOG} 2>&1 + +kill -s SIGHUP `cat ${PROFILE_PID}` +rm -f ${PROFILE_PID} + +# opreport ${OPROFILE_SHORT_ARGS} >${OPROFILE_SHORT_LOG} 2>&1 +# opreport ${OPROFILE_LONG_ARGS} >${OPROFILE_LONG_LOG} 2>&1 + +# opcontrol --deinit >>${OPROFILE_LOG} 2>&1 + +cat /proc/spl/kstat/zfs/arcstats >${PROFILE_ZPIOS_ARC_LOG} +cat /proc/spl/kstat/zfs/vdev_cache_stats >${PROFILE_ZPIOS_VDEV_LOG} + +# Summarize system time per pid +${PROFILE_ZPIOS_PIDS_BIN} ${RUN_LOG_DIR} ${RUN_ID} >${PROFILE_ZPIOS_PIDS_LOG} + +# Summarize per device performance +${PROFILE_ZPIOS_DISK_BIN} ${RUN_LOG_DIR} ${RUN_ID} >${PROFILE_ZPIOS_DISK_LOG} + +exit 0 diff --git a/scripts/profile-zpios-pre.sh b/scripts/profile-zpios-pre.sh new file mode 100644 index 0000000000..675b80240a --- /dev/null +++ b/scripts/profile-zpios-pre.sh @@ -0,0 +1,69 @@ +#!/bin/bash +# profile-zpios-pre.sh + +trap "PROFILE_ZPIOS_READY=1" SIGHUP + +RUN_PRE=${0} +RUN_PHASE=${1} +RUN_LOG_DIR=${2} +RUN_ID=${3} +RUN_POOL=${4} +RUN_CHUNK_SIZE=${5} +RUN_REGION_SIZE=${6} +RUN_THREAD_COUNT=${7} +RUN_REGION_COUNT=${8} +RUN_OFFSET=${9} +RUN_REGION_NOISE=${10} +RUN_CHUNK_NOISE=${11} +RUN_THREAD_DELAY=${12} +RUN_FLAGS=${13} +RUN_RESULT=${14} + +PROFILE_ZPIOS_BIN=/home/behlendo/src/zfs/scripts/profile-zpios.sh +PROFILE_ZPIOS_READY=0 + +OPROFILE_LOG=${RUN_LOG_DIR}/${RUN_ID}/oprofile.txt +PROFILE_PID=${RUN_LOG_DIR}/${RUN_ID}/pid +RUN_ARGS=${RUN_LOG_DIR}/${RUN_ID}/args + +if [ "${RUN_PHASE}" != "pre" ]; then + exit 1 +fi + +rm -Rf ${RUN_LOG_DIR}/${RUN_ID}/ +mkdir -p ${RUN_LOG_DIR}/${RUN_ID}/ + +echo "PHASE=${RUN_PHASE}" >>${RUN_ARGS} +echo "LOG_DIR=${RUN_LOG_DIR}" >>${RUN_ARGS} +echo "ID=${RUN_ID}" >>${RUN_ARGS} +echo "POOL=${RUN_POOL}" >>${RUN_ARGS} +echo "CHUNK_SIZE=${RUN_CHUNK_SIZE}" >>${RUN_ARGS} +echo "REGION_SIZE=${RUN_REGION_SIZE}" >>${RUN_ARGS} +echo "THREAD_COUNT=${RUN_THREAD_COUNT}" >>${RUN_ARGS} +echo "REGION_COUNT=${RUN_REGION_COUNT}" >>${RUN_ARGS} +echo "OFFSET=${RUN_OFFSET}" >>${RUN_ARGS} +echo "REGION_NOISE=${RUN_REGION_NOISE}" >>${RUN_ARGS} +echo "CHUNK_NOISE=${RUN_CHUNK_NOISE}" >>${RUN_ARGS} +echo "THREAD_DELAY=${RUN_THREAD_DELAY}" >>${RUN_ARGS} +echo "FLAGS=${RUN_FLAGS}" >>${RUN_ARGS} +echo "RESULT=${RUN_RESULT}" >>${RUN_ARGS} + +# XXX: Oprofile support seems to be broken when I try and start +# it via a user mode helper script, I suspect the setup is failing. +# opcontrol --init >>${OPROFILE_LOG} 2>&1 +# opcontrol --setup --vmlinux=/boot/vmlinux >>${OPROFILE_LOG} 2>&1 + +# Start the profile script +${PROFILE_ZPIOS_BIN} ${RUN_PHASE} ${RUN_LOG_DIR} ${RUN_ID} & +echo "$!" >${PROFILE_PID} + +# Sleep waiting for profile script to be ready, it will +# signal us via SIGHUP when it is ready to start profiling. +while [ ${PROFILE_ZPIOS_READY} -eq 0 ]; do + sleep 0.1 +done + +# opcontrol --start-daemon >>${OPROFILE_LOG} 2>&1 +# opcontrol --start >>${OPROFILE_LOG} 2>&1 + +exit 0 diff --git a/scripts/profile-zpios.sh b/scripts/profile-zpios.sh new file mode 100644 index 0000000000..2ea110c536 --- /dev/null +++ b/scripts/profile-zpios.sh @@ -0,0 +1,222 @@ +#!/bin/bash +# profile-zpios.sh + +trap "RUN_DONE=1" SIGHUP + +RUN_PHASE=${1} +RUN_LOG_DIR=${2} +RUN_ID=${3} +RUN_DONE=0 + +POLL_INTERVAL=2.99 + +# Log these pids, the exact pid numbers will vary from system to system +# so I harvest pid for all the following type of processes from /proc// +# +# zio_taskq/# +# spa_zio_issue/# +# spa_zio_intr/# +# txg_quiesce_thr +# txg_sync_thread +# txg_timelimit_t +# arc_reclaim_thr +# l2arc_feed_thre +# kpios_io/# + +ZIO_TASKQ_PIDS=() +ZIO_REQ_NUL_PIDS=() +ZIO_IRQ_NUL_PIDS=() +ZIO_REQ_RD_PIDS=() +ZIO_IRQ_RD_PIDS=() +ZIO_REQ_WR_PIDS=() +ZIO_IRQ_WR_PIDS=() +ZIO_REQ_FR_PIDS=() +ZIO_IRQ_FR_PIDS=() +ZIO_REQ_CM_PIDS=() +ZIO_IRQ_CM_PIDS=() +ZIO_REQ_CTL_PIDS=() +ZIO_IRQ_CTL_PIDS=() + +TXG_QUIESCE_PIDS=() +TXG_SYNC_PIDS=() +TXG_TIMELIMIT_PIDS=() + +ARC_RECLAIM_PIDS=() +L2ARC_FEED_PIDS=() + +KPIOS_IO_PIDS=() + +show_pids() { + echo "* zio_taskq: { ${ZIO_TASKQ_PIDS[@]} } = ${#ZIO_TASKQ_PIDS[@]}" + echo "* zio_req_nul: { ${ZIO_REQ_NUL_PIDS[@]} } = ${#ZIO_REQ_NUL_PIDS[@]}" + echo "* zio_irq_nul: { ${ZIO_IRQ_NUL_PIDS[@]} } = ${#ZIO_IRQ_NUL_PIDS[@]}" + echo "* zio_req_rd: { ${ZIO_REQ_RD_PIDS[@]} } = ${#ZIO_REQ_RD_PIDS[@]}" + echo "* zio_irq_rd: { ${ZIO_IRQ_RD_PIDS[@]} } = ${#ZIO_IRQ_RD_PIDS[@]}" + echo "* zio_req_wr: { ${ZIO_REQ_WR_PIDS[@]} } = ${#ZIO_REQ_WR_PIDS[@]}" + echo "* zio_irq_wr: { ${ZIO_IRQ_WR_PIDS[@]} } = ${#ZIO_IRQ_WR_PIDS[@]}" + echo "* zio_req_fr: { ${ZIO_REQ_FR_PIDS[@]} } = ${#ZIO_REQ_FR_PIDS[@]}" + echo "* zio_irq_fr: { ${ZIO_IRQ_FR_PIDS[@]} } = ${#ZIO_IRQ_FR_PIDS[@]}" + echo "* zio_req_cm: { ${ZIO_REQ_CM_PIDS[@]} } = ${#ZIO_REQ_CM_PIDS[@]}" + echo "* zio_irq_cm: { ${ZIO_IRQ_CM_PIDS[@]} } = ${#ZIO_IRQ_CM_PIDS[@]}" + echo "* zio_req_ctl: { ${ZIO_REQ_CTL_PIDS[@]} } = ${#ZIO_REQ_CTL_PIDS[@]}" + echo "* zio_irq_ctl: { ${ZIO_IRQ_CTL_PIDS[@]} } = ${#ZIO_IRQ_CTL_PIDS[@]}" + echo "* txg_quiesce: { ${TXG_QUIESCE_PIDS[@]} } = ${#TXG_QUIESCE_PIDS[@]}" + echo "* txg_sync: { ${TXG_SYNC_PIDS[@]} } = ${#TXG_SYNC_PIDS[@]}" + echo "* txg_timelimit: { ${TXG_TIMELIMIT_PIDS[@]} } = ${#TXG_TIMELIMIT_PIDS[@]}" + echo "* arc_reclaim: { ${ARC_RECLAIM_PIDS[@]} } = ${#ARC_RECLAIM_PIDS[@]}" + echo "* l2arc_feed: { ${L2ARC_FEED_PIDS[@]} } = ${#L2ARC_FEED_PIDS[@]}" + echo "* kpios_io: { ${KPIOS_IO_PIDS[@]} } = ${#KPIOS_IO_PIDS[@]}" +} + +check_pid() { + local PID=$1 + local NAME=$2 + local TYPE=$3 + local PIDS=( "$4" ) + local NAME_STRING=`echo ${NAME} | cut -f1 -d'/'` + local NAME_NUMBER=`echo ${NAME} | cut -f2 -d'/'` + + if [ "${NAME_STRING}" == "${TYPE}" ]; then + if [ -n "${NAME_NUMBER}" ]; then + PIDS[${NAME_NUMBER}]=${PID} + else + PIDS[${#PIDS[@]}]=${PID} + + fi + fi + + echo "${PIDS[@]}" +} + +# NOTE: This whole process is crazy slow but it will do for now +aquire_pids() { + echo "--- Aquiring ZFS pids ---" + + for PID in `ls /proc/ | grep [0-9] | sort -n -u`; do + if [ ! -e /proc/${PID}/status ]; then + continue + fi + + NAME=`cat /proc/${PID}/status | head -n1 | cut -f2` + + ZIO_TASKQ_PIDS=( `check_pid ${PID} ${NAME} "zio_taskq" \ + "$(echo "${ZIO_TASKQ_PIDS[@]}")"` ) + + ZIO_REQ_NUL_PIDS=( `check_pid ${PID} ${NAME} "zio_req_nul" \ + "$(echo "${ZIO_REQ_NUL_PIDS[@]}")"` ) + + ZIO_IRQ_NUL_PIDS=( `check_pid ${PID} ${NAME} "zio_irq_nul" \ + "$(echo "${ZIO_IRQ_NUL_PIDS[@]}")"` ) + + ZIO_REQ_RD_PIDS=( `check_pid ${PID} ${NAME} "zio_req_rd" \ + "$(echo "${ZIO_REQ_RD_PIDS[@]}")"` ) + + ZIO_IRQ_RD_PIDS=( `check_pid ${PID} ${NAME} "zio_irq_rd" \ + "$(echo "${ZIO_IRQ_RD_PIDS[@]}")"` ) + + ZIO_REQ_WR_PIDS=( `check_pid ${PID} ${NAME} "zio_req_wr" \ + "$(echo "${ZIO_REQ_WR_PIDS[@]}")"` ) + + ZIO_IRQ_WR_PIDS=( `check_pid ${PID} ${NAME} "zio_irq_wr" \ + "$(echo "${ZIO_IRQ_WR_PIDS[@]}")"` ) + + ZIO_REQ_FR_PIDS=( `check_pid ${PID} ${NAME} "zio_req_fr" \ + "$(echo "${ZIO_REQ_FR_PIDS[@]}")"` ) + + ZIO_IRQ_FR_PIDS=( `check_pid ${PID} ${NAME} "zio_irq_fr" \ + "$(echo "${ZIO_IRQ_FR_PIDS[@]}")"` ) + + ZIO_REQ_CM_PIDS=( `check_pid ${PID} ${NAME} "zio_req_cm" \ + "$(echo "${ZIO_REQ_CM_PIDS[@]}")"` ) + + ZIO_IRQ_CM_PIDS=( `check_pid ${PID} ${NAME} "zio_irq_cm" \ + "$(echo "${ZIO_IRQ_CM_PIDS[@]}")"` ) + + ZIO_REQ_CTL_PIDS=( `check_pid ${PID} ${NAME} "zio_req_ctl" \ + "$(echo "${ZIO_REQ_CTL_PIDS[@]}")"` ) + + ZIO_IRQ_CTL_PIDS=( `check_pid ${PID} ${NAME} "zio_irq_ctl" \ + "$(echo "${ZIO_IRQ_CTL_PIDS[@]}")"` ) + + TXG_QUIESCE_PIDS=( `check_pid ${PID} ${NAME} "txg_quiesce" \ + "$(echo "${TXG_QUIESCE_PIDS[@]}")"` ) + + TXG_SYNC_PIDS=( `check_pid ${PID} ${NAME} "txg_sync" \ + "$(echo "${TXG_SYNC_PIDS[@]}")"` ) + + TXG_TIMELIMIT_PIDS=( `check_pid ${PID} ${NAME} "txg_timelimit" \ + "$(echo "${TXG_TIMELIMIT_PIDS[@]}")"` ) + + ARC_RECLAIM_PIDS=( `check_pid ${PID} ${NAME} "arc_reclaim" \ + "$(echo "${ARC_RECLAIM_PIDS[@]}")"` ) + + L2ARC_FEED_PIDS=( `check_pid ${PID} ${NAME} "l2arc_feed" \ + "$(echo "${L2ARC_FEED_PIDS[@]}")"` ) + done + + # Wait for kpios_io threads to start + kill -s SIGHUP ${PPID} + echo "* Waiting for kpios_io threads to start" + while [ ${RUN_DONE} -eq 0 ]; do + KPIOS_IO_PIDS=( `ps ax | grep kpios_io | grep -v grep | \ + sed 's/^ *//g' | cut -f1 -d' '` ) + if [ ${#KPIOS_IO_PIDS[@]} -gt 0 ]; then + break; + fi + sleep 0.1 + done + + echo "`show_pids`" >${RUN_LOG_DIR}/${RUN_ID}/pids.txt +} + +log_pids() { + echo "--- Logging ZFS profile to ${RUN_LOG_DIR}/${RUN_ID}/ ---" + ALL_PIDS=( ${ZIO_TASKQ_PIDS[@]} \ + ${ZIO_REQ_NUL_PIDS[@]} \ + ${ZIO_IRQ_NUL_PIDS[@]} \ + ${ZIO_REQ_RD_PID[@]} \ + ${ZIO_IRQ_RD_PIDS[@]} \ + ${ZIO_REQ_WR_PIDS[@]} \ + ${ZIO_IRQ_WR_PIDS[@]} \ + ${ZIO_REQ_FR_PIDS[@]} \ + ${ZIO_IRQ_FR_PIDS[@]} \ + ${ZIO_REQ_CM_PIDS[@]} \ + ${ZIO_IRQ_CM_PIDS[@]} \ + ${ZIO_REQ_CTL_PIDS[@]} \ + ${ZIO_IRQ_CTL_PIDS[@]} \ + ${TXG_QUIESCE_PIDS[@]} \ + ${TXG_SYNC_PIDS[@]} \ + ${TXG_TIMELIMIT_PIDS[@]} \ + ${ARC_RECLAIM_PIDS[@]} \ + ${L2ARC_FEED_PIDS[@]} \ + ${KPIOS_IO_PIDS[@]} ) + + while [ ${RUN_DONE} -eq 0 ]; do + NOW=`date +%s.%N` + LOG_PIDS="${RUN_LOG_DIR}/${RUN_ID}/pids-${NOW}" + LOG_DISK="${RUN_LOG_DIR}/${RUN_ID}/disk-${NOW}" + + for PID in "${ALL_PIDS[@]}"; do + if [ -z ${PID} ]; then + continue; + fi + + if [ -e /proc/${PID}/stat ]; then + cat /proc/${PID}/stat | head -n1 >>${LOG_PIDS} + else + echo "<${PID} exited>" >>${LOG_PIDS} + fi + done + + cat /proc/diskstats >${LOG_DISK} + + NOW2=`date +%s.%N` + DELTA=`echo "${POLL_INTERVAL}-(${NOW2}-${NOW})" | bc` + sleep ${DELTA} + done +} + +aquire_pids +log_pids + +exit 0 diff --git a/scripts/survey.sh b/scripts/survey.sh new file mode 100644 index 0000000000..a75bb2d6f0 --- /dev/null +++ b/scripts/survey.sh @@ -0,0 +1,102 @@ +#!/bin/bash + +prog=survey.sh +. ../.script-config + +LOG=/home/`whoami`/zpios-logs/`uname -r`/zpios-`date +%Y%m%d`/ +mkdir -p ${LOG} + +# Apply all tunings described below to generate some best case +# numbers for what is acheivable with some more elbow grease. +NAME="prefetch+zerocopy+checksum+pending1024+kmem" +echo "----------------------- ${NAME} ------------------------------" +./zpios.sh \ + "" \ + "zfs_prefetch_disable=1 zfs_vdev_max_pending=1024 zio_bulk_flags=0x100" \ + "--zerocopy" \ + ${LOG}/${NAME}/ \ + "${CMDDIR}/zfs/zfs set checksum=off lustre" | \ + tee ${LOG}/${NAME}.txt + +# Baseline number for an out of the box config with no manual tuning. +# Ideally, we will want things to be automatically tuned and for this +# number to approach the tweaked out results above. +NAME="baseline" +echo "----------------------- ${NAME} ------------------------------" +./zpios.sh \ + "" \ + "" \ + "" \ + ${LOG}/${NAME}/ | \ + tee ${LOG}/${NAME}.txt + +# Disable ZFS's prefetching. For some reason still not clear to me +# current prefetching policy is quite bad for a random workload. +# Allow the algorithm to detect a random workload and not do anything +# may be the way to address this issue. +NAME="prefetch" +echo "----------------------- ${NAME} ------------------------------" +./zpios.sh \ + "" \ + "zfs_prefetch_disable=1" \ + "" \ + ${LOG}/${NAME}/ | \ + tee ${LOG}/${NAME}.txt + +# As expected, simulating a zerocopy IO path improves performance +# by freeing up lots of CPU which is wasted move data between buffers. +NAME="zerocopy" +echo "----------------------- ${NAME} ------------------------------" +./zpios.sh \ + "" \ + "" \ + "--zerocopy" \ + ${LOG}/${NAME}/ | \ + tee ${LOG}/${NAME}.txt + +# Disabling checksumming should show some (if small) improvement +# simply due to freeing up a modest amount of CPU. +NAME="checksum" +echo "----------------------- ${NAME} ------------------------------" +./zpios.sh \ + "" \ + "" \ + "" \ + ${LOG}/${NAME}/ \ + "${CMDDIR}/zfs/zfs set checksum=off lustre" | \ + tee ${LOG}/${NAME}.txt + +# Increasing the pending IO depth also seems to improve things likely +# at the expense of latency. This should be exported more because I'm +# seeing a much bigger impact there that I would have expected. There +# may be some low hanging fruit to be found here. +NAME="pending" +echo "----------------------- ${NAME} ------------------------------" +./zpios.sh \ + "" \ + "zfs_vdev_max_pending=1024" \ + "" \ + ${LOG}/${NAME}/ | \ + tee ${LOG}/${NAME}.txt + +# To avoid memory fragmentation issues our slab implementation can be +# based on a virtual address space. Interestingly, we take a pretty +# substantial performance penalty for this somewhere in the low level +# IO drivers. If we back the slab with kmem pages we see far better +# read performance numbers at the cost of memory fragmention and general +# system instability due to large allocations. This may be because of +# an optimization in the low level drivers due to the contigeous kmem +# based memory. This needs to be explained. The good news here is that +# with zerocopy interfaces added at the DMU layer we could gaurentee +# kmem based memory for a pool of pages. +# +# 0x100 = KMC_KMEM - Force kmem_* based slab +# 0x200 = KMC_VMEM - Force vmem_* based slab +NAME="kmem" +echo "----------------------- ${NAME} ------------------------------" +./zpios.sh \ + "" \ + "zio_bulk_flags=0x100" \ + "" \ + ${LOG}/${NAME}/ | \ + tee ${LOG}/${NAME}.txt diff --git a/scripts/zpios.sh b/scripts/zpios.sh new file mode 100644 index 0000000000..1b91c5cc55 --- /dev/null +++ b/scripts/zpios.sh @@ -0,0 +1,133 @@ +#!/bin/bash + +prog=zpios.sh +. ../.script-config + +SPL_OPTIONS="spl_debug_mask=0 spl_debug_subsys=0 ${1}" +ZPOOL_OPTIONS=$2 +ZPIOS_OPTIONS=$3 +PROFILE_ZPIOS_LOGS=$4 +ZPIOS_PRE=$5 +ZPIOS_POST=$6 + +PROFILE_ZPIOS_PRE=/home/behlendo/src/zfs/scripts/profile-zpios-pre.sh +PROFILE_ZPIOS_POST=/home/behlendo/src/zfs/scripts/profile-zpios-post.sh + +DEVICES="/dev/hda" + +echo ------------------------- ZFS TEST LOG --------------------------------- +echo -n "Date = "; date +echo -n "Kernel = "; uname -r +echo ------------------------------------------------------------------------ + +echo +./load-zfs.sh "${SPL_OPTIONS}" "${ZPOOL_OPTIONS}" + +echo ---------------------- SPL Sysctl Tunings ------------------------------ +sysctl -A | grep spl +echo + +echo ------------------- SPL/ZPOOL Module Tunings --------------------------- +if [ -d /sys/module/spl/parameters ]; then + grep [0-9] /sys/module/spl/parameters/* + grep [0-9] /sys/module/zpool/parameters/* +else + grep [0-9] /sys/module/spl/* + grep [0-9] /sys/module/zpool/* +fi +echo + +echo "${CMDDIR}/zpool/zpool create -f lustre ${DEVICES}" +${CMDDIR}/zpool/zpool create -f lustre ${DEVICES} + +echo "${CMDDIR}/zpool/zpool status lustre" +${CMDDIR}/zpool/zpool status lustre + +echo "Waiting for /dev/zpios to come up..." +while [ ! -c /dev/zpios ]; do + sleep 1 +done + +if [ -n "${ZPIOS_PRE}" ]; then + ${ZPIOS_PRE} +fi + +# Usage: zpios +# --chunksize -c =values +# --chunksize_low -a =value +# --chunksize_high -b =value +# --chunksize_incr -g =value +# --offset -o =values +# --offset_low -m =value +# --offset_high -q =value +# --offset_incr -r =value +# --regioncount -n =values +# --regioncount_low -i =value +# --regioncount_high -j =value +# --regioncount_incr -k =value +# --threadcount -t =values +# --threadcount_low -l =value +# --threadcount_high -h =value +# --threadcount_incr -e =value +# --regionsize -s =values +# --regionsize_low -A =value +# --regionsize_high -B =value +# --regionsize_incr -C =value +# --cleanup -x +# --verify -V +# --zerocopy -z +# --threaddelay -T =jiffies +# --regionnoise -I =shift +# --chunknoise -N =bytes +# --prerun -P =pre-command +# --postrun -R =post-command +# --log -G =log directory +# --pool | --path -p =pool name +# --load -L =dmuio +# --help -? =this help +# --verbose -v =increase verbosity + +# --prerun=${PROFILE_ZPIOS_PRE} \ +# --postrun=${PROFILE_ZPIOS_POST} \ + +CMD="${CMDDIR}/zpios/zpios \ + --load=dmuio \ + --path=lustre \ + --chunksize=1M \ + --regionsize=4M \ + --regioncount=64 \ + --threadcount=4 \ + --offset=4M \ + --cleanup \ + --verbose \ + --human-readable \ + ${ZPIOS_OPTIONS} \ + --log=${PROFILE_ZPIOS_LOGS}" +echo +date +echo ${CMD} +$CMD +date + +if [ -n "${ZPIOS_POST}" ]; then + ${ZPIOS_POST} +fi + +${CMDDIR}/zpool/zpool destroy lustre + +echo ---------------------- SPL Sysctl Tunings ------------------------------ +sysctl -A | grep spl +echo + +echo ------------------------ KSTAT Statistics ------------------------------ +echo ARCSTATS +cat /proc/spl/kstat/zfs/arcstats +echo +echo VDEV_CACHE_STATS +cat /proc/spl/kstat/zfs/vdev_cache_stats +echo +echo SLAB +cat /proc/spl/kmem/slab +echo + +./unload-zfs.sh diff --git a/zfs/lib/Makefile.in b/zfs/lib/Makefile.in index 8e328ca2df..575399286d 100644 --- a/zfs/lib/Makefile.in +++ b/zfs/lib/Makefile.in @@ -8,3 +8,5 @@ subdir-m += libzpool # Kernel | User SPA/DMU/ZVOL/ZPL subdir-m += libavl # Kernel &| User space AVL tree support subdir-m += libnvpair # Kernel &| User space name/value support subdir-m += libzcommon # Kernel &| User space common support + +subdir-m += libzpios # Kernel DMU test app diff --git a/zfs/lib/libzpios/Makefile.in b/zfs/lib/libzpios/Makefile.in new file mode 100644 index 0000000000..2aa1482a8d --- /dev/null +++ b/zfs/lib/libzpios/Makefile.in @@ -0,0 +1,17 @@ +DISTFILES = Makefile.in *.c + +MODULE := zpios + +# Compile as kernel module. Needed symlinks created for all +# k* objects created by top level configure script. + +EXTRA_CFLAGS = @KERNELCPPFLAGS@ +EXTRA_CFLAGS += -I@LIBDIR@/libzpios/include +EXTRA_CFLAGS += -I@LIBDIR@/libzcommon/include +EXTRA_CFLAGS += -I@LIBDIR@/libport/include +EXTRA_CFLAGS += -I@LIBDIR@/libavl/include +EXTRA_CFLAGS += -I@LIBDIR@/libnvpair/include + +obj-m := ${MODULE}.o + +${MODULE}-objs += kpios.o # Kernel PIOS test case diff --git a/zfs/lib/libzpios/include/Makefile.in b/zfs/lib/libzpios/include/Makefile.in new file mode 100644 index 0000000000..20e4bd7c9d --- /dev/null +++ b/zfs/lib/libzpios/include/Makefile.in @@ -0,0 +1 @@ +DISTFILES = kpios-ctl.h kpios-internal.h diff --git a/zfs/lib/libzpios/include/kpios-ctl.h b/zfs/lib/libzpios/include/kpios-ctl.h new file mode 100644 index 0000000000..c9c3526ade --- /dev/null +++ b/zfs/lib/libzpios/include/kpios-ctl.h @@ -0,0 +1,120 @@ +/* + * This file is part of the ZFS Linux port. + * + * Copyright (c) 2008 Lawrence Livermore National Security, LLC. + * Produced at Lawrence Livermore National Laboratory + * Written by: + * Brian Behlendorf , + * Herb Wartens , + * Jim Garlick + * LLNL-CODE-403049 + * + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#ifndef _KPIOS_CTL_H +#define _KPIOS_CTL_H + +/* Contains shared definitions which both the userspace + * and kernelspace portions of kpios must agree on. + */ +#ifndef _KERNEL +#include +#endif + +#define KPIOS_MAJOR 232 /* XXX - Arbitrary */ +#define KPIOS_MINORS 1 +#define KPIOS_DEV "/dev/kpios" + +#define DMU_IO 0x01 + +#define DMU_WRITE 0x01 +#define DMU_READ 0x02 +#define DMU_VERIFY 0x04 +#define DMU_REMOVE 0x08 +#define DMU_FPP 0x10 +#define DMU_WRITE_ZC 0x20 /* Incompatible with DMU_VERIFY */ +#define DMU_READ_ZC 0x40 /* Incompatible with DMU_VERIFY */ + +#define KPIOS_NAME_SIZE 16 +#define KPIOS_PATH_SIZE 128 + +#define PHASE_PRE "pre" +#define PHASE_POST "post" +#define PHASE_WRITE "write" +#define PHASE_READ "read" + +#define KPIOS_CFG_MAGIC 0x87237190U +typedef struct kpios_cfg { + uint32_t cfg_magic; /* Unique magic */ + int32_t cfg_cmd; /* Config command */ + int32_t cfg_arg1; /* Config command arg 1 */ + int32_t cfg_rc1; /* Config response 1 */ +} kpios_cfg_t; + +typedef struct kpios_time { + struct timespec start; + struct timespec stop; + struct timespec delta; +} kpios_time_t; + +typedef struct kpios_stats { + kpios_time_t total_time; + kpios_time_t cr_time; + kpios_time_t rm_time; + kpios_time_t wr_time; + kpios_time_t rd_time; + uint64_t wr_data; + uint64_t wr_chunks; + uint64_t rd_data; + uint64_t rd_chunks; +} kpios_stats_t; + +#define KPIOS_CMD_MAGIC 0x49715385U +typedef struct kpios_cmd { + uint32_t cmd_magic; /* Unique magic */ + uint32_t cmd_id; /* Run ID */ + char cmd_pool[KPIOS_NAME_SIZE]; /* Pool name */ + uint64_t cmd_chunk_size; /* Chunk size */ + uint32_t cmd_thread_count; /* Thread count */ + uint32_t cmd_region_count; /* Region count */ + uint64_t cmd_region_size; /* Region size */ + uint64_t cmd_offset; /* Region offset */ + uint32_t cmd_region_noise; /* Region noise */ + uint32_t cmd_chunk_noise; /* Chunk noise */ + uint32_t cmd_thread_delay; /* Thread delay */ + uint32_t cmd_flags; /* Test flags */ + char cmd_pre[KPIOS_PATH_SIZE]; /* Pre-exec hook */ + char cmd_post[KPIOS_PATH_SIZE]; /* Post-exec hook */ + char cmd_log[KPIOS_PATH_SIZE]; /* Requested log dir */ + uint64_t cmd_data_size; /* Opaque data size */ + char cmd_data_str[0]; /* Opaque data region */ +} kpios_cmd_t; + +/* Valid ioctls */ +#define KPIOS_CFG _IOWR('f', 101, long) +#define KPIOS_CMD _IOWR('f', 102, long) + +/* Valid configuration commands */ +#define KPIOS_CFG_BUFFER_CLEAR 0x001 /* Clear text buffer */ +#define KPIOS_CFG_BUFFER_SIZE 0x002 /* Resize text buffer */ + +#endif /* _KPIOS_CTL_H */ diff --git a/zfs/lib/libzpios/include/kpios-internal.h b/zfs/lib/libzpios/include/kpios-internal.h new file mode 100644 index 0000000000..3da1fe3823 --- /dev/null +++ b/zfs/lib/libzpios/include/kpios-internal.h @@ -0,0 +1,137 @@ +/* + * This file is part of the ZFS Linux port. + * + * Copyright (c) 2008 Lawrence Livermore National Security, LLC. + * Produced at Lawrence Livermore National Laboratory + * Written by: + * Brian Behlendorf , + * Herb Wartens , + * Jim Garlick + * LLNL-CODE-403049 + * + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#ifndef _KPIOS_INTERNAL_H +#define _KPIOS_INTERNAL_H + +#include "kpios-ctl.h" + +#define OBJ_SIZE 64 + +struct run_args; + +typedef struct dmu_obj { + objset_t *os; + uint64_t obj; +} dmu_obj_t; + +/* thread doing the IO data */ +typedef struct thread_data { + struct run_args *run_args; + int thread_no; + int rc; + kpios_stats_t stats; + kmutex_t lock; +} thread_data_t; + +/* region for IO data */ +typedef struct kpios_region { + __u64 wr_offset; + __u64 rd_offset; + __u64 init_offset; + __u64 max_offset; + dmu_obj_t obj; + kpios_stats_t stats; + kmutex_t lock; +} kpios_region_t; + +/* arguments for one run */ +typedef struct run_args { + /* Config args */ + int id; + char pool[KPIOS_NAME_SIZE]; + __u64 chunk_size; + __u32 thread_count; + __u32 region_count; + __u64 region_size; + __u64 offset; + __u32 region_noise; + __u32 chunk_noise; + __u32 thread_delay; + __u32 flags; + char pre[KPIOS_PATH_SIZE]; + char post[KPIOS_PATH_SIZE]; + char log[KPIOS_PATH_SIZE]; + + /* Control data */ + objset_t *os; + wait_queue_head_t waitq; + volatile uint64_t threads_done; + kmutex_t lock_work; + kmutex_t lock_ctl; + __u32 region_next; + + /* Results data */ + struct file *file; + kpios_stats_t stats; + + thread_data_t **threads; + kpios_region_t regions[0]; /* Must be last element */ +} run_args_t; + +#define KPIOS_INFO_BUFFER_SIZE 65536 +#define KPIOS_INFO_BUFFER_REDZONE 1024 + +typedef struct kpios_info { + spinlock_t info_lock; + int info_size; + char *info_buffer; + char *info_head; /* Internal kernel use only */ +} kpios_info_t; + +#define kpios_print(file, format, args...) \ +({ kpios_info_t *_info_ = (kpios_info_t *)file->private_data; \ + int _rc_; \ + \ + ASSERT(_info_); \ + ASSERT(_info_->info_buffer); \ + \ + spin_lock(&_info_->info_lock); \ + \ + /* Don't allow the kernel to start a write in the red zone */ \ + if ((int)(_info_->info_head - _info_->info_buffer) > \ + (_info_->info_size - KPIOS_INFO_BUFFER_REDZONE)) { \ + _rc_ = -EOVERFLOW; \ + } else { \ + _rc_ = sprintf(_info_->info_head, format, args); \ + if (_rc_ >= 0) \ + _info_->info_head += _rc_; \ + } \ + \ + spin_unlock(&_info_->info_lock); \ + _rc_; \ +}) + +#define kpios_vprint(file, test, format, args...) \ + kpios_print(file, "%*s: " format, KPIOS_NAME_SIZE, test, args) + +#endif /* _KPIOS_INTERNAL_H */ diff --git a/zfs/lib/libzpios/kpios.c b/zfs/lib/libzpios/kpios.c new file mode 100644 index 0000000000..a6493d8d50 --- /dev/null +++ b/zfs/lib/libzpios/kpios.c @@ -0,0 +1,1295 @@ +/* + * This file is part of the ZFS Linux port. + * + * Copyright (c) 2008 Lawrence Livermore National Security, LLC. + * Produced at Lawrence Livermore National Laboratory + * Written by: + * Brian Behlendorf , + * Herb Wartens , + * Jim Garlick + * LLNL-CODE-403049 + * + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Kernel PIOS DMU implemenation originally derived from PIOS test code. + * Character control interface derived from SPL code. + */ + +#include +#include +#include +#include +#include "kpios-internal.h" + + +static struct class *kpios_class; + + +static inline +struct timespec timespec_add(struct timespec lhs, struct timespec rhs) +{ + struct timespec ts_delta; + set_normalized_timespec(&ts_delta, lhs.tv_sec + rhs.tv_sec, + lhs.tv_nsec + rhs.tv_nsec); + return ts_delta; +} + +static +int kpios_upcall(char *path, char *phase, run_args_t *run_args, int rc) +{ + /* This is stack heavy but it should be OK since we are only + * making the upcall between tests when the stack is shallow. + */ + char id[16], chunk_size[16], region_size[16], thread_count[16]; + char region_count[16], offset[16], region_noise[16], chunk_noise[16]; + char thread_delay[16], flags[16], result[8]; + char *argv[16], *envp[4]; + + if (strlen(path) == 0) + return -ENOENT; + + snprintf(id, 15, "%d", run_args->id); + snprintf(chunk_size, 15, "%lu", (long unsigned)run_args->chunk_size); + snprintf(region_size, 15, "%lu",(long unsigned) run_args->region_size); + snprintf(thread_count, 15, "%u", run_args->thread_count); + snprintf(region_count, 15, "%u", run_args->region_count); + snprintf(offset, 15, "%lu", (long unsigned)run_args->offset); + snprintf(region_noise, 15, "%u", run_args->region_noise); + snprintf(chunk_noise, 15, "%u", run_args->chunk_noise); + snprintf(thread_delay, 15, "%u", run_args->thread_delay); + snprintf(flags, 15, "0x%x", run_args->flags); + snprintf(result, 7, "%d", rc); + + /* Passing 15 args to registered pre/post upcall */ + argv[0] = path; + argv[1] = phase; + argv[2] = strlen(run_args->log) ? run_args->log : ""; + argv[3] = id; + argv[4] = run_args->pool; + argv[5] = chunk_size; + argv[6] = region_size; + argv[7] = thread_count; + argv[8] = region_count; + argv[9] = offset; + argv[10] = region_noise; + argv[11] = chunk_noise; + argv[12] = thread_delay; + argv[13] = flags; + argv[14] = result; + argv[15] = NULL; + + /* Passing environment for userspace upcall */ + envp[0] = "HOME=/"; + envp[1] = "TERM=linux"; + envp[2] = "PATH=/sbin:/usr/sbin:/bin:/usr/bin"; + envp[3] = NULL; + + return call_usermodehelper(path, argv, envp, 1); +} + +static uint64_t +kpios_dmu_object_create(run_args_t *run_args, objset_t *os) +{ + struct dmu_tx *tx; + uint64_t obj = 0ULL; + int rc; + + tx = dmu_tx_create(os); + dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, OBJ_SIZE); + rc = dmu_tx_assign(tx, TXG_WAIT); + if (rc) { + kpios_print(run_args->file, + "dmu_tx_assign() failed: %d\n", rc); + dmu_tx_abort(tx); + return obj; + } + + obj = dmu_object_alloc(os, DMU_OT_UINT64_OTHER, 0, + DMU_OT_NONE, 0, tx); + rc = dmu_object_set_blocksize(os, obj, 128ULL << 10, 0, tx); + if (rc) { + kpios_print(run_args->file, + "dmu_object_set_blocksize() failed: %d\n", rc); + dmu_tx_abort(tx); + return obj; + } + + dmu_tx_commit(tx); + + return obj; +} + +static int +kpios_dmu_object_free(run_args_t *run_args, objset_t *os, uint64_t obj) +{ + struct dmu_tx *tx; + int rc; + + tx = dmu_tx_create(os); + dmu_tx_hold_free(tx, obj, 0, DMU_OBJECT_END); + rc = dmu_tx_assign(tx, TXG_WAIT); + if (rc) { + kpios_print(run_args->file, + "dmu_tx_assign() failed: %d\n", rc); + dmu_tx_abort(tx); + return rc; + } + + rc = dmu_object_free(os, obj, tx); + if (rc) { + kpios_print(run_args->file, + "dmu_object_free() failed: %d\n", rc); + dmu_tx_abort(tx); + return rc; + } + + dmu_tx_commit(tx); + + return 0; +} + +static int +kpios_dmu_setup(run_args_t *run_args) +{ + kpios_time_t *t = &(run_args->stats.cr_time); + objset_t *os; + uint64_t obj = 0ULL; + int i, rc = 0; + + t->start = current_kernel_time(); + + rc = dmu_objset_open(run_args->pool, DMU_OST_ZFS, DS_MODE_STANDARD, &os); + if (rc) { + kpios_print(run_args->file, "Error dmu_objset_open() " + "failed: %d\n", rc); + goto out; + } + + if (!(run_args->flags & DMU_FPP)) { + obj = kpios_dmu_object_create(run_args, os); + if (obj == 0) { + rc = -EBADF; + kpios_print(run_args->file, "Error kpios_dmu_" + "object_create() failed, %d\n", rc); + goto out; + } + } + + for (i = 0; i < run_args->region_count; i++) { + kpios_region_t *region; + + region = &run_args->regions[i]; + mutex_init(®ion->lock, NULL, MUTEX_DEFAULT, NULL); + + if (run_args->flags & DMU_FPP) { + /* File per process */ + region->obj.os = os; + region->obj.obj = kpios_dmu_object_create(run_args, os); + ASSERT(region->obj.obj > 0); /* XXX - Handle this */ + region->wr_offset = run_args->offset; + region->rd_offset = run_args->offset; + region->init_offset = run_args->offset; + region->max_offset = run_args->offset + + run_args->region_size; + } else { + /* Single shared file */ + region->obj.os = os; + region->obj.obj = obj; + region->wr_offset = run_args->offset * i; + region->rd_offset = run_args->offset * i; + region->init_offset = run_args->offset * i; + region->max_offset = run_args->offset * + i + run_args->region_size; + } + } + + run_args->os = os; +out: + t->stop = current_kernel_time(); + t->delta = timespec_sub(t->stop, t->start); + + return rc; +} + +static int +kpios_setup_run(run_args_t **run_args, kpios_cmd_t *kcmd, struct file *file) +{ + run_args_t *ra; + int rc, size; + + size = sizeof(*ra) + kcmd->cmd_region_count * sizeof(kpios_region_t); + + ra = vmem_zalloc(size, KM_SLEEP); + if (ra == NULL) { + kpios_print(file, "Unable to vmem_zalloc() %d bytes " + "for regions\n", size); + return -ENOMEM; + } + + *run_args = ra; + strncpy(ra->pool, kcmd->cmd_pool, KPIOS_NAME_SIZE - 1); + strncpy(ra->pre, kcmd->cmd_pre, KPIOS_PATH_SIZE - 1); + strncpy(ra->post, kcmd->cmd_post, KPIOS_PATH_SIZE - 1); + strncpy(ra->log, kcmd->cmd_log, KPIOS_PATH_SIZE - 1); + ra->id = kcmd->cmd_id; + ra->chunk_size = kcmd->cmd_chunk_size; + ra->thread_count = kcmd->cmd_thread_count; + ra->region_count = kcmd->cmd_region_count; + ra->region_size = kcmd->cmd_region_size; + ra->offset = kcmd->cmd_offset; + ra->region_noise = kcmd->cmd_region_noise; + ra->chunk_noise = kcmd->cmd_chunk_noise; + ra->thread_delay = kcmd->cmd_thread_delay; + ra->flags = kcmd->cmd_flags; + ra->stats.wr_data = 0; + ra->stats.wr_chunks = 0; + ra->stats.rd_data = 0; + ra->stats.rd_chunks = 0; + ra->region_next = 0; + ra->file = file; + mutex_init(&ra->lock_work, NULL, MUTEX_DEFAULT, NULL); + mutex_init(&ra->lock_ctl, NULL, MUTEX_DEFAULT, NULL); + + rc = kpios_dmu_setup(ra); + if (rc) { + mutex_destroy(&ra->lock_ctl); + mutex_destroy(&ra->lock_work); + vmem_free(ra, size); + *run_args = NULL; + } + + return rc; +} + +static int +kpios_get_work_item(run_args_t *run_args, dmu_obj_t *obj, __u64 *offset, + __u32 *chunk_size, kpios_region_t **region, __u32 flags) +{ + int i, j, count = 0; + unsigned int random_int; + + get_random_bytes(&random_int, sizeof(unsigned int)); + + mutex_enter(&run_args->lock_work); + i = run_args->region_next; + + /* XXX: I don't much care for this chunk selection mechansim + * there's the potential to burn a lot of time here doing nothing + * useful while holding the global lock. This could give some + * misleading performance results. I'll fix it latter. + */ + while (count < run_args->region_count) { + __u64 *rw_offset; + kpios_time_t *rw_time; + + j = i % run_args->region_count; + *region = &(run_args->regions[j]); + + if (flags & DMU_WRITE) { + rw_offset = &((*region)->wr_offset); + rw_time = &((*region)->stats.wr_time); + } else { + rw_offset = &((*region)->rd_offset); + rw_time = &((*region)->stats.rd_time); + } + + /* test if region is fully written */ + if (*rw_offset + *chunk_size > (*region)->max_offset) { + i++; + count++; + + if (unlikely(rw_time->stop.tv_sec == 0) && + unlikely(rw_time->stop.tv_nsec == 0)) + rw_time->stop = current_kernel_time(); + + continue; + } + + *offset = *rw_offset; + *obj = (*region)->obj; + *rw_offset += *chunk_size; + + /* update ctl structure */ + if (run_args->region_noise) { + get_random_bytes(&random_int, sizeof(unsigned int)); + run_args->region_next += random_int % run_args->region_noise; + } else { + run_args->region_next++; + } + + mutex_exit(&run_args->lock_work); + return 1; + } + + /* nothing left to do */ + mutex_exit(&run_args->lock_work); + + return 0; +} + +static void +kpios_remove_objects(run_args_t *run_args) +{ + kpios_time_t *t = &(run_args->stats.rm_time); + kpios_region_t *region; + int rc = 0, i; + + t->start = current_kernel_time(); + + if (run_args->flags & DMU_REMOVE) { + if (run_args->flags & DMU_FPP) { + for (i = 0; i < run_args->region_count; i++) { + region = &run_args->regions[i]; + rc = kpios_dmu_object_free(run_args, + region->obj.os, + region->obj.obj); + if (rc) + kpios_print(run_args->file, "Error " + "removing object %d, %d\n", + (int)region->obj.obj, rc); + } + } else { + region = &run_args->regions[0]; + rc = kpios_dmu_object_free(run_args, + region->obj.os, + region->obj.obj); + if (rc) + kpios_print(run_args->file, "Error " + "removing object %d, %d\n", + (int)region->obj.obj, rc); + } + } + + dmu_objset_close(run_args->os); + + t->stop = current_kernel_time(); + t->delta = timespec_sub(t->stop, t->start); +} + +static void +kpios_cleanup_run(run_args_t *run_args) +{ + int i, size = 0; + + if (run_args == NULL) + return; + + if (run_args->threads != NULL) { + for (i = 0; i < run_args->thread_count; i++) { + if (run_args->threads[i]) { + mutex_destroy(&run_args->threads[i]->lock); + kmem_free(run_args->threads[i], + sizeof(thread_data_t)); + } + } + + kmem_free(run_args->threads, + sizeof(thread_data_t *) * run_args->thread_count); + } + + if (run_args->regions != NULL) + for (i = 0; i < run_args->region_count; i++) + mutex_destroy(&run_args->regions[i].lock); + + mutex_destroy(&run_args->lock_work); + mutex_destroy(&run_args->lock_ctl); + + if (run_args->regions != NULL) + size = run_args->region_count * sizeof(kpios_region_t); + + vmem_free(run_args, sizeof(*run_args) + size); +} + +static int +kpios_dmu_write(run_args_t *run_args, objset_t *os, uint64_t object, + uint64_t offset, uint64_t size, const void *buf) +{ + struct dmu_tx *tx; + int rc, how = TXG_WAIT; + int flags = 0; + + while (1) { + tx = dmu_tx_create(os); + dmu_tx_hold_write(tx, object, offset, size); + rc = dmu_tx_assign(tx, how); + + if (rc) { + if (rc == ERESTART && how == TXG_NOWAIT) { + dmu_tx_wait(tx); + dmu_tx_abort(tx); + continue; + } + kpios_print(run_args->file, + "Error in dmu_tx_assign(), %d", rc); + dmu_tx_abort(tx); + return rc; + } + break; + } + + if (run_args->flags & DMU_WRITE_ZC) + flags |= DMU_WRITE_ZEROCOPY; + + dmu_write_impl(os, object, offset, size, buf, tx, flags); + dmu_tx_commit(tx); + + return 0; +} + +static int +kpios_dmu_read(run_args_t *run_args, objset_t *os, uint64_t object, + uint64_t offset, uint64_t size, void *buf) +{ + int flags = 0; + + if (run_args->flags & DMU_READ_ZC) + flags |= DMU_READ_ZEROCOPY; + + return dmu_read_impl(os, object, offset, size, buf, flags); +} + +static int +kpios_thread_main(void *data) +{ + thread_data_t *thr = (thread_data_t *)data; + run_args_t *run_args = thr->run_args; + kpios_time_t t; + + dmu_obj_t obj; + __u64 offset; + __u32 chunk_size; + kpios_region_t *region; + char *buf; + + unsigned int random_int; + int chunk_noise = run_args->chunk_noise; + int chunk_noise_tmp = 0; + int thread_delay = run_args->thread_delay; + int thread_delay_tmp = 0; + + int i, rc = 0; + + if (chunk_noise) { + get_random_bytes(&random_int, sizeof(unsigned int)); + chunk_noise_tmp = (random_int % (chunk_noise * 2)) - chunk_noise; + } + + /* It's OK to vmem_alloc() this memory because it will be copied + * in to the slab and pointers to the slab copy will be setup in + * the bio when the IO is submitted. This of course is not ideal + * since we want a zero-copy IO path if possible. It would be nice + * to have direct access to those slab entries. + */ + chunk_size = run_args->chunk_size + chunk_noise_tmp; + buf = (char *)vmem_alloc(chunk_size, KM_SLEEP); + ASSERT(buf); + + /* Trivial data verification pattern for now. */ + if (run_args->flags & DMU_VERIFY) + memset(buf, 'z', chunk_size); + + /* Write phase */ + mutex_enter(&thr->lock); + thr->stats.wr_time.start = current_kernel_time(); + mutex_exit(&thr->lock); + + while (kpios_get_work_item(run_args, &obj, &offset, + &chunk_size, ®ion, DMU_WRITE)) { + if (thread_delay) { + get_random_bytes(&random_int, sizeof(unsigned int)); + thread_delay_tmp = random_int % thread_delay; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(thread_delay_tmp); /* In jiffies */ + } + + t.start = current_kernel_time(); + rc = kpios_dmu_write(run_args, obj.os, obj.obj, + offset, chunk_size, buf); + t.stop = current_kernel_time(); + t.delta = timespec_sub(t.stop, t.start); + + if (rc) { + kpios_print(run_args->file, "IO error while doing " + "dmu_write(): %d\n", rc); + break; + } + + mutex_enter(&thr->lock); + thr->stats.wr_data += chunk_size; + thr->stats.wr_chunks++; + thr->stats.wr_time.delta = timespec_add( + thr->stats.wr_time.delta, t.delta); + mutex_exit(&thr->lock); + + mutex_enter(®ion->lock); + region->stats.wr_data += chunk_size; + region->stats.wr_chunks++; + region->stats.wr_time.delta = timespec_add( + region->stats.wr_time.delta, t.delta); + + /* First time region was accessed */ + if (region->init_offset == offset) + region->stats.wr_time.start = t.start; + + mutex_exit(®ion->lock); + } + + mutex_enter(&run_args->lock_ctl); + run_args->threads_done++; + mutex_exit(&run_args->lock_ctl); + + mutex_enter(&thr->lock); + thr->rc = rc; + thr->stats.wr_time.stop = current_kernel_time(); + mutex_exit(&thr->lock); + wake_up(&run_args->waitq); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + + /* Check if we should exit */ + mutex_enter(&thr->lock); + rc = thr->rc; + mutex_exit(&thr->lock); + if (rc) + goto out; + + /* Read phase */ + mutex_enter(&thr->lock); + thr->stats.rd_time.start = current_kernel_time(); + mutex_exit(&thr->lock); + + while (kpios_get_work_item(run_args, &obj, &offset, + &chunk_size, ®ion, DMU_READ)) { + if (thread_delay) { + get_random_bytes(&random_int, sizeof(unsigned int)); + thread_delay_tmp = random_int % thread_delay; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(thread_delay_tmp); /* In jiffies */ + } + + if (run_args->flags & DMU_VERIFY) + memset(buf, 0, chunk_size); + + t.start = current_kernel_time(); + rc = kpios_dmu_read(run_args, obj.os, obj.obj, + offset, chunk_size, buf); + t.stop = current_kernel_time(); + t.delta = timespec_sub(t.stop, t.start); + + if (rc) { + kpios_print(run_args->file, "IO error while doing " + "dmu_read(): %d\n", rc); + break; + } + + /* Trivial data verification, expensive! */ + if (run_args->flags & DMU_VERIFY) { + for (i = 0; i < chunk_size; i++) { + if (buf[i] != 'z') { + kpios_print(run_args->file, + "IO verify error: %d/%d/%d\n", + (int)obj.obj, (int)offset, + (int)chunk_size); + break; + } + } + } + + mutex_enter(&thr->lock); + thr->stats.rd_data += chunk_size; + thr->stats.rd_chunks++; + thr->stats.rd_time.delta = timespec_add( + thr->stats.rd_time.delta, t.delta); + mutex_exit(&thr->lock); + + mutex_enter(®ion->lock); + region->stats.rd_data += chunk_size; + region->stats.rd_chunks++; + region->stats.rd_time.delta = timespec_add( + region->stats.rd_time.delta, t.delta); + + /* First time region was accessed */ + if (region->init_offset == offset) + region->stats.rd_time.start = t.start; + + mutex_exit(®ion->lock); + } + + mutex_enter(&run_args->lock_ctl); + run_args->threads_done++; + mutex_exit(&run_args->lock_ctl); + + mutex_enter(&thr->lock); + thr->rc = rc; + thr->stats.rd_time.stop = current_kernel_time(); + mutex_exit(&thr->lock); + wake_up(&run_args->waitq); + +out: + vmem_free(buf, chunk_size); + do_exit(0); + + return rc; /* Unreachable, due to do_exit() */ +} + +static int +kpios_thread_done(run_args_t *run_args) +{ + ASSERT(run_args->threads_done <= run_args->thread_count); + return (run_args->threads_done == run_args->thread_count); +} + +static int +kpios_threads_run(run_args_t *run_args) +{ + struct task_struct *tsk, **tsks; + thread_data_t *thr = NULL; + kpios_time_t *tt = &(run_args->stats.total_time); + kpios_time_t *tw = &(run_args->stats.wr_time); + kpios_time_t *tr = &(run_args->stats.rd_time); + int i, rc = 0, tc = run_args->thread_count; + DEFINE_WAIT(wait); + + kpios_upcall(run_args->pre, PHASE_PRE, run_args, 0); + + tsks = kmem_zalloc(sizeof(struct task_struct *) * tc, KM_SLEEP); + if (tsks == NULL) { + rc = -ENOMEM; + goto cleanup2; + } + + run_args->threads = kmem_zalloc(sizeof(thread_data_t *) * tc, KM_SLEEP); + if (run_args->threads == NULL) { + rc = -ENOMEM; + goto cleanup; + } + + init_waitqueue_head(&run_args->waitq); + run_args->threads_done = 0; + + /* Create all the needed threads which will sleep until awoken */ + for (i = 0; i < tc; i++) { + thr = kmem_zalloc(sizeof(thread_data_t), KM_SLEEP); + if (thr == NULL) { + rc = -ENOMEM; + goto taskerr; + } + + thr->thread_no = i; + thr->run_args = run_args; + thr->rc = 0; + mutex_init(&thr->lock, NULL, MUTEX_DEFAULT, NULL); + run_args->threads[i] = thr; + + tsk = kthread_create(kpios_thread_main, (void *)thr, + "%s/%d", "kpios_io", i); + if (IS_ERR(tsk)) { + rc = -EINVAL; + goto taskerr; + } + + tsks[i] = tsk; + } + + tt->start = current_kernel_time(); + + /* Wake up all threads for write phase */ + kpios_upcall(run_args->pre, PHASE_WRITE, run_args, 0); + for (i = 0; i < tc; i++) + wake_up_process(tsks[i]); + + /* Wait for write phase to complete */ + tw->start = current_kernel_time(); + wait_event(run_args->waitq, kpios_thread_done(run_args)); + tw->stop = current_kernel_time(); + + for (i = 0; i < tc; i++) { + thr = run_args->threads[i]; + + mutex_enter(&thr->lock); + + if (!rc && thr->rc) + rc = thr->rc; + + run_args->stats.wr_data += thr->stats.wr_data; + run_args->stats.wr_chunks += thr->stats.wr_chunks; + mutex_exit(&thr->lock); + } + + kpios_upcall(run_args->post, PHASE_WRITE, run_args, rc); + if (rc) { + /* Wake up all threads and tell them to exit */ + for (i = 0; i < tc; i++) { + mutex_enter(&thr->lock); + thr->rc = rc; + mutex_exit(&thr->lock); + + wake_up_process(tsks[i]); + } + goto out; + } + + mutex_enter(&run_args->lock_ctl); + ASSERT(run_args->threads_done == run_args->thread_count); + run_args->threads_done = 0; + mutex_exit(&run_args->lock_ctl); + + /* Wake up all threads for read phase */ + kpios_upcall(run_args->pre, PHASE_READ, run_args, 0); + for (i = 0; i < tc; i++) + wake_up_process(tsks[i]); + + /* Wait for read phase to complete */ + tr->start = current_kernel_time(); + wait_event(run_args->waitq, kpios_thread_done(run_args)); + tr->stop = current_kernel_time(); + + for (i = 0; i < tc; i++) { + thr = run_args->threads[i]; + + mutex_enter(&thr->lock); + + if (!rc && thr->rc) + rc = thr->rc; + + run_args->stats.rd_data += thr->stats.rd_data; + run_args->stats.rd_chunks += thr->stats.rd_chunks; + mutex_exit(&thr->lock); + } + + kpios_upcall(run_args->post, PHASE_READ, run_args, rc); +out: + tt->stop = current_kernel_time(); + tt->delta = timespec_sub(tt->stop, tt->start); + tw->delta = timespec_sub(tw->stop, tw->start); + tr->delta = timespec_sub(tr->stop, tr->start); + +cleanup: + kmem_free(tsks, sizeof(struct task_struct *) * tc); +cleanup2: + kpios_upcall(run_args->post, PHASE_POST, run_args, rc); + + /* Returns first encountered thread error (if any) */ + return rc; + +taskerr: + /* Destroy all threads that were created successfully */ + for (i = 0; i < tc; i++) + if (tsks[i] != NULL) + (void) kthread_stop(tsks[i]); + + goto cleanup; +} + +static int +kpios_do_one_run(struct file *file, kpios_cmd_t *kcmd, + int data_size, void *data) +{ + run_args_t *run_args; + kpios_stats_t *stats = (kpios_stats_t *)data; + int i, n, m, size, rc; + + if ((!kcmd->cmd_chunk_size) || (!kcmd->cmd_region_size) || + (!kcmd->cmd_thread_count) || (!kcmd->cmd_region_count)) { + kpios_print(file, "Invalid chunk_size, region_size, " + "thread_count, or region_count, %d\n", -EINVAL); + return -EINVAL; + } + + if (!(kcmd->cmd_flags & DMU_WRITE) || + !(kcmd->cmd_flags & DMU_READ)) { + kpios_print(file, "Invalid flags, minimally DMU_WRITE " + "and DMU_READ must be set, %d\n", -EINVAL); + return -EINVAL; + } + + if ((kcmd->cmd_flags & (DMU_WRITE_ZC | DMU_READ_ZC)) && + (kcmd->cmd_flags & DMU_VERIFY)) { + kpios_print(file, "Invalid flags, DMU_*_ZC incompatible " + "with DMU_VERIFY, used for performance analysis " + "only, %d\n", -EINVAL); + return -EINVAL; + } + + /* Opaque data on return contains structs of the following form: + * + * kpios_stat_t stats[]; + * stats[0] = run_args->stats; + * stats[1-N] = threads[N]->stats; + * stats[N+1-M] = regions[M]->stats; + * + * Where N is the number of threads, and M is the number of regions. + */ + size = (sizeof(kpios_stats_t) + + (kcmd->cmd_thread_count * sizeof(kpios_stats_t)) + + (kcmd->cmd_region_count * sizeof(kpios_stats_t))); + if (data_size < size) { + kpios_print(file, "Invalid size, command data buffer " + "size too small, (%d < %d)\n", data_size, size); + return -ENOSPC; + } + + rc = kpios_setup_run(&run_args, kcmd, file); + if (rc) + return rc; + + rc = kpios_threads_run(run_args); + kpios_remove_objects(run_args); + if (rc) + goto cleanup; + + if (stats) { + n = 1; + m = 1 + kcmd->cmd_thread_count; + stats[0] = run_args->stats; + + for (i = 0; i < kcmd->cmd_thread_count; i++) + stats[n+i] = run_args->threads[i]->stats; + + for (i = 0; i < kcmd->cmd_region_count; i++) + stats[m+i] = run_args->regions[i].stats; + } + +cleanup: + kpios_cleanup_run(run_args); + return rc; +} + +static int +kpios_open(struct inode *inode, struct file *file) +{ + unsigned int minor = iminor(inode); + kpios_info_t *info; + + if (minor >= KPIOS_MINORS) + return -ENXIO; + + info = (kpios_info_t *)kmem_alloc(sizeof(*info), KM_SLEEP); + if (info == NULL) + return -ENOMEM; + + spin_lock_init(&info->info_lock); + info->info_size = KPIOS_INFO_BUFFER_SIZE; + info->info_buffer = (char *)vmem_alloc(KPIOS_INFO_BUFFER_SIZE,KM_SLEEP); + if (info->info_buffer == NULL) { + kmem_free(info, sizeof(*info)); + return -ENOMEM; + } + + info->info_head = info->info_buffer; + file->private_data = (void *)info; + + return 0; +} + +static int +kpios_release(struct inode *inode, struct file *file) +{ + unsigned int minor = iminor(inode); + kpios_info_t *info = (kpios_info_t *)file->private_data; + + if (minor >= KPIOS_MINORS) + return -ENXIO; + + ASSERT(info); + ASSERT(info->info_buffer); + + vmem_free(info->info_buffer, KPIOS_INFO_BUFFER_SIZE); + kmem_free(info, sizeof(*info)); + + return 0; +} + +static int +kpios_buffer_clear(struct file *file, kpios_cfg_t *kcfg, unsigned long arg) +{ + kpios_info_t *info = (kpios_info_t *)file->private_data; + + ASSERT(info); + ASSERT(info->info_buffer); + + spin_lock(&info->info_lock); + memset(info->info_buffer, 0, info->info_size); + info->info_head = info->info_buffer; + spin_unlock(&info->info_lock); + + return 0; +} + +static int +kpios_buffer_size(struct file *file, kpios_cfg_t *kcfg, unsigned long arg) +{ + kpios_info_t *info = (kpios_info_t *)file->private_data; + char *buf; + int min, size, rc = 0; + + ASSERT(info); + ASSERT(info->info_buffer); + + spin_lock(&info->info_lock); + if (kcfg->cfg_arg1 > 0) { + + size = kcfg->cfg_arg1; + buf = (char *)vmem_alloc(size, KM_SLEEP); + if (buf == NULL) { + rc = -ENOMEM; + goto out; + } + + /* Zero fill and truncate contents when coping buffer */ + min = ((size < info->info_size) ? size : info->info_size); + memset(buf, 0, size); + memcpy(buf, info->info_buffer, min); + vmem_free(info->info_buffer, info->info_size); + info->info_size = size; + info->info_buffer = buf; + info->info_head = info->info_buffer; + } + + kcfg->cfg_rc1 = info->info_size; + + if (copy_to_user((struct kpios_cfg_t __user *)arg, kcfg, sizeof(*kcfg))) + rc = -EFAULT; +out: + spin_unlock(&info->info_lock); + + return rc; +} + +static int +kpios_ioctl_cfg(struct file *file, unsigned long arg) +{ + kpios_cfg_t kcfg; + int rc = 0; + + if (copy_from_user(&kcfg, (kpios_cfg_t *)arg, sizeof(kcfg))) + return -EFAULT; + + if (kcfg.cfg_magic != KPIOS_CFG_MAGIC) { + kpios_print(file, "Bad config magic 0x%x != 0x%x\n", + kcfg.cfg_magic, KPIOS_CFG_MAGIC); + return -EINVAL; + } + + switch (kcfg.cfg_cmd) { + case KPIOS_CFG_BUFFER_CLEAR: + /* cfg_arg1 - Unused + * cfg_rc1 - Unused + */ + rc = kpios_buffer_clear(file, &kcfg, arg); + break; + case KPIOS_CFG_BUFFER_SIZE: + /* cfg_arg1 - 0 - query size; >0 resize + * cfg_rc1 - Set to current buffer size + */ + rc = kpios_buffer_size(file, &kcfg, arg); + break; + default: + kpios_print(file, "Bad config command %d\n", + kcfg.cfg_cmd); + rc = -EINVAL; + break; + } + + return rc; +} + +static int +kpios_ioctl_cmd(struct file *file, unsigned long arg) +{ + kpios_cmd_t kcmd; + int rc = -EINVAL; + void *data = NULL; + + rc = copy_from_user(&kcmd, (kpios_cfg_t *)arg, sizeof(kcmd)); + if (rc) { + kpios_print(file, "Unable to copy command structure " + "from user to kernel memory, %d\n", rc); + return -EFAULT; + } + + if (kcmd.cmd_magic != KPIOS_CMD_MAGIC) { + kpios_print(file, "Bad command magic 0x%x != 0x%x\n", + kcmd.cmd_magic, KPIOS_CFG_MAGIC); + return -EINVAL; + } + + /* Allocate memory for any opaque data the caller needed to pass on */ + if (kcmd.cmd_data_size > 0) { + data = (void *)vmem_alloc(kcmd.cmd_data_size, KM_SLEEP); + if (data == NULL) { + kpios_print(file, "Unable to vmem_alloc() %ld " + "bytes for data buffer\n", + (long)kcmd.cmd_data_size); + return -ENOMEM; + } + + rc = copy_from_user(data, (void *)(arg + offsetof(kpios_cmd_t, + cmd_data_str)), kcmd.cmd_data_size); + if (rc) { + kpios_print(file, "Unable to copy data buffer " + "from user to kernel memory, %d\n", rc); + vmem_free(data, kcmd.cmd_data_size); + return -EFAULT; + } + } + + rc = kpios_do_one_run(file, &kcmd, kcmd.cmd_data_size, data); + + if (data != NULL) { + /* If the test failed do not print out the stats */ + if (rc) + goto cleanup; + + rc = copy_to_user((void *)(arg + offsetof(kpios_cmd_t, + cmd_data_str)), data, kcmd.cmd_data_size); + if (rc) { + kpios_print(file, "Unable to copy data buffer " + "from kernel to user memory, %d\n", rc); + rc = -EFAULT; + } + +cleanup: + vmem_free(data, kcmd.cmd_data_size); + } + + return rc; +} + +static int +kpios_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + unsigned int minor = iminor(file->f_dentry->d_inode); + int rc = 0; + + /* Ignore tty ioctls */ + if ((cmd & 0xffffff00) == ((int)'T') << 8) + return -ENOTTY; + + if (minor >= KPIOS_MINORS) + return -ENXIO; + + switch (cmd) { + case KPIOS_CFG: + rc = kpios_ioctl_cfg(file, arg); + break; + case KPIOS_CMD: + rc = kpios_ioctl_cmd(file, arg); + break; + default: + kpios_print(file, "Bad ioctl command %d\n", cmd); + rc = -EINVAL; + break; + } + + return rc; +} + +/* I'm not sure why you would want to write in to this buffer from + * user space since its principle use is to pass test status info + * back to the user space, but I don't see any reason to prevent it. + */ +static ssize_t +kpios_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + unsigned int minor = iminor(file->f_dentry->d_inode); + kpios_info_t *info = (kpios_info_t *)file->private_data; + int rc = 0; + + if (minor >= KPIOS_MINORS) + return -ENXIO; + + ASSERT(info); + ASSERT(info->info_buffer); + + spin_lock(&info->info_lock); + + /* Write beyond EOF */ + if (*ppos >= info->info_size) { + rc = -EFBIG; + goto out; + } + + /* Resize count if beyond EOF */ + if (*ppos + count > info->info_size) + count = info->info_size - *ppos; + + if (copy_from_user(info->info_buffer, buf, count)) { + rc = -EFAULT; + goto out; + } + + *ppos += count; + rc = count; +out: + spin_unlock(&info->info_lock); + return rc; +} + +static ssize_t +kpios_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + unsigned int minor = iminor(file->f_dentry->d_inode); + kpios_info_t *info = (kpios_info_t *)file->private_data; + int rc = 0; + + if (minor >= KPIOS_MINORS) + return -ENXIO; + + ASSERT(info); + ASSERT(info->info_buffer); + + spin_lock(&info->info_lock); + + /* Read beyond EOF */ + if (*ppos >= info->info_size) + goto out; + + /* Resize count if beyond EOF */ + if (*ppos + count > info->info_size) + count = info->info_size - *ppos; + + if (copy_to_user(buf, info->info_buffer + *ppos, count)) { + rc = -EFAULT; + goto out; + } + + *ppos += count; + rc = count; +out: + spin_unlock(&info->info_lock); + return rc; +} + +static loff_t kpios_seek(struct file *file, loff_t offset, int origin) +{ + unsigned int minor = iminor(file->f_dentry->d_inode); + kpios_info_t *info = (kpios_info_t *)file->private_data; + int rc = -EINVAL; + + if (minor >= KPIOS_MINORS) + return -ENXIO; + + ASSERT(info); + ASSERT(info->info_buffer); + + spin_lock(&info->info_lock); + + switch (origin) { + case 0: /* SEEK_SET - No-op just do it */ + break; + case 1: /* SEEK_CUR - Seek from current */ + offset = file->f_pos + offset; + break; + case 2: /* SEEK_END - Seek from end */ + offset = info->info_size + offset; + break; + } + + if (offset >= 0) { + file->f_pos = offset; + file->f_version = 0; + rc = offset; + } + + spin_unlock(&info->info_lock); + + return rc; +} + +static struct file_operations kpios_fops = { + .owner = THIS_MODULE, + .open = kpios_open, + .release = kpios_release, + .ioctl = kpios_ioctl, + .read = kpios_read, + .write = kpios_write, + .llseek = kpios_seek, +}; + +static struct cdev kpios_cdev = { + .owner = THIS_MODULE, + .kobj = { .name = "kpios", }, +}; + +static int __init +kpios_init(void) +{ + dev_t dev; + int rc; + + dev = MKDEV(KPIOS_MAJOR, 0); + if ((rc = register_chrdev_region(dev, KPIOS_MINORS, "kpios"))) + goto error; + + /* Support for registering a character driver */ + cdev_init(&kpios_cdev, &kpios_fops); + if ((rc = cdev_add(&kpios_cdev, dev, KPIOS_MINORS))) { + printk(KERN_ERR "kpios: Error adding cdev, %d\n", rc); + kobject_put(&kpios_cdev.kobj); + unregister_chrdev_region(dev, KPIOS_MINORS); + goto error; + } + + /* Support for udev make driver info available in sysfs */ + kpios_class = class_create(THIS_MODULE, "kpios"); + if (IS_ERR(kpios_class)) { + rc = PTR_ERR(kpios_class); + printk(KERN_ERR "kpios: Error creating kpios class, %d\n", rc); + cdev_del(&kpios_cdev); + unregister_chrdev_region(dev, KPIOS_MINORS); + goto error; + } + + class_device_create(kpios_class, NULL, dev, NULL, "kpios"); + + printk(KERN_INFO "kpios: Loaded Kernel PIOS Tests v%s\n", VERSION); + return 0; +error: + printk(KERN_ERR "kpios: Error registering kpios device, %d\n", rc); + return rc; +} + +static void +kpios_fini(void) +{ + dev_t dev = MKDEV(KPIOS_MAJOR, 0); + + class_device_destroy(kpios_class, dev); + class_destroy(kpios_class); + + cdev_del(&kpios_cdev); + unregister_chrdev_region(dev, KPIOS_MINORS); + + printk(KERN_INFO "kpios: Unloaded Kernel PIOS Tests\n"); + return; +} + +module_init(kpios_init); +module_exit(kpios_fini); + +MODULE_AUTHOR("LLNL / Sun"); +MODULE_DESCRIPTION("Kernel PIOS implementation"); +MODULE_LICENSE("GPL"); diff --git a/zfs/zcmd/Makefile.in b/zfs/zcmd/Makefile.in index 23720a5c77..276e3f73af 100644 --- a/zfs/zcmd/Makefile.in +++ b/zfs/zcmd/Makefile.in @@ -4,3 +4,4 @@ subdir-m += zpool #subdir-m += ztest #subdir-m += zdump #subdir-m += zinject +subdir-m += zpios diff --git a/zfs/zcmd/zpios/Makefile.in b/zfs/zcmd/zpios/Makefile.in new file mode 100644 index 0000000000..3d4421bb7d --- /dev/null +++ b/zfs/zcmd/zpios/Makefile.in @@ -0,0 +1,13 @@ +DISTFILES = Makefile.in *.c zpios.h + +CMD := zpios + +HOSTCFLAGS += @HOSTCFLAGS@ +HOSTCFLAGS += -I@CMDDIR@/lzpios +HOSTCFLAGS += -I@LIBDIR@/libzpios/include + +hostprogs-y := ${CMD} +always := $(hostprogs-y) + +${CMD}-objs += zpios_main.o +${CMD}-objs += zpios_util.o diff --git a/zfs/zcmd/zpios/zpios.h b/zfs/zcmd/zpios/zpios.h new file mode 100644 index 0000000000..01c2a9b6c6 --- /dev/null +++ b/zfs/zcmd/zpios/zpios.h @@ -0,0 +1,117 @@ +/* + * This file is part of the ZFS Linux port. + * + * Copyright (c) 2008 Lawrence Livermore National Security, LLC. + * Produced at Lawrence Livermore National Laboratory + * Written by: + * Brian Behlendorf , + * Herb Wartens , + * Jim Garlick + * LLNL-CODE-403049 + * + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#ifndef _ZPIOS_H +#define _ZPIOS_H + +#include + +#define VERSION_SIZE 64 + +/* Regular expressions */ +#define REGEX_NUMBERS "^[0-9]*[0-9]$" +#define REGEX_NUMBERS_COMMA "^([0-9]+,)*[0-9]+$" +#define REGEX_SIZE "^[0-9][0-9]*[kmgt]$" +#define REGEX_SIZE_COMMA "^([0-9][0-9]*[kmgt]+,)*[0-9][0-9]*[kmgt]$" + +/* Flags for low, high, incr */ +#define FLAG_SET 0x01 +#define FLAG_LOW 0x02 +#define FLAG_HIGH 0x04 +#define FLAG_INCR 0x08 + +#define TRUE 1 +#define FALSE 0 + +#define KB (1024) +#define MB (KB * 1024) +#define GB (MB * 1024) +#define TB (GB * 1024) + +/* All offsets, sizes and counts can be passed to the application in + * multiple ways. + * 1. a value (stored in val[0], val_count will be 1) + * 2. a comma separated list of values (stored in val[], using val_count) + * 3. a range and block sizes, low, high, factor (val_count must be 0) + */ +typedef struct pios_range_repeat { + uint64_t val[32]; /* Comma sep array, or low, high, inc */ + uint64_t val_count; /* Num of values */ + uint64_t val_low; + uint64_t val_high; + uint64_t val_inc_perc; + uint64_t next_val; /* Used for multiple runs in get_next() */ +} range_repeat_t; + +typedef struct cmd_args { + range_repeat_t T; /* Thread count */ + range_repeat_t N; /* Region count */ + range_repeat_t O; /* Offset count */ + range_repeat_t C; /* Chunksize */ + range_repeat_t S; /* Regionsize */ + + const char *pool; /* Pool */ + uint32_t flags; /* Flags */ + uint32_t io_type; /* DMUIO only */ + uint32_t verbose; /* Verbose */ + uint32_t human_readable; /* Human readable output */ + + uint64_t regionnoise; /* Region noise */ + uint64_t chunknoise; /* Chunk noise */ + uint64_t thread_delay; /* Thread delay */ + + char pre[KPIOS_PATH_SIZE]; /* Pre-exec hook */ + char post[KPIOS_PATH_SIZE]; /* Post-exec hook */ + char log[KPIOS_PATH_SIZE]; /* Requested log dir */ + + /* Control */ + int current_id; + uint64_t current_T; + uint64_t current_N; + uint64_t current_C; + uint64_t current_S; + uint64_t current_O; + + uint32_t rc; +} cmd_args_t; + +int set_count(char *pattern1, char *pattern2, range_repeat_t *range, + char *optarg, uint32_t *flags, char *arg); +int set_lhi(char *pattern, range_repeat_t *range, char *optarg, + int flag, uint32_t *flag_thread, char *arg); +int set_noise(uint64_t *noise, char *optarg, char *arg); +int set_load_params(cmd_args_t *args, char *optarg); +int check_mutual_exclusive_command_lines(uint32_t flag, char *arg); +void print_stats_header(void); +void print_stats(cmd_args_t *args, kpios_cmd_t *cmd); + +#endif /* _ZPIOS_H */ diff --git a/zfs/zcmd/zpios/zpios_main.c b/zfs/zcmd/zpios/zpios_main.c new file mode 100644 index 0000000000..e1e988680a --- /dev/null +++ b/zfs/zcmd/zpios/zpios_main.c @@ -0,0 +1,619 @@ +/* + * This file is part of the ZFS Linux port. + * + * Copyright (c) 2008 Lawrence Livermore National Security, LLC. + * Produced at Lawrence Livermore National Laboratory + * Written by: + * Brian Behlendorf , + * Herb Wartens , + * Jim Garlick + * LLNL-CODE-403049 + * + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Kernel PIOS DMU implemenation originally derived from PIOS test code. + * Character control interface derived from SPL code. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "zpios.h" + +static const char short_opt[] = "t:l:h:e:n:i:j:k:c:u:a:b:g:L:P:R:I:" + "G:T:Vzs:A:B:C:o:m:q:r:fwxdp:v?"; +static const struct option long_opt[] = { + {"chunksize", required_argument, 0, 'c' }, + {"chunksize_low", required_argument, 0, 'a' }, + {"chunksize_high", required_argument, 0, 'b' }, + {"chunksize_incr", required_argument, 0, 'g' }, + {"offset", required_argument, 0, 'o' }, + {"offset_low", required_argument, 0, 'm' }, + {"offset_high", required_argument, 0, 'q' }, + {"offset_incr", required_argument, 0, 'r' }, + {"regioncount", required_argument, 0, 'n' }, + {"regioncount_low", required_argument, 0, 'i' }, + {"regioncount_high", required_argument, 0, 'j' }, + {"regioncount_incr", required_argument, 0, 'k' }, + {"threadcount", required_argument, 0, 't' }, + {"threadcount_low", required_argument, 0, 'l' }, + {"threadcount_high", required_argument, 0, 'h' }, + {"threadcount_incr", required_argument, 0, 'e' }, + {"regionsize", required_argument, 0, 's' }, + {"regionsize_low", required_argument, 0, 'A' }, + {"regionsize_high", required_argument, 0, 'B' }, + {"regionsize_incr", required_argument, 0, 'C' }, + {"cleanup", no_argument, 0, 'x' }, + {"verify", no_argument, 0, 'V' }, + {"zerocopy", no_argument, 0, 'z' }, + {"threaddelay", required_argument, 0, 'T' }, + {"regionnoise", required_argument, 0, 'I' }, + {"chunknoise", required_argument, 0, 'N' }, + {"prerun", required_argument, 0, 'P' }, + {"postrun", required_argument, 0, 'R' }, + {"log", required_argument, 0, 'G' }, + {"path", required_argument, 0, 'p' }, + {"pool", required_argument, 0, 'p' }, + {"load", required_argument, 0, 'L' }, + {"human-readable", no_argument, 0, 'H' }, + {"help", no_argument, 0, '?' }, + {"verbose", no_argument, 0, 'v' }, + { 0, 0, 0, 0 }, +}; + +static int zpiosctl_fd; /* Control file descriptor */ +static char zpios_version[VERSION_SIZE]; /* Kernel version string */ +static char *zpios_buffer = NULL; /* Scratch space area */ +static int zpios_buffer_size = 0; /* Scratch space size */ + +static int +usage(void) +{ + fprintf(stderr, "Usage: zpios\n"); + fprintf(stderr, + " --chunksize -c =values\n" + " --chunksize_low -a =value\n" + " --chunksize_high -b =value\n" + " --chunksize_incr -g =value\n" + " --offset -o =values\n" + " --offset_low -m =value\n" + " --offset_high -q =value\n" + " --offset_incr -r =value\n" + " --regioncount -n =values\n" + " --regioncount_low -i =value\n" + " --regioncount_high -j =value\n" + " --regioncount_incr -k =value\n" + " --threadcount -t =values\n" + " --threadcount_low -l =value\n" + " --threadcount_high -h =value\n" + " --threadcount_incr -e =value\n" + " --regionsize -s =values\n" + " --regionsize_low -A =value\n" + " --regionsize_high -B =value\n" + " --regionsize_incr -C =value\n" + " --cleanup -x\n" + " --verify -V\n" + " --zerocopy -z\n" + " --threaddelay -T =jiffies\n" + " --regionnoise -I =shift\n" + " --chunknoise -N =bytes\n" + " --prerun -P =pre-command\n" + " --postrun -R =post-command\n" + " --log -G =log directory\n" + " --pool | --path -p =pool name\n" + " --load -L =dmuio\n" + " --human-readable -H\n" + " --help -? =this help\n" + " --verbose -v =increase verbosity\n\n"); + + return 0; +} + +static void args_fini(cmd_args_t *args) +{ + assert(args != NULL); + free(args); +} + +static cmd_args_t * +args_init(int argc, char **argv) +{ + cmd_args_t *args; + uint32_t fl_th = 0; + uint32_t fl_rc = 0; + uint32_t fl_of = 0; + uint32_t fl_rs = 0; + uint32_t fl_cs = 0; + int c, rc; + + if (argc == 1) { + usage(); + return (cmd_args_t *)NULL; + } + + /* Configure and populate the args structures */ + args = malloc(sizeof(*args)); + if (args == NULL) + return NULL; + + memset(args, 0, sizeof(*args)); + + while ((c=getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) { + rc = 0; + + switch (c) { + case 'v': /* --verbose */ + args->verbose++; + break; + case 't': /* --thread count */ + rc = set_count(REGEX_NUMBERS, REGEX_NUMBERS_COMMA, + &args->T, optarg, &fl_th, "threadcount"); + break; + case 'l': /* --threadcount_low */ + rc = set_lhi(REGEX_NUMBERS, &args->T, optarg, + FLAG_LOW, &fl_th, "threadcount_low"); + break; + case 'h': /* --threadcount_high */ + rc = set_lhi(REGEX_NUMBERS, &args->T, optarg, + FLAG_HIGH, &fl_th, "threadcount_high"); + break; + case 'e': /* --threadcount_inc */ + rc = set_lhi(REGEX_NUMBERS, &args->T, optarg, + FLAG_INCR, &fl_th, "threadcount_incr"); + break; + case 'n': /* --regioncount */ + rc = set_count(REGEX_NUMBERS, REGEX_NUMBERS_COMMA, + &args->N, optarg, &fl_rc, "regioncount"); + break; + case 'i': /* --regioncount_low */ + rc = set_lhi(REGEX_NUMBERS, &args->N, optarg, + FLAG_LOW, &fl_rc, "regioncount_low"); + break; + case 'j': /* --regioncount_high */ + rc = set_lhi(REGEX_NUMBERS, &args->N, optarg, + FLAG_HIGH, &fl_rc, "regioncount_high"); + break; + case 'k': /* --regioncount_inc */ + rc = set_lhi(REGEX_NUMBERS, &args->N, optarg, + FLAG_INCR, &fl_rc, "regioncount_incr"); + break; + case 'o': /* --offset */ + rc = set_count(REGEX_SIZE, REGEX_SIZE_COMMA, + &args->O, optarg, &fl_of, "offset"); + break; + case 'm': /* --offset_low */ + rc = set_lhi(REGEX_SIZE, &args->O, optarg, + FLAG_LOW, &fl_of, "offset_low"); + break; + case 'q': /* --offset_high */ + rc = set_lhi(REGEX_SIZE, &args->O, optarg, + FLAG_HIGH, &fl_of, "offset_high"); + break; + case 'r': /* --offset_inc */ + rc = set_lhi(REGEX_NUMBERS, &args->O, optarg, + FLAG_INCR, &fl_of, "offset_incr"); + break; + case 'c': /* --chunksize */ + rc = set_count(REGEX_SIZE, REGEX_SIZE_COMMA, + &args->C, optarg, &fl_cs, "chunksize"); + break; + case 'a': /* --chunksize_low */ + rc = set_lhi(REGEX_SIZE, &args->C, optarg, + FLAG_LOW, &fl_cs, "chunksize_low"); + break; + case 'b': /* --chunksize_high */ + rc = set_lhi(REGEX_SIZE, &args->C, optarg, + FLAG_HIGH, &fl_cs, "chunksize_high"); + break; + case 'g': /* --chunksize_inc */ + rc = set_lhi(REGEX_NUMBERS, &args->C, optarg, + FLAG_INCR, &fl_cs, "chunksize_incr"); + break; + case 's': /* --regionsize */ + rc = set_count(REGEX_SIZE, REGEX_SIZE_COMMA, + &args->S, optarg, &fl_rs, "regionsize"); + break; + case 'A': /* --regionsize_low */ + rc = set_lhi(REGEX_SIZE, &args->S, optarg, + FLAG_LOW, &fl_rs, "regionsize_low"); + break; + case 'B': /* --regionsize_high */ + rc = set_lhi(REGEX_SIZE, &args->S, optarg, + FLAG_HIGH, &fl_rs, "regionsize_high"); + break; + case 'C': /* --regionsize_inc */ + rc = set_lhi(REGEX_NUMBERS, &args->S, optarg, + FLAG_INCR, &fl_rs, "regionsize_incr"); + break; + case 'L': /* --load */ + rc = set_load_params(args, optarg); + break; + case 'p': /* --pool */ + args->pool = optarg; + break; + case 'x': /* --cleanup */ + args->flags |= DMU_REMOVE; + break; + case 'P': /* --prerun */ + strncpy(args->pre, optarg, KPIOS_PATH_SIZE - 1); + break; + case 'R': /* --postrun */ + strncpy(args->post, optarg, KPIOS_PATH_SIZE - 1); + break; + case 'G': /* --log */ + strncpy(args->log, optarg, KPIOS_PATH_SIZE - 1); + break; + case 'I': /* --regionnoise */ + rc = set_noise(&args->regionnoise, optarg, "regionnoise"); + break; + case 'N': /* --chunknoise */ + rc = set_noise(&args->chunknoise, optarg, "chunknoise"); + break; + case 'T': /* --threaddelay */ + rc = set_noise(&args->thread_delay, optarg, "threaddelay"); + break; + case 'V': /* --verify */ + args->flags |= DMU_VERIFY; + break; + case 'z': /* --verify */ + args->flags |= (DMU_WRITE_ZC | DMU_READ_ZC); + break; + case 'H': + args->human_readable = 1; + break; + case '?': + rc = 1; + break; + default: + fprintf(stderr,"Unknown option '%s'\n",argv[optind-1]); + rc = EINVAL; + break; + } + + if (rc) { + usage(); + args_fini(args); + return NULL; + } + } + + check_mutual_exclusive_command_lines(fl_th, "threadcount"); + check_mutual_exclusive_command_lines(fl_rc, "regioncount"); + check_mutual_exclusive_command_lines(fl_of, "offset"); + check_mutual_exclusive_command_lines(fl_rs, "regionsize"); + check_mutual_exclusive_command_lines(fl_cs, "chunksize"); + + if (args->pool == NULL) { + fprintf(stderr, "Error: Pool not specificed\n"); + usage(); + args_fini(args); + return NULL; + } + + if ((args->flags & (DMU_WRITE_ZC | DMU_READ_ZC)) && + (args->flags & DMU_VERIFY)) { + fprintf(stderr, "Error, --zerocopy incompatible --verify, " + "used for performance analysis only\n"); + usage(); + args_fini(args); + return NULL; + } + + return args; +} + +static int +dev_clear(void) +{ + kpios_cfg_t cfg; + int rc; + + memset(&cfg, 0, sizeof(cfg)); + cfg.cfg_magic = KPIOS_CFG_MAGIC; + cfg.cfg_cmd = KPIOS_CFG_BUFFER_CLEAR; + cfg.cfg_arg1 = 0; + + rc = ioctl(zpiosctl_fd, KPIOS_CFG, &cfg); + if (rc) + fprintf(stderr, "Ioctl() error %lu / %d: %d\n", + (unsigned long) KPIOS_CFG, cfg.cfg_cmd, errno); + + lseek(zpiosctl_fd, 0, SEEK_SET); + + return rc; +} + +/* Passing a size of zero simply results in querying the current size */ +static int +dev_size(int size) +{ + kpios_cfg_t cfg; + int rc; + + memset(&cfg, 0, sizeof(cfg)); + cfg.cfg_magic = KPIOS_CFG_MAGIC; + cfg.cfg_cmd = KPIOS_CFG_BUFFER_SIZE; + cfg.cfg_arg1 = size; + + rc = ioctl(zpiosctl_fd, KPIOS_CFG, &cfg); + if (rc) { + fprintf(stderr, "Ioctl() error %lu / %d: %d\n", + (unsigned long) KPIOS_CFG, cfg.cfg_cmd, errno); + return rc; + } + + return cfg.cfg_rc1; +} + +static void +dev_fini(void) +{ + if (zpios_buffer) + free(zpios_buffer); + + if (zpiosctl_fd != -1) { + if (close(zpiosctl_fd) == -1) { + fprintf(stderr, "Unable to close %s: %d\n", + KPIOS_DEV, errno); + } + } +} + +static int +dev_init(void) +{ + int rc; + + zpiosctl_fd = open(KPIOS_DEV, O_RDONLY); + if (zpiosctl_fd == -1) { + fprintf(stderr, "Unable to open %s: %d\n" + "Is the zpios module loaded?\n", KPIOS_DEV, errno); + rc = errno; + goto error; + } + + if ((rc = dev_clear())) + goto error; + + if ((rc = dev_size(0)) < 0) + goto error; + + zpios_buffer_size = rc; + zpios_buffer = (char *)malloc(zpios_buffer_size); + if (zpios_buffer == NULL) { + rc = ENOMEM; + goto error; + } + + memset(zpios_buffer, 0, zpios_buffer_size); + return 0; +error: + if (zpiosctl_fd != -1) { + if (close(zpiosctl_fd) == -1) { + fprintf(stderr, "Unable to close %s: %d\n", + KPIOS_DEV, errno); + } + } + + return rc; +} + +static int +get_next(uint64_t *val, range_repeat_t *range) +{ + int i; + + /* if low, incr, high is given */ + if (range->val_count == 0) { + *val = (range->val_low) + + (range->val_low * range->next_val / 100); + + if (*val > range->val_high) + return 0; /* No more values, limit exceeded */ + + if (!range->next_val) + range->next_val = range->val_inc_perc; + else + range->next_val = range->next_val+range->val_inc_perc; + + return 1; /* more values to come */ + + /* if only one val is given */ + } else if (range->val_count == 1) { + if (range->next_val) + return 0; /* No more values, we only have one */ + + *val = range->val[0]; + range->next_val = 1; + return 1; /* more values to come */ + + /* if comma separated values are given */ + } else if (range->val_count > 1) { + if (range->next_val > range->val_count - 1) + return 0; /* No more values, limit exceeded */ + + *val = range->val[range->next_val]; + range->next_val++; + return 1; /* more values to come */ + } + + return 0; +} + +static int +run_one(cmd_args_t *args, uint32_t id, uint32_t T, uint32_t N, + uint64_t C, uint64_t S, uint64_t O) +{ + kpios_cmd_t *cmd; + int rc, rc2, cmd_size; + + dev_clear(); + + cmd_size = sizeof(kpios_cmd_t) + ((T + N + 1) * sizeof(kpios_stats_t)); + cmd = (kpios_cmd_t *)malloc(cmd_size); + if (cmd == NULL) + return ENOMEM; + + memset(cmd, 0, cmd_size); + cmd->cmd_magic = KPIOS_CMD_MAGIC; + strncpy(cmd->cmd_pool, args->pool, KPIOS_NAME_SIZE - 1); + strncpy(cmd->cmd_pre, args->pre, KPIOS_PATH_SIZE - 1); + strncpy(cmd->cmd_post, args->post, KPIOS_PATH_SIZE - 1); + strncpy(cmd->cmd_log, args->log, KPIOS_PATH_SIZE - 1); + cmd->cmd_id = id; + cmd->cmd_chunk_size = C; + cmd->cmd_thread_count = T; + cmd->cmd_region_count = N; + cmd->cmd_region_size = S; + cmd->cmd_offset = O; + cmd->cmd_region_noise = args->regionnoise; + cmd->cmd_chunk_noise = args->chunknoise; + cmd->cmd_thread_delay = args->thread_delay; + cmd->cmd_flags = args->flags; + cmd->cmd_data_size = (T + N + 1) * sizeof(kpios_stats_t); + + rc = ioctl(zpiosctl_fd, KPIOS_CMD, cmd); + if (rc) + args->rc = errno; + + print_stats(args, cmd); + + if (args->verbose) { + rc2 = read(zpiosctl_fd, zpios_buffer, zpios_buffer_size - 1); + if (rc2 < 0) { + fprintf(stdout, "Error reading results: %d\n", rc2); + } else if ((rc2 > 0) && (strlen(zpios_buffer) > 0)) { + fprintf(stdout, "\n%s\n", zpios_buffer); + fflush(stdout); + } + } + + free(cmd); + + return rc; +} + +static int +run_offsets(cmd_args_t *args) +{ + int rc = 0; + + while (rc == 0 && get_next(&args->current_O, &args->O)) { + rc = run_one(args, args->current_id, + args->current_T, args->current_N, args->current_C, + args->current_S, args->current_O); + args->current_id++; + } + + args->O.next_val = 0; + return rc; +} + +static int +run_region_counts(cmd_args_t *args) +{ + int rc = 0; + + while (rc == 0 && get_next((uint64_t *)&args->current_N, &args->N)) + rc = run_offsets(args); + + args->N.next_val = 0; + return rc; +} + +static int +run_region_sizes(cmd_args_t *args) +{ + int rc = 0; + + while (rc == 0 && get_next(&args->current_S, &args->S)) { + if (args->current_S < args->current_C) { + fprintf(stderr, "Error: in any run chunksize can " + "not be smaller than regionsize.\n"); + return EINVAL; + } + + rc = run_region_counts(args); + } + + args->S.next_val = 0; + return rc; +} + +static int +run_chunk_sizes(cmd_args_t *args) +{ + int rc = 0; + + while (rc == 0 && get_next(&args->current_C, &args->C)) { + rc = run_region_sizes(args); + } + + args->C.next_val = 0; + return rc; +} + +static int +run_thread_counts(cmd_args_t *args) +{ + int rc = 0; + + while (rc == 0 && get_next((uint64_t *)&args->current_T, &args->T)) + rc = run_chunk_sizes(args); + + return rc; +} + +int +main(int argc, char **argv) +{ + cmd_args_t *args; + int rc = 0; + + /* Argument init and parsing */ + if ((args = args_init(argc, argv)) == NULL) { + rc = -1; + goto out; + } + + /* Device specific init */ + if ((rc = dev_init())) + goto out; + + /* Generic kernel version string */ + if (args->verbose) + fprintf(stdout, "%s", zpios_version); + + print_stats_header(); + rc = run_thread_counts(args); +out: + if (args != NULL) + args_fini(args); + + dev_fini(); + return rc; +} diff --git a/zfs/zcmd/zpios/zpios_util.c b/zfs/zcmd/zpios/zpios_util.c new file mode 100644 index 0000000000..4d7e52d648 --- /dev/null +++ b/zfs/zcmd/zpios/zpios_util.c @@ -0,0 +1,440 @@ +/* + * This file is part of the ZFS Linux port. + * + * Copyright (c) 2008 Lawrence Livermore National Security, LLC. + * Produced at Lawrence Livermore National Laboratory + * Written by: + * Brian Behlendorf , + * Herb Wartens , + * Jim Garlick + * LLNL-CODE-403049 + * + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Kernel PIOS DMU implemenation originally derived from PIOS test code. + * Character control interface derived from SPL code. + */ + +#include +#include +#include +#include +#include +#include +#include "zpios.h" + +/* extracts an unsigned int (64) and K,M,G,T from the string */ +/* and returns a 64 bit value converted to the proper units */ +static int +kmgt_to_uint64(const char *str, uint64_t *val) +{ + char *endptr; + int rc = 0; + + *val = strtoll(str, &endptr, 0); + if ((str == endptr) && (*val == 0)) + return EINVAL; + + switch (endptr[0]) { + case 'k': case 'K': + *val = (*val) << 10; + break; + case 'm': case 'M': + *val = (*val) << 20; + break; + case 'g': case 'G': + *val = (*val) << 30; + break; + case 't': case 'T': + *val = (*val) << 40; + break; + case '\0': + break; + default: + rc = EINVAL; + } + + return rc; +} + +static char * +uint64_to_kmgt(char *str, uint64_t val) +{ + char postfix[] = "kmgt"; + int i = -1; + + while ((val >= KB) && (i < 4)) { + val = (val >> 10); + i++; + } + + if (i >= 4) + sprintf(str, "inf"); + else + sprintf(str, "%lu%c", (unsigned long)val, + (i == -1) ? '\0' : postfix[i]); + + return str; +} + +static char * +kmgt_per_sec(char *str, uint64_t v, double t) +{ + char postfix[] = "kmgt"; + double val = ((double)v) / t; + int i = -1; + + while ((val >= (double)KB) && (i < 4)) { + val /= (double)KB; + i++; + } + + if (i >= 4) + sprintf(str, "inf"); + else + sprintf(str, "%.2f%c", val, + (i == -1) ? '\0' : postfix[i]); + + return str; +} + +static char * +print_flags(char *str, uint32_t flags) +{ + str[0] = (flags & DMU_WRITE) ? 'w' : '-'; + str[1] = (flags & DMU_READ) ? 'r' : '-'; + str[2] = (flags & DMU_VERIFY) ? 'v' : '-'; + str[3] = (flags & DMU_REMOVE) ? 'c' : '-'; + str[4] = (flags & DMU_FPP) ? 'p' : 's'; + str[5] = (flags & (DMU_WRITE_ZC | DMU_READ_ZC)) ? 'z' : '-'; + str[6] = '\0'; + + return str; +} + +static double +timespec_to_double(struct timespec t) +{ + return ((double)(t.tv_sec) + + ((double)(t.tv_nsec) / (double)(1000*1000*1000))); +} + +static int +regex_match(const char *string, char *pattern) +{ + regex_t re; + int rc; + + rc = regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB | REG_ICASE); + if (rc) { + fprintf(stderr, "Error: Couldn't do regcomp, %d\n", rc); + return rc; + } + + rc = regexec(&re, string, (size_t) 0, NULL, 0); + regfree(&re); + + return rc; +} + +/* fills the pios_range_repeat structure of comma separated values */ +static int +split_string(const char *optarg, char *pattern, range_repeat_t *range) +{ + const char comma[] = ","; + char *cp, *token[32]; + int rc, i = 0; + + if ((rc = regex_match(optarg, pattern))) + return rc; + + cp = strdup(optarg); + if (cp == NULL) + return ENOMEM; + + do { + /* STRTOK(3) Each subsequent call, with a null pointer as the + * value of the * first argument, starts searching from the + * saved pointer and behaves as described above. + */ + token[i] = strtok(cp, comma); + cp = NULL; + } while ((token[i++] != NULL) && (i < 32)); + + range->val_count = i - 1; + + for (i = 0; i < range->val_count; i++) + kmgt_to_uint64(token[i], &range->val[i]); + + free(cp); + return 0; +} + +int +set_count(char *pattern1, char *pattern2, range_repeat_t *range, + char *optarg, uint32_t *flags, char *arg) +{ + if (flags) + *flags |= FLAG_SET; + + range->next_val = 0; + + if (regex_match(optarg, pattern1) == 0) { + kmgt_to_uint64(optarg, &range->val[0]); + range->val_count = 1; + } else if (split_string(optarg, pattern2, range) < 0) { + fprintf(stderr, "Error: Incorrect pattern for %s, '%s'\n", + arg, optarg); + return EINVAL; + } + + return 0; +} + +/* validates the value with regular expression and sets low, high, incr + * according to value at which flag will be set. Sets the flag after. */ +int +set_lhi(char *pattern, range_repeat_t *range, char *optarg, + int flag, uint32_t *flag_thread, char *arg) +{ + int rc; + + if ((rc = regex_match(optarg, pattern))) { + fprintf(stderr, "Error: Wrong pattern in %s, '%s'\n", + arg, optarg); + return rc; + } + + switch (flag) { + case FLAG_LOW: + kmgt_to_uint64(optarg, &range->val_low); + break; + case FLAG_HIGH: + kmgt_to_uint64(optarg, &range->val_high); + break; + case FLAG_INCR: + kmgt_to_uint64(optarg, &range->val_inc_perc); + break; + default: + assert(0); + } + + *flag_thread |= flag; + + return 0; +} + +int +set_noise(uint64_t *noise, char *optarg, char *arg) +{ + if (regex_match(optarg, REGEX_NUMBERS) == 0) { + kmgt_to_uint64(optarg, noise); + } else { + fprintf(stderr, "Error: Incorrect pattern for %s\n", arg); + return EINVAL; + } + + return 0; +} + +int +set_load_params(cmd_args_t *args, char *optarg) +{ + char *param, *search, comma[] = ","; + int rc = 0; + + search = strdup(optarg); + if (search == NULL) + return ENOMEM; + + while ((param = strtok(search, comma)) != NULL) { + search = NULL; + + if (strcmp("fpp", param) == 0) { + args->flags |= DMU_FPP; /* File Per Process/Thread */ + } else if (strcmp("sff", param) == 0) { + args->flags &= ~DMU_FPP; /* Shared Shared File */ + } else if (strcmp("dmuio", param) == 0) { + args->io_type |= DMU_IO; + args->flags |= (DMU_WRITE | DMU_READ); + } else { + fprintf(stderr, "Invalid load: %s\n", param); + rc = EINVAL; + } + } + + free(search); + + return rc; +} + + +/* checks the low, high, increment values against the single value for + * mutual exclusion, for e.g threadcount is mutually exclusive to + * threadcount_low, ..._high, ..._incr */ +int +check_mutual_exclusive_command_lines(uint32_t flag, char *arg) +{ + if ((flag & FLAG_SET) && (flag & (FLAG_LOW | FLAG_HIGH | FLAG_INCR))) { + fprintf(stderr, "Error: --%s can not be given with --%s_low, " + "--%s_high or --%s_incr.\n", arg, arg, arg, arg); + return 0; + } + + if ((flag & (FLAG_LOW | FLAG_HIGH | FLAG_INCR)) && !(flag & FLAG_SET)) { + if (flag != (FLAG_LOW | FLAG_HIGH | FLAG_INCR)) { + fprintf(stderr, "Error: One or more values missing " + "from --%s_low, --%s_high, --%s_incr.\n", + arg, arg, arg); + return 0; + } + } + + return 1; +} + +void +print_stats_header(void) +{ + printf("ret-code id\tth-cnt\trg-cnt\trg-sz\tch-sz\toffset\trg-no\tch-no\t" + "th-dly\tflags\ttime\tcr-time\trm-time\twr-time\t" + "rd-time\twr-data\twr-ch\twr-bw\trd-data\trd-ch\trd-bw\n"); + printf("------------------------------------------------------------" + "------------------------------------------------------------" + "-----------------------------------------------------------\n"); +} + +static void +print_stats_human_readable(cmd_args_t *args, kpios_cmd_t *cmd) +{ + kpios_stats_t *summary_stats; + double t_time, wr_time, rd_time, cr_time, rm_time; + char str[16]; + + if (args->rc) + printf("FAILED: %3d ", args->rc); + else + printf("PASSED: %3d ", args->rc); + + printf("%u\t", cmd->cmd_id); + printf("%u\t", cmd->cmd_thread_count); + printf("%u\t", cmd->cmd_region_count); + printf("%s\t", uint64_to_kmgt(str, cmd->cmd_region_size)); + printf("%s\t", uint64_to_kmgt(str, cmd->cmd_chunk_size)); + printf("%s\t", uint64_to_kmgt(str, cmd->cmd_offset)); + printf("%s\t", uint64_to_kmgt(str, cmd->cmd_region_noise)); + printf("%s\t", uint64_to_kmgt(str, cmd->cmd_chunk_noise)); + printf("%s\t", uint64_to_kmgt(str, cmd->cmd_thread_delay)); + printf("%s\t", print_flags(str, cmd->cmd_flags)); + + if (args->rc) { + printf("\n"); + return; + } + + summary_stats = (kpios_stats_t *)cmd->cmd_data_str; + t_time = timespec_to_double(summary_stats->total_time.delta); + wr_time = timespec_to_double(summary_stats->wr_time.delta); + rd_time = timespec_to_double(summary_stats->rd_time.delta); + cr_time = timespec_to_double(summary_stats->cr_time.delta); + rm_time = timespec_to_double(summary_stats->rm_time.delta); + + printf("%.2f\t", t_time); + printf("%.3f\t", cr_time); + printf("%.3f\t", rm_time); + printf("%.2f\t", wr_time); + printf("%.2f\t", rd_time); + + printf("%s\t", uint64_to_kmgt(str, summary_stats->wr_data)); + printf("%s\t", uint64_to_kmgt(str, summary_stats->wr_chunks)); + printf("%s\t", kmgt_per_sec(str, summary_stats->wr_data, wr_time)); + + printf("%s\t", uint64_to_kmgt(str, summary_stats->rd_data)); + printf("%s\t", uint64_to_kmgt(str, summary_stats->rd_chunks)); + printf("%s\n", kmgt_per_sec(str, summary_stats->rd_data, rd_time)); + fflush(stdout); +} + +static void +print_stats_table(cmd_args_t *args, kpios_cmd_t *cmd) +{ + kpios_stats_t *summary_stats; + double wr_time, rd_time; + + if (args->rc) + printf("FAILED: %3d ", args->rc); + else + printf("PASSED: %3d ", args->rc); + + printf("%u\t", cmd->cmd_id); + printf("%u\t", cmd->cmd_thread_count); + printf("%u\t", cmd->cmd_region_count); + printf("%llu\t", (long long unsigned)cmd->cmd_region_size); + printf("%llu\t", (long long unsigned)cmd->cmd_chunk_size); + printf("%llu\t", (long long unsigned)cmd->cmd_offset); + printf("%u\t", cmd->cmd_region_noise); + printf("%u\t", cmd->cmd_chunk_noise); + printf("%u\t", cmd->cmd_thread_delay); + printf("0x%x\t", cmd->cmd_flags); + + if (args->rc) { + printf("\n"); + return; + } + + summary_stats = (kpios_stats_t *)cmd->cmd_data_str; + wr_time = timespec_to_double(summary_stats->wr_time.delta); + rd_time = timespec_to_double(summary_stats->rd_time.delta); + + printf("%ld.%02ld\t", + summary_stats->total_time.delta.tv_sec, + summary_stats->total_time.delta.tv_nsec); + printf("%ld.%02ld\t", + summary_stats->cr_time.delta.tv_sec, + summary_stats->cr_time.delta.tv_nsec); + printf("%ld.%02ld\t", + summary_stats->rm_time.delta.tv_sec, + summary_stats->rm_time.delta.tv_nsec); + printf("%ld.%02ld\t", + summary_stats->wr_time.delta.tv_sec, + summary_stats->wr_time.delta.tv_nsec); + printf("%ld.%02ld\t", + summary_stats->rd_time.delta.tv_sec, + summary_stats->rd_time.delta.tv_nsec); + + printf("%lld\t", (long long unsigned)summary_stats->wr_data); + printf("%lld\t", (long long unsigned)summary_stats->wr_chunks); + printf("%.4f\t", (double)summary_stats->wr_data / wr_time); + + printf("%lld\t", (long long unsigned)summary_stats->rd_data); + printf("%lld\t", (long long unsigned)summary_stats->rd_chunks); + printf("%.4f\n", (double)summary_stats->rd_data / rd_time); + fflush(stdout); +} + +void +print_stats(cmd_args_t *args, kpios_cmd_t *cmd) +{ + if (args->human_readable) + print_stats_human_readable(args, cmd); + else + print_stats_table(args, cmd); +} From fc5f5929e73f29a7cc02491155e60e9e8c62e552 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Thu, 11 Dec 2008 15:17:33 -0800 Subject: [PATCH 02/45] move zpios to the correct dirs --- {zfs/zcmd => cmd}/zpios/zpios.h | 0 {zfs/zcmd => cmd}/zpios/zpios_main.c | 0 {zfs/zcmd => cmd}/zpios/zpios_util.c | 0 configure.ac | 1 + module/Makefile.in | 2 +- {zfs/lib/libzpios => module/zpios}/Makefile.in | 0 .../libzpios => module/zpios}/include/Makefile.in | 0 .../libzpios => module/zpios}/include/kpios-ctl.h | 0 .../zpios}/include/kpios-internal.h | 0 {zfs/lib/libzpios => module/zpios}/kpios.c | 0 zfs/zcmd/zpios/Makefile.in | 13 ------------- 11 files changed, 2 insertions(+), 14 deletions(-) rename {zfs/zcmd => cmd}/zpios/zpios.h (100%) rename {zfs/zcmd => cmd}/zpios/zpios_main.c (100%) rename {zfs/zcmd => cmd}/zpios/zpios_util.c (100%) rename {zfs/lib/libzpios => module/zpios}/Makefile.in (100%) rename {zfs/lib/libzpios => module/zpios}/include/Makefile.in (100%) rename {zfs/lib/libzpios => module/zpios}/include/kpios-ctl.h (100%) rename {zfs/lib/libzpios => module/zpios}/include/kpios-internal.h (100%) rename {zfs/lib/libzpios => module/zpios}/kpios.c (100%) delete mode 100644 zfs/zcmd/zpios/Makefile.in diff --git a/zfs/zcmd/zpios/zpios.h b/cmd/zpios/zpios.h similarity index 100% rename from zfs/zcmd/zpios/zpios.h rename to cmd/zpios/zpios.h diff --git a/zfs/zcmd/zpios/zpios_main.c b/cmd/zpios/zpios_main.c similarity index 100% rename from zfs/zcmd/zpios/zpios_main.c rename to cmd/zpios/zpios_main.c diff --git a/zfs/zcmd/zpios/zpios_util.c b/cmd/zpios/zpios_util.c similarity index 100% rename from zfs/zcmd/zpios/zpios_util.c rename to cmd/zpios/zpios_util.c diff --git a/configure.ac b/configure.ac index 2400bb47d9..c68e80da73 100644 --- a/configure.ac +++ b/configure.ac @@ -120,5 +120,6 @@ AC_CONFIG_FILES([ Makefile cmd/zinject/Makefile cmd/zpool/Makefile cmd/ztest/Makefile + cmd/zpios/Makefile ]) AC_OUTPUT diff --git a/module/Makefile.in b/module/Makefile.in index 031d97adfc..f93b196b07 100644 --- a/module/Makefile.in +++ b/module/Makefile.in @@ -1,4 +1,4 @@ -subdir-m = avl nvpair zcommon zfs +subdir-m = avl nvpair zcommon zfs zpios # Make the exported SPL symbols available to these modules. # Unfortunately there is not a cleaner way to do this, modpost diff --git a/zfs/lib/libzpios/Makefile.in b/module/zpios/Makefile.in similarity index 100% rename from zfs/lib/libzpios/Makefile.in rename to module/zpios/Makefile.in diff --git a/zfs/lib/libzpios/include/Makefile.in b/module/zpios/include/Makefile.in similarity index 100% rename from zfs/lib/libzpios/include/Makefile.in rename to module/zpios/include/Makefile.in diff --git a/zfs/lib/libzpios/include/kpios-ctl.h b/module/zpios/include/kpios-ctl.h similarity index 100% rename from zfs/lib/libzpios/include/kpios-ctl.h rename to module/zpios/include/kpios-ctl.h diff --git a/zfs/lib/libzpios/include/kpios-internal.h b/module/zpios/include/kpios-internal.h similarity index 100% rename from zfs/lib/libzpios/include/kpios-internal.h rename to module/zpios/include/kpios-internal.h diff --git a/zfs/lib/libzpios/kpios.c b/module/zpios/kpios.c similarity index 100% rename from zfs/lib/libzpios/kpios.c rename to module/zpios/kpios.c diff --git a/zfs/zcmd/zpios/Makefile.in b/zfs/zcmd/zpios/Makefile.in deleted file mode 100644 index 3d4421bb7d..0000000000 --- a/zfs/zcmd/zpios/Makefile.in +++ /dev/null @@ -1,13 +0,0 @@ -DISTFILES = Makefile.in *.c zpios.h - -CMD := zpios - -HOSTCFLAGS += @HOSTCFLAGS@ -HOSTCFLAGS += -I@CMDDIR@/lzpios -HOSTCFLAGS += -I@LIBDIR@/libzpios/include - -hostprogs-y := ${CMD} -always := $(hostprogs-y) - -${CMD}-objs += zpios_main.o -${CMD}-objs += zpios_util.o From bc1ce928f6c7edf1e829c596943c58865fde40c0 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Fri, 12 Dec 2008 08:57:54 -0800 Subject: [PATCH 03/45] Add makefiles --- cmd/Makefile.am | 2 +- cmd/zpios/Makefile.am | 8 ++++++++ module/zpios/Makefile.in | 9 +-------- 3 files changed, 10 insertions(+), 9 deletions(-) create mode 100644 cmd/zpios/Makefile.am diff --git a/cmd/Makefile.am b/cmd/Makefile.am index 30d3701c3f..b94adce038 100644 --- a/cmd/Makefile.am +++ b/cmd/Makefile.am @@ -1 +1 @@ -SUBDIRS = zdb zdump zfs zinject zpool ztest +SUBDIRS = zdb zdump zfs zinject zpool ztest zpios diff --git a/cmd/zpios/Makefile.am b/cmd/zpios/Makefile.am new file mode 100644 index 0000000000..94a218d679 --- /dev/null +++ b/cmd/zpios/Makefile.am @@ -0,0 +1,8 @@ +include $(top_srcdir)/config/Rules.am + +sbin_PROGRAMS = zpios + +zpios_SOURCES = \ + zpios.h \ + zpios_main.c \ + zpios_util.c diff --git a/module/zpios/Makefile.in b/module/zpios/Makefile.in index 2aa1482a8d..a6584b4aee 100644 --- a/module/zpios/Makefile.in +++ b/module/zpios/Makefile.in @@ -2,15 +2,8 @@ DISTFILES = Makefile.in *.c MODULE := zpios -# Compile as kernel module. Needed symlinks created for all -# k* objects created by top level configure script. - EXTRA_CFLAGS = @KERNELCPPFLAGS@ -EXTRA_CFLAGS += -I@LIBDIR@/libzpios/include -EXTRA_CFLAGS += -I@LIBDIR@/libzcommon/include -EXTRA_CFLAGS += -I@LIBDIR@/libport/include -EXTRA_CFLAGS += -I@LIBDIR@/libavl/include -EXTRA_CFLAGS += -I@LIBDIR@/libnvpair/include +EXTRA_CFLAGS += -I@MODDIR@/zpios/include obj-m := ${MODULE}.o From 56f1015f8b7494048d887a7575907b305b85c336 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Fri, 12 Dec 2008 09:32:53 -0800 Subject: [PATCH 04/45] Refresh Makefile.am --- cmd/zpios/Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/zpios/Makefile.am b/cmd/zpios/Makefile.am index 94a218d679..91029dbe70 100644 --- a/cmd/zpios/Makefile.am +++ b/cmd/zpios/Makefile.am @@ -3,6 +3,6 @@ include $(top_srcdir)/config/Rules.am sbin_PROGRAMS = zpios zpios_SOURCES = \ - zpios.h \ - zpios_main.c \ - zpios_util.c + $(top_srcdir)/cmd/zpios/zpios.h \ + $(top_srcdir)/cmd/zpios/zpios_main.c \ + $(top_srcdir)/cmd/zpios/zpios_util.c From fe119cee5788fef8e721d7442c6cae651118d94a Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 23 Dec 2008 09:24:19 -0800 Subject: [PATCH 05/45] Minor zpios cleanup --- cmd/zpios/Makefile.am | 6 ++++++ cmd/zpios/zpios.h | 2 +- module/zpios/include/Makefile.in | 2 +- module/zpios/include/{kpios-ctl.h => zpios-ctl.h} | 0 module/zpios/include/{kpios-internal.h => zpios-internal.h} | 2 +- module/zpios/{kpios.c => zpios.c} | 2 +- 6 files changed, 10 insertions(+), 4 deletions(-) rename module/zpios/include/{kpios-ctl.h => zpios-ctl.h} (100%) rename module/zpios/include/{kpios-internal.h => zpios-internal.h} (99%) rename module/zpios/{kpios.c => zpios.c} (99%) diff --git a/cmd/zpios/Makefile.am b/cmd/zpios/Makefile.am index 91029dbe70..95c9d0f306 100644 --- a/cmd/zpios/Makefile.am +++ b/cmd/zpios/Makefile.am @@ -1,5 +1,11 @@ include $(top_srcdir)/config/Rules.am +DEFAULT_INCLUDES += \ + -I${top_srcdir}/module/zpios/include \ + -I${top_srcdir}/module/zfs \ + -I${top_srcdir}/module/zfs/include \ + -I${top_srcdir}/module/zcommon/include + sbin_PROGRAMS = zpios zpios_SOURCES = \ diff --git a/cmd/zpios/zpios.h b/cmd/zpios/zpios.h index 01c2a9b6c6..ca21188296 100644 --- a/cmd/zpios/zpios.h +++ b/cmd/zpios/zpios.h @@ -33,7 +33,7 @@ #ifndef _ZPIOS_H #define _ZPIOS_H -#include +#include #define VERSION_SIZE 64 diff --git a/module/zpios/include/Makefile.in b/module/zpios/include/Makefile.in index 20e4bd7c9d..3aa71bfa19 100644 --- a/module/zpios/include/Makefile.in +++ b/module/zpios/include/Makefile.in @@ -1 +1 @@ -DISTFILES = kpios-ctl.h kpios-internal.h +DISTFILES = zpios-ctl.h zpios-internal.h diff --git a/module/zpios/include/kpios-ctl.h b/module/zpios/include/zpios-ctl.h similarity index 100% rename from module/zpios/include/kpios-ctl.h rename to module/zpios/include/zpios-ctl.h diff --git a/module/zpios/include/kpios-internal.h b/module/zpios/include/zpios-internal.h similarity index 99% rename from module/zpios/include/kpios-internal.h rename to module/zpios/include/zpios-internal.h index 3da1fe3823..5fecd81ab5 100644 --- a/module/zpios/include/kpios-internal.h +++ b/module/zpios/include/zpios-internal.h @@ -33,7 +33,7 @@ #ifndef _KPIOS_INTERNAL_H #define _KPIOS_INTERNAL_H -#include "kpios-ctl.h" +#include "zpios-ctl.h" #define OBJ_SIZE 64 diff --git a/module/zpios/kpios.c b/module/zpios/zpios.c similarity index 99% rename from module/zpios/kpios.c rename to module/zpios/zpios.c index a6493d8d50..2ba81860ee 100644 --- a/module/zpios/kpios.c +++ b/module/zpios/zpios.c @@ -37,7 +37,7 @@ #include #include #include -#include "kpios-internal.h" +#include "zpios-internal.h" static struct class *kpios_class; From 2475a871b0d6aad42329afbd2d6328fb323d1eed Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 23 Dec 2008 09:42:55 -0800 Subject: [PATCH 06/45] Minimal include set --- cmd/zpios/Makefile.am | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cmd/zpios/Makefile.am b/cmd/zpios/Makefile.am index 95c9d0f306..4e13a76c9e 100644 --- a/cmd/zpios/Makefile.am +++ b/cmd/zpios/Makefile.am @@ -1,14 +1,12 @@ include $(top_srcdir)/config/Rules.am DEFAULT_INCLUDES += \ - -I${top_srcdir}/module/zpios/include \ - -I${top_srcdir}/module/zfs \ - -I${top_srcdir}/module/zfs/include \ - -I${top_srcdir}/module/zcommon/include + -I${top_srcdir}/module/zpios/include sbin_PROGRAMS = zpios zpios_SOURCES = \ - $(top_srcdir)/cmd/zpios/zpios.h \ $(top_srcdir)/cmd/zpios/zpios_main.c \ - $(top_srcdir)/cmd/zpios/zpios_util.c + $(top_srcdir)/cmd/zpios/zpios_util.c \ + $(top_srcdir)/cmd/zpios/zpios.h + From 11b7f20ce13ff5c15525afc8d40e2d69c64a163e Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 6 Jan 2009 09:48:33 -0800 Subject: [PATCH 07/45] Ensure zpios module makefile is built --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 4090a38dcb..b9280718ba 100644 --- a/configure.ac +++ b/configure.ac @@ -92,5 +92,6 @@ AC_CONFIG_FILES([ module/zcommon/include/sys/fm/Makefile module/zcommon/include/sys/fm/fs/Makefile module/zfs/Makefile + module/zpios/Makefile ]) AC_OUTPUT From d785c6d77ad80784884fe4c8c587463b4ee64b29 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 6 Jan 2009 09:55:40 -0800 Subject: [PATCH 08/45] Should use zpios not kpios --- module/zpios/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/zpios/Makefile.in b/module/zpios/Makefile.in index a6584b4aee..d007d3b4ae 100644 --- a/module/zpios/Makefile.in +++ b/module/zpios/Makefile.in @@ -7,4 +7,4 @@ EXTRA_CFLAGS += -I@MODDIR@/zpios/include obj-m := ${MODULE}.o -${MODULE}-objs += kpios.o # Kernel PIOS test case +${MODULE}-objs += zpios.o # Kernel PIOS test case From fa03d4582f34e87d10ab47d3d15789f03a63a8bf Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 6 Jan 2009 11:02:36 -0800 Subject: [PATCH 09/45] Remove circular dependency --- module/zpios/Makefile.in | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/module/zpios/Makefile.in b/module/zpios/Makefile.in index d007d3b4ae..88770784d9 100644 --- a/module/zpios/Makefile.in +++ b/module/zpios/Makefile.in @@ -1,10 +1,9 @@ -DISTFILES = Makefile.in *.c +subdir-m += include +DISTFILES = zpios.c -MODULE := zpios +MODULE := zpios -EXTRA_CFLAGS = @KERNELCPPFLAGS@ -EXTRA_CFLAGS += -I@MODDIR@/zpios/include +EXTRA_CFLAGS = -I@MODDIR@/zpios/include +EXTRA_CFLAGS += @KERNELCPPFLAGS@ obj-m := ${MODULE}.o - -${MODULE}-objs += zpios.o # Kernel PIOS test case From a6dba6330c1f81514d6feac479d132f869c3456e Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 6 Jan 2009 11:36:56 -0800 Subject: [PATCH 10/45] Add missing include paths --- module/zpios/Makefile.in | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/module/zpios/Makefile.in b/module/zpios/Makefile.in index 88770784d9..c93e666da2 100644 --- a/module/zpios/Makefile.in +++ b/module/zpios/Makefile.in @@ -3,7 +3,12 @@ DISTFILES = zpios.c MODULE := zpios -EXTRA_CFLAGS = -I@MODDIR@/zpios/include +EXTRA_CFLAGS = -I@MODDIR@/zfs/include +EXTRA_CFLAGS += -I@MODDIR@/zcommon/include +EXTRA_CFLAGS += -I@MODDIR@/avl/include +EXTRA_CFLAGS += -I@MODDIR@/nvpair/include +EXTRA_CFLAGS += -I@MODDIR@/unicode/include +EXTRA_CFLAGS += -I@MODDIR@/zpios/include EXTRA_CFLAGS += @KERNELCPPFLAGS@ obj-m := ${MODULE}.o From 65923b99f9193bdf815c9b306029d6c72f283ca8 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 6 Jan 2009 12:32:44 -0800 Subject: [PATCH 11/45] Update to use DS_MODE_USER not removed DS_MODE_STANDARD --- configure.ac | 1 + module/zpios/zpios.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index b9280718ba..e9c6ba3552 100644 --- a/configure.ac +++ b/configure.ac @@ -93,5 +93,6 @@ AC_CONFIG_FILES([ module/zcommon/include/sys/fm/fs/Makefile module/zfs/Makefile module/zpios/Makefile + module/zpios/include/Makefile ]) AC_OUTPUT diff --git a/module/zpios/zpios.c b/module/zpios/zpios.c index 2ba81860ee..94065eb27f 100644 --- a/module/zpios/zpios.c +++ b/module/zpios/zpios.c @@ -176,7 +176,7 @@ kpios_dmu_setup(run_args_t *run_args) t->start = current_kernel_time(); - rc = dmu_objset_open(run_args->pool, DMU_OST_ZFS, DS_MODE_STANDARD, &os); + rc = dmu_objset_open(run_args->pool, DMU_OST_ZFS, DS_MODE_USER, &os); if (rc) { kpios_print(run_args->file, "Error dmu_objset_open() " "failed: %d\n", rc); From 9f7833f915edacf24ad0b07a0c28148c3a799223 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Thu, 8 Jan 2009 10:56:53 -0800 Subject: [PATCH 12/45] Update execute permissions --- scripts/profile-zpios-disk.sh | 0 scripts/profile-zpios-pids.sh | 0 scripts/profile-zpios-post.sh | 0 scripts/profile-zpios-pre.sh | 0 scripts/profile-zpios.sh | 0 scripts/survey.sh | 0 scripts/zpios.sh | 0 7 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/profile-zpios-disk.sh mode change 100644 => 100755 scripts/profile-zpios-pids.sh mode change 100644 => 100755 scripts/profile-zpios-post.sh mode change 100644 => 100755 scripts/profile-zpios-pre.sh mode change 100644 => 100755 scripts/profile-zpios.sh mode change 100644 => 100755 scripts/survey.sh mode change 100644 => 100755 scripts/zpios.sh diff --git a/scripts/profile-zpios-disk.sh b/scripts/profile-zpios-disk.sh old mode 100644 new mode 100755 diff --git a/scripts/profile-zpios-pids.sh b/scripts/profile-zpios-pids.sh old mode 100644 new mode 100755 diff --git a/scripts/profile-zpios-post.sh b/scripts/profile-zpios-post.sh old mode 100644 new mode 100755 diff --git a/scripts/profile-zpios-pre.sh b/scripts/profile-zpios-pre.sh old mode 100644 new mode 100755 diff --git a/scripts/profile-zpios.sh b/scripts/profile-zpios.sh old mode 100644 new mode 100755 diff --git a/scripts/survey.sh b/scripts/survey.sh old mode 100644 new mode 100755 diff --git a/scripts/zpios.sh b/scripts/zpios.sh old mode 100644 new mode 100755 From 7b4f45a7fc954d48872cf744637a4f4e4a16ba51 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Thu, 8 Jan 2009 16:53:29 -0800 Subject: [PATCH 13/45] Update zpios.sh to use zfs.sh plus error handling --- scripts/zpios.sh | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/scripts/zpios.sh b/scripts/zpios.sh index 1b91c5cc55..e48c28df13 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -3,8 +3,8 @@ prog=zpios.sh . ../.script-config -SPL_OPTIONS="spl_debug_mask=0 spl_debug_subsys=0 ${1}" -ZPOOL_OPTIONS=$2 +SPL_OPTIONS="spl=spl_debug_mask=0 spl_debug_subsys=0 ${1}" +ZPOOL_OPTIONS="zpool=$2" ZPIOS_OPTIONS=$3 PROFILE_ZPIOS_LOGS=$4 ZPIOS_PRE=$5 @@ -21,7 +21,7 @@ echo -n "Kernel = "; uname -r echo ------------------------------------------------------------------------ echo -./load-zfs.sh "${SPL_OPTIONS}" "${ZPOOL_OPTIONS}" +./zfs.sh -v "${SPL_OPTIONS}" "${ZPOOL_OPTIONS}" || exit 1 echo ---------------------- SPL Sysctl Tunings ------------------------------ sysctl -A | grep spl @@ -38,10 +38,10 @@ fi echo echo "${CMDDIR}/zpool/zpool create -f lustre ${DEVICES}" -${CMDDIR}/zpool/zpool create -f lustre ${DEVICES} +${CMDDIR}/zpool/zpool create -f lustre ${DEVICES} || exit 1 echo "${CMDDIR}/zpool/zpool status lustre" -${CMDDIR}/zpool/zpool status lustre +${CMDDIR}/zpool/zpool status lustre || exit 1 echo "Waiting for /dev/zpios to come up..." while [ ! -c /dev/zpios ]; do @@ -49,7 +49,7 @@ while [ ! -c /dev/zpios ]; do done if [ -n "${ZPIOS_PRE}" ]; then - ${ZPIOS_PRE} + ${ZPIOS_PRE} || exit 1 fi # Usage: zpios @@ -106,11 +106,11 @@ CMD="${CMDDIR}/zpios/zpios \ echo date echo ${CMD} -$CMD +$CMD || exit 1 date if [ -n "${ZPIOS_POST}" ]; then - ${ZPIOS_POST} + ${ZPIOS_POST} || exit 1 fi ${CMDDIR}/zpool/zpool destroy lustre @@ -130,4 +130,6 @@ echo SLAB cat /proc/spl/kmem/slab echo -./unload-zfs.sh +./zfs.sh -vu || exit 1 + +exit 0 From 7356c2045ea6b255a1dc6895de32d030e5d82cb4 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 13 Jan 2009 11:16:12 -0800 Subject: [PATCH 14/45] Update zpios.sh script to reference zfs not zpool, additionally remove unneed module load console message --- module/zpios/zpios.c | 3 --- scripts/zpios.sh | 16 +++++++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/module/zpios/zpios.c b/module/zpios/zpios.c index 94065eb27f..e4a7285d74 100644 --- a/module/zpios/zpios.c +++ b/module/zpios/zpios.c @@ -1264,8 +1264,6 @@ kpios_init(void) } class_device_create(kpios_class, NULL, dev, NULL, "kpios"); - - printk(KERN_INFO "kpios: Loaded Kernel PIOS Tests v%s\n", VERSION); return 0; error: printk(KERN_ERR "kpios: Error registering kpios device, %d\n", rc); @@ -1283,7 +1281,6 @@ kpios_fini(void) cdev_del(&kpios_cdev); unregister_chrdev_region(dev, KPIOS_MINORS); - printk(KERN_INFO "kpios: Unloaded Kernel PIOS Tests\n"); return; } diff --git a/scripts/zpios.sh b/scripts/zpios.sh index e48c28df13..8b32d4feaa 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -3,8 +3,8 @@ prog=zpios.sh . ../.script-config -SPL_OPTIONS="spl=spl_debug_mask=0 spl_debug_subsys=0 ${1}" -ZPOOL_OPTIONS="zpool=$2" +SPL_OPTIONS="spl=spl_debug_mask=-1 spl_debug_subsys=-1 spl_debug_mb=10 ${1}" +ZFS_OPTIONS="zfs=$2" ZPIOS_OPTIONS=$3 PROFILE_ZPIOS_LOGS=$4 ZPIOS_PRE=$5 @@ -27,13 +27,19 @@ echo ---------------------- SPL Sysctl Tunings ------------------------------ sysctl -A | grep spl echo -echo ------------------- SPL/ZPOOL Module Tunings --------------------------- +echo ------------------- SPL Module Tunings --------------------------- if [ -d /sys/module/spl/parameters ]; then grep [0-9] /sys/module/spl/parameters/* - grep [0-9] /sys/module/zpool/parameters/* else grep [0-9] /sys/module/spl/* - grep [0-9] /sys/module/zpool/* +fi +echo + +echo ------------------- ZFS Module Tunings --------------------------- +if [ -d /sys/module/zfs/parameters ]; then + grep [0-9] /sys/module/zfs/parameters/* +else + grep [0-9] /sys/module/zfs/* fi echo From 6caf53f20899a4c64247a98a0e049ed6b002c618 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 13 Jan 2009 11:53:51 -0800 Subject: [PATCH 15/45] Minor script update --- scripts/zpios.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/zpios.sh b/scripts/zpios.sh index 8b32d4feaa..4a666db159 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -4,7 +4,7 @@ prog=zpios.sh . ../.script-config SPL_OPTIONS="spl=spl_debug_mask=-1 spl_debug_subsys=-1 spl_debug_mb=10 ${1}" -ZFS_OPTIONS="zfs=$2" +ZFS_OPTIONS="zfs=${2}" ZPIOS_OPTIONS=$3 PROFILE_ZPIOS_LOGS=$4 ZPIOS_PRE=$5 From 9ab30b2e96d2056b130dff8dcf628176e9e36a25 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 13 Jan 2009 16:42:21 -0800 Subject: [PATCH 16/45] Use zpios not kpios for referce --- module/zpios/include/zpios-ctl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/zpios/include/zpios-ctl.h b/module/zpios/include/zpios-ctl.h index c9c3526ade..1e2b7c1e16 100644 --- a/module/zpios/include/zpios-ctl.h +++ b/module/zpios/include/zpios-ctl.h @@ -42,7 +42,7 @@ #define KPIOS_MAJOR 232 /* XXX - Arbitrary */ #define KPIOS_MINORS 1 -#define KPIOS_DEV "/dev/kpios" +#define KPIOS_DEV "/dev/zpios" #define DMU_IO 0x01 From 1194e0412f2256d701180f7f284794e74ce7512e Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Wed, 14 Jan 2009 08:38:35 -0800 Subject: [PATCH 17/45] Change all instances of kpios to zpios --- ChangeLog | 2 +- cmd/zpios/zpios.h | 8 +- cmd/zpios/zpios_main.c | 54 ++--- cmd/zpios/zpios_util.c | 14 +- module/zpios/include/zpios-ctl.h | 64 ++--- module/zpios/include/zpios-internal.h | 44 ++-- module/zpios/zpios.c | 330 +++++++++++++------------- scripts/profile-zpios-pids.sh | 4 +- scripts/profile-zpios.sh | 16 +- scripts/zpios.sh | 2 +- 10 files changed, 269 insertions(+), 269 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8a74328d6c..eed43af514 100644 --- a/ChangeLog +++ b/ChangeLog @@ -46,7 +46,7 @@ - Minor build system improvements - Minor script improvements - Create a full copy and not a link tree with quilt - - KPIOS_MAJOR changed from 231 to 232 + - ZPIOS_MAJOR changed from 231 to 232 - BIO_RW_BARRIER flag removed from IO request 2008-06-30 Brian Behlendorf diff --git a/cmd/zpios/zpios.h b/cmd/zpios/zpios.h index ca21188296..88c7c2fee9 100644 --- a/cmd/zpios/zpios.h +++ b/cmd/zpios/zpios.h @@ -89,9 +89,9 @@ typedef struct cmd_args { uint64_t chunknoise; /* Chunk noise */ uint64_t thread_delay; /* Thread delay */ - char pre[KPIOS_PATH_SIZE]; /* Pre-exec hook */ - char post[KPIOS_PATH_SIZE]; /* Post-exec hook */ - char log[KPIOS_PATH_SIZE]; /* Requested log dir */ + char pre[ZPIOS_PATH_SIZE]; /* Pre-exec hook */ + char post[ZPIOS_PATH_SIZE]; /* Post-exec hook */ + char log[ZPIOS_PATH_SIZE]; /* Requested log dir */ /* Control */ int current_id; @@ -112,6 +112,6 @@ int set_noise(uint64_t *noise, char *optarg, char *arg); int set_load_params(cmd_args_t *args, char *optarg); int check_mutual_exclusive_command_lines(uint32_t flag, char *arg); void print_stats_header(void); -void print_stats(cmd_args_t *args, kpios_cmd_t *cmd); +void print_stats(cmd_args_t *args, zpios_cmd_t *cmd); #endif /* _ZPIOS_H */ diff --git a/cmd/zpios/zpios_main.c b/cmd/zpios/zpios_main.c index e1e988680a..fbaf8eeefd 100644 --- a/cmd/zpios/zpios_main.c +++ b/cmd/zpios/zpios_main.c @@ -259,13 +259,13 @@ args_init(int argc, char **argv) args->flags |= DMU_REMOVE; break; case 'P': /* --prerun */ - strncpy(args->pre, optarg, KPIOS_PATH_SIZE - 1); + strncpy(args->pre, optarg, ZPIOS_PATH_SIZE - 1); break; case 'R': /* --postrun */ - strncpy(args->post, optarg, KPIOS_PATH_SIZE - 1); + strncpy(args->post, optarg, ZPIOS_PATH_SIZE - 1); break; case 'G': /* --log */ - strncpy(args->log, optarg, KPIOS_PATH_SIZE - 1); + strncpy(args->log, optarg, ZPIOS_PATH_SIZE - 1); break; case 'I': /* --regionnoise */ rc = set_noise(&args->regionnoise, optarg, "regionnoise"); @@ -329,18 +329,18 @@ args_init(int argc, char **argv) static int dev_clear(void) { - kpios_cfg_t cfg; + zpios_cfg_t cfg; int rc; memset(&cfg, 0, sizeof(cfg)); - cfg.cfg_magic = KPIOS_CFG_MAGIC; - cfg.cfg_cmd = KPIOS_CFG_BUFFER_CLEAR; + cfg.cfg_magic = ZPIOS_CFG_MAGIC; + cfg.cfg_cmd = ZPIOS_CFG_BUFFER_CLEAR; cfg.cfg_arg1 = 0; - rc = ioctl(zpiosctl_fd, KPIOS_CFG, &cfg); + rc = ioctl(zpiosctl_fd, ZPIOS_CFG, &cfg); if (rc) fprintf(stderr, "Ioctl() error %lu / %d: %d\n", - (unsigned long) KPIOS_CFG, cfg.cfg_cmd, errno); + (unsigned long) ZPIOS_CFG, cfg.cfg_cmd, errno); lseek(zpiosctl_fd, 0, SEEK_SET); @@ -351,18 +351,18 @@ dev_clear(void) static int dev_size(int size) { - kpios_cfg_t cfg; + zpios_cfg_t cfg; int rc; memset(&cfg, 0, sizeof(cfg)); - cfg.cfg_magic = KPIOS_CFG_MAGIC; - cfg.cfg_cmd = KPIOS_CFG_BUFFER_SIZE; + cfg.cfg_magic = ZPIOS_CFG_MAGIC; + cfg.cfg_cmd = ZPIOS_CFG_BUFFER_SIZE; cfg.cfg_arg1 = size; - rc = ioctl(zpiosctl_fd, KPIOS_CFG, &cfg); + rc = ioctl(zpiosctl_fd, ZPIOS_CFG, &cfg); if (rc) { fprintf(stderr, "Ioctl() error %lu / %d: %d\n", - (unsigned long) KPIOS_CFG, cfg.cfg_cmd, errno); + (unsigned long) ZPIOS_CFG, cfg.cfg_cmd, errno); return rc; } @@ -378,7 +378,7 @@ dev_fini(void) if (zpiosctl_fd != -1) { if (close(zpiosctl_fd) == -1) { fprintf(stderr, "Unable to close %s: %d\n", - KPIOS_DEV, errno); + ZPIOS_DEV, errno); } } } @@ -388,10 +388,10 @@ dev_init(void) { int rc; - zpiosctl_fd = open(KPIOS_DEV, O_RDONLY); + zpiosctl_fd = open(ZPIOS_DEV, O_RDONLY); if (zpiosctl_fd == -1) { fprintf(stderr, "Unable to open %s: %d\n" - "Is the zpios module loaded?\n", KPIOS_DEV, errno); + "Is the zpios module loaded?\n", ZPIOS_DEV, errno); rc = errno; goto error; } @@ -415,7 +415,7 @@ error: if (zpiosctl_fd != -1) { if (close(zpiosctl_fd) == -1) { fprintf(stderr, "Unable to close %s: %d\n", - KPIOS_DEV, errno); + ZPIOS_DEV, errno); } } @@ -468,22 +468,22 @@ static int run_one(cmd_args_t *args, uint32_t id, uint32_t T, uint32_t N, uint64_t C, uint64_t S, uint64_t O) { - kpios_cmd_t *cmd; + zpios_cmd_t *cmd; int rc, rc2, cmd_size; dev_clear(); - cmd_size = sizeof(kpios_cmd_t) + ((T + N + 1) * sizeof(kpios_stats_t)); - cmd = (kpios_cmd_t *)malloc(cmd_size); + cmd_size = sizeof(zpios_cmd_t) + ((T + N + 1) * sizeof(zpios_stats_t)); + cmd = (zpios_cmd_t *)malloc(cmd_size); if (cmd == NULL) return ENOMEM; memset(cmd, 0, cmd_size); - cmd->cmd_magic = KPIOS_CMD_MAGIC; - strncpy(cmd->cmd_pool, args->pool, KPIOS_NAME_SIZE - 1); - strncpy(cmd->cmd_pre, args->pre, KPIOS_PATH_SIZE - 1); - strncpy(cmd->cmd_post, args->post, KPIOS_PATH_SIZE - 1); - strncpy(cmd->cmd_log, args->log, KPIOS_PATH_SIZE - 1); + cmd->cmd_magic = ZPIOS_CMD_MAGIC; + strncpy(cmd->cmd_pool, args->pool, ZPIOS_NAME_SIZE - 1); + strncpy(cmd->cmd_pre, args->pre, ZPIOS_PATH_SIZE - 1); + strncpy(cmd->cmd_post, args->post, ZPIOS_PATH_SIZE - 1); + strncpy(cmd->cmd_log, args->log, ZPIOS_PATH_SIZE - 1); cmd->cmd_id = id; cmd->cmd_chunk_size = C; cmd->cmd_thread_count = T; @@ -494,9 +494,9 @@ run_one(cmd_args_t *args, uint32_t id, uint32_t T, uint32_t N, cmd->cmd_chunk_noise = args->chunknoise; cmd->cmd_thread_delay = args->thread_delay; cmd->cmd_flags = args->flags; - cmd->cmd_data_size = (T + N + 1) * sizeof(kpios_stats_t); + cmd->cmd_data_size = (T + N + 1) * sizeof(zpios_stats_t); - rc = ioctl(zpiosctl_fd, KPIOS_CMD, cmd); + rc = ioctl(zpiosctl_fd, ZPIOS_CMD, cmd); if (rc) args->rc = errno; diff --git a/cmd/zpios/zpios_util.c b/cmd/zpios/zpios_util.c index 4d7e52d648..6a43446500 100644 --- a/cmd/zpios/zpios_util.c +++ b/cmd/zpios/zpios_util.c @@ -323,9 +323,9 @@ print_stats_header(void) } static void -print_stats_human_readable(cmd_args_t *args, kpios_cmd_t *cmd) +print_stats_human_readable(cmd_args_t *args, zpios_cmd_t *cmd) { - kpios_stats_t *summary_stats; + zpios_stats_t *summary_stats; double t_time, wr_time, rd_time, cr_time, rm_time; char str[16]; @@ -350,7 +350,7 @@ print_stats_human_readable(cmd_args_t *args, kpios_cmd_t *cmd) return; } - summary_stats = (kpios_stats_t *)cmd->cmd_data_str; + summary_stats = (zpios_stats_t *)cmd->cmd_data_str; t_time = timespec_to_double(summary_stats->total_time.delta); wr_time = timespec_to_double(summary_stats->wr_time.delta); rd_time = timespec_to_double(summary_stats->rd_time.delta); @@ -374,9 +374,9 @@ print_stats_human_readable(cmd_args_t *args, kpios_cmd_t *cmd) } static void -print_stats_table(cmd_args_t *args, kpios_cmd_t *cmd) +print_stats_table(cmd_args_t *args, zpios_cmd_t *cmd) { - kpios_stats_t *summary_stats; + zpios_stats_t *summary_stats; double wr_time, rd_time; if (args->rc) @@ -400,7 +400,7 @@ print_stats_table(cmd_args_t *args, kpios_cmd_t *cmd) return; } - summary_stats = (kpios_stats_t *)cmd->cmd_data_str; + summary_stats = (zpios_stats_t *)cmd->cmd_data_str; wr_time = timespec_to_double(summary_stats->wr_time.delta); rd_time = timespec_to_double(summary_stats->rd_time.delta); @@ -431,7 +431,7 @@ print_stats_table(cmd_args_t *args, kpios_cmd_t *cmd) } void -print_stats(cmd_args_t *args, kpios_cmd_t *cmd) +print_stats(cmd_args_t *args, zpios_cmd_t *cmd) { if (args->human_readable) print_stats_human_readable(args, cmd); diff --git a/module/zpios/include/zpios-ctl.h b/module/zpios/include/zpios-ctl.h index 1e2b7c1e16..79cbfa3ac6 100644 --- a/module/zpios/include/zpios-ctl.h +++ b/module/zpios/include/zpios-ctl.h @@ -30,19 +30,19 @@ * CDDL HEADER END */ -#ifndef _KPIOS_CTL_H -#define _KPIOS_CTL_H +#ifndef _ZPIOS_CTL_H +#define _ZPIOS_CTL_H /* Contains shared definitions which both the userspace - * and kernelspace portions of kpios must agree on. + * and kernelspace portions of zpios must agree on. */ #ifndef _KERNEL #include #endif -#define KPIOS_MAJOR 232 /* XXX - Arbitrary */ -#define KPIOS_MINORS 1 -#define KPIOS_DEV "/dev/zpios" +#define ZPIOS_MAJOR 232 /* XXX - Arbitrary */ +#define ZPIOS_MINORS 1 +#define ZPIOS_DEV "/dev/zpios" #define DMU_IO 0x01 @@ -54,45 +54,45 @@ #define DMU_WRITE_ZC 0x20 /* Incompatible with DMU_VERIFY */ #define DMU_READ_ZC 0x40 /* Incompatible with DMU_VERIFY */ -#define KPIOS_NAME_SIZE 16 -#define KPIOS_PATH_SIZE 128 +#define ZPIOS_NAME_SIZE 16 +#define ZPIOS_PATH_SIZE 128 #define PHASE_PRE "pre" #define PHASE_POST "post" #define PHASE_WRITE "write" #define PHASE_READ "read" -#define KPIOS_CFG_MAGIC 0x87237190U -typedef struct kpios_cfg { +#define ZPIOS_CFG_MAGIC 0x87237190U +typedef struct zpios_cfg { uint32_t cfg_magic; /* Unique magic */ int32_t cfg_cmd; /* Config command */ int32_t cfg_arg1; /* Config command arg 1 */ int32_t cfg_rc1; /* Config response 1 */ -} kpios_cfg_t; +} zpios_cfg_t; -typedef struct kpios_time { +typedef struct zpios_time { struct timespec start; struct timespec stop; struct timespec delta; -} kpios_time_t; +} zpios_time_t; -typedef struct kpios_stats { - kpios_time_t total_time; - kpios_time_t cr_time; - kpios_time_t rm_time; - kpios_time_t wr_time; - kpios_time_t rd_time; +typedef struct zpios_stats { + zpios_time_t total_time; + zpios_time_t cr_time; + zpios_time_t rm_time; + zpios_time_t wr_time; + zpios_time_t rd_time; uint64_t wr_data; uint64_t wr_chunks; uint64_t rd_data; uint64_t rd_chunks; -} kpios_stats_t; +} zpios_stats_t; -#define KPIOS_CMD_MAGIC 0x49715385U -typedef struct kpios_cmd { +#define ZPIOS_CMD_MAGIC 0x49715385U +typedef struct zpios_cmd { uint32_t cmd_magic; /* Unique magic */ uint32_t cmd_id; /* Run ID */ - char cmd_pool[KPIOS_NAME_SIZE]; /* Pool name */ + char cmd_pool[ZPIOS_NAME_SIZE]; /* Pool name */ uint64_t cmd_chunk_size; /* Chunk size */ uint32_t cmd_thread_count; /* Thread count */ uint32_t cmd_region_count; /* Region count */ @@ -102,19 +102,19 @@ typedef struct kpios_cmd { uint32_t cmd_chunk_noise; /* Chunk noise */ uint32_t cmd_thread_delay; /* Thread delay */ uint32_t cmd_flags; /* Test flags */ - char cmd_pre[KPIOS_PATH_SIZE]; /* Pre-exec hook */ - char cmd_post[KPIOS_PATH_SIZE]; /* Post-exec hook */ - char cmd_log[KPIOS_PATH_SIZE]; /* Requested log dir */ + char cmd_pre[ZPIOS_PATH_SIZE]; /* Pre-exec hook */ + char cmd_post[ZPIOS_PATH_SIZE]; /* Post-exec hook */ + char cmd_log[ZPIOS_PATH_SIZE]; /* Requested log dir */ uint64_t cmd_data_size; /* Opaque data size */ char cmd_data_str[0]; /* Opaque data region */ -} kpios_cmd_t; +} zpios_cmd_t; /* Valid ioctls */ -#define KPIOS_CFG _IOWR('f', 101, long) -#define KPIOS_CMD _IOWR('f', 102, long) +#define ZPIOS_CFG _IOWR('f', 101, long) +#define ZPIOS_CMD _IOWR('f', 102, long) /* Valid configuration commands */ -#define KPIOS_CFG_BUFFER_CLEAR 0x001 /* Clear text buffer */ -#define KPIOS_CFG_BUFFER_SIZE 0x002 /* Resize text buffer */ +#define ZPIOS_CFG_BUFFER_CLEAR 0x001 /* Clear text buffer */ +#define ZPIOS_CFG_BUFFER_SIZE 0x002 /* Resize text buffer */ -#endif /* _KPIOS_CTL_H */ +#endif /* _ZPIOS_CTL_H */ diff --git a/module/zpios/include/zpios-internal.h b/module/zpios/include/zpios-internal.h index 5fecd81ab5..cafe8b7d09 100644 --- a/module/zpios/include/zpios-internal.h +++ b/module/zpios/include/zpios-internal.h @@ -30,8 +30,8 @@ * CDDL HEADER END */ -#ifndef _KPIOS_INTERNAL_H -#define _KPIOS_INTERNAL_H +#ifndef _ZPIOS_INTERNAL_H +#define _ZPIOS_INTERNAL_H #include "zpios-ctl.h" @@ -49,26 +49,26 @@ typedef struct thread_data { struct run_args *run_args; int thread_no; int rc; - kpios_stats_t stats; + zpios_stats_t stats; kmutex_t lock; } thread_data_t; /* region for IO data */ -typedef struct kpios_region { +typedef struct zpios_region { __u64 wr_offset; __u64 rd_offset; __u64 init_offset; __u64 max_offset; dmu_obj_t obj; - kpios_stats_t stats; + zpios_stats_t stats; kmutex_t lock; -} kpios_region_t; +} zpios_region_t; /* arguments for one run */ typedef struct run_args { /* Config args */ int id; - char pool[KPIOS_NAME_SIZE]; + char pool[ZPIOS_NAME_SIZE]; __u64 chunk_size; __u32 thread_count; __u32 region_count; @@ -78,9 +78,9 @@ typedef struct run_args { __u32 chunk_noise; __u32 thread_delay; __u32 flags; - char pre[KPIOS_PATH_SIZE]; - char post[KPIOS_PATH_SIZE]; - char log[KPIOS_PATH_SIZE]; + char pre[ZPIOS_PATH_SIZE]; + char post[ZPIOS_PATH_SIZE]; + char log[ZPIOS_PATH_SIZE]; /* Control data */ objset_t *os; @@ -92,24 +92,24 @@ typedef struct run_args { /* Results data */ struct file *file; - kpios_stats_t stats; + zpios_stats_t stats; thread_data_t **threads; - kpios_region_t regions[0]; /* Must be last element */ + zpios_region_t regions[0]; /* Must be last element */ } run_args_t; -#define KPIOS_INFO_BUFFER_SIZE 65536 -#define KPIOS_INFO_BUFFER_REDZONE 1024 +#define ZPIOS_INFO_BUFFER_SIZE 65536 +#define ZPIOS_INFO_BUFFER_REDZONE 1024 -typedef struct kpios_info { +typedef struct zpios_info { spinlock_t info_lock; int info_size; char *info_buffer; char *info_head; /* Internal kernel use only */ -} kpios_info_t; +} zpios_info_t; -#define kpios_print(file, format, args...) \ -({ kpios_info_t *_info_ = (kpios_info_t *)file->private_data; \ +#define zpios_print(file, format, args...) \ +({ zpios_info_t *_info_ = (zpios_info_t *)file->private_data; \ int _rc_; \ \ ASSERT(_info_); \ @@ -119,7 +119,7 @@ typedef struct kpios_info { \ /* Don't allow the kernel to start a write in the red zone */ \ if ((int)(_info_->info_head - _info_->info_buffer) > \ - (_info_->info_size - KPIOS_INFO_BUFFER_REDZONE)) { \ + (_info_->info_size - ZPIOS_INFO_BUFFER_REDZONE)) { \ _rc_ = -EOVERFLOW; \ } else { \ _rc_ = sprintf(_info_->info_head, format, args); \ @@ -131,7 +131,7 @@ typedef struct kpios_info { _rc_; \ }) -#define kpios_vprint(file, test, format, args...) \ - kpios_print(file, "%*s: " format, KPIOS_NAME_SIZE, test, args) +#define zpios_vprint(file, test, format, args...) \ + zpios_print(file, "%*s: " format, ZPIOS_NAME_SIZE, test, args) -#endif /* _KPIOS_INTERNAL_H */ +#endif /* _ZPIOS_INTERNAL_H */ diff --git a/module/zpios/zpios.c b/module/zpios/zpios.c index e4a7285d74..4b1c4dbbc3 100644 --- a/module/zpios/zpios.c +++ b/module/zpios/zpios.c @@ -40,7 +40,7 @@ #include "zpios-internal.h" -static struct class *kpios_class; +static struct class *zpios_class; static inline @@ -53,7 +53,7 @@ struct timespec timespec_add(struct timespec lhs, struct timespec rhs) } static -int kpios_upcall(char *path, char *phase, run_args_t *run_args, int rc) +int zpios_upcall(char *path, char *phase, run_args_t *run_args, int rc) { /* This is stack heavy but it should be OK since we are only * making the upcall between tests when the stack is shallow. @@ -106,7 +106,7 @@ int kpios_upcall(char *path, char *phase, run_args_t *run_args, int rc) } static uint64_t -kpios_dmu_object_create(run_args_t *run_args, objset_t *os) +zpios_dmu_object_create(run_args_t *run_args, objset_t *os) { struct dmu_tx *tx; uint64_t obj = 0ULL; @@ -116,7 +116,7 @@ kpios_dmu_object_create(run_args_t *run_args, objset_t *os) dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, OBJ_SIZE); rc = dmu_tx_assign(tx, TXG_WAIT); if (rc) { - kpios_print(run_args->file, + zpios_print(run_args->file, "dmu_tx_assign() failed: %d\n", rc); dmu_tx_abort(tx); return obj; @@ -126,7 +126,7 @@ kpios_dmu_object_create(run_args_t *run_args, objset_t *os) DMU_OT_NONE, 0, tx); rc = dmu_object_set_blocksize(os, obj, 128ULL << 10, 0, tx); if (rc) { - kpios_print(run_args->file, + zpios_print(run_args->file, "dmu_object_set_blocksize() failed: %d\n", rc); dmu_tx_abort(tx); return obj; @@ -138,7 +138,7 @@ kpios_dmu_object_create(run_args_t *run_args, objset_t *os) } static int -kpios_dmu_object_free(run_args_t *run_args, objset_t *os, uint64_t obj) +zpios_dmu_object_free(run_args_t *run_args, objset_t *os, uint64_t obj) { struct dmu_tx *tx; int rc; @@ -147,7 +147,7 @@ kpios_dmu_object_free(run_args_t *run_args, objset_t *os, uint64_t obj) dmu_tx_hold_free(tx, obj, 0, DMU_OBJECT_END); rc = dmu_tx_assign(tx, TXG_WAIT); if (rc) { - kpios_print(run_args->file, + zpios_print(run_args->file, "dmu_tx_assign() failed: %d\n", rc); dmu_tx_abort(tx); return rc; @@ -155,7 +155,7 @@ kpios_dmu_object_free(run_args_t *run_args, objset_t *os, uint64_t obj) rc = dmu_object_free(os, obj, tx); if (rc) { - kpios_print(run_args->file, + zpios_print(run_args->file, "dmu_object_free() failed: %d\n", rc); dmu_tx_abort(tx); return rc; @@ -167,9 +167,9 @@ kpios_dmu_object_free(run_args_t *run_args, objset_t *os, uint64_t obj) } static int -kpios_dmu_setup(run_args_t *run_args) +zpios_dmu_setup(run_args_t *run_args) { - kpios_time_t *t = &(run_args->stats.cr_time); + zpios_time_t *t = &(run_args->stats.cr_time); objset_t *os; uint64_t obj = 0ULL; int i, rc = 0; @@ -178,23 +178,23 @@ kpios_dmu_setup(run_args_t *run_args) rc = dmu_objset_open(run_args->pool, DMU_OST_ZFS, DS_MODE_USER, &os); if (rc) { - kpios_print(run_args->file, "Error dmu_objset_open() " + zpios_print(run_args->file, "Error dmu_objset_open() " "failed: %d\n", rc); goto out; } if (!(run_args->flags & DMU_FPP)) { - obj = kpios_dmu_object_create(run_args, os); + obj = zpios_dmu_object_create(run_args, os); if (obj == 0) { rc = -EBADF; - kpios_print(run_args->file, "Error kpios_dmu_" + zpios_print(run_args->file, "Error zpios_dmu_" "object_create() failed, %d\n", rc); goto out; } } for (i = 0; i < run_args->region_count; i++) { - kpios_region_t *region; + zpios_region_t *region; region = &run_args->regions[i]; mutex_init(®ion->lock, NULL, MUTEX_DEFAULT, NULL); @@ -202,7 +202,7 @@ kpios_dmu_setup(run_args_t *run_args) if (run_args->flags & DMU_FPP) { /* File per process */ region->obj.os = os; - region->obj.obj = kpios_dmu_object_create(run_args, os); + region->obj.obj = zpios_dmu_object_create(run_args, os); ASSERT(region->obj.obj > 0); /* XXX - Handle this */ region->wr_offset = run_args->offset; region->rd_offset = run_args->offset; @@ -230,25 +230,25 @@ out: } static int -kpios_setup_run(run_args_t **run_args, kpios_cmd_t *kcmd, struct file *file) +zpios_setup_run(run_args_t **run_args, zpios_cmd_t *kcmd, struct file *file) { run_args_t *ra; int rc, size; - size = sizeof(*ra) + kcmd->cmd_region_count * sizeof(kpios_region_t); + size = sizeof(*ra) + kcmd->cmd_region_count * sizeof(zpios_region_t); ra = vmem_zalloc(size, KM_SLEEP); if (ra == NULL) { - kpios_print(file, "Unable to vmem_zalloc() %d bytes " + zpios_print(file, "Unable to vmem_zalloc() %d bytes " "for regions\n", size); return -ENOMEM; } *run_args = ra; - strncpy(ra->pool, kcmd->cmd_pool, KPIOS_NAME_SIZE - 1); - strncpy(ra->pre, kcmd->cmd_pre, KPIOS_PATH_SIZE - 1); - strncpy(ra->post, kcmd->cmd_post, KPIOS_PATH_SIZE - 1); - strncpy(ra->log, kcmd->cmd_log, KPIOS_PATH_SIZE - 1); + strncpy(ra->pool, kcmd->cmd_pool, ZPIOS_NAME_SIZE - 1); + strncpy(ra->pre, kcmd->cmd_pre, ZPIOS_PATH_SIZE - 1); + strncpy(ra->post, kcmd->cmd_post, ZPIOS_PATH_SIZE - 1); + strncpy(ra->log, kcmd->cmd_log, ZPIOS_PATH_SIZE - 1); ra->id = kcmd->cmd_id; ra->chunk_size = kcmd->cmd_chunk_size; ra->thread_count = kcmd->cmd_thread_count; @@ -268,7 +268,7 @@ kpios_setup_run(run_args_t **run_args, kpios_cmd_t *kcmd, struct file *file) mutex_init(&ra->lock_work, NULL, MUTEX_DEFAULT, NULL); mutex_init(&ra->lock_ctl, NULL, MUTEX_DEFAULT, NULL); - rc = kpios_dmu_setup(ra); + rc = zpios_dmu_setup(ra); if (rc) { mutex_destroy(&ra->lock_ctl); mutex_destroy(&ra->lock_work); @@ -280,8 +280,8 @@ kpios_setup_run(run_args_t **run_args, kpios_cmd_t *kcmd, struct file *file) } static int -kpios_get_work_item(run_args_t *run_args, dmu_obj_t *obj, __u64 *offset, - __u32 *chunk_size, kpios_region_t **region, __u32 flags) +zpios_get_work_item(run_args_t *run_args, dmu_obj_t *obj, __u64 *offset, + __u32 *chunk_size, zpios_region_t **region, __u32 flags) { int i, j, count = 0; unsigned int random_int; @@ -298,7 +298,7 @@ kpios_get_work_item(run_args_t *run_args, dmu_obj_t *obj, __u64 *offset, */ while (count < run_args->region_count) { __u64 *rw_offset; - kpios_time_t *rw_time; + zpios_time_t *rw_time; j = i % run_args->region_count; *region = &(run_args->regions[j]); @@ -346,10 +346,10 @@ kpios_get_work_item(run_args_t *run_args, dmu_obj_t *obj, __u64 *offset, } static void -kpios_remove_objects(run_args_t *run_args) +zpios_remove_objects(run_args_t *run_args) { - kpios_time_t *t = &(run_args->stats.rm_time); - kpios_region_t *region; + zpios_time_t *t = &(run_args->stats.rm_time); + zpios_region_t *region; int rc = 0, i; t->start = current_kernel_time(); @@ -358,21 +358,21 @@ kpios_remove_objects(run_args_t *run_args) if (run_args->flags & DMU_FPP) { for (i = 0; i < run_args->region_count; i++) { region = &run_args->regions[i]; - rc = kpios_dmu_object_free(run_args, + rc = zpios_dmu_object_free(run_args, region->obj.os, region->obj.obj); if (rc) - kpios_print(run_args->file, "Error " + zpios_print(run_args->file, "Error " "removing object %d, %d\n", (int)region->obj.obj, rc); } } else { region = &run_args->regions[0]; - rc = kpios_dmu_object_free(run_args, + rc = zpios_dmu_object_free(run_args, region->obj.os, region->obj.obj); if (rc) - kpios_print(run_args->file, "Error " + zpios_print(run_args->file, "Error " "removing object %d, %d\n", (int)region->obj.obj, rc); } @@ -385,7 +385,7 @@ kpios_remove_objects(run_args_t *run_args) } static void -kpios_cleanup_run(run_args_t *run_args) +zpios_cleanup_run(run_args_t *run_args) { int i, size = 0; @@ -413,13 +413,13 @@ kpios_cleanup_run(run_args_t *run_args) mutex_destroy(&run_args->lock_ctl); if (run_args->regions != NULL) - size = run_args->region_count * sizeof(kpios_region_t); + size = run_args->region_count * sizeof(zpios_region_t); vmem_free(run_args, sizeof(*run_args) + size); } static int -kpios_dmu_write(run_args_t *run_args, objset_t *os, uint64_t object, +zpios_dmu_write(run_args_t *run_args, objset_t *os, uint64_t object, uint64_t offset, uint64_t size, const void *buf) { struct dmu_tx *tx; @@ -437,7 +437,7 @@ kpios_dmu_write(run_args_t *run_args, objset_t *os, uint64_t object, dmu_tx_abort(tx); continue; } - kpios_print(run_args->file, + zpios_print(run_args->file, "Error in dmu_tx_assign(), %d", rc); dmu_tx_abort(tx); return rc; @@ -455,7 +455,7 @@ kpios_dmu_write(run_args_t *run_args, objset_t *os, uint64_t object, } static int -kpios_dmu_read(run_args_t *run_args, objset_t *os, uint64_t object, +zpios_dmu_read(run_args_t *run_args, objset_t *os, uint64_t object, uint64_t offset, uint64_t size, void *buf) { int flags = 0; @@ -467,16 +467,16 @@ kpios_dmu_read(run_args_t *run_args, objset_t *os, uint64_t object, } static int -kpios_thread_main(void *data) +zpios_thread_main(void *data) { thread_data_t *thr = (thread_data_t *)data; run_args_t *run_args = thr->run_args; - kpios_time_t t; + zpios_time_t t; dmu_obj_t obj; __u64 offset; __u32 chunk_size; - kpios_region_t *region; + zpios_region_t *region; char *buf; unsigned int random_int; @@ -511,7 +511,7 @@ kpios_thread_main(void *data) thr->stats.wr_time.start = current_kernel_time(); mutex_exit(&thr->lock); - while (kpios_get_work_item(run_args, &obj, &offset, + while (zpios_get_work_item(run_args, &obj, &offset, &chunk_size, ®ion, DMU_WRITE)) { if (thread_delay) { get_random_bytes(&random_int, sizeof(unsigned int)); @@ -521,13 +521,13 @@ kpios_thread_main(void *data) } t.start = current_kernel_time(); - rc = kpios_dmu_write(run_args, obj.os, obj.obj, + rc = zpios_dmu_write(run_args, obj.os, obj.obj, offset, chunk_size, buf); t.stop = current_kernel_time(); t.delta = timespec_sub(t.stop, t.start); if (rc) { - kpios_print(run_args->file, "IO error while doing " + zpios_print(run_args->file, "IO error while doing " "dmu_write(): %d\n", rc); break; } @@ -577,7 +577,7 @@ kpios_thread_main(void *data) thr->stats.rd_time.start = current_kernel_time(); mutex_exit(&thr->lock); - while (kpios_get_work_item(run_args, &obj, &offset, + while (zpios_get_work_item(run_args, &obj, &offset, &chunk_size, ®ion, DMU_READ)) { if (thread_delay) { get_random_bytes(&random_int, sizeof(unsigned int)); @@ -590,13 +590,13 @@ kpios_thread_main(void *data) memset(buf, 0, chunk_size); t.start = current_kernel_time(); - rc = kpios_dmu_read(run_args, obj.os, obj.obj, + rc = zpios_dmu_read(run_args, obj.os, obj.obj, offset, chunk_size, buf); t.stop = current_kernel_time(); t.delta = timespec_sub(t.stop, t.start); if (rc) { - kpios_print(run_args->file, "IO error while doing " + zpios_print(run_args->file, "IO error while doing " "dmu_read(): %d\n", rc); break; } @@ -605,7 +605,7 @@ kpios_thread_main(void *data) if (run_args->flags & DMU_VERIFY) { for (i = 0; i < chunk_size; i++) { if (buf[i] != 'z') { - kpios_print(run_args->file, + zpios_print(run_args->file, "IO verify error: %d/%d/%d\n", (int)obj.obj, (int)offset, (int)chunk_size); @@ -652,24 +652,24 @@ out: } static int -kpios_thread_done(run_args_t *run_args) +zpios_thread_done(run_args_t *run_args) { ASSERT(run_args->threads_done <= run_args->thread_count); return (run_args->threads_done == run_args->thread_count); } static int -kpios_threads_run(run_args_t *run_args) +zpios_threads_run(run_args_t *run_args) { struct task_struct *tsk, **tsks; thread_data_t *thr = NULL; - kpios_time_t *tt = &(run_args->stats.total_time); - kpios_time_t *tw = &(run_args->stats.wr_time); - kpios_time_t *tr = &(run_args->stats.rd_time); + zpios_time_t *tt = &(run_args->stats.total_time); + zpios_time_t *tw = &(run_args->stats.wr_time); + zpios_time_t *tr = &(run_args->stats.rd_time); int i, rc = 0, tc = run_args->thread_count; DEFINE_WAIT(wait); - kpios_upcall(run_args->pre, PHASE_PRE, run_args, 0); + zpios_upcall(run_args->pre, PHASE_PRE, run_args, 0); tsks = kmem_zalloc(sizeof(struct task_struct *) * tc, KM_SLEEP); if (tsks == NULL) { @@ -700,8 +700,8 @@ kpios_threads_run(run_args_t *run_args) mutex_init(&thr->lock, NULL, MUTEX_DEFAULT, NULL); run_args->threads[i] = thr; - tsk = kthread_create(kpios_thread_main, (void *)thr, - "%s/%d", "kpios_io", i); + tsk = kthread_create(zpios_thread_main, (void *)thr, + "%s/%d", "zpios_io", i); if (IS_ERR(tsk)) { rc = -EINVAL; goto taskerr; @@ -713,13 +713,13 @@ kpios_threads_run(run_args_t *run_args) tt->start = current_kernel_time(); /* Wake up all threads for write phase */ - kpios_upcall(run_args->pre, PHASE_WRITE, run_args, 0); + zpios_upcall(run_args->pre, PHASE_WRITE, run_args, 0); for (i = 0; i < tc; i++) wake_up_process(tsks[i]); /* Wait for write phase to complete */ tw->start = current_kernel_time(); - wait_event(run_args->waitq, kpios_thread_done(run_args)); + wait_event(run_args->waitq, zpios_thread_done(run_args)); tw->stop = current_kernel_time(); for (i = 0; i < tc; i++) { @@ -735,7 +735,7 @@ kpios_threads_run(run_args_t *run_args) mutex_exit(&thr->lock); } - kpios_upcall(run_args->post, PHASE_WRITE, run_args, rc); + zpios_upcall(run_args->post, PHASE_WRITE, run_args, rc); if (rc) { /* Wake up all threads and tell them to exit */ for (i = 0; i < tc; i++) { @@ -754,13 +754,13 @@ kpios_threads_run(run_args_t *run_args) mutex_exit(&run_args->lock_ctl); /* Wake up all threads for read phase */ - kpios_upcall(run_args->pre, PHASE_READ, run_args, 0); + zpios_upcall(run_args->pre, PHASE_READ, run_args, 0); for (i = 0; i < tc; i++) wake_up_process(tsks[i]); /* Wait for read phase to complete */ tr->start = current_kernel_time(); - wait_event(run_args->waitq, kpios_thread_done(run_args)); + wait_event(run_args->waitq, zpios_thread_done(run_args)); tr->stop = current_kernel_time(); for (i = 0; i < tc; i++) { @@ -776,7 +776,7 @@ kpios_threads_run(run_args_t *run_args) mutex_exit(&thr->lock); } - kpios_upcall(run_args->post, PHASE_READ, run_args, rc); + zpios_upcall(run_args->post, PHASE_READ, run_args, rc); out: tt->stop = current_kernel_time(); tt->delta = timespec_sub(tt->stop, tt->start); @@ -786,7 +786,7 @@ out: cleanup: kmem_free(tsks, sizeof(struct task_struct *) * tc); cleanup2: - kpios_upcall(run_args->post, PHASE_POST, run_args, rc); + zpios_upcall(run_args->post, PHASE_POST, run_args, rc); /* Returns first encountered thread error (if any) */ return rc; @@ -801,30 +801,30 @@ taskerr: } static int -kpios_do_one_run(struct file *file, kpios_cmd_t *kcmd, +zpios_do_one_run(struct file *file, zpios_cmd_t *kcmd, int data_size, void *data) { run_args_t *run_args; - kpios_stats_t *stats = (kpios_stats_t *)data; + zpios_stats_t *stats = (zpios_stats_t *)data; int i, n, m, size, rc; if ((!kcmd->cmd_chunk_size) || (!kcmd->cmd_region_size) || (!kcmd->cmd_thread_count) || (!kcmd->cmd_region_count)) { - kpios_print(file, "Invalid chunk_size, region_size, " + zpios_print(file, "Invalid chunk_size, region_size, " "thread_count, or region_count, %d\n", -EINVAL); return -EINVAL; } if (!(kcmd->cmd_flags & DMU_WRITE) || !(kcmd->cmd_flags & DMU_READ)) { - kpios_print(file, "Invalid flags, minimally DMU_WRITE " + zpios_print(file, "Invalid flags, minimally DMU_WRITE " "and DMU_READ must be set, %d\n", -EINVAL); return -EINVAL; } if ((kcmd->cmd_flags & (DMU_WRITE_ZC | DMU_READ_ZC)) && (kcmd->cmd_flags & DMU_VERIFY)) { - kpios_print(file, "Invalid flags, DMU_*_ZC incompatible " + zpios_print(file, "Invalid flags, DMU_*_ZC incompatible " "with DMU_VERIFY, used for performance analysis " "only, %d\n", -EINVAL); return -EINVAL; @@ -832,28 +832,28 @@ kpios_do_one_run(struct file *file, kpios_cmd_t *kcmd, /* Opaque data on return contains structs of the following form: * - * kpios_stat_t stats[]; + * zpios_stat_t stats[]; * stats[0] = run_args->stats; * stats[1-N] = threads[N]->stats; * stats[N+1-M] = regions[M]->stats; * * Where N is the number of threads, and M is the number of regions. */ - size = (sizeof(kpios_stats_t) + - (kcmd->cmd_thread_count * sizeof(kpios_stats_t)) + - (kcmd->cmd_region_count * sizeof(kpios_stats_t))); + size = (sizeof(zpios_stats_t) + + (kcmd->cmd_thread_count * sizeof(zpios_stats_t)) + + (kcmd->cmd_region_count * sizeof(zpios_stats_t))); if (data_size < size) { - kpios_print(file, "Invalid size, command data buffer " + zpios_print(file, "Invalid size, command data buffer " "size too small, (%d < %d)\n", data_size, size); return -ENOSPC; } - rc = kpios_setup_run(&run_args, kcmd, file); + rc = zpios_setup_run(&run_args, kcmd, file); if (rc) return rc; - rc = kpios_threads_run(run_args); - kpios_remove_objects(run_args); + rc = zpios_threads_run(run_args); + zpios_remove_objects(run_args); if (rc) goto cleanup; @@ -870,26 +870,26 @@ kpios_do_one_run(struct file *file, kpios_cmd_t *kcmd, } cleanup: - kpios_cleanup_run(run_args); + zpios_cleanup_run(run_args); return rc; } static int -kpios_open(struct inode *inode, struct file *file) +zpios_open(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode); - kpios_info_t *info; + zpios_info_t *info; - if (minor >= KPIOS_MINORS) + if (minor >= ZPIOS_MINORS) return -ENXIO; - info = (kpios_info_t *)kmem_alloc(sizeof(*info), KM_SLEEP); + info = (zpios_info_t *)kmem_alloc(sizeof(*info), KM_SLEEP); if (info == NULL) return -ENOMEM; spin_lock_init(&info->info_lock); - info->info_size = KPIOS_INFO_BUFFER_SIZE; - info->info_buffer = (char *)vmem_alloc(KPIOS_INFO_BUFFER_SIZE,KM_SLEEP); + info->info_size = ZPIOS_INFO_BUFFER_SIZE; + info->info_buffer = (char *)vmem_alloc(ZPIOS_INFO_BUFFER_SIZE,KM_SLEEP); if (info->info_buffer == NULL) { kmem_free(info, sizeof(*info)); return -ENOMEM; @@ -902,27 +902,27 @@ kpios_open(struct inode *inode, struct file *file) } static int -kpios_release(struct inode *inode, struct file *file) +zpios_release(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode); - kpios_info_t *info = (kpios_info_t *)file->private_data; + zpios_info_t *info = (zpios_info_t *)file->private_data; - if (minor >= KPIOS_MINORS) + if (minor >= ZPIOS_MINORS) return -ENXIO; ASSERT(info); ASSERT(info->info_buffer); - vmem_free(info->info_buffer, KPIOS_INFO_BUFFER_SIZE); + vmem_free(info->info_buffer, ZPIOS_INFO_BUFFER_SIZE); kmem_free(info, sizeof(*info)); return 0; } static int -kpios_buffer_clear(struct file *file, kpios_cfg_t *kcfg, unsigned long arg) +zpios_buffer_clear(struct file *file, zpios_cfg_t *kcfg, unsigned long arg) { - kpios_info_t *info = (kpios_info_t *)file->private_data; + zpios_info_t *info = (zpios_info_t *)file->private_data; ASSERT(info); ASSERT(info->info_buffer); @@ -936,9 +936,9 @@ kpios_buffer_clear(struct file *file, kpios_cfg_t *kcfg, unsigned long arg) } static int -kpios_buffer_size(struct file *file, kpios_cfg_t *kcfg, unsigned long arg) +zpios_buffer_size(struct file *file, zpios_cfg_t *kcfg, unsigned long arg) { - kpios_info_t *info = (kpios_info_t *)file->private_data; + zpios_info_t *info = (zpios_info_t *)file->private_data; char *buf; int min, size, rc = 0; @@ -967,7 +967,7 @@ kpios_buffer_size(struct file *file, kpios_cfg_t *kcfg, unsigned long arg) kcfg->cfg_rc1 = info->info_size; - if (copy_to_user((struct kpios_cfg_t __user *)arg, kcfg, sizeof(*kcfg))) + if (copy_to_user((struct zpios_cfg_t __user *)arg, kcfg, sizeof(*kcfg))) rc = -EFAULT; out: spin_unlock(&info->info_lock); @@ -976,35 +976,35 @@ out: } static int -kpios_ioctl_cfg(struct file *file, unsigned long arg) +zpios_ioctl_cfg(struct file *file, unsigned long arg) { - kpios_cfg_t kcfg; + zpios_cfg_t kcfg; int rc = 0; - if (copy_from_user(&kcfg, (kpios_cfg_t *)arg, sizeof(kcfg))) + if (copy_from_user(&kcfg, (zpios_cfg_t *)arg, sizeof(kcfg))) return -EFAULT; - if (kcfg.cfg_magic != KPIOS_CFG_MAGIC) { - kpios_print(file, "Bad config magic 0x%x != 0x%x\n", - kcfg.cfg_magic, KPIOS_CFG_MAGIC); + if (kcfg.cfg_magic != ZPIOS_CFG_MAGIC) { + zpios_print(file, "Bad config magic 0x%x != 0x%x\n", + kcfg.cfg_magic, ZPIOS_CFG_MAGIC); return -EINVAL; } switch (kcfg.cfg_cmd) { - case KPIOS_CFG_BUFFER_CLEAR: + case ZPIOS_CFG_BUFFER_CLEAR: /* cfg_arg1 - Unused * cfg_rc1 - Unused */ - rc = kpios_buffer_clear(file, &kcfg, arg); + rc = zpios_buffer_clear(file, &kcfg, arg); break; - case KPIOS_CFG_BUFFER_SIZE: + case ZPIOS_CFG_BUFFER_SIZE: /* cfg_arg1 - 0 - query size; >0 resize * cfg_rc1 - Set to current buffer size */ - rc = kpios_buffer_size(file, &kcfg, arg); + rc = zpios_buffer_size(file, &kcfg, arg); break; default: - kpios_print(file, "Bad config command %d\n", + zpios_print(file, "Bad config command %d\n", kcfg.cfg_cmd); rc = -EINVAL; break; @@ -1014,22 +1014,22 @@ kpios_ioctl_cfg(struct file *file, unsigned long arg) } static int -kpios_ioctl_cmd(struct file *file, unsigned long arg) +zpios_ioctl_cmd(struct file *file, unsigned long arg) { - kpios_cmd_t kcmd; + zpios_cmd_t kcmd; int rc = -EINVAL; void *data = NULL; - rc = copy_from_user(&kcmd, (kpios_cfg_t *)arg, sizeof(kcmd)); + rc = copy_from_user(&kcmd, (zpios_cfg_t *)arg, sizeof(kcmd)); if (rc) { - kpios_print(file, "Unable to copy command structure " + zpios_print(file, "Unable to copy command structure " "from user to kernel memory, %d\n", rc); return -EFAULT; } - if (kcmd.cmd_magic != KPIOS_CMD_MAGIC) { - kpios_print(file, "Bad command magic 0x%x != 0x%x\n", - kcmd.cmd_magic, KPIOS_CFG_MAGIC); + if (kcmd.cmd_magic != ZPIOS_CMD_MAGIC) { + zpios_print(file, "Bad command magic 0x%x != 0x%x\n", + kcmd.cmd_magic, ZPIOS_CFG_MAGIC); return -EINVAL; } @@ -1037,33 +1037,33 @@ kpios_ioctl_cmd(struct file *file, unsigned long arg) if (kcmd.cmd_data_size > 0) { data = (void *)vmem_alloc(kcmd.cmd_data_size, KM_SLEEP); if (data == NULL) { - kpios_print(file, "Unable to vmem_alloc() %ld " + zpios_print(file, "Unable to vmem_alloc() %ld " "bytes for data buffer\n", (long)kcmd.cmd_data_size); return -ENOMEM; } - rc = copy_from_user(data, (void *)(arg + offsetof(kpios_cmd_t, + rc = copy_from_user(data, (void *)(arg + offsetof(zpios_cmd_t, cmd_data_str)), kcmd.cmd_data_size); if (rc) { - kpios_print(file, "Unable to copy data buffer " + zpios_print(file, "Unable to copy data buffer " "from user to kernel memory, %d\n", rc); vmem_free(data, kcmd.cmd_data_size); return -EFAULT; } } - rc = kpios_do_one_run(file, &kcmd, kcmd.cmd_data_size, data); + rc = zpios_do_one_run(file, &kcmd, kcmd.cmd_data_size, data); if (data != NULL) { /* If the test failed do not print out the stats */ if (rc) goto cleanup; - rc = copy_to_user((void *)(arg + offsetof(kpios_cmd_t, + rc = copy_to_user((void *)(arg + offsetof(zpios_cmd_t, cmd_data_str)), data, kcmd.cmd_data_size); if (rc) { - kpios_print(file, "Unable to copy data buffer " + zpios_print(file, "Unable to copy data buffer " "from kernel to user memory, %d\n", rc); rc = -EFAULT; } @@ -1076,7 +1076,7 @@ cleanup: } static int -kpios_ioctl(struct inode *inode, struct file *file, +zpios_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { unsigned int minor = iminor(file->f_dentry->d_inode); @@ -1086,18 +1086,18 @@ kpios_ioctl(struct inode *inode, struct file *file, if ((cmd & 0xffffff00) == ((int)'T') << 8) return -ENOTTY; - if (minor >= KPIOS_MINORS) + if (minor >= ZPIOS_MINORS) return -ENXIO; switch (cmd) { - case KPIOS_CFG: - rc = kpios_ioctl_cfg(file, arg); + case ZPIOS_CFG: + rc = zpios_ioctl_cfg(file, arg); break; - case KPIOS_CMD: - rc = kpios_ioctl_cmd(file, arg); + case ZPIOS_CMD: + rc = zpios_ioctl_cmd(file, arg); break; default: - kpios_print(file, "Bad ioctl command %d\n", cmd); + zpios_print(file, "Bad ioctl command %d\n", cmd); rc = -EINVAL; break; } @@ -1110,14 +1110,14 @@ kpios_ioctl(struct inode *inode, struct file *file, * back to the user space, but I don't see any reason to prevent it. */ static ssize_t -kpios_write(struct file *file, const char __user *buf, +zpios_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { unsigned int minor = iminor(file->f_dentry->d_inode); - kpios_info_t *info = (kpios_info_t *)file->private_data; + zpios_info_t *info = (zpios_info_t *)file->private_data; int rc = 0; - if (minor >= KPIOS_MINORS) + if (minor >= ZPIOS_MINORS) return -ENXIO; ASSERT(info); @@ -1148,14 +1148,14 @@ out: } static ssize_t -kpios_read(struct file *file, char __user *buf, +zpios_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { unsigned int minor = iminor(file->f_dentry->d_inode); - kpios_info_t *info = (kpios_info_t *)file->private_data; + zpios_info_t *info = (zpios_info_t *)file->private_data; int rc = 0; - if (minor >= KPIOS_MINORS) + if (minor >= ZPIOS_MINORS) return -ENXIO; ASSERT(info); @@ -1183,13 +1183,13 @@ out: return rc; } -static loff_t kpios_seek(struct file *file, loff_t offset, int origin) +static loff_t zpios_seek(struct file *file, loff_t offset, int origin) { unsigned int minor = iminor(file->f_dentry->d_inode); - kpios_info_t *info = (kpios_info_t *)file->private_data; + zpios_info_t *info = (zpios_info_t *)file->private_data; int rc = -EINVAL; - if (minor >= KPIOS_MINORS) + if (minor >= ZPIOS_MINORS) return -ENXIO; ASSERT(info); @@ -1219,73 +1219,73 @@ static loff_t kpios_seek(struct file *file, loff_t offset, int origin) return rc; } -static struct file_operations kpios_fops = { +static struct file_operations zpios_fops = { .owner = THIS_MODULE, - .open = kpios_open, - .release = kpios_release, - .ioctl = kpios_ioctl, - .read = kpios_read, - .write = kpios_write, - .llseek = kpios_seek, + .open = zpios_open, + .release = zpios_release, + .ioctl = zpios_ioctl, + .read = zpios_read, + .write = zpios_write, + .llseek = zpios_seek, }; -static struct cdev kpios_cdev = { +static struct cdev zpios_cdev = { .owner = THIS_MODULE, - .kobj = { .name = "kpios", }, + .kobj = { .name = "zpios", }, }; static int __init -kpios_init(void) +zpios_init(void) { dev_t dev; int rc; - dev = MKDEV(KPIOS_MAJOR, 0); - if ((rc = register_chrdev_region(dev, KPIOS_MINORS, "kpios"))) + dev = MKDEV(ZPIOS_MAJOR, 0); + if ((rc = register_chrdev_region(dev, ZPIOS_MINORS, "zpios"))) goto error; /* Support for registering a character driver */ - cdev_init(&kpios_cdev, &kpios_fops); - if ((rc = cdev_add(&kpios_cdev, dev, KPIOS_MINORS))) { - printk(KERN_ERR "kpios: Error adding cdev, %d\n", rc); - kobject_put(&kpios_cdev.kobj); - unregister_chrdev_region(dev, KPIOS_MINORS); + cdev_init(&zpios_cdev, &zpios_fops); + if ((rc = cdev_add(&zpios_cdev, dev, ZPIOS_MINORS))) { + printk(KERN_ERR "ZPIOS: Error adding cdev, %d\n", rc); + kobject_put(&zpios_cdev.kobj); + unregister_chrdev_region(dev, ZPIOS_MINORS); goto error; } /* Support for udev make driver info available in sysfs */ - kpios_class = class_create(THIS_MODULE, "kpios"); - if (IS_ERR(kpios_class)) { - rc = PTR_ERR(kpios_class); - printk(KERN_ERR "kpios: Error creating kpios class, %d\n", rc); - cdev_del(&kpios_cdev); - unregister_chrdev_region(dev, KPIOS_MINORS); + zpios_class = class_create(THIS_MODULE, "zpios"); + if (IS_ERR(zpios_class)) { + rc = PTR_ERR(zpios_class); + printk(KERN_ERR "ZPIOS: Error creating zpios class, %d\n", rc); + cdev_del(&zpios_cdev); + unregister_chrdev_region(dev, ZPIOS_MINORS); goto error; } - class_device_create(kpios_class, NULL, dev, NULL, "kpios"); + class_device_create(zpios_class, NULL, dev, NULL, "zpios"); return 0; error: - printk(KERN_ERR "kpios: Error registering kpios device, %d\n", rc); + printk(KERN_ERR "ZPIOS: Error registering zpios device, %d\n", rc); return rc; } static void -kpios_fini(void) +zpios_fini(void) { - dev_t dev = MKDEV(KPIOS_MAJOR, 0); + dev_t dev = MKDEV(ZPIOS_MAJOR, 0); - class_device_destroy(kpios_class, dev); - class_destroy(kpios_class); + class_device_destroy(zpios_class, dev); + class_destroy(zpios_class); - cdev_del(&kpios_cdev); - unregister_chrdev_region(dev, KPIOS_MINORS); + cdev_del(&zpios_cdev); + unregister_chrdev_region(dev, ZPIOS_MINORS); return; } -module_init(kpios_init); -module_exit(kpios_fini); +module_init(zpios_init); +module_exit(zpios_fini); MODULE_AUTHOR("LLNL / Sun"); MODULE_DESCRIPTION("Kernel PIOS implementation"); diff --git a/scripts/profile-zpios-pids.sh b/scripts/profile-zpios-pids.sh index 4d8adb1a15..22779dc194 100755 --- a/scripts/profile-zpios-pids.sh +++ b/scripts/profile-zpios-pids.sh @@ -43,7 +43,7 @@ for PID_FILE in `ls -r --sort=time --time=ctime ${RUN_LOG_DIR}/${RUN_ID}/pids-[0 txg_timelimit) IDX=15;; arc_reclaim) IDX=16;; l2arc_feed) IDX=17;; - kpios_io) IDX=18;; + zpios_io) IDX=18;; *) continue;; esac @@ -55,7 +55,7 @@ for PID_FILE in `ls -r --sort=time --time=ctime ${RUN_LOG_DIR}/${RUN_ID}/pids-[0 "zio_req_rd, zio_irq_rd, zio_req_wr, zio_irq_wr, " \ "zio_req_fr, zio_irq_fr, zio_req_cm, zio_irq_cm, " \ "zio_req_ctl, zio_irq_ctl, txg_quiesce, txg_sync, " \ - "txg_timelimit, arc_reclaim, l2arc_feed, kpios_io, " \ + "txg_timelimit, arc_reclaim, l2arc_feed, zpios_io, " \ "idle" HEADER=0 fi diff --git a/scripts/profile-zpios.sh b/scripts/profile-zpios.sh index 2ea110c536..fe4fc3cd35 100755 --- a/scripts/profile-zpios.sh +++ b/scripts/profile-zpios.sh @@ -21,7 +21,7 @@ POLL_INTERVAL=2.99 # txg_timelimit_t # arc_reclaim_thr # l2arc_feed_thre -# kpios_io/# +# zpios_io/# ZIO_TASKQ_PIDS=() ZIO_REQ_NUL_PIDS=() @@ -44,7 +44,7 @@ TXG_TIMELIMIT_PIDS=() ARC_RECLAIM_PIDS=() L2ARC_FEED_PIDS=() -KPIOS_IO_PIDS=() +ZPIOS_IO_PIDS=() show_pids() { echo "* zio_taskq: { ${ZIO_TASKQ_PIDS[@]} } = ${#ZIO_TASKQ_PIDS[@]}" @@ -65,7 +65,7 @@ show_pids() { echo "* txg_timelimit: { ${TXG_TIMELIMIT_PIDS[@]} } = ${#TXG_TIMELIMIT_PIDS[@]}" echo "* arc_reclaim: { ${ARC_RECLAIM_PIDS[@]} } = ${#ARC_RECLAIM_PIDS[@]}" echo "* l2arc_feed: { ${L2ARC_FEED_PIDS[@]} } = ${#L2ARC_FEED_PIDS[@]}" - echo "* kpios_io: { ${KPIOS_IO_PIDS[@]} } = ${#KPIOS_IO_PIDS[@]}" + echo "* zpios_io: { ${ZPIOS_IO_PIDS[@]} } = ${#ZPIOS_IO_PIDS[@]}" } check_pid() { @@ -154,13 +154,13 @@ aquire_pids() { "$(echo "${L2ARC_FEED_PIDS[@]}")"` ) done - # Wait for kpios_io threads to start + # Wait for zpios_io threads to start kill -s SIGHUP ${PPID} - echo "* Waiting for kpios_io threads to start" + echo "* Waiting for zpios_io threads to start" while [ ${RUN_DONE} -eq 0 ]; do - KPIOS_IO_PIDS=( `ps ax | grep kpios_io | grep -v grep | \ + ZPIOS_IO_PIDS=( `ps ax | grep zpios_io | grep -v grep | \ sed 's/^ *//g' | cut -f1 -d' '` ) - if [ ${#KPIOS_IO_PIDS[@]} -gt 0 ]; then + if [ ${#ZPIOS_IO_PIDS[@]} -gt 0 ]; then break; fi sleep 0.1 @@ -189,7 +189,7 @@ log_pids() { ${TXG_TIMELIMIT_PIDS[@]} \ ${ARC_RECLAIM_PIDS[@]} \ ${L2ARC_FEED_PIDS[@]} \ - ${KPIOS_IO_PIDS[@]} ) + ${ZPIOS_IO_PIDS[@]} ) while [ ${RUN_DONE} -eq 0 ]; do NOW=`date +%s.%N` diff --git a/scripts/zpios.sh b/scripts/zpios.sh index 4a666db159..6373a52407 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -3,7 +3,7 @@ prog=zpios.sh . ../.script-config -SPL_OPTIONS="spl=spl_debug_mask=-1 spl_debug_subsys=-1 spl_debug_mb=10 ${1}" +SPL_OPTIONS="spl=spl_debug_mask=0 spl_debug_subsys=0 spl_debug_mb=-1 ${1}" ZFS_OPTIONS="zfs=${2}" ZPIOS_OPTIONS=$3 PROFILE_ZPIOS_LOGS=$4 From b0bf494b37c3774fd145db007ae5f2ce307308af Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Wed, 14 Jan 2009 09:18:16 -0800 Subject: [PATCH 18/45] Refresh script to handle errors (missing stat files) more gracefully, additionally lengthen the default test to a useful length --- scripts/zpios.sh | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/scripts/zpios.sh b/scripts/zpios.sh index 6373a52407..9be7831e49 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -19,8 +19,10 @@ echo ------------------------- ZFS TEST LOG --------------------------------- echo -n "Date = "; date echo -n "Kernel = "; uname -r echo ------------------------------------------------------------------------ - echo + +echo "rm /etc/zfs/zpool.cache" || exit 1 +rm -f /etc/zfs/zpool.cache ./zfs.sh -v "${SPL_OPTIONS}" "${ZPOOL_OPTIONS}" || exit 1 echo ---------------------- SPL Sysctl Tunings ------------------------------ @@ -101,7 +103,7 @@ CMD="${CMDDIR}/zpios/zpios \ --path=lustre \ --chunksize=1M \ --regionsize=4M \ - --regioncount=64 \ + --regioncount=256 \ --threadcount=4 \ --offset=4M \ --cleanup \ @@ -125,16 +127,25 @@ echo ---------------------- SPL Sysctl Tunings ------------------------------ sysctl -A | grep spl echo -echo ------------------------ KSTAT Statistics ------------------------------ -echo ARCSTATS -cat /proc/spl/kstat/zfs/arcstats -echo -echo VDEV_CACHE_STATS -cat /proc/spl/kstat/zfs/vdev_cache_stats -echo -echo SLAB -cat /proc/spl/kmem/slab -echo +if [ -d /proc/spl/kstat/ ]; then + if [ -f /proc/spl/kstat/zfs/arcstats ]; then + echo "------------------ ARCSTATS --------------------------" + cat /proc/spl/kstat/zfs/arcstats + echo + fi + + if [ -f /proc/spl/kstat/zfs/vdev_cache_stats ]; then + echo "-------------- VDEV_CACHE_STATS ----------------------" + cat /proc/spl/kstat/zfs/vdev_cache_stats + echo + fi +fi + +if [ -f /proc/spl/kmem/slab ]; then + echo "-------------------- SLAB ----------------------------" + cat /proc/spl/kmem/slab + echo +fi ./zfs.sh -vu || exit 1 From bbd8816aff3ce26012f32fce95eb9ad246f37825 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Wed, 14 Jan 2009 09:59:10 -0800 Subject: [PATCH 19/45] Add missing echo --- scripts/zpios.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/zpios.sh b/scripts/zpios.sh index 9be7831e49..54601402d2 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -121,6 +121,7 @@ if [ -n "${ZPIOS_POST}" ]; then ${ZPIOS_POST} || exit 1 fi +echo "${CMDDIR}/zpool/zpool destroy lustre" ${CMDDIR}/zpool/zpool destroy lustre echo ---------------------- SPL Sysctl Tunings ------------------------------ From e090338e7bf48c16c86c2c707d274862f5c8e21b Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Wed, 14 Jan 2009 10:40:50 -0800 Subject: [PATCH 20/45] Update zpios script --- scripts/zpios.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/scripts/zpios.sh b/scripts/zpios.sh index 54601402d2..09dbb1603e 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -23,7 +23,10 @@ echo echo "rm /etc/zfs/zpool.cache" || exit 1 rm -f /etc/zfs/zpool.cache -./zfs.sh -v "${SPL_OPTIONS}" "${ZPOOL_OPTIONS}" || exit 1 + +echo "./zfs.sh" +./zfs.sh "${SPL_OPTIONS}" "${ZPOOL_OPTIONS}" || exit 1 +echo echo ---------------------- SPL Sysctl Tunings ------------------------------ sysctl -A | grep spl @@ -121,8 +124,10 @@ if [ -n "${ZPIOS_POST}" ]; then ${ZPIOS_POST} || exit 1 fi +echo echo "${CMDDIR}/zpool/zpool destroy lustre" ${CMDDIR}/zpool/zpool destroy lustre +echo echo ---------------------- SPL Sysctl Tunings ------------------------------ sysctl -A | grep spl @@ -148,6 +153,7 @@ if [ -f /proc/spl/kmem/slab ]; then echo fi -./zfs.sh -vu || exit 1 +echo "./zfs.sh -u" +./zfs.sh -u || exit 1 exit 0 From 7c98f76d302b154eece3fbb55dc1b4c70afe4265 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Fri, 16 Jan 2009 12:19:15 -0800 Subject: [PATCH 21/45] Update zpios infrastructure to be more flexible --- .../zpios-profile-disk.sh} | 0 .../zpios-profile-pids.sh} | 0 .../zpios-profile-post.sh} | 4 +- .../zpios-profile-pre.sh} | 6 +- .../zpios-profile.sh} | 0 scripts/{survey.sh => zpios-survey.sh} | 0 scripts/zpios-test/small.cfg | 50 +++ scripts/zpios.sh | 305 +++++++++++------- 8 files changed, 238 insertions(+), 127 deletions(-) rename scripts/{profile-zpios-disk.sh => zpios-profile/zpios-profile-disk.sh} (100%) rename scripts/{profile-zpios-pids.sh => zpios-profile/zpios-profile-pids.sh} (100%) rename scripts/{profile-zpios-post.sh => zpios-profile/zpios-profile-post.sh} (92%) rename scripts/{profile-zpios-pre.sh => zpios-profile/zpios-profile-pre.sh} (94%) rename scripts/{profile-zpios.sh => zpios-profile/zpios-profile.sh} (100%) rename scripts/{survey.sh => zpios-survey.sh} (100%) create mode 100755 scripts/zpios-test/small.cfg diff --git a/scripts/profile-zpios-disk.sh b/scripts/zpios-profile/zpios-profile-disk.sh similarity index 100% rename from scripts/profile-zpios-disk.sh rename to scripts/zpios-profile/zpios-profile-disk.sh diff --git a/scripts/profile-zpios-pids.sh b/scripts/zpios-profile/zpios-profile-pids.sh similarity index 100% rename from scripts/profile-zpios-pids.sh rename to scripts/zpios-profile/zpios-profile-pids.sh diff --git a/scripts/profile-zpios-post.sh b/scripts/zpios-profile/zpios-profile-post.sh similarity index 92% rename from scripts/profile-zpios-post.sh rename to scripts/zpios-profile/zpios-profile-post.sh index 16bc590f80..8f770f3819 100755 --- a/scripts/profile-zpios-post.sh +++ b/scripts/zpios-profile/zpios-profile-post.sh @@ -19,10 +19,10 @@ RUN_THREAD_DELAY=${12} RUN_FLAGS=${13} RUN_RESULT=${14} -PROFILE_ZPIOS_PIDS_BIN=/home/behlendo/src/zfs/scripts/profile-zpios-pids.sh +PROFILE_ZPIOS_PIDS_BIN=${TOPDIR}/scripts/profile-zpios-pids.sh PROFILE_ZPIOS_PIDS_LOG=${RUN_LOG_DIR}/${RUN_ID}/pids-summary.csv -PROFILE_ZPIOS_DISK_BIN=/home/behlendo/src/zfs/scripts/profile-zpios-disk.sh +PROFILE_ZPIOS_DISK_BIN=${TOPDIR}/scripts/profile-zpios-disk.sh PROFILE_ZPIOS_DISK_LOG=${RUN_LOG_DIR}/${RUN_ID}/disk-summary.csv PROFILE_ZPIOS_ARC_LOG=${RUN_LOG_DIR}/${RUN_ID}/arcstats diff --git a/scripts/profile-zpios-pre.sh b/scripts/zpios-profile/zpios-profile-pre.sh similarity index 94% rename from scripts/profile-zpios-pre.sh rename to scripts/zpios-profile/zpios-profile-pre.sh index 675b80240a..64801d3bf7 100755 --- a/scripts/profile-zpios-pre.sh +++ b/scripts/zpios-profile/zpios-profile-pre.sh @@ -1,5 +1,7 @@ #!/bin/bash -# profile-zpios-pre.sh + +prog=profile-zpios-pre.sh +. ../.script-config trap "PROFILE_ZPIOS_READY=1" SIGHUP @@ -19,7 +21,7 @@ RUN_THREAD_DELAY=${12} RUN_FLAGS=${13} RUN_RESULT=${14} -PROFILE_ZPIOS_BIN=/home/behlendo/src/zfs/scripts/profile-zpios.sh +PROFILE_ZPIOS_BIN=${IOPDIR}/scripts/profile-zpios.sh PROFILE_ZPIOS_READY=0 OPROFILE_LOG=${RUN_LOG_DIR}/${RUN_ID}/oprofile.txt diff --git a/scripts/profile-zpios.sh b/scripts/zpios-profile/zpios-profile.sh similarity index 100% rename from scripts/profile-zpios.sh rename to scripts/zpios-profile/zpios-profile.sh diff --git a/scripts/survey.sh b/scripts/zpios-survey.sh similarity index 100% rename from scripts/survey.sh rename to scripts/zpios-survey.sh diff --git a/scripts/zpios-test/small.cfg b/scripts/zpios-test/small.cfg new file mode 100755 index 0000000000..3e2d0d8454 --- /dev/null +++ b/scripts/zpios-test/small.cfg @@ -0,0 +1,50 @@ +#!/bin/bash +# +# +# Usage: zpios +# --chunksize -c =values +# --chunksize_low -a =value +# --chunksize_high -b =value +# --chunksize_incr -g =value +# --offset -o =values +# --offset_low -m =value +# --offset_high -q =value +# --offset_incr -r =value +# --regioncount -n =values +# --regioncount_low -i =value +# --regioncount_high -j =value +# --regioncount_incr -k =value +# --threadcount -t =values +# --threadcount_low -l =value +# --threadcount_high -h =value +# --threadcount_incr -e =value +# --regionsize -s =values +# --regionsize_low -A =value +# --regionsize_high -B =value +# --regionsize_incr -C =value +# --cleanup -x +# --verify -V +# --zerocopy -z +# --threaddelay -T =jiffies +# --regionnoise -I =shift +# --chunknoise -N =bytes +# --prerun -P =pre-command +# --postrun -R =post-command +# --log -G =log directory +# --pool | --path -p =pool name +# --load -L =dmuio +# --help -? =this help +# --verbose -v =increase verbosity + +ZPIOS_CMD="${CMDDIR}/zpios/zpios \ + --load=dmuio \ + --path=zpios \ + --chunksize=1M \ + --regionsize=4M \ + --regioncount=256 \ + --threadcount=4 \ + --offset=4M \ + --cleanup \ + --verbose \ + --human-readable \ + ${ZPIOS_OPTIONS} diff --git a/scripts/zpios.sh b/scripts/zpios.sh index 09dbb1603e..740ec8bdb9 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -1,159 +1,218 @@ #!/bin/bash +# +# Wrapper script for easily running zpios based tests +# -prog=zpios.sh -. ../.script-config +. ./common.sh +PROG=zpios.sh -SPL_OPTIONS="spl=spl_debug_mask=0 spl_debug_subsys=0 spl_debug_mb=-1 ${1}" -ZFS_OPTIONS="zfs=${2}" -ZPIOS_OPTIONS=$3 -PROFILE_ZPIOS_LOGS=$4 -ZPIOS_PRE=$5 -ZPIOS_POST=$6 +PROFILE_ZPIOS_PRE=${TOPDIR}/scripts/profile-zpios-pre.sh +PROFILE_ZPIOS_POST=${TOPDIR}/scripts/profile-zpios-post.sh -PROFILE_ZPIOS_PRE=/home/behlendo/src/zfs/scripts/profile-zpios-pre.sh -PROFILE_ZPIOS_POST=/home/behlendo/src/zfs/scripts/profile-zpios-post.sh +MODULES=( \ + ${MODDIR}/zpios/zpios.ko \ +) -DEVICES="/dev/hda" +usage() { +cat << EOF +USAGE: +$0 [hvp] [c ] -echo ------------------------- ZFS TEST LOG --------------------------------- -echo -n "Date = "; date -echo -n "Kernel = "; uname -r -echo ------------------------------------------------------------------------ -echo +DESCRIPTION: + Helper script for easy zpios benchmarking. -echo "rm /etc/zfs/zpool.cache" || exit 1 -rm -f /etc/zfs/zpool.cache +OPTIONS: + -h Show this message + -v Verbose + -p Enable profiling + -c Specify disk configuration -echo "./zfs.sh" -./zfs.sh "${SPL_OPTIONS}" "${ZPOOL_OPTIONS}" || exit 1 -echo +EOF +} -echo ---------------------- SPL Sysctl Tunings ------------------------------ -sysctl -A | grep spl -echo +print_header() { + echo --------------------- ZPIOS RESULTS ---------------------------- + echo -n "Date: "; date + echo -n "Kernel: "; uname -r + dmesg | grep "Loaded Solaris Porting Layer" | tail -n1 + dmesg | grep "Loaded ZFS Filesystem" | tail -n1 + echo +} -echo ------------------- SPL Module Tunings --------------------------- -if [ -d /sys/module/spl/parameters ]; then - grep [0-9] /sys/module/spl/parameters/* -else - grep [0-9] /sys/module/spl/* +print_spl_info() { + echo --------------------- SPL Tunings ------------------------------ + sysctl -A | grep spl + + if [ -d /sys/module/spl/parameters ]; then + grep [0-9] /sys/module/spl/parameters/* + else + grep [0-9] /sys/module/spl/* + fi + + echo +} + +print_zfs_info() { + echo --------------------- ZFS Tunings ------------------------------ + sysctl -A | grep zfs + + if [ -d /sys/module/zfs/parameters ]; then + grep [0-9] /sys/module/zfs/parameters/* + else + grep [0-9] /sys/module/zfs/* + fi + + echo +} + +print_stats() { + echo ---------------------- Statistics ------------------------------- + sysctl -A | grep spl | grep stack_max + + if [ -d /proc/spl/kstat/ ]; then + if [ -f /proc/spl/kstat/zfs/arcstats ]; then + echo "* ARC" + cat /proc/spl/kstat/zfs/arcstats + echo + fi + + if [ -f /proc/spl/kstat/zfs/vdev_cache_stats ]; then + echo "* VDEV Cache" + cat /proc/spl/kstat/zfs/vdev_cache_stats + echo + fi + fi + + if [ -f /proc/spl/kmem/slab ]; then + echo "* SPL SLAB" + cat /proc/spl/kmem/slab + echo + fi +} + +check_config() { + + if [ ! -f ${ZPOOL_CONFIG} ]; then + local NAME=`basename ${ZPOOL_CONFIG} .cfg` + ERROR="Unknown config '${NAME}', available configs are:\n" + + for CFG in `ls ${TOPDIR}/scripts/zpool-config/`; do + local NAME=`basename ${CFG} .cfg` + ERROR="${ERROR}${NAME}\n" + done + + return 1 + fi + + return 0 +} + +check_test() { + + if [ ! -f ${ZPIOS_TEST} ]; then + local NAME=`basename ${ZPIOS_TEST} .cfg` + ERROR="Unknown test '${NAME}', available tests are:\n" + + for TST in `ls ${TOPDIR}/scripts/zpios-test/`; do + local NAME=`basename ${TST} .cfg` + ERROR="${ERROR}${NAME}\n" + done + + return 1 + fi + + return 0 +} + +PROFILE= +ZPOOL_CONFIG="zpool-config.cfg" +ZPIOS_TEST="zpios-test.cfg" + +while getopts 'hvpc:t:' OPTION; do + case $OPTION in + h) + usage + exit 1 + ;; + v) + VERBOSE=1 + ;; + p) + PROFILE=1 + ;; + c) + ZPOOL_CONFIG=${TOPDIR}/scripts/zpool-config/${OPTARG}.cfg + ;; + t) + ZPIOS_TEST=${TOPDIR}/scripts/zpios-test/${OPTARG}.cfg + ;; + ?) + usage + exit + ;; + esac +done + +if [ $(id -u) != 0 ]; then + die "Must run as root" fi -echo -echo ------------------- ZFS Module Tunings --------------------------- -if [ -d /sys/module/zfs/parameters ]; then - grep [0-9] /sys/module/zfs/parameters/* -else - grep [0-9] /sys/module/zfs/* +# Validate your using a known config and test +check_config || die "${ERROR}" +check_test || die "${ERROR}" + +# Pull in the zpios test module is not loaded. If this fails it is +# likely because the full module stack was not yet loaded with zfs.sh +if check_modules; then + if ! load_modules; then + die "Run 'zfs.sh' to ensure the full module stack is loaded" + fi fi -echo -echo "${CMDDIR}/zpool/zpool create -f lustre ${DEVICES}" -${CMDDIR}/zpool/zpool create -f lustre ${DEVICES} || exit 1 +if [ ${VERBOSE} ]; then + print_header + print_spl_info + print_zfs_info +fi -echo "${CMDDIR}/zpool/zpool status lustre" -${CMDDIR}/zpool/zpool status lustre || exit 1 +# Source the zpool configuration +. ${ZPOOL_CONFIG} -echo "Waiting for /dev/zpios to come up..." +msg "${CMDDIR}/zpool/zpool status zpios" +${CMDDIR}/zpool/zpool status zpios || exit 1 + +msg "Waiting for /dev/zpios to come up..." while [ ! -c /dev/zpios ]; do sleep 1 done if [ -n "${ZPIOS_PRE}" ]; then + msg "Executing ${ZPIOS_PRE}" ${ZPIOS_PRE} || exit 1 fi -# Usage: zpios -# --chunksize -c =values -# --chunksize_low -a =value -# --chunksize_high -b =value -# --chunksize_incr -g =value -# --offset -o =values -# --offset_low -m =value -# --offset_high -q =value -# --offset_incr -r =value -# --regioncount -n =values -# --regioncount_low -i =value -# --regioncount_high -j =value -# --regioncount_incr -k =value -# --threadcount -t =values -# --threadcount_low -l =value -# --threadcount_high -h =value -# --threadcount_incr -e =value -# --regionsize -s =values -# --regionsize_low -A =value -# --regionsize_high -B =value -# --regionsize_incr -C =value -# --cleanup -x -# --verify -V -# --zerocopy -z -# --threaddelay -T =jiffies -# --regionnoise -I =shift -# --chunknoise -N =bytes -# --prerun -P =pre-command -# --postrun -R =post-command -# --log -G =log directory -# --pool | --path -p =pool name -# --load -L =dmuio -# --help -? =this help -# --verbose -v =increase verbosity +# Source the zpios test configuration +. ${ZPIOS_TEST} -# --prerun=${PROFILE_ZPIOS_PRE} \ -# --postrun=${PROFILE_ZPIOS_POST} \ +if [ $PROFILE ]; then + ZPIOS_CMD="${ZPIOS_CMD} --log=${PROFILE_ZPIOS_LOGS}" + ZPIOS_CMD="${ZPIOS_CMD} --prerun=${PROFILE_ZPIOS_PRE}" + ZPIOS_CMD="${ZPIOS_CMD} --postrun=${PROFILE_ZPIOS_POST}" +fi -CMD="${CMDDIR}/zpios/zpios \ - --load=dmuio \ - --path=lustre \ - --chunksize=1M \ - --regionsize=4M \ - --regioncount=256 \ - --threadcount=4 \ - --offset=4M \ - --cleanup \ - --verbose \ - --human-readable \ - ${ZPIOS_OPTIONS} \ - --log=${PROFILE_ZPIOS_LOGS}" echo date -echo ${CMD} -$CMD || exit 1 -date +echo ${ZPIOS_CMD} +$ZPIOS_CMD || exit 1 if [ -n "${ZPIOS_POST}" ]; then + msg "Executing ${ZPIOS_POST}" ${ZPIOS_POST} || exit 1 fi -echo -echo "${CMDDIR}/zpool/zpool destroy lustre" -${CMDDIR}/zpool/zpool destroy lustre -echo +msg "${CMDDIR}/zpool/zpool destroy zpios" +${CMDDIR}/zpool/zpool destroy zpios -echo ---------------------- SPL Sysctl Tunings ------------------------------ -sysctl -A | grep spl -echo - -if [ -d /proc/spl/kstat/ ]; then - if [ -f /proc/spl/kstat/zfs/arcstats ]; then - echo "------------------ ARCSTATS --------------------------" - cat /proc/spl/kstat/zfs/arcstats - echo - fi - - if [ -f /proc/spl/kstat/zfs/vdev_cache_stats ]; then - echo "-------------- VDEV_CACHE_STATS ----------------------" - cat /proc/spl/kstat/zfs/vdev_cache_stats - echo - fi -fi - -if [ -f /proc/spl/kmem/slab ]; then - echo "-------------------- SLAB ----------------------------" - cat /proc/spl/kmem/slab - echo -fi - -echo "./zfs.sh -u" -./zfs.sh -u || exit 1 +print_stats exit 0 From 0289edb7e6a25de094811841ff90c045305e8c4a Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Fri, 16 Jan 2009 12:23:53 -0800 Subject: [PATCH 22/45] Update to use the zpool-create.sh script --- scripts/zpios.sh | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/scripts/zpios.sh b/scripts/zpios.sh index 740ec8bdb9..844ab55153 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -90,23 +90,6 @@ print_stats() { fi } -check_config() { - - if [ ! -f ${ZPOOL_CONFIG} ]; then - local NAME=`basename ${ZPOOL_CONFIG} .cfg` - ERROR="Unknown config '${NAME}', available configs are:\n" - - for CFG in `ls ${TOPDIR}/scripts/zpool-config/`; do - local NAME=`basename ${CFG} .cfg` - ERROR="${ERROR}${NAME}\n" - done - - return 1 - fi - - return 0 -} - check_test() { if [ ! -f ${ZPIOS_TEST} ]; then @@ -141,7 +124,7 @@ while getopts 'hvpc:t:' OPTION; do PROFILE=1 ;; c) - ZPOOL_CONFIG=${TOPDIR}/scripts/zpool-config/${OPTARG}.cfg + ZPOOL_CONFIG=${OPTARG} ;; t) ZPIOS_TEST=${TOPDIR}/scripts/zpios-test/${OPTARG}.cfg @@ -157,8 +140,7 @@ if [ $(id -u) != 0 ]; then die "Must run as root" fi -# Validate your using a known config and test -check_config || die "${ERROR}" +# Validate your using a known test check_test || die "${ERROR}" # Pull in the zpios test module is not loaded. If this fails it is @@ -175,8 +157,8 @@ if [ ${VERBOSE} ]; then print_zfs_info fi -# Source the zpool configuration -. ${ZPOOL_CONFIG} +# Create the zpool configuration +./zpool-create.sh -c ${ZPOOL_CONFIG} || exit 1 msg "${CMDDIR}/zpool/zpool status zpios" ${CMDDIR}/zpool/zpool status zpios || exit 1 From e7b183b7f22ff700fcb779438e57bed5f3cbf8c8 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Fri, 16 Jan 2009 13:25:16 -0800 Subject: [PATCH 23/45] Minor script updates almost ready to test --- scripts/zpios.sh | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/scripts/zpios.sh b/scripts/zpios.sh index 844ab55153..57c90ba750 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -108,8 +108,9 @@ check_test() { } PROFILE= -ZPOOL_CONFIG="zpool-config.cfg" -ZPIOS_TEST="zpios-test.cfg" +ZPOOL_CONFIG=zpool-config.cfg +ZPIOS_TEST=zpios-test.cfg +ZPOOL_NAME=zpios while getopts 'hvpc:t:' OPTION; do case $OPTION in @@ -119,6 +120,7 @@ while getopts 'hvpc:t:' OPTION; do ;; v) VERBOSE=1 + VERBOSE_FLAG="-v" ;; p) PROFILE=1 @@ -151,6 +153,11 @@ if check_modules; then fi fi +msg "Waiting for /dev/zpios to come up..." +while [ ! -c /dev/zpios ]; do + sleep 1 +done + if [ ${VERBOSE} ]; then print_header print_spl_info @@ -158,15 +165,7 @@ if [ ${VERBOSE} ]; then fi # Create the zpool configuration -./zpool-create.sh -c ${ZPOOL_CONFIG} || exit 1 - -msg "${CMDDIR}/zpool/zpool status zpios" -${CMDDIR}/zpool/zpool status zpios || exit 1 - -msg "Waiting for /dev/zpios to come up..." -while [ ! -c /dev/zpios ]; do - sleep 1 -done +./zpool-create.sh ${VERBOSE_FLAG} -p ${ZPOOL_NAME} -c ${ZPOOL_CONFIG} || exit 1 if [ -n "${ZPIOS_PRE}" ]; then msg "Executing ${ZPIOS_PRE}" From 87d7387f6297c29cb532988f96998d231cabd5a4 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Fri, 16 Jan 2009 13:56:14 -0800 Subject: [PATCH 24/45] Minor fixes --- scripts/zpios-profile/zpios-profile-disk.sh | 3 ++- scripts/zpios-profile/zpios-profile-pids.sh | 3 ++- scripts/zpios-profile/zpios-profile-post.sh | 6 +++--- scripts/zpios-profile/zpios-profile-pre.sh | 6 +++--- scripts/zpios-profile/zpios-profile.sh | 4 +++- scripts/zpios-test/small.cfg | 2 +- scripts/zpios.sh | 10 +++++----- 7 files changed, 19 insertions(+), 15 deletions(-) diff --git a/scripts/zpios-profile/zpios-profile-disk.sh b/scripts/zpios-profile/zpios-profile-disk.sh index 38607a5492..b56ee1ee40 100755 --- a/scripts/zpios-profile/zpios-profile-disk.sh +++ b/scripts/zpios-profile/zpios-profile-disk.sh @@ -1,5 +1,4 @@ #!/bin/bash -# profile-zpios-disk.sh # # /proc/diskinfo # Field 1 -- device name @@ -15,6 +14,8 @@ # Field 11 -- # of milliseconds spent doing I/Os # Field 12 -- weighted # of milliseconds spent doing I/Os +PROG=zpios-profile-disk.sh + RUN_PIDS=${0} RUN_LOG_DIR=${1} RUN_ID=${2} diff --git a/scripts/zpios-profile/zpios-profile-pids.sh b/scripts/zpios-profile/zpios-profile-pids.sh index 22779dc194..3514b38e2a 100755 --- a/scripts/zpios-profile/zpios-profile-pids.sh +++ b/scripts/zpios-profile/zpios-profile-pids.sh @@ -1,5 +1,6 @@ #!/bin/bash -# profile-zpios-pids.sh + +PROG=zpios-profile-pids.sh RUN_PIDS=${0} RUN_LOG_DIR=${1} diff --git a/scripts/zpios-profile/zpios-profile-post.sh b/scripts/zpios-profile/zpios-profile-post.sh index 8f770f3819..0f2d59b0bb 100755 --- a/scripts/zpios-profile/zpios-profile-post.sh +++ b/scripts/zpios-profile/zpios-profile-post.sh @@ -1,7 +1,7 @@ #!/bin/bash -prog=profile-zpios-post.sh . ../.script-config +PROG=zpios-profile-post.sh RUN_POST=${0} RUN_PHASE=${1} @@ -19,10 +19,10 @@ RUN_THREAD_DELAY=${12} RUN_FLAGS=${13} RUN_RESULT=${14} -PROFILE_ZPIOS_PIDS_BIN=${TOPDIR}/scripts/profile-zpios-pids.sh +PROFILE_ZPIOS_PIDS_BIN=${TOPDIR}/scripts/zpios-profile/zpios-profile-pids.sh PROFILE_ZPIOS_PIDS_LOG=${RUN_LOG_DIR}/${RUN_ID}/pids-summary.csv -PROFILE_ZPIOS_DISK_BIN=${TOPDIR}/scripts/profile-zpios-disk.sh +PROFILE_ZPIOS_DISK_BIN=${TOPDIR}/scripts/zpios-/profile/zpios-profile-disk.sh PROFILE_ZPIOS_DISK_LOG=${RUN_LOG_DIR}/${RUN_ID}/disk-summary.csv PROFILE_ZPIOS_ARC_LOG=${RUN_LOG_DIR}/${RUN_ID}/arcstats diff --git a/scripts/zpios-profile/zpios-profile-pre.sh b/scripts/zpios-profile/zpios-profile-pre.sh index 64801d3bf7..2d6d1be2dd 100755 --- a/scripts/zpios-profile/zpios-profile-pre.sh +++ b/scripts/zpios-profile/zpios-profile-pre.sh @@ -1,7 +1,7 @@ #!/bin/bash -prog=profile-zpios-pre.sh -. ../.script-config +. ../common.sh +PROG=zpios-profile-pre.sh trap "PROFILE_ZPIOS_READY=1" SIGHUP @@ -21,7 +21,7 @@ RUN_THREAD_DELAY=${12} RUN_FLAGS=${13} RUN_RESULT=${14} -PROFILE_ZPIOS_BIN=${IOPDIR}/scripts/profile-zpios.sh +PROFILE_ZPIOS_BIN=${IOPDIR}/scripts/zpios-profile/zpios-profile.sh PROFILE_ZPIOS_READY=0 OPROFILE_LOG=${RUN_LOG_DIR}/${RUN_ID}/oprofile.txt diff --git a/scripts/zpios-profile/zpios-profile.sh b/scripts/zpios-profile/zpios-profile.sh index fe4fc3cd35..d3ff779eac 100755 --- a/scripts/zpios-profile/zpios-profile.sh +++ b/scripts/zpios-profile/zpios-profile.sh @@ -1,5 +1,7 @@ #!/bin/bash -# profile-zpios.sh + + +PROG=zpios-profile.sh trap "RUN_DONE=1" SIGHUP diff --git a/scripts/zpios-test/small.cfg b/scripts/zpios-test/small.cfg index 3e2d0d8454..35dbf016df 100755 --- a/scripts/zpios-test/small.cfg +++ b/scripts/zpios-test/small.cfg @@ -47,4 +47,4 @@ ZPIOS_CMD="${CMDDIR}/zpios/zpios \ --cleanup \ --verbose \ --human-readable \ - ${ZPIOS_OPTIONS} + ${ZPIOS_OPTIONS}" diff --git a/scripts/zpios.sh b/scripts/zpios.sh index 57c90ba750..aca22026b8 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -6,8 +6,9 @@ . ./common.sh PROG=zpios.sh -PROFILE_ZPIOS_PRE=${TOPDIR}/scripts/profile-zpios-pre.sh -PROFILE_ZPIOS_POST=${TOPDIR}/scripts/profile-zpios-post.sh +PROFILE_ZPIOS_PRE=${TOPDIR}/scripts/zpios-profile/zpios-profile-pre.sh +PROFILE_ZPIOS_POST=${TOPDIR}/scripts/zpios-profile/zpios-profile-post.sh +PROFILE_ZPIOS_LOG=/tmp/ MODULES=( \ ${MODDIR}/zpios/zpios.ko \ @@ -25,7 +26,7 @@ OPTIONS: -h Show this message -v Verbose -p Enable profiling - -c Specify disk configuration + -c Zpool configuration EOF } @@ -153,7 +154,6 @@ if check_modules; then fi fi -msg "Waiting for /dev/zpios to come up..." while [ ! -c /dev/zpios ]; do sleep 1 done @@ -176,7 +176,7 @@ fi . ${ZPIOS_TEST} if [ $PROFILE ]; then - ZPIOS_CMD="${ZPIOS_CMD} --log=${PROFILE_ZPIOS_LOGS}" + ZPIOS_CMD="${ZPIOS_CMD} --log=${PROFILE_ZPIOS_LOG}" ZPIOS_CMD="${ZPIOS_CMD} --prerun=${PROFILE_ZPIOS_PRE}" ZPIOS_CMD="${ZPIOS_CMD} --postrun=${PROFILE_ZPIOS_POST}" fi From 81a6dfd781809acd23bded992dca51243f1e9a70 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Fri, 16 Jan 2009 14:58:48 -0800 Subject: [PATCH 25/45] Minor cleanup, module unload --- scripts/zpios.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/zpios.sh b/scripts/zpios.sh index aca22026b8..680f5c54b2 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -186,14 +186,16 @@ date echo ${ZPIOS_CMD} $ZPIOS_CMD || exit 1 +print_stats + if [ -n "${ZPIOS_POST}" ]; then msg "Executing ${ZPIOS_POST}" ${ZPIOS_POST} || exit 1 fi -msg "${CMDDIR}/zpool/zpool destroy zpios" -${CMDDIR}/zpool/zpool destroy zpios +msg "${CMDDIR}/zpool/zpool destroy ${ZPOOL_NAME}" +${CMDDIR}/zpool/zpool destroy ${ZPOOL_NAME} -print_stats +unload_modules exit 0 From 7ac621f98b13bdf882a3bead51d8ea13193ddace Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Fri, 16 Jan 2009 15:07:30 -0800 Subject: [PATCH 26/45] Update zpios usage --- scripts/zpios.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/zpios.sh b/scripts/zpios.sh index 680f5c54b2..49165c3562 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -17,7 +17,7 @@ MODULES=( \ usage() { cat << EOF USAGE: -$0 [hvp] [c ] +$0 [hvp] <-c config> <-t test> DESCRIPTION: Helper script for easy zpios benchmarking. @@ -27,6 +27,7 @@ OPTIONS: -v Verbose -p Enable profiling -c Zpool configuration + -t Zpios test EOF } From eb205c6e624008d7e4aa0db40464e2a1eec64205 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 20 Jan 2009 14:32:02 -0800 Subject: [PATCH 27/45] Update zpios to use zpool-create -d arg, and zpios-start/stop --- .../{small.cfg => 1th-16rc-4rs-1cs-4off.sh} | 14 ++++++-- scripts/zpios-test/tiny.sh | 1 + scripts/zpios.sh | 36 +++++++------------ 3 files changed, 24 insertions(+), 27 deletions(-) rename scripts/zpios-test/{small.cfg => 1th-16rc-4rs-1cs-4off.sh} (91%) create mode 120000 scripts/zpios-test/tiny.sh diff --git a/scripts/zpios-test/small.cfg b/scripts/zpios-test/1th-16rc-4rs-1cs-4off.sh similarity index 91% rename from scripts/zpios-test/small.cfg rename to scripts/zpios-test/1th-16rc-4rs-1cs-4off.sh index 35dbf016df..61f85253b2 100755 --- a/scripts/zpios-test/small.cfg +++ b/scripts/zpios-test/1th-16rc-4rs-1cs-4off.sh @@ -39,12 +39,20 @@ ZPIOS_CMD="${CMDDIR}/zpios/zpios \ --load=dmuio \ --path=zpios \ - --chunksize=1M \ + --threadcount=1 \ + --regioncount=16 \ --regionsize=4M \ - --regioncount=256 \ - --threadcount=4 \ + --chunksize=1M \ --offset=4M \ --cleanup \ --verbose \ --human-readable \ ${ZPIOS_OPTIONS}" + +zpios_start() { + echo ${ZPIOS_CMD} + $ZPIOS_CMD || exit 1 +} + +zpios_stop() { +} diff --git a/scripts/zpios-test/tiny.sh b/scripts/zpios-test/tiny.sh new file mode 120000 index 0000000000..ba8b7cd0c1 --- /dev/null +++ b/scripts/zpios-test/tiny.sh @@ -0,0 +1 @@ +1th-16rc-4rs-1cs-4off.sh \ No newline at end of file diff --git a/scripts/zpios.sh b/scripts/zpios.sh index 49165c3562..8d452522d9 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -95,11 +95,11 @@ print_stats() { check_test() { if [ ! -f ${ZPIOS_TEST} ]; then - local NAME=`basename ${ZPIOS_TEST} .cfg` + local NAME=`basename ${ZPIOS_TEST} .sh` ERROR="Unknown test '${NAME}', available tests are:\n" for TST in `ls ${TOPDIR}/scripts/zpios-test/`; do - local NAME=`basename ${TST} .cfg` + local NAME=`basename ${TST} .sh` ERROR="${ERROR}${NAME}\n" done @@ -110,8 +110,8 @@ check_test() { } PROFILE= -ZPOOL_CONFIG=zpool-config.cfg -ZPIOS_TEST=zpios-test.cfg +ZPOOL_CONFIG=zpool-config.sh +ZPIOS_TEST=zpios-test.sh ZPOOL_NAME=zpios while getopts 'hvpc:t:' OPTION; do @@ -131,7 +131,7 @@ while getopts 'hvpc:t:' OPTION; do ZPOOL_CONFIG=${OPTARG} ;; t) - ZPIOS_TEST=${TOPDIR}/scripts/zpios-test/${OPTARG}.cfg + ZPIOS_TEST=${TOPDIR}/scripts/zpios-test/${OPTARG}.sh ;; ?) usage @@ -144,8 +144,9 @@ if [ $(id -u) != 0 ]; then die "Must run as root" fi -# Validate your using a known test +# Validate and source your test config check_test || die "${ERROR}" +. ${ZPIOS_TEST} # Pull in the zpios test module is not loaded. If this fails it is # likely because the full module stack was not yet loaded with zfs.sh @@ -168,14 +169,6 @@ fi # Create the zpool configuration ./zpool-create.sh ${VERBOSE_FLAG} -p ${ZPOOL_NAME} -c ${ZPOOL_CONFIG} || exit 1 -if [ -n "${ZPIOS_PRE}" ]; then - msg "Executing ${ZPIOS_PRE}" - ${ZPIOS_PRE} || exit 1 -fi - -# Source the zpios test configuration -. ${ZPIOS_TEST} - if [ $PROFILE ]; then ZPIOS_CMD="${ZPIOS_CMD} --log=${PROFILE_ZPIOS_LOG}" ZPIOS_CMD="${ZPIOS_CMD} --prerun=${PROFILE_ZPIOS_PRE}" @@ -184,19 +177,14 @@ fi echo date -echo ${ZPIOS_CMD} -$ZPIOS_CMD || exit 1 - +zpios_start +zpios_stop print_stats -if [ -n "${ZPIOS_POST}" ]; then - msg "Executing ${ZPIOS_POST}" - ${ZPIOS_POST} || exit 1 -fi - -msg "${CMDDIR}/zpool/zpool destroy ${ZPOOL_NAME}" -${CMDDIR}/zpool/zpool destroy ${ZPOOL_NAME} +# Destroy the zpool configuration +./zpool-create.sh ${VERBOSE_FLAG} -p ${ZPOOL_NAME} -c ${ZPOOL_CONFIG} -d || exit 1 +# Unload the test module stack unload_modules exit 0 From e125a95615099c533601576613d2bb08997682d8 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 20 Jan 2009 15:34:02 -0800 Subject: [PATCH 28/45] Minor script cleanup --- scripts/zpios-test/1th-16rc-4rs-1cs-4off.sh | 5 +++-- scripts/zpios.sh | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/zpios-test/1th-16rc-4rs-1cs-4off.sh b/scripts/zpios-test/1th-16rc-4rs-1cs-4off.sh index 61f85253b2..37493b6f32 100755 --- a/scripts/zpios-test/1th-16rc-4rs-1cs-4off.sh +++ b/scripts/zpios-test/1th-16rc-4rs-1cs-4off.sh @@ -38,7 +38,7 @@ ZPIOS_CMD="${CMDDIR}/zpios/zpios \ --load=dmuio \ - --path=zpios \ + --path=${ZPOOL_NAME} \ --threadcount=1 \ --regioncount=16 \ --regionsize=4M \ @@ -51,8 +51,9 @@ ZPIOS_CMD="${CMDDIR}/zpios/zpios \ zpios_start() { echo ${ZPIOS_CMD} - $ZPIOS_CMD || exit 1 + ${ZPIOS_CMD} || exit 1 } zpios_stop() { + echo } diff --git a/scripts/zpios.sh b/scripts/zpios.sh index 8d452522d9..5ba97b0a68 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -90,6 +90,8 @@ print_stats() { cat /proc/spl/kmem/slab echo fi + + echo } check_test() { From 2334ba2bb1f5e2a780aecac079a33b5d0f1df1ef Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 20 Jan 2009 15:54:50 -0800 Subject: [PATCH 29/45] Add a script scripts, update Makefiles --- configure.ac | 2 + scripts/Makefile.am | 3 +- scripts/zpios-profile/Makefile.am | 1 + .../zpios-test/16th-8192rc-4rs-1cs-4off.sh | 59 +++++++++++++++++++ .../zpios-test/256th-65536rc-4rs-1cs-4off.sh | 59 +++++++++++++++++++ scripts/zpios-test/Makefile.am | 1 + scripts/zpios-test/large.sh | 1 + scripts/zpios-test/medium.sh | 1 + 8 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 scripts/zpios-profile/Makefile.am create mode 100755 scripts/zpios-test/16th-8192rc-4rs-1cs-4off.sh create mode 100755 scripts/zpios-test/256th-65536rc-4rs-1cs-4off.sh create mode 100644 scripts/zpios-test/Makefile.am create mode 120000 scripts/zpios-test/large.sh create mode 120000 scripts/zpios-test/medium.sh diff --git a/configure.ac b/configure.ac index 3d9e1ae97c..5bb238d953 100644 --- a/configure.ac +++ b/configure.ac @@ -95,5 +95,7 @@ AC_CONFIG_FILES([ module/zpios/include/Makefile scripts/Makefile scripts/zpool-config/Makefile + scripts/zpios-test/Makefile + scripts/zpios-profile/Makefile ]) AC_OUTPUT diff --git a/scripts/Makefile.am b/scripts/Makefile.am index ccfe5267ad..eed2ba25a0 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -1,5 +1,6 @@ -SUBDIRS = zpool-config +SUBDIRS = zpool-config zpios-test zpios-profile EXTRA_DIST = common.sh zfs-update.sh zfs.sh zpool-create.sh +EXTRA_DIST += zpios.sh zpios-survey.sh check: ./zfs.sh -v diff --git a/scripts/zpios-profile/Makefile.am b/scripts/zpios-profile/Makefile.am new file mode 100644 index 0000000000..07cf7ead3a --- /dev/null +++ b/scripts/zpios-profile/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = *.sh diff --git a/scripts/zpios-test/16th-8192rc-4rs-1cs-4off.sh b/scripts/zpios-test/16th-8192rc-4rs-1cs-4off.sh new file mode 100755 index 0000000000..37493b6f32 --- /dev/null +++ b/scripts/zpios-test/16th-8192rc-4rs-1cs-4off.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# +# Usage: zpios +# --chunksize -c =values +# --chunksize_low -a =value +# --chunksize_high -b =value +# --chunksize_incr -g =value +# --offset -o =values +# --offset_low -m =value +# --offset_high -q =value +# --offset_incr -r =value +# --regioncount -n =values +# --regioncount_low -i =value +# --regioncount_high -j =value +# --regioncount_incr -k =value +# --threadcount -t =values +# --threadcount_low -l =value +# --threadcount_high -h =value +# --threadcount_incr -e =value +# --regionsize -s =values +# --regionsize_low -A =value +# --regionsize_high -B =value +# --regionsize_incr -C =value +# --cleanup -x +# --verify -V +# --zerocopy -z +# --threaddelay -T =jiffies +# --regionnoise -I =shift +# --chunknoise -N =bytes +# --prerun -P =pre-command +# --postrun -R =post-command +# --log -G =log directory +# --pool | --path -p =pool name +# --load -L =dmuio +# --help -? =this help +# --verbose -v =increase verbosity + +ZPIOS_CMD="${CMDDIR}/zpios/zpios \ + --load=dmuio \ + --path=${ZPOOL_NAME} \ + --threadcount=1 \ + --regioncount=16 \ + --regionsize=4M \ + --chunksize=1M \ + --offset=4M \ + --cleanup \ + --verbose \ + --human-readable \ + ${ZPIOS_OPTIONS}" + +zpios_start() { + echo ${ZPIOS_CMD} + ${ZPIOS_CMD} || exit 1 +} + +zpios_stop() { + echo +} diff --git a/scripts/zpios-test/256th-65536rc-4rs-1cs-4off.sh b/scripts/zpios-test/256th-65536rc-4rs-1cs-4off.sh new file mode 100755 index 0000000000..4a160507f4 --- /dev/null +++ b/scripts/zpios-test/256th-65536rc-4rs-1cs-4off.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# +# Usage: zpios +# --chunksize -c =values +# --chunksize_low -a =value +# --chunksize_high -b =value +# --chunksize_incr -g =value +# --offset -o =values +# --offset_low -m =value +# --offset_high -q =value +# --offset_incr -r =value +# --regioncount -n =values +# --regioncount_low -i =value +# --regioncount_high -j =value +# --regioncount_incr -k =value +# --threadcount -t =values +# --threadcount_low -l =value +# --threadcount_high -h =value +# --threadcount_incr -e =value +# --regionsize -s =values +# --regionsize_low -A =value +# --regionsize_high -B =value +# --regionsize_incr -C =value +# --cleanup -x +# --verify -V +# --zerocopy -z +# --threaddelay -T =jiffies +# --regionnoise -I =shift +# --chunknoise -N =bytes +# --prerun -P =pre-command +# --postrun -R =post-command +# --log -G =log directory +# --pool | --path -p =pool name +# --load -L =dmuio +# --help -? =this help +# --verbose -v =increase verbosity + +ZPIOS_CMD="${CMDDIR}/zpios/zpios \ + --load=dmuio \ + --path=${ZPOOL_NAME} \ + --threadcount=256 \ + --regioncount=65536 \ + --regionsize=4M \ + --chunksize=1M \ + --offset=4M \ + --cleanup \ + --verbose \ + --human-readable \ + ${ZPIOS_OPTIONS}" + +zpios_start() { + echo ${ZPIOS_CMD} + ${ZPIOS_CMD} || exit 1 +} + +zpios_stop() { + echo +} diff --git a/scripts/zpios-test/Makefile.am b/scripts/zpios-test/Makefile.am new file mode 100644 index 0000000000..07cf7ead3a --- /dev/null +++ b/scripts/zpios-test/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = *.sh diff --git a/scripts/zpios-test/large.sh b/scripts/zpios-test/large.sh new file mode 120000 index 0000000000..b8e22bf54b --- /dev/null +++ b/scripts/zpios-test/large.sh @@ -0,0 +1 @@ +256th-65536rc-4rs-1cs-4off.sh \ No newline at end of file diff --git a/scripts/zpios-test/medium.sh b/scripts/zpios-test/medium.sh new file mode 120000 index 0000000000..d81027b739 --- /dev/null +++ b/scripts/zpios-test/medium.sh @@ -0,0 +1 @@ +16th-8192rc-4rs-1cs-4off.sh \ No newline at end of file From 9991894b2106b068ac8b4c066f7bbc277113b75b Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 20 Jan 2009 21:34:09 -0800 Subject: [PATCH 30/45] Minor script fix --- scripts/zpios.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scripts/zpios.sh b/scripts/zpios.sh index 5ba97b0a68..bfce363a81 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -158,6 +158,7 @@ if check_modules; then fi fi +# Wait for device creation while [ ! -c /dev/zpios ]; do sleep 1 done @@ -181,12 +182,18 @@ echo date zpios_start zpios_stop -print_stats + +if [ ${VERBOSE} ]; then + print_stats +fi # Destroy the zpool configuration ./zpool-create.sh ${VERBOSE_FLAG} -p ${ZPOOL_NAME} -c ${ZPOOL_CONFIG} -d || exit 1 -# Unload the test module stack +# Unload the test module stack and wait for device removal unload_modules +while [ -c /dev/zpios ]; do + sleep 1 +done exit 0 From 59008dc2b203e2901d505c669a8004606ee59568 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 3 Feb 2009 09:28:19 -0800 Subject: [PATCH 31/45] Updated script to actually make name --- scripts/zpios-test/16th-8192rc-4rs-1cs-4off.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/zpios-test/16th-8192rc-4rs-1cs-4off.sh b/scripts/zpios-test/16th-8192rc-4rs-1cs-4off.sh index 37493b6f32..d06e9d0870 100755 --- a/scripts/zpios-test/16th-8192rc-4rs-1cs-4off.sh +++ b/scripts/zpios-test/16th-8192rc-4rs-1cs-4off.sh @@ -39,12 +39,12 @@ ZPIOS_CMD="${CMDDIR}/zpios/zpios \ --load=dmuio \ --path=${ZPOOL_NAME} \ - --threadcount=1 \ - --regioncount=16 \ + --threadcount=16 \ + --regioncount=8192 \ --regionsize=4M \ --chunksize=1M \ --offset=4M \ - --cleanup \ + --cleanup \ --verbose \ --human-readable \ ${ZPIOS_OPTIONS}" From 4bb45ceef20330d418ff79b63a5da7d0ff22a127 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Fri, 6 Feb 2009 14:58:31 -0800 Subject: [PATCH 32/45] Update zpios survey script to use new scripts --- scripts/zpios-survey.sh | 249 ++++++++++++++++++++++++++++------------ scripts/zpios.sh | 22 +++- 2 files changed, 196 insertions(+), 75 deletions(-) diff --git a/scripts/zpios-survey.sh b/scripts/zpios-survey.sh index a75bb2d6f0..a37ae56869 100755 --- a/scripts/zpios-survey.sh +++ b/scripts/zpios-survey.sh @@ -1,83 +1,115 @@ #!/bin/bash +# +# Wrapper script for easily running a survey of zpios based tests +# -prog=survey.sh -. ../.script-config +. ./common.sh +PROG=zpios-survey.sh -LOG=/home/`whoami`/zpios-logs/`uname -r`/zpios-`date +%Y%m%d`/ -mkdir -p ${LOG} +usage() { +cat << EOF +USAGE: +$0 [hvp] <-c config> <-t test> -# Apply all tunings described below to generate some best case -# numbers for what is acheivable with some more elbow grease. -NAME="prefetch+zerocopy+checksum+pending1024+kmem" -echo "----------------------- ${NAME} ------------------------------" -./zpios.sh \ - "" \ - "zfs_prefetch_disable=1 zfs_vdev_max_pending=1024 zio_bulk_flags=0x100" \ - "--zerocopy" \ - ${LOG}/${NAME}/ \ - "${CMDDIR}/zfs/zfs set checksum=off lustre" | \ - tee ${LOG}/${NAME}.txt +DESCRIPTION: + Helper script for easy zpios survey benchmarking. -# Baseline number for an out of the box config with no manual tuning. -# Ideally, we will want things to be automatically tuned and for this -# number to approach the tweaked out results above. -NAME="baseline" -echo "----------------------- ${NAME} ------------------------------" -./zpios.sh \ - "" \ - "" \ - "" \ - ${LOG}/${NAME}/ | \ - tee ${LOG}/${NAME}.txt +OPTIONS: + -h Show this message + -v Verbose + -p Enable profiling + -c Zpool configuration + -t Zpios test + -l Zpios survey log + +EOF +} + +print_header() { + echo + echo "================================================================" + echo "Test: $1" + echo +} + +# Baseline performance for an out of the box config with no manual tuning. +# Ideally, we want everything to be automatically tuned for your system and +# for this to perform reasonably well. +zpios_survey_base() { + TEST_NAME="${ZPOOL_CONFIG}+${ZPIOS_TEST}+baseline" + print_header ${TEST_NAME} + + ./zfs.sh ${VERBOSE_FLAG} | \ + tee -a ${ZPIOS_SURVEY_LOG} + ./zpios.sh ${VERBOSE_FLAG} -c ${ZPOOL_CONFIG} -t ${ZPIOS_TEST} | \ + tee -a ${ZPIOS_SURVEY_LOG} + ./zfs.sh -u ${VERBOSE_FLAG} | \ + tee -a ${ZPIOS_SURVEY_LOG} +} # Disable ZFS's prefetching. For some reason still not clear to me # current prefetching policy is quite bad for a random workload. -# Allow the algorithm to detect a random workload and not do anything -# may be the way to address this issue. -NAME="prefetch" -echo "----------------------- ${NAME} ------------------------------" -./zpios.sh \ - "" \ - "zfs_prefetch_disable=1" \ - "" \ - ${LOG}/${NAME}/ | \ - tee ${LOG}/${NAME}.txt +# Allowint the algorithm to detect a random workload and not do +# anything may be the way to address this issue. +zpios_survey_prefetch() { + TEST_NAME="${ZPOOL_CONFIG}+${ZPIOS_TEST}+prefetch" + print_header ${TEST_NAME} -# As expected, simulating a zerocopy IO path improves performance -# by freeing up lots of CPU which is wasted move data between buffers. -NAME="zerocopy" -echo "----------------------- ${NAME} ------------------------------" -./zpios.sh \ - "" \ - "" \ - "--zerocopy" \ - ${LOG}/${NAME}/ | \ - tee ${LOG}/${NAME}.txt + ./zfs.sh ${VERBOSE_FLAG} \ + zfs="zfs_prefetch_disable=1" | \ + tee -a ${ZPIOS_SURVEY_LOG} + ./zpios.sh ${VERBOSE_FLAG} -c ${ZPOOL_CONFIG} -t ${ZPIOS_TEST} | \ + tee -a ${ZPIOS_SURVEY_LOG} + ./zfs.sh -u ${VERBOSE_FLAG} | \ + tee -a ${ZPIOS_SURVEY_LOG} +} + +# Simulating a zerocopy IO path should improve performance by freeing up +# lots of CPU which is wasted move data between buffers. +zpios_survey_zerocopy() { + TEST_NAME="${ZPOOL_CONFIG}+${ZPIOS_TEST}+zerocopy" + print_header ${TEST_NAME} + + ./zfs.sh ${VERBOSE_FLAG} | \ + tee -a ${ZPIOS_SURVEY_LOG} + ./zpios.sh ${VERBOSE_FLAG} -c ${ZPOOL_CONFIG} -t ${ZPIOS_TEST} \ + -o "--zerocopy" | \ + tee -a ${ZPIOS_SURVEY_LOG} + ./zfs.sh -u ${VERBOSE_FLAG} | \ + tee -a ${ZPIOS_SURVEY_LOG} +} # Disabling checksumming should show some (if small) improvement # simply due to freeing up a modest amount of CPU. -NAME="checksum" -echo "----------------------- ${NAME} ------------------------------" -./zpios.sh \ - "" \ - "" \ - "" \ - ${LOG}/${NAME}/ \ - "${CMDDIR}/zfs/zfs set checksum=off lustre" | \ - tee ${LOG}/${NAME}.txt +zpios_survey_checksum() { + TEST_NAME="${ZPOOL_CONFIG}+${ZPIOS_TEST}+checksum" + print_header ${TEST_NAME} + + ./zfs.sh ${VERBOSE_FLAG} | \ + tee -a ${ZPIOS_SURVEY_LOG} + ./zpios.sh ${VERBOSE_FLAG} -c ${ZPOOL_CONFIG} -t ${ZPIOS_TEST} \ + -s "set checksum=off" | \ + tee -a ${ZPIOS_SURVEY_LOG} + ./zfs.sh -u ${VERBOSE_FLAG} | \ + tee -a ${ZPIOS_SURVEY_LOG} +} # Increasing the pending IO depth also seems to improve things likely -# at the expense of latency. This should be exported more because I'm +# at the expense of latency. This should be explored more because I'm # seeing a much bigger impact there that I would have expected. There # may be some low hanging fruit to be found here. -NAME="pending" -echo "----------------------- ${NAME} ------------------------------" -./zpios.sh \ - "" \ - "zfs_vdev_max_pending=1024" \ - "" \ - ${LOG}/${NAME}/ | \ - tee ${LOG}/${NAME}.txt +zpios_survey_pending() { + TEST_NAME="${ZPOOL_CONFIG}+${ZPIOS_TEST}+pending" + print_header ${TEST_NAME} + + ./zfs.sh ${VERBOSE_FLAG} \ + zfs="zfs_vdev_max_pending=1024" | \ + tee -a ${ZPIOS_SURVEY_LOG} + ./zpios.sh ${VERBOSE_FLAG} -c ${ZPOOL_CONFIG} -t ${ZPIOS_TEST} | \ + tee -a ${ZPIOS_SURVEY_LOG} + ./zfs.sh -u ${VERBOSE_FLAG} | \ + tee -a ${ZPIOS_SURVEY_LOG} +} # To avoid memory fragmentation issues our slab implementation can be # based on a virtual address space. Interestingly, we take a pretty @@ -92,11 +124,84 @@ echo "----------------------- ${NAME} ------------------------------" # # 0x100 = KMC_KMEM - Force kmem_* based slab # 0x200 = KMC_VMEM - Force vmem_* based slab -NAME="kmem" -echo "----------------------- ${NAME} ------------------------------" -./zpios.sh \ - "" \ - "zio_bulk_flags=0x100" \ - "" \ - ${LOG}/${NAME}/ | \ - tee ${LOG}/${NAME}.txt +zpios_survey_kmem() { + TEST_NAME="${ZPOOL_CONFIG}+${ZPIOS_TEST}+kmem" + print_header ${TEST_NAME} + + ./zfs.sh ${VERBOSE_FLAG} \ + zfs="zio_bulk_flags=0x100" | \ + tee -a ${ZPIOS_SURVEY_LOG} + ./zpios.sh ${VERBOSE_FLAG} -c ${ZPOOL_CONFIG} -t ${ZPIOS_TEST} | \ + tee -a ${ZPIOS_SURVEY_LOG} + ./zfs.sh -u ${VERBOSE_FLAG} | \ + tee -a ${ZPIOS_SURVEY_LOG} +} + +# Apply all possible turning concurrently to get a best case number +zpios_survey_all() { + TEST_NAME="${ZPOOL_CONFIG}+${ZPIOS_TEST}+all" + print_header ${TEST_NAME} + + ./zfs.sh ${VERBOSE_FLAG} \ + zfs="zfs_prefetch_disable=1" \ + zfs="zfs_vdev_max_pending=1024" \ + zfs="zio_bulk_flags=0x100" | \ + tee -a ${ZPIOS_SURVEY_LOG} + ./zpios.sh ${VERBOSE_FLAG} -c ${ZPOOL_CONFIG} -t ${ZPIOS_TEST} \ + -o "--zerocopy" \ + -s "set checksum=off" | \ + tee -a ${ZPIOS_SURVEY_LOG} + ./zfs.sh -u ${VERBOSE_FLAG} | \ + tee -a ${ZPIOS_SURVEY_LOG} +} + + +PROFILE= +ZPOOL_NAME=zpios-survey +ZPOOL_CONFIG=zpool-config.sh +ZPIOS_TEST=zpios-test.sh +ZPIOS_SURVEY_LOG=/dev/null + +while getopts 'hvpc:t:l:' OPTION; do + case $OPTION in + h) + usage + exit 1 + ;; + v) + VERBOSE=1 + VERBOSE_FLAG="-v" + ;; + p) + PROFILE=1 + PROFILE_FLAG="-p" + ;; + c) + ZPOOL_CONFIG=${OPTARG} + ;; + t) + ZPIOS_TEST=${OPTARG} + ;; + l) + ZPIOS_SURVEY_LOG=${OPTARG} + ;; + ?) + usage + exit + ;; + esac +done + +if [ $(id -u) != 0 ]; then + die "Must run as root" +fi + +zpios_survey_base +zpios_survey_prefetch +zpios_survey_zerocopy +zpios_survey_checksum +zpios_survey_pending +zpios_survey_kmem +zpios_survey_all + +exit 0 diff --git a/scripts/zpios.sh b/scripts/zpios.sh index bfce363a81..dc55dd0c99 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -26,8 +26,11 @@ OPTIONS: -h Show this message -v Verbose -p Enable profiling - -c Zpool configuration + -c Zpool configuration -t Zpios test + -o Additional zpios options + -l Additional zpool options + -s Additional zfs options EOF } @@ -115,8 +118,11 @@ PROFILE= ZPOOL_CONFIG=zpool-config.sh ZPIOS_TEST=zpios-test.sh ZPOOL_NAME=zpios +ZPIOS_OPTIONS= +ZPOOL_OPTIONS="" +ZFS_OPTIONS="" -while getopts 'hvpc:t:' OPTION; do +while getopts 'hvpc:t:o:l:s:' OPTION; do case $OPTION in h) usage @@ -135,6 +141,15 @@ while getopts 'hvpc:t:' OPTION; do t) ZPIOS_TEST=${TOPDIR}/scripts/zpios-test/${OPTARG}.sh ;; + o) + ZPIOS_OPTIONS=${OPTARG} + ;; + l) # Passed through to zpool-create.sh + ZPOOL_OPTIONS=${OPTARG} + ;; + s) # Passed through to zpool-create.sh + ZFS_OPTIONS=${OPTARG} + ;; ?) usage exit @@ -170,7 +185,8 @@ if [ ${VERBOSE} ]; then fi # Create the zpool configuration -./zpool-create.sh ${VERBOSE_FLAG} -p ${ZPOOL_NAME} -c ${ZPOOL_CONFIG} || exit 1 +./zpool-create.sh ${VERBOSE_FLAG} -p ${ZPOOL_NAME} -c ${ZPOOL_CONFIG} \ + -l "${ZPOOL_OPTIONS}" -s "${ZFS_OPTIONS}" || exit 1 if [ $PROFILE ]; then ZPIOS_CMD="${ZPIOS_CMD} --log=${PROFILE_ZPIOS_LOG}" From a06c9a3bd97dd624e6d68e2493efa28aa94c35b9 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Fri, 6 Feb 2009 15:08:15 -0800 Subject: [PATCH 33/45] Add 2 more zpios test configurations --- .../1x256th-65536rc-4rs-1cs-4off.sh | 59 +++++++++++++++++++ scripts/zpios-test/4th-1024rc-4rs-1cs-4off.sh | 59 +++++++++++++++++++ scripts/zpios-test/large-thread-survey.sh | 1 + scripts/zpios-test/small.sh | 1 + 4 files changed, 120 insertions(+) create mode 100755 scripts/zpios-test/1x256th-65536rc-4rs-1cs-4off.sh create mode 100755 scripts/zpios-test/4th-1024rc-4rs-1cs-4off.sh create mode 120000 scripts/zpios-test/large-thread-survey.sh create mode 120000 scripts/zpios-test/small.sh diff --git a/scripts/zpios-test/1x256th-65536rc-4rs-1cs-4off.sh b/scripts/zpios-test/1x256th-65536rc-4rs-1cs-4off.sh new file mode 100755 index 0000000000..f090c5f2e4 --- /dev/null +++ b/scripts/zpios-test/1x256th-65536rc-4rs-1cs-4off.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# +# Usage: zpios +# --chunksize -c =values +# --chunksize_low -a =value +# --chunksize_high -b =value +# --chunksize_incr -g =value +# --offset -o =values +# --offset_low -m =value +# --offset_high -q =value +# --offset_incr -r =value +# --regioncount -n =values +# --regioncount_low -i =value +# --regioncount_high -j =value +# --regioncount_incr -k =value +# --threadcount -t =values +# --threadcount_low -l =value +# --threadcount_high -h =value +# --threadcount_incr -e =value +# --regionsize -s =values +# --regionsize_low -A =value +# --regionsize_high -B =value +# --regionsize_incr -C =value +# --cleanup -x +# --verify -V +# --zerocopy -z +# --threaddelay -T =jiffies +# --regionnoise -I =shift +# --chunknoise -N =bytes +# --prerun -P =pre-command +# --postrun -R =post-command +# --log -G =log directory +# --pool | --path -p =pool name +# --load -L =dmuio +# --help -? =this help +# --verbose -v =increase verbosity + +ZPIOS_CMD="${CMDDIR}/zpios/zpios \ + --load=dmuio \ + --path=${ZPOOL_NAME} \ + --threadcount=1,2,4,8,16,32,64,128,256 \ + --regioncount=65536 \ + --regionsize=4M \ + --chunksize=1M \ + --offset=4M \ + --cleanup \ + --verbose \ + --human-readable \ + ${ZPIOS_OPTIONS}" + +zpios_start() { + echo ${ZPIOS_CMD} + ${ZPIOS_CMD} || exit 1 +} + +zpios_stop() { + echo +} diff --git a/scripts/zpios-test/4th-1024rc-4rs-1cs-4off.sh b/scripts/zpios-test/4th-1024rc-4rs-1cs-4off.sh new file mode 100755 index 0000000000..d83635e324 --- /dev/null +++ b/scripts/zpios-test/4th-1024rc-4rs-1cs-4off.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# +# Usage: zpios +# --chunksize -c =values +# --chunksize_low -a =value +# --chunksize_high -b =value +# --chunksize_incr -g =value +# --offset -o =values +# --offset_low -m =value +# --offset_high -q =value +# --offset_incr -r =value +# --regioncount -n =values +# --regioncount_low -i =value +# --regioncount_high -j =value +# --regioncount_incr -k =value +# --threadcount -t =values +# --threadcount_low -l =value +# --threadcount_high -h =value +# --threadcount_incr -e =value +# --regionsize -s =values +# --regionsize_low -A =value +# --regionsize_high -B =value +# --regionsize_incr -C =value +# --cleanup -x +# --verify -V +# --zerocopy -z +# --threaddelay -T =jiffies +# --regionnoise -I =shift +# --chunknoise -N =bytes +# --prerun -P =pre-command +# --postrun -R =post-command +# --log -G =log directory +# --pool | --path -p =pool name +# --load -L =dmuio +# --help -? =this help +# --verbose -v =increase verbosity + +ZPIOS_CMD="${CMDDIR}/zpios/zpios \ + --load=dmuio \ + --path=${ZPOOL_NAME} \ + --threadcount=4 \ + --regioncount=1024 \ + --regionsize=4M \ + --chunksize=1M \ + --offset=4M \ + --cleanup \ + --verbose \ + --human-readable \ + ${ZPIOS_OPTIONS}" + +zpios_start() { + echo ${ZPIOS_CMD} + ${ZPIOS_CMD} || exit 1 +} + +zpios_stop() { + echo +} diff --git a/scripts/zpios-test/large-thread-survey.sh b/scripts/zpios-test/large-thread-survey.sh new file mode 120000 index 0000000000..90b6e3c47c --- /dev/null +++ b/scripts/zpios-test/large-thread-survey.sh @@ -0,0 +1 @@ +1x256th-65536rc-4rs-1cs-4off.sh \ No newline at end of file diff --git a/scripts/zpios-test/small.sh b/scripts/zpios-test/small.sh new file mode 120000 index 0000000000..cbf03b5cee --- /dev/null +++ b/scripts/zpios-test/small.sh @@ -0,0 +1 @@ +4th-1024rc-4rs-1cs-4off.sh \ No newline at end of file From 9b649b23eff62af9de5dc4ed6e50fecd1f22b509 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Fri, 6 Feb 2009 15:28:49 -0800 Subject: [PATCH 34/45] Minor update to ensure heads make it in to the log --- scripts/zpios-survey.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/zpios-survey.sh b/scripts/zpios-survey.sh index a37ae56869..2a3a33033e 100755 --- a/scripts/zpios-survey.sh +++ b/scripts/zpios-survey.sh @@ -26,10 +26,11 @@ EOF } print_header() { - echo - echo "================================================================" - echo "Test: $1" - echo +tee -a ${ZPIOS_SURVEY_LOG} << EOF + +================================================================ +Test: $1 +EOF } # Baseline performance for an out of the box config with no manual tuning. From 68346c54feef2f60819462a2366b7e0eab1b1d81 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Fri, 13 Feb 2009 12:07:34 -0800 Subject: [PATCH 35/45] Misnamed --load option sff changed to ssf --- cmd/zpios/zpios_util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/zpios/zpios_util.c b/cmd/zpios/zpios_util.c index 6a43446500..14150d7289 100644 --- a/cmd/zpios/zpios_util.c +++ b/cmd/zpios/zpios_util.c @@ -270,8 +270,8 @@ set_load_params(cmd_args_t *args, char *optarg) if (strcmp("fpp", param) == 0) { args->flags |= DMU_FPP; /* File Per Process/Thread */ - } else if (strcmp("sff", param) == 0) { - args->flags &= ~DMU_FPP; /* Shared Shared File */ + } else if (strcmp("ssf", param) == 0) { + args->flags &= ~DMU_FPP; /* Single Shared File */ } else if (strcmp("dmuio", param) == 0) { args->io_type |= DMU_IO; args->flags |= (DMU_WRITE | DMU_READ); From 23710f130877d66b83b05c83c0c91bda53675728 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Thu, 19 Feb 2009 12:56:50 -0800 Subject: [PATCH 36/45] Minor zpios cleanup plus addition of --nowait feature --- cmd/zpios/zpios.h | 2 ++ cmd/zpios/zpios_main.c | 17 +++++++----- cmd/zpios/zpios_util.c | 19 +++++++------- module/zpios/include/zpios-ctl.h | 1 + module/zpios/zpios.c | 44 +++++++++++++++++--------------- 5 files changed, 47 insertions(+), 36 deletions(-) diff --git a/cmd/zpios/zpios.h b/cmd/zpios/zpios.h index 88c7c2fee9..79fdf8be1e 100644 --- a/cmd/zpios/zpios.h +++ b/cmd/zpios/zpios.h @@ -57,6 +57,8 @@ #define GB (MB * 1024) #define TB (GB * 1024) +#define KMGT_SIZE 16 + /* All offsets, sizes and counts can be passed to the application in * multiple ways. * 1. a value (stored in val[0], val_count will be 1) diff --git a/cmd/zpios/zpios_main.c b/cmd/zpios/zpios_main.c index fbaf8eeefd..fca2fb63c0 100644 --- a/cmd/zpios/zpios_main.c +++ b/cmd/zpios/zpios_main.c @@ -45,7 +45,7 @@ #include "zpios.h" static const char short_opt[] = "t:l:h:e:n:i:j:k:c:u:a:b:g:L:P:R:I:" - "G:T:Vzs:A:B:C:o:m:q:r:fwxdp:v?"; + "G:T:N:VHzOs:A:B:C:o:m:q:r:fwxdp:v?"; static const struct option long_opt[] = { {"chunksize", required_argument, 0, 'c' }, {"chunksize_low", required_argument, 0, 'a' }, @@ -70,6 +70,7 @@ static const struct option long_opt[] = { {"cleanup", no_argument, 0, 'x' }, {"verify", no_argument, 0, 'V' }, {"zerocopy", no_argument, 0, 'z' }, + {"nowait", no_argument, 0, 'O' }, {"threaddelay", required_argument, 0, 'T' }, {"regionnoise", required_argument, 0, 'I' }, {"chunknoise", required_argument, 0, 'N' }, @@ -118,6 +119,7 @@ usage(void) " --cleanup -x\n" " --verify -V\n" " --zerocopy -z\n" + " --nowait -O\n" " --threaddelay -T =jiffies\n" " --regionnoise -I =shift\n" " --chunknoise -N =bytes\n" @@ -166,9 +168,6 @@ args_init(int argc, char **argv) rc = 0; switch (c) { - case 'v': /* --verbose */ - args->verbose++; - break; case 't': /* --thread count */ rc = set_count(REGEX_NUMBERS, REGEX_NUMBERS_COMMA, &args->T, optarg, &fl_th, "threadcount"); @@ -279,12 +278,18 @@ args_init(int argc, char **argv) case 'V': /* --verify */ args->flags |= DMU_VERIFY; break; - case 'z': /* --verify */ + case 'z': /* --zerocopy */ args->flags |= (DMU_WRITE_ZC | DMU_READ_ZC); break; - case 'H': + case 'O': /* --nowait */ + args->flags |= DMU_WRITE_NOWAIT; + break; + case 'H': /* --human-readable */ args->human_readable = 1; break; + case 'v': /* --verbose */ + args->verbose++; + break; case '?': rc = 1; break; diff --git a/cmd/zpios/zpios_util.c b/cmd/zpios/zpios_util.c index 14150d7289..c923673702 100644 --- a/cmd/zpios/zpios_util.c +++ b/cmd/zpios/zpios_util.c @@ -87,10 +87,10 @@ uint64_to_kmgt(char *str, uint64_t val) } if (i >= 4) - sprintf(str, "inf"); + (void)snprintf(str, KMGT_SIZE-1, "inf"); else - sprintf(str, "%lu%c", (unsigned long)val, - (i == -1) ? '\0' : postfix[i]); + (void)snprintf(str, KMGT_SIZE-1, "%lu%c", (unsigned long)val, + (i == -1) ? '\0' : postfix[i]); return str; } @@ -108,10 +108,10 @@ kmgt_per_sec(char *str, uint64_t v, double t) } if (i >= 4) - sprintf(str, "inf"); + (void)snprintf(str, KMGT_SIZE-1, "inf"); else - sprintf(str, "%.2f%c", val, - (i == -1) ? '\0' : postfix[i]); + (void)snprintf(str, KMGT_SIZE-1, "%.2f%c", val, + (i == -1) ? '\0' : postfix[i]); return str; } @@ -125,7 +125,8 @@ print_flags(char *str, uint32_t flags) str[3] = (flags & DMU_REMOVE) ? 'c' : '-'; str[4] = (flags & DMU_FPP) ? 'p' : 's'; str[5] = (flags & (DMU_WRITE_ZC | DMU_READ_ZC)) ? 'z' : '-'; - str[6] = '\0'; + str[6] = (flags & DMU_WRITE_NOWAIT) ? 'O' : '-'; + str[7] = '\0'; return str; } @@ -140,7 +141,7 @@ timespec_to_double(struct timespec t) static int regex_match(const char *string, char *pattern) { - regex_t re; + regex_t re = { 0 }; int rc; rc = regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB | REG_ICASE); @@ -327,7 +328,7 @@ print_stats_human_readable(cmd_args_t *args, zpios_cmd_t *cmd) { zpios_stats_t *summary_stats; double t_time, wr_time, rd_time, cr_time, rm_time; - char str[16]; + char str[KMGT_SIZE]; if (args->rc) printf("FAILED: %3d ", args->rc); diff --git a/module/zpios/include/zpios-ctl.h b/module/zpios/include/zpios-ctl.h index 79cbfa3ac6..767fdfdb15 100644 --- a/module/zpios/include/zpios-ctl.h +++ b/module/zpios/include/zpios-ctl.h @@ -53,6 +53,7 @@ #define DMU_FPP 0x10 #define DMU_WRITE_ZC 0x20 /* Incompatible with DMU_VERIFY */ #define DMU_READ_ZC 0x40 /* Incompatible with DMU_VERIFY */ +#define DMU_WRITE_NOWAIT 0x80 #define ZPIOS_NAME_SIZE 16 #define ZPIOS_PATH_SIZE 128 diff --git a/module/zpios/zpios.c b/module/zpios/zpios.c index 4b1c4dbbc3..5b447d4f5b 100644 --- a/module/zpios/zpios.c +++ b/module/zpios/zpios.c @@ -426,6 +426,9 @@ zpios_dmu_write(run_args_t *run_args, objset_t *os, uint64_t object, int rc, how = TXG_WAIT; int flags = 0; + if (run_args->flags & DMU_WRITE_NOWAIT) + how = TXG_NOWAIT; + while (1) { tx = dmu_tx_create(os); dmu_tx_hold_write(tx, object, offset, size); @@ -661,13 +664,12 @@ zpios_thread_done(run_args_t *run_args) static int zpios_threads_run(run_args_t *run_args) { - struct task_struct *tsk, **tsks; + struct task_struct *tsk, **tsks; thread_data_t *thr = NULL; zpios_time_t *tt = &(run_args->stats.total_time); zpios_time_t *tw = &(run_args->stats.wr_time); zpios_time_t *tr = &(run_args->stats.rd_time); - int i, rc = 0, tc = run_args->thread_count; - DEFINE_WAIT(wait); + int i, rc = 0, tc = run_args->thread_count; zpios_upcall(run_args->pre, PHASE_PRE, run_args, 0); @@ -697,32 +699,32 @@ zpios_threads_run(run_args_t *run_args) thr->thread_no = i; thr->run_args = run_args; thr->rc = 0; - mutex_init(&thr->lock, NULL, MUTEX_DEFAULT, NULL); + mutex_init(&thr->lock, NULL, MUTEX_DEFAULT, NULL); run_args->threads[i] = thr; - tsk = kthread_create(zpios_thread_main, (void *)thr, - "%s/%d", "zpios_io", i); - if (IS_ERR(tsk)) { + tsk = kthread_create(zpios_thread_main, (void *)thr, + "%s/%d", "zpios_io", i); + if (IS_ERR(tsk)) { rc = -EINVAL; goto taskerr; } tsks[i] = tsk; - } + } - tt->start = current_kernel_time(); + tt->start = current_kernel_time(); /* Wake up all threads for write phase */ zpios_upcall(run_args->pre, PHASE_WRITE, run_args, 0); - for (i = 0; i < tc; i++) + for (i = 0; i < tc; i++) wake_up_process(tsks[i]); /* Wait for write phase to complete */ - tw->start = current_kernel_time(); - wait_event(run_args->waitq, zpios_thread_done(run_args)); - tw->stop = current_kernel_time(); + tw->start = current_kernel_time(); + wait_event(run_args->waitq, zpios_thread_done(run_args)); + tw->stop = current_kernel_time(); - for (i = 0; i < tc; i++) { + for (i = 0; i < tc; i++) { thr = run_args->threads[i]; mutex_enter(&thr->lock); @@ -759,11 +761,11 @@ zpios_threads_run(run_args_t *run_args) wake_up_process(tsks[i]); /* Wait for read phase to complete */ - tr->start = current_kernel_time(); - wait_event(run_args->waitq, zpios_thread_done(run_args)); - tr->stop = current_kernel_time(); + tr->start = current_kernel_time(); + wait_event(run_args->waitq, zpios_thread_done(run_args)); + tr->stop = current_kernel_time(); - for (i = 0; i < tc; i++) { + for (i = 0; i < tc; i++) { thr = run_args->threads[i]; mutex_enter(&thr->lock); @@ -778,7 +780,7 @@ zpios_threads_run(run_args_t *run_args) zpios_upcall(run_args->post, PHASE_READ, run_args, rc); out: - tt->stop = current_kernel_time(); + tt->stop = current_kernel_time(); tt->delta = timespec_sub(tt->stop, tt->start); tw->delta = timespec_sub(tw->stop, tw->start); tr->delta = timespec_sub(tr->stop, tr->start); @@ -804,7 +806,7 @@ static int zpios_do_one_run(struct file *file, zpios_cmd_t *kcmd, int data_size, void *data) { - run_args_t *run_args; + run_args_t *run_args; zpios_stats_t *stats = (zpios_stats_t *)data; int i, n, m, size, rc; @@ -848,7 +850,7 @@ zpios_do_one_run(struct file *file, zpios_cmd_t *kcmd, return -ENOSPC; } - rc = zpios_setup_run(&run_args, kcmd, file); + rc = zpios_setup_run(&run_args, kcmd, file); if (rc) return rc; From 5ae73585fb23637f96f939b6f409bad1c69e9ebc Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Thu, 19 Feb 2009 13:53:17 -0800 Subject: [PATCH 37/45] Cleanup zpios option handling --- cmd/zpios/zpios_main.c | 91 +++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/cmd/zpios/zpios_main.c b/cmd/zpios/zpios_main.c index fca2fb63c0..63edccc22d 100644 --- a/cmd/zpios/zpios_main.c +++ b/cmd/zpios/zpios_main.c @@ -44,45 +44,44 @@ #include #include "zpios.h" -static const char short_opt[] = "t:l:h:e:n:i:j:k:c:u:a:b:g:L:P:R:I:" - "G:T:N:VHzOs:A:B:C:o:m:q:r:fwxdp:v?"; +static const char short_opt[] = "t:l:h:e:n:i:j:k:o:m:q:r:c:a:b:g:s:A:B:C:" + "L:p:xP:R:G:I:N:T:VzOHv?"; static const struct option long_opt[] = { - {"chunksize", required_argument, 0, 'c' }, - {"chunksize_low", required_argument, 0, 'a' }, - {"chunksize_high", required_argument, 0, 'b' }, - {"chunksize_incr", required_argument, 0, 'g' }, - {"offset", required_argument, 0, 'o' }, - {"offset_low", required_argument, 0, 'm' }, - {"offset_high", required_argument, 0, 'q' }, - {"offset_incr", required_argument, 0, 'r' }, - {"regioncount", required_argument, 0, 'n' }, - {"regioncount_low", required_argument, 0, 'i' }, - {"regioncount_high", required_argument, 0, 'j' }, - {"regioncount_incr", required_argument, 0, 'k' }, {"threadcount", required_argument, 0, 't' }, {"threadcount_low", required_argument, 0, 'l' }, {"threadcount_high", required_argument, 0, 'h' }, {"threadcount_incr", required_argument, 0, 'e' }, + {"regioncount", required_argument, 0, 'n' }, + {"regioncount_low", required_argument, 0, 'i' }, + {"regioncount_high", required_argument, 0, 'j' }, + {"regioncount_incr", required_argument, 0, 'k' }, + {"offset", required_argument, 0, 'o' }, + {"offset_low", required_argument, 0, 'm' }, + {"offset_high", required_argument, 0, 'q' }, + {"offset_incr", required_argument, 0, 'r' }, + {"chunksize", required_argument, 0, 'c' }, + {"chunksize_low", required_argument, 0, 'a' }, + {"chunksize_high", required_argument, 0, 'b' }, + {"chunksize_incr", required_argument, 0, 'g' }, {"regionsize", required_argument, 0, 's' }, {"regionsize_low", required_argument, 0, 'A' }, {"regionsize_high", required_argument, 0, 'B' }, {"regionsize_incr", required_argument, 0, 'C' }, + {"load", required_argument, 0, 'L' }, + {"pool", required_argument, 0, 'p' }, {"cleanup", no_argument, 0, 'x' }, - {"verify", no_argument, 0, 'V' }, - {"zerocopy", no_argument, 0, 'z' }, - {"nowait", no_argument, 0, 'O' }, - {"threaddelay", required_argument, 0, 'T' }, - {"regionnoise", required_argument, 0, 'I' }, - {"chunknoise", required_argument, 0, 'N' }, {"prerun", required_argument, 0, 'P' }, {"postrun", required_argument, 0, 'R' }, {"log", required_argument, 0, 'G' }, - {"path", required_argument, 0, 'p' }, - {"pool", required_argument, 0, 'p' }, - {"load", required_argument, 0, 'L' }, + {"regionnoise", required_argument, 0, 'I' }, + {"chunknoise", required_argument, 0, 'N' }, + {"threaddelay", required_argument, 0, 'T' }, + {"verify", no_argument, 0, 'V' }, + {"zerocopy", no_argument, 0, 'z' }, + {"nowait", no_argument, 0, 'O' }, {"human-readable", no_argument, 0, 'H' }, - {"help", no_argument, 0, '?' }, {"verbose", no_argument, 0, 'v' }, + {"help", no_argument, 0, '?' }, { 0, 0, 0, 0 }, }; @@ -96,41 +95,41 @@ usage(void) { fprintf(stderr, "Usage: zpios\n"); fprintf(stderr, - " --chunksize -c =values\n" - " --chunksize_low -a =value\n" - " --chunksize_high -b =value\n" - " --chunksize_incr -g =value\n" - " --offset -o =values\n" - " --offset_low -m =value\n" - " --offset_high -q =value\n" - " --offset_incr -r =value\n" - " --regioncount -n =values\n" - " --regioncount_low -i =value\n" - " --regioncount_high -j =value\n" - " --regioncount_incr -k =value\n" " --threadcount -t =values\n" " --threadcount_low -l =value\n" " --threadcount_high -h =value\n" " --threadcount_incr -e =value\n" + " --regioncount -n =values\n" + " --regioncount_low -i =value\n" + " --regioncount_high -j =value\n" + " --regioncount_incr -k =value\n" + " --offset -o =values\n" + " --offset_low -m =value\n" + " --offset_high -q =value\n" + " --offset_incr -r =value\n" + " --chunksize -c =values\n" + " --chunksize_low -a =value\n" + " --chunksize_high -b =value\n" + " --chunksize_incr -g =value\n" " --regionsize -s =values\n" " --regionsize_low -A =value\n" " --regionsize_high -B =value\n" " --regionsize_incr -C =value\n" + " --load -L =dmuio|ssf|fpp\n" + " --pool -p =pool name\n" " --cleanup -x\n" - " --verify -V\n" - " --zerocopy -z\n" - " --nowait -O\n" - " --threaddelay -T =jiffies\n" - " --regionnoise -I =shift\n" - " --chunknoise -N =bytes\n" " --prerun -P =pre-command\n" " --postrun -R =post-command\n" " --log -G =log directory\n" - " --pool | --path -p =pool name\n" - " --load -L =dmuio\n" + " --regionnoise -I =shift\n" + " --chunknoise -N =bytes\n" + " --threaddelay -T =jiffies\n" + " --verify -V\n" + " --zerocopy -z\n" + " --nowait -O\n" " --human-readable -H\n" - " --help -? =this help\n" - " --verbose -v =increase verbosity\n\n"); + " --verbose -v =increase verbosity\n" + " --help -? =this help\n\n"); return 0; } From d51fcd107f828014ba0c2bb1d3d54ddbe14ce769 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Thu, 19 Feb 2009 14:35:41 -0800 Subject: [PATCH 38/45] Remove useless run_args->regions check which was always true --- module/zpios/zpios.c | 122 ++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 64 deletions(-) diff --git a/module/zpios/zpios.c b/module/zpios/zpios.c index 5b447d4f5b..9b3ab28b90 100644 --- a/module/zpios/zpios.c +++ b/module/zpios/zpios.c @@ -405,15 +405,12 @@ zpios_cleanup_run(run_args_t *run_args) sizeof(thread_data_t *) * run_args->thread_count); } - if (run_args->regions != NULL) - for (i = 0; i < run_args->region_count; i++) - mutex_destroy(&run_args->regions[i].lock); + for (i = 0; i < run_args->region_count; i++) + mutex_destroy(&run_args->regions[i].lock); - mutex_destroy(&run_args->lock_work); - mutex_destroy(&run_args->lock_ctl); - - if (run_args->regions != NULL) - size = run_args->region_count * sizeof(zpios_region_t); + mutex_destroy(&run_args->lock_work); + mutex_destroy(&run_args->lock_ctl); + size = run_args->region_count * sizeof(zpios_region_t); vmem_free(run_args, sizeof(*run_args) + size); } @@ -422,39 +419,39 @@ static int zpios_dmu_write(run_args_t *run_args, objset_t *os, uint64_t object, uint64_t offset, uint64_t size, const void *buf) { - struct dmu_tx *tx; - int rc, how = TXG_WAIT; + struct dmu_tx *tx; + int rc, how = TXG_WAIT; int flags = 0; if (run_args->flags & DMU_WRITE_NOWAIT) how = TXG_NOWAIT; - while (1) { - tx = dmu_tx_create(os); - dmu_tx_hold_write(tx, object, offset, size); - rc = dmu_tx_assign(tx, how); + while (1) { + tx = dmu_tx_create(os); + dmu_tx_hold_write(tx, object, offset, size); + rc = dmu_tx_assign(tx, how); - if (rc) { - if (rc == ERESTART && how == TXG_NOWAIT) { - dmu_tx_wait(tx); - dmu_tx_abort(tx); - continue; - } - zpios_print(run_args->file, + if (rc) { + if (rc == ERESTART && how == TXG_NOWAIT) { + dmu_tx_wait(tx); + dmu_tx_abort(tx); + continue; + } + zpios_print(run_args->file, "Error in dmu_tx_assign(), %d", rc); - dmu_tx_abort(tx); - return rc; - } - break; - } + dmu_tx_abort(tx); + return rc; + } + break; + } if (run_args->flags & DMU_WRITE_ZC) flags |= DMU_WRITE_ZEROCOPY; - dmu_write_impl(os, object, offset, size, buf, tx, flags); - dmu_tx_commit(tx); + dmu_write_impl(os, object, offset, size, buf, tx, flags); + dmu_tx_commit(tx); - return 0; + return 0; } static int @@ -475,25 +472,22 @@ zpios_thread_main(void *data) thread_data_t *thr = (thread_data_t *)data; run_args_t *run_args = thr->run_args; zpios_time_t t; - - dmu_obj_t obj; - __u64 offset; + dmu_obj_t obj; + __u64 offset; __u32 chunk_size; zpios_region_t *region; - char *buf; - + char *buf; unsigned int random_int; - int chunk_noise = run_args->chunk_noise; - int chunk_noise_tmp = 0; - int thread_delay = run_args->thread_delay; - int thread_delay_tmp = 0; + int chunk_noise = run_args->chunk_noise; + int chunk_noise_tmp = 0; + int thread_delay = run_args->thread_delay; + int thread_delay_tmp = 0; + int i, rc = 0; - int i, rc = 0; - - if (chunk_noise) { + if (chunk_noise) { get_random_bytes(&random_int, sizeof(unsigned int)); - chunk_noise_tmp = (random_int % (chunk_noise * 2)) - chunk_noise; - } + chunk_noise_tmp = (random_int % (chunk_noise * 2))-chunk_noise; + } /* It's OK to vmem_alloc() this memory because it will be copied * in to the slab and pointers to the slab copy will be setup in @@ -511,22 +505,22 @@ zpios_thread_main(void *data) /* Write phase */ mutex_enter(&thr->lock); - thr->stats.wr_time.start = current_kernel_time(); + thr->stats.wr_time.start = current_kernel_time(); mutex_exit(&thr->lock); - while (zpios_get_work_item(run_args, &obj, &offset, + while (zpios_get_work_item(run_args, &obj, &offset, &chunk_size, ®ion, DMU_WRITE)) { if (thread_delay) { get_random_bytes(&random_int, sizeof(unsigned int)); - thread_delay_tmp = random_int % thread_delay; - set_current_state(TASK_UNINTERRUPTIBLE); + thread_delay_tmp = random_int % thread_delay; + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(thread_delay_tmp); /* In jiffies */ } - t.start = current_kernel_time(); + t.start = current_kernel_time(); rc = zpios_dmu_write(run_args, obj.os, obj.obj, offset, chunk_size, buf); - t.stop = current_kernel_time(); + t.stop = current_kernel_time(); t.delta = timespec_sub(t.stop, t.start); if (rc) { @@ -553,7 +547,7 @@ zpios_thread_main(void *data) region->stats.wr_time.start = t.start; mutex_exit(®ion->lock); - } + } mutex_enter(&run_args->lock_ctl); run_args->threads_done++; @@ -561,11 +555,11 @@ zpios_thread_main(void *data) mutex_enter(&thr->lock); thr->rc = rc; - thr->stats.wr_time.stop = current_kernel_time(); + thr->stats.wr_time.stop = current_kernel_time(); mutex_exit(&thr->lock); - wake_up(&run_args->waitq); + wake_up(&run_args->waitq); - set_current_state(TASK_UNINTERRUPTIBLE); + set_current_state(TASK_UNINTERRUPTIBLE); schedule(); /* Check if we should exit */ @@ -577,25 +571,25 @@ zpios_thread_main(void *data) /* Read phase */ mutex_enter(&thr->lock); - thr->stats.rd_time.start = current_kernel_time(); + thr->stats.rd_time.start = current_kernel_time(); mutex_exit(&thr->lock); - while (zpios_get_work_item(run_args, &obj, &offset, + while (zpios_get_work_item(run_args, &obj, &offset, &chunk_size, ®ion, DMU_READ)) { if (thread_delay) { get_random_bytes(&random_int, sizeof(unsigned int)); - thread_delay_tmp = random_int % thread_delay; - set_current_state(TASK_UNINTERRUPTIBLE); + thread_delay_tmp = random_int % thread_delay; + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(thread_delay_tmp); /* In jiffies */ } if (run_args->flags & DMU_VERIFY) memset(buf, 0, chunk_size); - t.start = current_kernel_time(); + t.start = current_kernel_time(); rc = zpios_dmu_read(run_args, obj.os, obj.obj, offset, chunk_size, buf); - t.stop = current_kernel_time(); + t.stop = current_kernel_time(); t.delta = timespec_sub(t.stop, t.start); if (rc) { @@ -635,7 +629,7 @@ zpios_thread_main(void *data) region->stats.rd_time.start = t.start; mutex_exit(®ion->lock); - } + } mutex_enter(&run_args->lock_ctl); run_args->threads_done++; @@ -643,9 +637,9 @@ zpios_thread_main(void *data) mutex_enter(&thr->lock); thr->rc = rc; - thr->stats.rd_time.stop = current_kernel_time(); + thr->stats.rd_time.stop = current_kernel_time(); mutex_exit(&thr->lock); - wake_up(&run_args->waitq); + wake_up(&run_args->waitq); out: vmem_free(buf, chunk_size); @@ -658,7 +652,7 @@ static int zpios_thread_done(run_args_t *run_args) { ASSERT(run_args->threads_done <= run_args->thread_count); - return (run_args->threads_done == run_args->thread_count); + return (run_args->threads_done == run_args->thread_count); } static int @@ -689,7 +683,7 @@ zpios_threads_run(run_args_t *run_args) run_args->threads_done = 0; /* Create all the needed threads which will sleep until awoken */ - for (i = 0; i < tc; i++) { + for (i = 0; i < tc; i++) { thr = kmem_zalloc(sizeof(thread_data_t), KM_SLEEP); if (thr == NULL) { rc = -ENOMEM; From ddfa570f42da8f4b933fb40ac6d8c199f3c8bec2 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Thu, 19 Feb 2009 14:51:40 -0800 Subject: [PATCH 39/45] Initial update to support zpios.sh profiling option. --- cmd/zpios/zpios_main.c | 4 +- scripts/zpios-profile/zpios-profile-post.sh | 48 ++++------ scripts/zpios-profile/zpios-profile-pre.sh | 87 ++++++++++++------- .../zpios-test/16th-8192rc-4rs-1cs-4off.sh | 71 +++++++-------- scripts/zpios-test/1th-16rc-4rs-1cs-4off.sh | 74 ++++++++-------- .../1x256th-65536rc-4rs-1cs-4off.sh | 71 +++++++-------- .../zpios-test/256th-65536rc-4rs-1cs-4off.sh | 71 +++++++-------- scripts/zpios-test/4th-1024rc-4rs-1cs-4off.sh | 71 +++++++-------- scripts/zpios.sh | 55 ++++++++++-- 9 files changed, 302 insertions(+), 250 deletions(-) diff --git a/cmd/zpios/zpios_main.c b/cmd/zpios/zpios_main.c index 63edccc22d..6c1905201f 100644 --- a/cmd/zpios/zpios_main.c +++ b/cmd/zpios/zpios_main.c @@ -120,14 +120,14 @@ usage(void) " --cleanup -x\n" " --prerun -P =pre-command\n" " --postrun -R =post-command\n" - " --log -G =log directory\n" + " --log -G =log directory\n" " --regionnoise -I =shift\n" " --chunknoise -N =bytes\n" " --threaddelay -T =jiffies\n" " --verify -V\n" " --zerocopy -z\n" " --nowait -O\n" - " --human-readable -H\n" + " --human-readable -H\n" " --verbose -v =increase verbosity\n" " --help -? =this help\n\n"); diff --git a/scripts/zpios-profile/zpios-profile-post.sh b/scripts/zpios-profile/zpios-profile-post.sh index 0f2d59b0bb..9f53daa2b1 100755 --- a/scripts/zpios-profile/zpios-profile-post.sh +++ b/scripts/zpios-profile/zpios-profile-post.sh @@ -1,6 +1,5 @@ #!/bin/bash -. ../.script-config PROG=zpios-profile-post.sh RUN_POST=${0} @@ -19,44 +18,31 @@ RUN_THREAD_DELAY=${12} RUN_FLAGS=${13} RUN_RESULT=${14} -PROFILE_ZPIOS_PIDS_BIN=${TOPDIR}/scripts/zpios-profile/zpios-profile-pids.sh -PROFILE_ZPIOS_PIDS_LOG=${RUN_LOG_DIR}/${RUN_ID}/pids-summary.csv - -PROFILE_ZPIOS_DISK_BIN=${TOPDIR}/scripts/zpios-/profile/zpios-profile-disk.sh -PROFILE_ZPIOS_DISK_LOG=${RUN_LOG_DIR}/${RUN_ID}/disk-summary.csv - -PROFILE_ZPIOS_ARC_LOG=${RUN_LOG_DIR}/${RUN_ID}/arcstats -PROFILE_ZPIOS_VDEV_LOG=${RUN_LOG_DIR}/${RUN_ID}/vdev_cache_stats - -KERNEL_BIN="/lib/modules/`uname -r`/kernel/" -SPL_BIN="${SPLBUILD}/modules/spl/" -ZFS_BIN="${ZFSBUILD}/lib/" - -OPROFILE_SHORT_ARGS="-a -g -l -p ${KERNEL_BIN},${SPL_BIN},${ZFS_BIN}" -OPROFILE_LONG_ARGS="-d -a -g -l -p ${KERNEL_BIN},${SPL_BIN},${ZFS_BIN}" - -OPROFILE_LOG=${RUN_LOG_DIR}/${RUN_ID}/oprofile.txt -OPROFILE_SHORT_LOG=${RUN_LOG_DIR}/${RUN_ID}/oprofile-short.txt -OPROFILE_LONG_LOG=${RUN_LOG_DIR}/${RUN_ID}/oprofile-long.txt -PROFILE_PID=${RUN_LOG_DIR}/${RUN_ID}/pid - if [ "${RUN_PHASE}" != "post" ]; then exit 1 fi -# opcontrol --stop >>${OPROFILE_LOG} 2>&1 -# opcontrol --dump >>${OPROFILE_LOG} 2>&1 +. ${RUN_LOG_DIR}/zpios-config.sh +. ${RUN_LOG_DIR}/${RUN_ID}/zpios-config-run.sh -kill -s SIGHUP `cat ${PROFILE_PID}` -rm -f ${PROFILE_PID} +#kill -s SIGHUP `cat ${PROFILE_PID}` +#rm -f ${PROFILE_PID} -# opreport ${OPROFILE_SHORT_ARGS} >${OPROFILE_SHORT_LOG} 2>&1 -# opreport ${OPROFILE_LONG_ARGS} >${OPROFILE_LONG_LOG} 2>&1 +OPROFILE_SHORT_ARGS="-a -g -l -p ${KERNEL_BIN},${SPL_BIN},${ZFS_BIN}" +OPROFILE_LONG_ARGS="-d -a -g -l -p ${KERNEL_BIN},${SPL_BIN},${ZFS_BIN}" -# opcontrol --deinit >>${OPROFILE_LOG} 2>&1 +/usr/bin/opcontrol --stop >>${OPROFILE_LOG} 2>&1 +/usr/bin/opcontrol --dump >>${OPROFILE_LOG} 2>&1 +/usr/bin/opreport ${OPROFILE_SHORT_ARGS} >${OPROFILE_SHORT_LOG} 2>&1 +/usr/bin/opreport ${OPROFILE_LONG_ARGS} >${OPROFILE_LONG_LOG} 2>&1 -cat /proc/spl/kstat/zfs/arcstats >${PROFILE_ZPIOS_ARC_LOG} -cat /proc/spl/kstat/zfs/vdev_cache_stats >${PROFILE_ZPIOS_VDEV_LOG} +if [ -f ${PROFILE_ARC_PROC} ]; then + cat ${PROFILE_ARC_PROC} >${PROFILE_ARC_LOG} +fi + +if [ -f ${PROFILE_VDEV_CACHE_PROC} ]; then + cat ${PROFILE_VDEV_CACHE_PROC} >${PROFILE_VDEV_CACHE_LOG} +fi # Summarize system time per pid ${PROFILE_ZPIOS_PIDS_BIN} ${RUN_LOG_DIR} ${RUN_ID} >${PROFILE_ZPIOS_PIDS_LOG} diff --git a/scripts/zpios-profile/zpios-profile-pre.sh b/scripts/zpios-profile/zpios-profile-pre.sh index 2d6d1be2dd..09b4aba779 100755 --- a/scripts/zpios-profile/zpios-profile-pre.sh +++ b/scripts/zpios-profile/zpios-profile-pre.sh @@ -1,8 +1,8 @@ #!/bin/bash -. ../common.sh PROG=zpios-profile-pre.sh +PROFILE_ZPIOS_READY=0 trap "PROFILE_ZPIOS_READY=1" SIGHUP RUN_PRE=${0} @@ -21,51 +21,74 @@ RUN_THREAD_DELAY=${12} RUN_FLAGS=${13} RUN_RESULT=${14} -PROFILE_ZPIOS_BIN=${IOPDIR}/scripts/zpios-profile/zpios-profile.sh -PROFILE_ZPIOS_READY=0 +zpios_profile_run_cfg() { +cat > ${RUN_LOG_DIR}/${RUN_ID}/zpios-config-run.sh << EOF +# +# Zpios Profiling Configuration for Run ${RUN_ID} +# + +PROFILE_PID=${RUN_LOG_DIR}/${RUN_ID}/profile.pid + +PROFILE_ZPIOS_PIDS_LOG=${RUN_LOG_DIR}/${RUN_ID}/pids-summary.csv +PROFILE_ZPIOS_DISK_LOG=${RUN_LOG_DIR}/${RUN_ID}/disk-summary.csv + +PROFILE_ARC_LOG=${RUN_LOG_DIR}/${RUN_ID}/arcstats +PROFILE_ARC_PROC=/proc/spl/kstat/zfs/arcstats + +PROFILE_VDEV_CACHE_LOG=${RUN_LOG_DIR}/${RUN_ID}/vdev_cache_stats +PROFILE_VDEV_CACHE_PROC=/proc/spl/kstat/zfs/vdev_cache_stats OPROFILE_LOG=${RUN_LOG_DIR}/${RUN_ID}/oprofile.txt -PROFILE_PID=${RUN_LOG_DIR}/${RUN_ID}/pid -RUN_ARGS=${RUN_LOG_DIR}/${RUN_ID}/args +OPROFILE_SHORT_LOG=${RUN_LOG_DIR}/${RUN_ID}/oprofile-short.txt +OPROFILE_LONG_LOG=${RUN_LOG_DIR}/${RUN_ID}/oprofile-long.txt + +EOF +} + +zpios_profile_run_args() { +cat > ${RUN_LOG_DIR}/${RUN_ID}/zpios-args.txt << EOF +# +# Zpios Arguments for Run ${RUN_ID} +# + +LOG_DIR=${RUN_LOG_DIR} +ID=${RUN_ID} +POOL=${RUN_POOL} +CHUNK_SIZE=${RUN_CHUNK_SIZE} +REGION_SIZE=${RUN_REGION_SIZE} +THREAD_COUNT=${RUN_THREAD_COUNT} +REGION_COUNT=${RUN_REGION_COUNT} +OFFSET=${RUN_OFFSET} +REGION_NOISE=${RUN_REGION_NOISE} +CHUNK_NOISE=${RUN_CHUNK_NOISE} +THREAD_DELAY=${RUN_THREAD_DELAY} +FLAGS=${RUN_FLAGS} +RESULT=${RUN_RESULT} +EOF +} if [ "${RUN_PHASE}" != "pre" ]; then exit 1 fi -rm -Rf ${RUN_LOG_DIR}/${RUN_ID}/ mkdir -p ${RUN_LOG_DIR}/${RUN_ID}/ +zpios_profile_run_cfg +zpios_profile_run_args -echo "PHASE=${RUN_PHASE}" >>${RUN_ARGS} -echo "LOG_DIR=${RUN_LOG_DIR}" >>${RUN_ARGS} -echo "ID=${RUN_ID}" >>${RUN_ARGS} -echo "POOL=${RUN_POOL}" >>${RUN_ARGS} -echo "CHUNK_SIZE=${RUN_CHUNK_SIZE}" >>${RUN_ARGS} -echo "REGION_SIZE=${RUN_REGION_SIZE}" >>${RUN_ARGS} -echo "THREAD_COUNT=${RUN_THREAD_COUNT}" >>${RUN_ARGS} -echo "REGION_COUNT=${RUN_REGION_COUNT}" >>${RUN_ARGS} -echo "OFFSET=${RUN_OFFSET}" >>${RUN_ARGS} -echo "REGION_NOISE=${RUN_REGION_NOISE}" >>${RUN_ARGS} -echo "CHUNK_NOISE=${RUN_CHUNK_NOISE}" >>${RUN_ARGS} -echo "THREAD_DELAY=${RUN_THREAD_DELAY}" >>${RUN_ARGS} -echo "FLAGS=${RUN_FLAGS}" >>${RUN_ARGS} -echo "RESULT=${RUN_RESULT}" >>${RUN_ARGS} - -# XXX: Oprofile support seems to be broken when I try and start -# it via a user mode helper script, I suspect the setup is failing. -# opcontrol --init >>${OPROFILE_LOG} 2>&1 -# opcontrol --setup --vmlinux=/boot/vmlinux >>${OPROFILE_LOG} 2>&1 +. ${RUN_LOG_DIR}/zpios-config.sh +. ${RUN_LOG_DIR}/${RUN_ID}/zpios-config-run.sh # Start the profile script -${PROFILE_ZPIOS_BIN} ${RUN_PHASE} ${RUN_LOG_DIR} ${RUN_ID} & -echo "$!" >${PROFILE_PID} +#${PROFILE_ZPIOS_BIN} ${RUN_PHASE} ${RUN_LOG_DIR} ${RUN_ID} & +#echo "$!" >${PROFILE_PID} # Sleep waiting for profile script to be ready, it will # signal us via SIGHUP when it is ready to start profiling. -while [ ${PROFILE_ZPIOS_READY} -eq 0 ]; do - sleep 0.1 -done +#while [ ${PROFILE_ZPIOS_READY} -eq 0 ]; do +# sleep 0.1 +#done -# opcontrol --start-daemon >>${OPROFILE_LOG} 2>&1 -# opcontrol --start >>${OPROFILE_LOG} 2>&1 +/usr/bin/opcontrol --reset >>${OPROFILE_LOG} 2>&1 +/usr/bin/opcontrol --start >>${OPROFILE_LOG} 2>&1 exit 0 diff --git a/scripts/zpios-test/16th-8192rc-4rs-1cs-4off.sh b/scripts/zpios-test/16th-8192rc-4rs-1cs-4off.sh index d06e9d0870..d80a71fe47 100755 --- a/scripts/zpios-test/16th-8192rc-4rs-1cs-4off.sh +++ b/scripts/zpios-test/16th-8192rc-4rs-1cs-4off.sh @@ -1,44 +1,45 @@ #!/bin/bash # -# # Usage: zpios -# --chunksize -c =values -# --chunksize_low -a =value -# --chunksize_high -b =value -# --chunksize_incr -g =value -# --offset -o =values -# --offset_low -m =value -# --offset_high -q =value -# --offset_incr -r =value -# --regioncount -n =values -# --regioncount_low -i =value -# --regioncount_high -j =value -# --regioncount_incr -k =value -# --threadcount -t =values -# --threadcount_low -l =value -# --threadcount_high -h =value -# --threadcount_incr -e =value -# --regionsize -s =values -# --regionsize_low -A =value -# --regionsize_high -B =value -# --regionsize_incr -C =value -# --cleanup -x -# --verify -V -# --zerocopy -z -# --threaddelay -T =jiffies -# --regionnoise -I =shift -# --chunknoise -N =bytes -# --prerun -P =pre-command -# --postrun -R =post-command -# --log -G =log directory -# --pool | --path -p =pool name -# --load -L =dmuio -# --help -? =this help -# --verbose -v =increase verbosity +# --threadcount -t =values +# --threadcount_low -l =value +# --threadcount_high -h =value +# --threadcount_incr -e =value +# --regioncount -n =values +# --regioncount_low -i =value +# --regioncount_high -j =value +# --regioncount_incr -k =value +# --offset -o =values +# --offset_low -m =value +# --offset_high -q =value +# --offset_incr -r =value +# --chunksize -c =values +# --chunksize_low -a =value +# --chunksize_high -b =value +# --chunksize_incr -g =value +# --regionsize -s =values +# --regionsize_low -A =value +# --regionsize_high -B =value +# --regionsize_incr -C =value +# --load -L =dmuio|ssf|fpp +# --pool -p =pool name +# --cleanup -x +# --prerun -P =pre-command +# --postrun -R =post-command +# --log -G =log directory +# --regionnoise -I =shift +# --chunknoise -N =bytes +# --threaddelay -T =jiffies +# --verify -V +# --zerocopy -z +# --nowait -O +# --human-readable -H +# --verbose -v =increase verbosity +# --help -? =this help ZPIOS_CMD="${CMDDIR}/zpios/zpios \ --load=dmuio \ - --path=${ZPOOL_NAME} \ + --pool=${ZPOOL_NAME} \ --threadcount=16 \ --regioncount=8192 \ --regionsize=4M \ diff --git a/scripts/zpios-test/1th-16rc-4rs-1cs-4off.sh b/scripts/zpios-test/1th-16rc-4rs-1cs-4off.sh index 37493b6f32..799b6aa4db 100755 --- a/scripts/zpios-test/1th-16rc-4rs-1cs-4off.sh +++ b/scripts/zpios-test/1th-16rc-4rs-1cs-4off.sh @@ -1,50 +1,52 @@ #!/bin/bash # -# # Usage: zpios -# --chunksize -c =values -# --chunksize_low -a =value -# --chunksize_high -b =value -# --chunksize_incr -g =value -# --offset -o =values -# --offset_low -m =value -# --offset_high -q =value -# --offset_incr -r =value -# --regioncount -n =values -# --regioncount_low -i =value -# --regioncount_high -j =value -# --regioncount_incr -k =value -# --threadcount -t =values -# --threadcount_low -l =value -# --threadcount_high -h =value -# --threadcount_incr -e =value -# --regionsize -s =values -# --regionsize_low -A =value -# --regionsize_high -B =value -# --regionsize_incr -C =value -# --cleanup -x -# --verify -V -# --zerocopy -z -# --threaddelay -T =jiffies -# --regionnoise -I =shift -# --chunknoise -N =bytes -# --prerun -P =pre-command -# --postrun -R =post-command -# --log -G =log directory -# --pool | --path -p =pool name -# --load -L =dmuio -# --help -? =this help -# --verbose -v =increase verbosity +# --threadcount -t =values +# --threadcount_low -l =value +# --threadcount_high -h =value +# --threadcount_incr -e =value +# --regioncount -n =values +# --regioncount_low -i =value +# --regioncount_high -j =value +# --regioncount_incr -k =value +# --offset -o =values +# --offset_low -m =value +# --offset_high -q =value +# --offset_incr -r =value +# --chunksize -c =values +# --chunksize_low -a =value +# --chunksize_high -b =value +# --chunksize_incr -g =value +# --regionsize -s =values +# --regionsize_low -A =value +# --regionsize_high -B =value +# --regionsize_incr -C =value +# --load -L =dmuio|ssf|fpp +# --pool -p =pool name +# --cleanup -x +# --prerun -P =pre-command +# --postrun -R =post-command +# --log -G =log directory +# --regionnoise -I =shift +# --chunknoise -N =bytes +# --threaddelay -T =jiffies +# --verify -V +# --zerocopy -z +# --nowait -O +# --human-readable -H +# --verbose -v =increase verbosity +# --help -? =this help + ZPIOS_CMD="${CMDDIR}/zpios/zpios \ --load=dmuio \ - --path=${ZPOOL_NAME} \ + --pool=${ZPOOL_NAME} \ --threadcount=1 \ --regioncount=16 \ --regionsize=4M \ --chunksize=1M \ --offset=4M \ - --cleanup \ + --cleanup \ --verbose \ --human-readable \ ${ZPIOS_OPTIONS}" diff --git a/scripts/zpios-test/1x256th-65536rc-4rs-1cs-4off.sh b/scripts/zpios-test/1x256th-65536rc-4rs-1cs-4off.sh index f090c5f2e4..ddec717acd 100755 --- a/scripts/zpios-test/1x256th-65536rc-4rs-1cs-4off.sh +++ b/scripts/zpios-test/1x256th-65536rc-4rs-1cs-4off.sh @@ -1,44 +1,45 @@ #!/bin/bash # -# # Usage: zpios -# --chunksize -c =values -# --chunksize_low -a =value -# --chunksize_high -b =value -# --chunksize_incr -g =value -# --offset -o =values -# --offset_low -m =value -# --offset_high -q =value -# --offset_incr -r =value -# --regioncount -n =values -# --regioncount_low -i =value -# --regioncount_high -j =value -# --regioncount_incr -k =value -# --threadcount -t =values -# --threadcount_low -l =value -# --threadcount_high -h =value -# --threadcount_incr -e =value -# --regionsize -s =values -# --regionsize_low -A =value -# --regionsize_high -B =value -# --regionsize_incr -C =value -# --cleanup -x -# --verify -V -# --zerocopy -z -# --threaddelay -T =jiffies -# --regionnoise -I =shift -# --chunknoise -N =bytes -# --prerun -P =pre-command -# --postrun -R =post-command -# --log -G =log directory -# --pool | --path -p =pool name -# --load -L =dmuio -# --help -? =this help -# --verbose -v =increase verbosity +# --threadcount -t =values +# --threadcount_low -l =value +# --threadcount_high -h =value +# --threadcount_incr -e =value +# --regioncount -n =values +# --regioncount_low -i =value +# --regioncount_high -j =value +# --regioncount_incr -k =value +# --offset -o =values +# --offset_low -m =value +# --offset_high -q =value +# --offset_incr -r =value +# --chunksize -c =values +# --chunksize_low -a =value +# --chunksize_high -b =value +# --chunksize_incr -g =value +# --regionsize -s =values +# --regionsize_low -A =value +# --regionsize_high -B =value +# --regionsize_incr -C =value +# --load -L =dmuio|ssf|fpp +# --pool -p =pool name +# --cleanup -x +# --prerun -P =pre-command +# --postrun -R =post-command +# --log -G =log directory +# --regionnoise -I =shift +# --chunknoise -N =bytes +# --threaddelay -T =jiffies +# --verify -V +# --zerocopy -z +# --nowait -O +# --human-readable -H +# --verbose -v =increase verbosity +# --help -? =this help ZPIOS_CMD="${CMDDIR}/zpios/zpios \ --load=dmuio \ - --path=${ZPOOL_NAME} \ + --pool=${ZPOOL_NAME} \ --threadcount=1,2,4,8,16,32,64,128,256 \ --regioncount=65536 \ --regionsize=4M \ diff --git a/scripts/zpios-test/256th-65536rc-4rs-1cs-4off.sh b/scripts/zpios-test/256th-65536rc-4rs-1cs-4off.sh index 4a160507f4..167bdad735 100755 --- a/scripts/zpios-test/256th-65536rc-4rs-1cs-4off.sh +++ b/scripts/zpios-test/256th-65536rc-4rs-1cs-4off.sh @@ -1,44 +1,45 @@ #!/bin/bash # -# # Usage: zpios -# --chunksize -c =values -# --chunksize_low -a =value -# --chunksize_high -b =value -# --chunksize_incr -g =value -# --offset -o =values -# --offset_low -m =value -# --offset_high -q =value -# --offset_incr -r =value -# --regioncount -n =values -# --regioncount_low -i =value -# --regioncount_high -j =value -# --regioncount_incr -k =value -# --threadcount -t =values -# --threadcount_low -l =value -# --threadcount_high -h =value -# --threadcount_incr -e =value -# --regionsize -s =values -# --regionsize_low -A =value -# --regionsize_high -B =value -# --regionsize_incr -C =value -# --cleanup -x -# --verify -V -# --zerocopy -z -# --threaddelay -T =jiffies -# --regionnoise -I =shift -# --chunknoise -N =bytes -# --prerun -P =pre-command -# --postrun -R =post-command -# --log -G =log directory -# --pool | --path -p =pool name -# --load -L =dmuio -# --help -? =this help -# --verbose -v =increase verbosity +# --threadcount -t =values +# --threadcount_low -l =value +# --threadcount_high -h =value +# --threadcount_incr -e =value +# --regioncount -n =values +# --regioncount_low -i =value +# --regioncount_high -j =value +# --regioncount_incr -k =value +# --offset -o =values +# --offset_low -m =value +# --offset_high -q =value +# --offset_incr -r =value +# --chunksize -c =values +# --chunksize_low -a =value +# --chunksize_high -b =value +# --chunksize_incr -g =value +# --regionsize -s =values +# --regionsize_low -A =value +# --regionsize_high -B =value +# --regionsize_incr -C =value +# --load -L =dmuio|ssf|fpp +# --pool -p =pool name +# --cleanup -x +# --prerun -P =pre-command +# --postrun -R =post-command +# --log -G =log directory +# --regionnoise -I =shift +# --chunknoise -N =bytes +# --threaddelay -T =jiffies +# --verify -V +# --zerocopy -z +# --nowait -O +# --human-readable -H +# --verbose -v =increase verbosity +# --help -? =this help ZPIOS_CMD="${CMDDIR}/zpios/zpios \ --load=dmuio \ - --path=${ZPOOL_NAME} \ + --pool=${ZPOOL_NAME} \ --threadcount=256 \ --regioncount=65536 \ --regionsize=4M \ diff --git a/scripts/zpios-test/4th-1024rc-4rs-1cs-4off.sh b/scripts/zpios-test/4th-1024rc-4rs-1cs-4off.sh index d83635e324..910129b16c 100755 --- a/scripts/zpios-test/4th-1024rc-4rs-1cs-4off.sh +++ b/scripts/zpios-test/4th-1024rc-4rs-1cs-4off.sh @@ -1,44 +1,45 @@ #!/bin/bash # -# # Usage: zpios -# --chunksize -c =values -# --chunksize_low -a =value -# --chunksize_high -b =value -# --chunksize_incr -g =value -# --offset -o =values -# --offset_low -m =value -# --offset_high -q =value -# --offset_incr -r =value -# --regioncount -n =values -# --regioncount_low -i =value -# --regioncount_high -j =value -# --regioncount_incr -k =value -# --threadcount -t =values -# --threadcount_low -l =value -# --threadcount_high -h =value -# --threadcount_incr -e =value -# --regionsize -s =values -# --regionsize_low -A =value -# --regionsize_high -B =value -# --regionsize_incr -C =value -# --cleanup -x -# --verify -V -# --zerocopy -z -# --threaddelay -T =jiffies -# --regionnoise -I =shift -# --chunknoise -N =bytes -# --prerun -P =pre-command -# --postrun -R =post-command -# --log -G =log directory -# --pool | --path -p =pool name -# --load -L =dmuio -# --help -? =this help -# --verbose -v =increase verbosity +# --threadcount -t =values +# --threadcount_low -l =value +# --threadcount_high -h =value +# --threadcount_incr -e =value +# --regioncount -n =values +# --regioncount_low -i =value +# --regioncount_high -j =value +# --regioncount_incr -k =value +# --offset -o =values +# --offset_low -m =value +# --offset_high -q =value +# --offset_incr -r =value +# --chunksize -c =values +# --chunksize_low -a =value +# --chunksize_high -b =value +# --chunksize_incr -g =value +# --regionsize -s =values +# --regionsize_low -A =value +# --regionsize_high -B =value +# --regionsize_incr -C =value +# --load -L =dmuio|ssf|fpp +# --pool -p =pool name +# --cleanup -x +# --prerun -P =pre-command +# --postrun -R =post-command +# --log -G =log directory +# --regionnoise -I =shift +# --chunknoise -N =bytes +# --threaddelay -T =jiffies +# --verify -V +# --zerocopy -z +# --nowait -O +# --human-readable -H +# --verbose -v =increase verbosity +# --help -? =this help ZPIOS_CMD="${CMDDIR}/zpios/zpios \ --load=dmuio \ - --path=${ZPOOL_NAME} \ + --pool=${ZPOOL_NAME} \ --threadcount=4 \ --regioncount=1024 \ --regionsize=4M \ diff --git a/scripts/zpios.sh b/scripts/zpios.sh index dc55dd0c99..4188a8883b 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -5,10 +5,7 @@ . ./common.sh PROG=zpios.sh - -PROFILE_ZPIOS_PRE=${TOPDIR}/scripts/zpios-profile/zpios-profile-pre.sh -PROFILE_ZPIOS_POST=${TOPDIR}/scripts/zpios-profile/zpios-profile-post.sh -PROFILE_ZPIOS_LOG=/tmp/ +DATE=`date +%Y%m%d-%H%M%S` MODULES=( \ ${MODDIR}/zpios/zpios.ko \ @@ -114,6 +111,43 @@ check_test() { return 0 } +zpios_profile_config() { +cat > ${PROFILE_ZPIOS_LOG}/zpios-config.sh << EOF +# +# Zpios Profiling Configuration +# + +KERNEL_BIN="/lib/modules/`uname -r`/kernel/" +SPL_BIN="${SPLBUILD}/module/" +ZFS_BIN="${TOPDIR}/module/" + +PROFILE_ZPIOS_BIN=${TOPDIR}/scripts/zpios-profile/zpios-profile.sh +PROFILE_ZPIOS_PIDS_BIN=${TOPDIR}/scripts/zpios-profile/zpios-profile-pids.sh +PROFILE_ZPIOS_DISK_BIN=${TOPDIR}/scripts/zpios-/profile/zpios-profile-disk.sh + +EOF +} + +zpios_profile_start() { + PROFILE_ZPIOS_PRE=${TOPDIR}/scripts/zpios-profile/zpios-profile-pre.sh + PROFILE_ZPIOS_POST=${TOPDIR}/scripts/zpios-profile/zpios-profile-post.sh + PROFILE_ZPIOS_LOG=/tmp/zpios/${ZPOOL_CONFIG}+${ZPIOS_TEST_ARG}+${DATE} + ZPIOS_OPTIONS="${ZPIOS_OPTIONS} --log=${PROFILE_ZPIOS_LOG}" + ZPIOS_OPTIONS="${ZPIOS_OPTIONS} --prerun=${PROFILE_ZPIOS_PRE}" + ZPIOS_OPTIONS="${ZPIOS_OPTIONS} --postrun=${PROFILE_ZPIOS_POST}" + + mkdir -p ${PROFILE_ZPIOS_LOG} + zpios_profile_config + + /usr/bin/opcontrol --init || exit 1 + /usr/bin/opcontrol --setup --vmlinux=/boot/vmlinux || exit 1 +} + +zpios_profile_stop() { + /usr/bin/opcontrol --shutdown + /usr/bin/opcontrol --deinit +} + PROFILE= ZPOOL_CONFIG=zpool-config.sh ZPIOS_TEST=zpios-test.sh @@ -139,6 +173,7 @@ while getopts 'hvpc:t:o:l:s:' OPTION; do ZPOOL_CONFIG=${OPTARG} ;; t) + ZPIOS_TEST_ARG=${OPTARG} ZPIOS_TEST=${TOPDIR}/scripts/zpios-test/${OPTARG}.sh ;; o) @@ -188,17 +223,19 @@ fi ./zpool-create.sh ${VERBOSE_FLAG} -p ${ZPOOL_NAME} -c ${ZPOOL_CONFIG} \ -l "${ZPOOL_OPTIONS}" -s "${ZFS_OPTIONS}" || exit 1 -if [ $PROFILE ]; then - ZPIOS_CMD="${ZPIOS_CMD} --log=${PROFILE_ZPIOS_LOG}" - ZPIOS_CMD="${ZPIOS_CMD} --prerun=${PROFILE_ZPIOS_PRE}" - ZPIOS_CMD="${ZPIOS_CMD} --postrun=${PROFILE_ZPIOS_POST}" +if [ ${PROFILE} ]; then + zpios_profile_start fi echo -date +echo "${DATE}" zpios_start zpios_stop +if [ ${PROFILE} ]; then + zpios_profile_stop +fi + if [ ${VERBOSE} ]; then print_stats fi From 4d28f29b6c9d5ba754eef584c7866c3ffee1adbc Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Fri, 20 Feb 2009 14:28:00 -0800 Subject: [PATCH 40/45] Update profile scripts with additional upcalls for fine grained profiling --- module/zpios/include/zpios-ctl.h | 14 ++++++++++---- module/zpios/zpios.c | 28 ++++++++++++++++------------ scripts/zpios.sh | 30 +++++++++++++++++------------- 3 files changed, 43 insertions(+), 29 deletions(-) diff --git a/module/zpios/include/zpios-ctl.h b/module/zpios/include/zpios-ctl.h index 767fdfdb15..abe4b814bf 100644 --- a/module/zpios/include/zpios-ctl.h +++ b/module/zpios/include/zpios-ctl.h @@ -58,10 +58,16 @@ #define ZPIOS_NAME_SIZE 16 #define ZPIOS_PATH_SIZE 128 -#define PHASE_PRE "pre" -#define PHASE_POST "post" -#define PHASE_WRITE "write" -#define PHASE_READ "read" +#define PHASE_PRE_RUN "pre-run" +#define PHASE_PRE_CREATE "pre-create" +#define PHASE_PRE_WRITE "pre-write" +#define PHASE_PRE_READ "pre-read" +#define PHASE_PRE_REMOVE "pre-remove" +#define PHASE_POST_RUN "post-run" +#define PHASE_POST_CREATE "post-create" +#define PHASE_POST_WRITE "post-write" +#define PHASE_POST_READ "post-read" +#define PHASE_POST_REMOVE "post-remove" #define ZPIOS_CFG_MAGIC 0x87237190U typedef struct zpios_cfg { diff --git a/module/zpios/zpios.c b/module/zpios/zpios.c index 9b3ab28b90..7d170d17ee 100644 --- a/module/zpios/zpios.c +++ b/module/zpios/zpios.c @@ -29,7 +29,7 @@ * * CDDL HEADER END * - * Kernel PIOS DMU implemenation originally derived from PIOS test code. + * Kernel PIOS DMU implementation originally derived from PIOS test code. * Character control interface derived from SPL code. */ @@ -63,7 +63,7 @@ int zpios_upcall(char *path, char *phase, run_args_t *run_args, int rc) char thread_delay[16], flags[16], result[8]; char *argv[16], *envp[4]; - if (strlen(path) == 0) + if ((path == NULL) || (strlen(path) == 0)) return -ENOENT; snprintf(id, 15, "%d", run_args->id); @@ -96,7 +96,7 @@ int zpios_upcall(char *path, char *phase, run_args_t *run_args, int rc) argv[14] = result; argv[15] = NULL; - /* Passing environment for userspace upcall */ + /* Passing environment for user space upcall */ envp[0] = "HOME=/"; envp[1] = "TERM=linux"; envp[2] = "PATH=/sbin:/usr/sbin:/bin:/usr/bin"; @@ -174,6 +174,7 @@ zpios_dmu_setup(run_args_t *run_args) uint64_t obj = 0ULL; int i, rc = 0; + (void)zpios_upcall(run_args->pre, PHASE_PRE_CREATE, run_args, 0); t->start = current_kernel_time(); rc = dmu_objset_open(run_args->pool, DMU_OST_ZFS, DS_MODE_USER, &os); @@ -225,6 +226,7 @@ zpios_dmu_setup(run_args_t *run_args) out: t->stop = current_kernel_time(); t->delta = timespec_sub(t->stop, t->start); + (void)zpios_upcall(run_args->post, PHASE_POST_CREATE, run_args, rc); return rc; } @@ -352,6 +354,7 @@ zpios_remove_objects(run_args_t *run_args) zpios_region_t *region; int rc = 0, i; + (void)zpios_upcall(run_args->pre, PHASE_PRE_REMOVE, run_args, 0); t->start = current_kernel_time(); if (run_args->flags & DMU_REMOVE) { @@ -382,6 +385,7 @@ zpios_remove_objects(run_args_t *run_args) t->stop = current_kernel_time(); t->delta = timespec_sub(t->stop, t->start); + (void)zpios_upcall(run_args->post, PHASE_POST_REMOVE, run_args, rc); } static void @@ -665,8 +669,6 @@ zpios_threads_run(run_args_t *run_args) zpios_time_t *tr = &(run_args->stats.rd_time); int i, rc = 0, tc = run_args->thread_count; - zpios_upcall(run_args->pre, PHASE_PRE, run_args, 0); - tsks = kmem_zalloc(sizeof(struct task_struct *) * tc, KM_SLEEP); if (tsks == NULL) { rc = -ENOMEM; @@ -709,7 +711,7 @@ zpios_threads_run(run_args_t *run_args) tt->start = current_kernel_time(); /* Wake up all threads for write phase */ - zpios_upcall(run_args->pre, PHASE_WRITE, run_args, 0); + (void)zpios_upcall(run_args->pre, PHASE_PRE_WRITE, run_args, 0); for (i = 0; i < tc; i++) wake_up_process(tsks[i]); @@ -717,6 +719,7 @@ zpios_threads_run(run_args_t *run_args) tw->start = current_kernel_time(); wait_event(run_args->waitq, zpios_thread_done(run_args)); tw->stop = current_kernel_time(); + (void)zpios_upcall(run_args->post, PHASE_POST_WRITE, run_args, rc); for (i = 0; i < tc; i++) { thr = run_args->threads[i]; @@ -731,7 +734,6 @@ zpios_threads_run(run_args_t *run_args) mutex_exit(&thr->lock); } - zpios_upcall(run_args->post, PHASE_WRITE, run_args, rc); if (rc) { /* Wake up all threads and tell them to exit */ for (i = 0; i < tc; i++) { @@ -750,7 +752,7 @@ zpios_threads_run(run_args_t *run_args) mutex_exit(&run_args->lock_ctl); /* Wake up all threads for read phase */ - zpios_upcall(run_args->pre, PHASE_READ, run_args, 0); + (void)zpios_upcall(run_args->pre, PHASE_PRE_READ, run_args, 0); for (i = 0; i < tc; i++) wake_up_process(tsks[i]); @@ -758,6 +760,7 @@ zpios_threads_run(run_args_t *run_args) tr->start = current_kernel_time(); wait_event(run_args->waitq, zpios_thread_done(run_args)); tr->stop = current_kernel_time(); + (void)zpios_upcall(run_args->post, PHASE_POST_READ, run_args, rc); for (i = 0; i < tc; i++) { thr = run_args->threads[i]; @@ -771,8 +774,6 @@ zpios_threads_run(run_args_t *run_args) run_args->stats.rd_chunks += thr->stats.rd_chunks; mutex_exit(&thr->lock); } - - zpios_upcall(run_args->post, PHASE_READ, run_args, rc); out: tt->stop = current_kernel_time(); tt->delta = timespec_sub(tt->stop, tt->start); @@ -782,8 +783,6 @@ out: cleanup: kmem_free(tsks, sizeof(struct task_struct *) * tc); cleanup2: - zpios_upcall(run_args->post, PHASE_POST, run_args, rc); - /* Returns first encountered thread error (if any) */ return rc; @@ -844,6 +843,8 @@ zpios_do_one_run(struct file *file, zpios_cmd_t *kcmd, return -ENOSPC; } + (void)zpios_upcall(kcmd->cmd_pre, PHASE_PRE_RUN, run_args, 0); + rc = zpios_setup_run(&run_args, kcmd, file); if (rc) return rc; @@ -867,6 +868,9 @@ zpios_do_one_run(struct file *file, zpios_cmd_t *kcmd, cleanup: zpios_cleanup_run(run_args); + + (void)zpios_upcall(kcmd->cmd_post, PHASE_POST_RUN, run_args, 0); + return rc; } diff --git a/scripts/zpios.sh b/scripts/zpios.sh index 4188a8883b..ed7de35df0 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -117,30 +117,34 @@ cat > ${PROFILE_ZPIOS_LOG}/zpios-config.sh << EOF # Zpios Profiling Configuration # -KERNEL_BIN="/lib/modules/`uname -r`/kernel/" -SPL_BIN="${SPLBUILD}/module/" -ZFS_BIN="${TOPDIR}/module/" +PROFILE_ZPIOS_LOG=/tmp/zpios/${ZPOOL_CONFIG}+${ZPIOS_TEST_ARG}+${DATE} +PROFILE_ZPIOS_PRE=${TOPDIR}/scripts/zpios-profile/zpios-profile-pre.sh +PROFILE_ZPIOS_POST=${TOPDIR}/scripts/zpios-profile/zpios-profile-post.sh +PROFILE_ZPIOS_USER=${TOPDIR}/scripts/zpios-profile/zpios-profile.sh +PROFILE_ZPIOS_PIDS=${TOPDIR}/scripts/zpios-profile/zpios-profile-pids.sh +PROFILE_ZPIOS_DISK=${TOPDIR}/scripts/zpios-/profile/zpios-profile-disk.sh -PROFILE_ZPIOS_BIN=${TOPDIR}/scripts/zpios-profile/zpios-profile.sh -PROFILE_ZPIOS_PIDS_BIN=${TOPDIR}/scripts/zpios-profile/zpios-profile-pids.sh -PROFILE_ZPIOS_DISK_BIN=${TOPDIR}/scripts/zpios-/profile/zpios-profile-disk.sh +OPROFILE_KERNEL_BIN="/boot/vmlinux-`uname -r`" +OPROFILE_KERNEL_BIN_DIR="/lib/modules/`uname -r`/kernel/" +OPROFILE_SPL_BIN_DIR="${SPLBUILD}/module/" +OPROFILE_ZFS_BIN_DIR="${TOPDIR}/module/" EOF } zpios_profile_start() { - PROFILE_ZPIOS_PRE=${TOPDIR}/scripts/zpios-profile/zpios-profile-pre.sh - PROFILE_ZPIOS_POST=${TOPDIR}/scripts/zpios-profile/zpios-profile-post.sh PROFILE_ZPIOS_LOG=/tmp/zpios/${ZPOOL_CONFIG}+${ZPIOS_TEST_ARG}+${DATE} + + mkdir -p ${PROFILE_ZPIOS_LOG} + zpios_profile_config + . ${PROFILE_ZPIOS_LOG}/zpios-config.sh + ZPIOS_OPTIONS="${ZPIOS_OPTIONS} --log=${PROFILE_ZPIOS_LOG}" ZPIOS_OPTIONS="${ZPIOS_OPTIONS} --prerun=${PROFILE_ZPIOS_PRE}" ZPIOS_OPTIONS="${ZPIOS_OPTIONS} --postrun=${PROFILE_ZPIOS_POST}" - mkdir -p ${PROFILE_ZPIOS_LOG} - zpios_profile_config - - /usr/bin/opcontrol --init || exit 1 - /usr/bin/opcontrol --setup --vmlinux=/boot/vmlinux || exit 1 + /usr/bin/opcontrol --init + /usr/bin/opcontrol --setup --vmlinux=${OPROFILE_KERNEL_BIN} } zpios_profile_stop() { From a31814f47bf164e3d9b75dce9bf6319824af225f Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Fri, 20 Feb 2009 22:27:18 -0800 Subject: [PATCH 41/45] Further profile infrastructure --- scripts/zpios-profile/zpios-profile-post.sh | 138 ++++++++++++---- scripts/zpios-profile/zpios-profile-pre.sh | 174 +++++++++++++++----- scripts/zpios-profile/zpios-profile.sh | 2 + scripts/zpios.sh | 38 +++-- 4 files changed, 261 insertions(+), 91 deletions(-) diff --git a/scripts/zpios-profile/zpios-profile-post.sh b/scripts/zpios-profile/zpios-profile-post.sh index 9f53daa2b1..3a454ba045 100755 --- a/scripts/zpios-profile/zpios-profile-post.sh +++ b/scripts/zpios-profile/zpios-profile-post.sh @@ -4,50 +4,126 @@ PROG=zpios-profile-post.sh RUN_POST=${0} RUN_PHASE=${1} -RUN_LOG_DIR=${2} +RUN_DIR=${2} RUN_ID=${3} RUN_POOL=${4} RUN_CHUNK_SIZE=${5} RUN_REGION_SIZE=${6} -RUN_THREAD_COUNT=${7} +RUN_THRD_COUNT=${7} RUN_REGION_COUNT=${8} RUN_OFFSET=${9} RUN_REGION_NOISE=${10} RUN_CHUNK_NOISE=${11} -RUN_THREAD_DELAY=${12} +RUN_THRD_DELAY=${12} RUN_FLAGS=${13} RUN_RESULT=${14} -if [ "${RUN_PHASE}" != "post" ]; then - exit 1 -fi +# Summarize system time per process +zpios_profile_post_pids() { + ${PROFILE_PIDS} ${PROFILE_RUN_CR_PIDS_LOG} >${PROFILE_RUN_CR_PIDS_CSV} + ${PROFILE_PIDS} ${PROFILE_RUN_WR_PIDS_LOG} >${PROFILE_RUN_WR_PIDS_CSV} + ${PROFILE_PIDS} ${PROFILE_RUN_RD_PIDS_LOG} >${PROFILE_RUN_RD_PIDS_CSV} + ${PROFILE_PIDS} ${PROFILE_RUN_RM_PIDS_LOG} >${PROFILE_RUN_RM_PIDS_CSV} +} -. ${RUN_LOG_DIR}/zpios-config.sh -. ${RUN_LOG_DIR}/${RUN_ID}/zpios-config-run.sh - -#kill -s SIGHUP `cat ${PROFILE_PID}` -#rm -f ${PROFILE_PID} - -OPROFILE_SHORT_ARGS="-a -g -l -p ${KERNEL_BIN},${SPL_BIN},${ZFS_BIN}" -OPROFILE_LONG_ARGS="-d -a -g -l -p ${KERNEL_BIN},${SPL_BIN},${ZFS_BIN}" - -/usr/bin/opcontrol --stop >>${OPROFILE_LOG} 2>&1 -/usr/bin/opcontrol --dump >>${OPROFILE_LOG} 2>&1 -/usr/bin/opreport ${OPROFILE_SHORT_ARGS} >${OPROFILE_SHORT_LOG} 2>&1 -/usr/bin/opreport ${OPROFILE_LONG_ARGS} >${OPROFILE_LONG_LOG} 2>&1 - -if [ -f ${PROFILE_ARC_PROC} ]; then - cat ${PROFILE_ARC_PROC} >${PROFILE_ARC_LOG} -fi - -if [ -f ${PROFILE_VDEV_CACHE_PROC} ]; then - cat ${PROFILE_VDEV_CACHE_PROC} >${PROFILE_VDEV_CACHE_LOG} -fi - -# Summarize system time per pid -${PROFILE_ZPIOS_PIDS_BIN} ${RUN_LOG_DIR} ${RUN_ID} >${PROFILE_ZPIOS_PIDS_LOG} +zpios_profile_post_disk() { + ${PROFILE_DISK} ${PROFILE_RUN_CR_DISK_LOG} >${PROFILE_RUN_CR_DISK_CSV} + ${PROFILE_DISK} ${PROFILE_RUN_WR_DISK_LOG} >${PROFILE_RUN_WR_DISK_CSV} + ${PROFILE_DISK} ${PROFILE_RUN_RD_DISK_LOG} >${PROFILE_RUN_RD_DISK_CSV} + ${PROFILE_DISK} ${PROFILE_RUN_RM_DISK_LOG} >${PROFILE_RUN_RM_DISK_CSV} +} # Summarize per device performance -${PROFILE_ZPIOS_DISK_BIN} ${RUN_LOG_DIR} ${RUN_ID} >${PROFILE_ZPIOS_DISK_LOG} + +# Stop a user defined profiling script which is gathering additional data +zpios_profile_post_stop() { + local PROFILE_PID=$1 + + kill -s SIGHUP `cat ${PROFILE_PID}` + + + # Sleep waiting for profile script to exit + while [ -f ${PROFILE_PID} ]; do + sleep 0.01 + done +} + +zpios_profile_post_proc_stop() { + local PROC_DIR=$1 + + if [ -f ${PROFILE_ARC_PROC} ]; then + cat ${PROFILE_ARC_PROC} >${PROC_DIR}/arcstats.txt + fi + + if [ -f ${PROFILE_VDEV_CACHE_PROC} ]; then + cat ${PROFILE_VDEV_CACHE_PROC} >${PROC_DIR}/vdev_cache_stats.txt + fi +} + +zpios_profile_post_oprofile_stop() { + local OPROFILE_LOG=$1 + local OPROFILE_ARGS="-a -g -l -p ${OPROFILE_KERNEL_DIR},${OPROFILE_SPL_DIR},${OPROFILE_ZFS_DIR}" + + /usr/bin/opcontrol --stop >>${OPROFILE_LOG} 2>&1 + /usr/bin/opcontrol --dump >>${OPROFILE_LOG} 2>&1 + /usr/bin/opreport ${OPROFILE_ARGS} >${OPROFILE_LOG} 2>&1 + /usr/bin/oparchive +} + +zpios_profile_post_create() { + zpios_profile_post_oprofile_stop ${PROFILE_RUN_CR_OPROFILE_LOG} + zpios_profile_post_proc_stop ${PROFILE_RUN_CR_DIR} + zpios_profile_post_stop ${PROFILE_RUN_CR_PID} +} + +zpios_profile_post_write() { + zpios_profile_post_oprofile_stop ${PROFILE_RUN_WR_OPROFILE_LOG} + zpios_profile_post_proc_stop ${PROFILE_RUN_WR_DIR} + zpios_profile_post_stop ${PROFILE_RUN_WR_PID} +} + +zpios_profile_post_read() { + zpios_profile_post_oprofile_stop ${PROFILE_RUN_CR_RD_LOG} + zpios_profile_post_proc_stop ${PROFILE_RUN_RD_DIR} + zpios_profile_post_stop ${PROFILE_RUN_RD_PID} +} + +zpios_profile_post_remove() { + zpios_profile_post_oprofile_stop ${PROFILE_RUN_RM_OPROFILE_LOG} + zpios_profile_post_proc_stop ${PROFILE_RUN_RM_DIR} + zpios_profile_post_stop ${PROFILE_RUN_RM_PID} +} + +# Source global zpios test configuration +if [ -f ${RUN_DIR}/zpios-config.sh ]; then + . ${RUN_DIR}/zpios-config.sh +fi + +# Source global per-run test configuration +if [ -f ${RUN_DIR}/${RUN_ID}/zpios-config-run.sh ]; then + . ${RUN_DIR}/${RUN_ID}/zpios-config-run.sh +fi + +case "${RUN_PHASE}" in + post-run) + zpios_profile_post_pids + zpios_profile_post_disk + ;; + post-create) + zpios_profile_post_create + ;; + post-write) + zpios_profile_post_write + ;; + post-read) + zpios_profile_post_read + ;; + post-remove) + zpios_profile_post_remove + ;; + *) + echo "Usage: ${PROG} {post-run|post-create|post-write|post-read|post-remove}" + exit 1 +esac exit 0 diff --git a/scripts/zpios-profile/zpios-profile-pre.sh b/scripts/zpios-profile/zpios-profile-pre.sh index 09b4aba779..a2a885798d 100755 --- a/scripts/zpios-profile/zpios-profile-pre.sh +++ b/scripts/zpios-profile/zpios-profile-pre.sh @@ -2,93 +2,183 @@ PROG=zpios-profile-pre.sh -PROFILE_ZPIOS_READY=0 -trap "PROFILE_ZPIOS_READY=1" SIGHUP +PROFILE_RDY=0 +trap "PROFILE_RDY=1" SIGHUP RUN_PRE=${0} RUN_PHASE=${1} -RUN_LOG_DIR=${2} +RUN_DIR=${2} RUN_ID=${3} RUN_POOL=${4} RUN_CHUNK_SIZE=${5} RUN_REGION_SIZE=${6} -RUN_THREAD_COUNT=${7} +RUN_THRD_COUNT=${7} RUN_REGION_COUNT=${8} RUN_OFFSET=${9} RUN_REGION_NOISE=${10} RUN_CHUNK_NOISE=${11} -RUN_THREAD_DELAY=${12} +RUN_THRD_DELAY=${12} RUN_FLAGS=${13} RUN_RESULT=${14} -zpios_profile_run_cfg() { -cat > ${RUN_LOG_DIR}/${RUN_ID}/zpios-config-run.sh << EOF +zpios_profile_pre_run_cfg() { +cat > ${RUN_DIR}/${RUN_ID}/zpios-config-run.sh << EOF # # Zpios Profiling Configuration for Run ${RUN_ID} # -PROFILE_PID=${RUN_LOG_DIR}/${RUN_ID}/profile.pid +PROFILE_RUN_DIR=${RUN_DIR}/${RUN_ID} -PROFILE_ZPIOS_PIDS_LOG=${RUN_LOG_DIR}/${RUN_ID}/pids-summary.csv -PROFILE_ZPIOS_DISK_LOG=${RUN_LOG_DIR}/${RUN_ID}/disk-summary.csv +PROFILE_RUN_CR_DIR=${RUN_DIR}/${RUN_ID}/create +PROFILE_RUN_CR_PID=${RUN_DIR}/${RUN_ID}/create/profile.pid +PROFILE_RUN_CR_OPROFILE_LOG=${RUN_DIR}/${RUN_ID}/create/oprofile.txt +PROFILE_RUN_CR_PIDS_LOG=${RUN_DIR}/${RUN_ID}/create/pids.txt +PROFILE_RUN_CR_PIDS_CSV=${RUN_DIR}/${RUN_ID}/create/pids.csv +PROFILE_RUN_CR_DISK_LOG=${RUN_DIR}/${RUN_ID}/create/disk.txt +PROFILE_RUN_CR_DISK_CSV=${RUN_DIR}/${RUN_ID}/create/disk.csv -PROFILE_ARC_LOG=${RUN_LOG_DIR}/${RUN_ID}/arcstats -PROFILE_ARC_PROC=/proc/spl/kstat/zfs/arcstats +PROFILE_RUN_WR_DIR=${RUN_DIR}/${RUN_ID}/write +PROFILE_RUN_WR_PID=${RUN_DIR}/${RUN_ID}/write/profile.pid +PROFILE_RUN_WR_OPROFILE_LOG=${RUN_DIR}/${RUN_ID}/write/oprofile.txt +PROFILE_RUN_WR_PIDS_LOG=${RUN_DIR}/${RUN_ID}/write/pids.txt +PROFILE_RUN_WR_PIDS_CSV=${RUN_DIR}/${RUN_ID}/write/pids.csv +PROFILE_RUN_WR_DISK_LOG=${RUN_DIR}/${RUN_ID}/write/disk.txt +PROFILE_RUN_WR_DISK_CSV=${RUN_DIR}/${RUN_ID}/write/disk.csv -PROFILE_VDEV_CACHE_LOG=${RUN_LOG_DIR}/${RUN_ID}/vdev_cache_stats -PROFILE_VDEV_CACHE_PROC=/proc/spl/kstat/zfs/vdev_cache_stats +PROFILE_RUN_RD_DIR=${RUN_DIR}/${RUN_ID}/read +PROFILE_RUN_RD_PID=${RUN_DIR}/${RUN_ID}/read/profile.pid +PROFILE_RUN_RD_OPROFILE_LOG=${RUN_DIR}/${RUN_ID}/read/oprofile.txt +PROFILE_RUN_RD_PIDS_LOG=${RUN_DIR}/${RUN_ID}/read/pids.txt +PROFILE_RUN_RD_PIDS_CSV=${RUN_DIR}/${RUN_ID}/read/pids.csv +PROFILE_RUN_RD_DISK_LOG=${RUN_DIR}/${RUN_ID}/read/disk.txt +PROFILE_RUN_RD_DISK_CSV=${RUN_DIR}/${RUN_ID}/read/disk.csv -OPROFILE_LOG=${RUN_LOG_DIR}/${RUN_ID}/oprofile.txt -OPROFILE_SHORT_LOG=${RUN_LOG_DIR}/${RUN_ID}/oprofile-short.txt -OPROFILE_LONG_LOG=${RUN_LOG_DIR}/${RUN_ID}/oprofile-long.txt +PROFILE_RUN_RM_DIR=${RUN_DIR}/${RUN_ID}/remove +PROFILE_RUN_RM_PID=${RUN_DIR}/${RUN_ID}/remove/profile.pid +PROFILE_RUN_RM_OPROFILE_LOG=${RUN_DIR}/${RUN_ID}/remove/oprofile.txt +PROFILE_RUN_RM_PIDS_LOG=${RUN_DIR}/${RUN_ID}/remove/pids.txt +PROFILE_RUN_RM_PIDS_CSV=${RUN_DIR}/${RUN_ID}/remove/pids.csv +PROFILE_RUN_RM_DISK_LOG=${RUN_DIR}/${RUN_ID}/remove/disk.txt +PROFILE_RUN_RM_DISK_CSV=${RUN_DIR}/${RUN_ID}/remove/disk.csv +# PROFILE_PIDS_LOG=${RUN_DIR}/${RUN_ID}/pids-summary.csv +# PROFILE_DISK_LOG=${RUN_DIR}/${RUN_ID}/disk-summary.csv EOF } -zpios_profile_run_args() { -cat > ${RUN_LOG_DIR}/${RUN_ID}/zpios-args.txt << EOF +zpios_profile_pre_run_args() { +cat > ${RUN_DIR}/${RUN_ID}/zpios-args.txt << EOF # # Zpios Arguments for Run ${RUN_ID} # -LOG_DIR=${RUN_LOG_DIR} +DIR=${RUN_DIR} ID=${RUN_ID} POOL=${RUN_POOL} CHUNK_SIZE=${RUN_CHUNK_SIZE} REGION_SIZE=${RUN_REGION_SIZE} -THREAD_COUNT=${RUN_THREAD_COUNT} +THRD_COUNT=${RUN_THRD_COUNT} REGION_COUNT=${RUN_REGION_COUNT} OFFSET=${RUN_OFFSET} REGION_NOISE=${RUN_REGION_NOISE} CHUNK_NOISE=${RUN_CHUNK_NOISE} -THREAD_DELAY=${RUN_THREAD_DELAY} +THRD_DELAY=${RUN_THRD_DELAY} FLAGS=${RUN_FLAGS} RESULT=${RUN_RESULT} EOF } -if [ "${RUN_PHASE}" != "pre" ]; then - exit 1 +# Spawn a user defined profiling script to gather additional data +zpios_profile_pre_start() { + local PROFILE_PID=$1 + + ${PROFILE_USER} ${RUN_PHASE} ${RUN_DIR} ${RUN_ID} & + echo "$!" >${PROFILE_PID} + + # Sleep waiting for profile script to be ready, it will + # signal us via SIGHUP when it is ready to start profiling. + while [ ${PROFILE_RDY} -eq 0 ]; do + sleep 0.01 + done +} + +zpios_profile_post_proc_start() { + + if [ -f ${PROFILE_ARC_PROC} ]; then + echo 0 >${PROFILE_ARC_PROC} + fi + + if [ -f ${PROFILE_VDEV_CACHE_PROC} ]; then + echo 0 >${PROFILE_VDEV_CACHE_PROC} + fi +} + +zpios_profile_pre_oprofile_start() { + local OPROFILE_LOG=$1 + + /usr/bin/opcontrol --reset >>${OPROFILE_LOG} 2>&1 + /usr/bin/opcontrol --start >>${OPROFILE_LOG} 2>&1 +} + +zpios_profile_pre_create() { + mkdir ${PROFILE_RUN_CR_DIR} + zpios_profile_pre_start ${PROFILE_RUN_CR_PID} + zpios_profile_post_proc_start + zpios_profile_pre_oprofile_start ${PROFILE_RUN_CR_OPROFILE_LOG} +} + +zpios_profile_pre_write() { + mkdir ${PROFILE_RUN_WR_DIR} + zpios_profile_pre_start ${PROFILE_RUN_WR_PID} + zpios_profile_post_proc_start + zpios_profile_pre_oprofile_start ${PROFILE_RUN_WR_OPROFILE_LOG} +} + +zpios_profile_pre_read() { + mkdir ${PROFILE_RUN_RD_DIR} + zpios_profile_pre_start ${PROFILE_RUN_RD_PID} + zpios_profile_post_proc_start + zpios_profile_pre_oprofile_start ${PROFILE_RUN_CR_RD_LOG} +} + +zpios_profile_pre_remove() { + mkdir ${PROFILE_RUN_RM_DIR} + zpios_profile_pre_start ${PROFILE_RUN_RM_PID} + zpios_profile_post_proc_start + zpios_profile_pre_oprofile_start ${PROFILE_RUN_RM_OPROFILE_LOG} +} + +# Source global zpios test configuration +if [ -f ${RUN_DIR}/zpios-config.sh ]; then + . ${RUN_DIR}/zpios-config.sh fi -mkdir -p ${RUN_LOG_DIR}/${RUN_ID}/ -zpios_profile_run_cfg -zpios_profile_run_args +# Source global per-run test configuration +if [ -f ${RUN_DIR}/${RUN_ID}/zpios-config-run.sh ]; then + . ${RUN_DIR}/${RUN_ID}/zpios-config-run.sh +fi -. ${RUN_LOG_DIR}/zpios-config.sh -. ${RUN_LOG_DIR}/${RUN_ID}/zpios-config-run.sh - -# Start the profile script -#${PROFILE_ZPIOS_BIN} ${RUN_PHASE} ${RUN_LOG_DIR} ${RUN_ID} & -#echo "$!" >${PROFILE_PID} - -# Sleep waiting for profile script to be ready, it will -# signal us via SIGHUP when it is ready to start profiling. -#while [ ${PROFILE_ZPIOS_READY} -eq 0 ]; do -# sleep 0.1 -#done - -/usr/bin/opcontrol --reset >>${OPROFILE_LOG} 2>&1 -/usr/bin/opcontrol --start >>${OPROFILE_LOG} 2>&1 +case "${RUN_PHASE}" in + pre-run) + mkdir -p ${RUN_DIR}/${RUN_ID}/ + zpios_profile_pre_run_cfg + zpios_profile_pre_run_args + ;; + pre-create) + zpios_profile_pre_create + ;; + pre-write) + zpios_profile_pre_write + ;; + pre-read) + zpios_profile_pre_read + ;; + pre-remove) + zpios_profile_pre_remove + ;; + *) + echo "Usage: ${PROG} {pre-run|pre-create|pre-write|pre-read|pre-remove}" + exit 1 +esac exit 0 diff --git a/scripts/zpios-profile/zpios-profile.sh b/scripts/zpios-profile/zpios-profile.sh index d3ff779eac..f4f0ee97fd 100755 --- a/scripts/zpios-profile/zpios-profile.sh +++ b/scripts/zpios-profile/zpios-profile.sh @@ -221,4 +221,6 @@ log_pids() { aquire_pids log_pids +# rm ${PROFILE_PID} + exit 0 diff --git a/scripts/zpios.sh b/scripts/zpios.sh index ed7de35df0..fec44f57bb 100755 --- a/scripts/zpios.sh +++ b/scripts/zpios.sh @@ -112,39 +112,41 @@ check_test() { } zpios_profile_config() { -cat > ${PROFILE_ZPIOS_LOG}/zpios-config.sh << EOF +cat > ${PROFILE_DIR}/zpios-config.sh << EOF # # Zpios Profiling Configuration # -PROFILE_ZPIOS_LOG=/tmp/zpios/${ZPOOL_CONFIG}+${ZPIOS_TEST_ARG}+${DATE} -PROFILE_ZPIOS_PRE=${TOPDIR}/scripts/zpios-profile/zpios-profile-pre.sh -PROFILE_ZPIOS_POST=${TOPDIR}/scripts/zpios-profile/zpios-profile-post.sh -PROFILE_ZPIOS_USER=${TOPDIR}/scripts/zpios-profile/zpios-profile.sh -PROFILE_ZPIOS_PIDS=${TOPDIR}/scripts/zpios-profile/zpios-profile-pids.sh -PROFILE_ZPIOS_DISK=${TOPDIR}/scripts/zpios-/profile/zpios-profile-disk.sh +PROFILE_DIR=/tmp/zpios/${ZPOOL_CONFIG}+${ZPIOS_TEST_ARG}+${DATE} +PROFILE_PRE=${TOPDIR}/scripts/zpios-profile/zpios-profile-pre.sh +PROFILE_POST=${TOPDIR}/scripts/zpios-profile/zpios-profile-post.sh +PROFILE_USER=${TOPDIR}/scripts/zpios-profile/zpios-profile.sh +PROFILE_PIDS=${TOPDIR}/scripts/zpios-profile/zpios-profile-pids.sh +PROFILE_DISK=${TOPDIR}/scripts/zpios-/profile/zpios-profile-disk.sh +PROFILE_ARC_PROC=/proc/spl/kstat/zfs/arcstats +PROFILE_VDEV_CACHE_PROC=/proc/spl/kstat/zfs/vdev_cache_stats -OPROFILE_KERNEL_BIN="/boot/vmlinux-`uname -r`" -OPROFILE_KERNEL_BIN_DIR="/lib/modules/`uname -r`/kernel/" -OPROFILE_SPL_BIN_DIR="${SPLBUILD}/module/" -OPROFILE_ZFS_BIN_DIR="${TOPDIR}/module/" +OPROFILE_KERNEL="/boot/vmlinux-`uname -r`" +OPROFILE_KERNEL_DIR="/lib/modules/`uname -r`/kernel/" +OPROFILE_SPL_DIR="${SPLBUILD}/module/" +OPROFILE_ZFS_DIR="${TOPDIR}/module/" EOF } zpios_profile_start() { - PROFILE_ZPIOS_LOG=/tmp/zpios/${ZPOOL_CONFIG}+${ZPIOS_TEST_ARG}+${DATE} + PROFILE_DIR=/tmp/zpios/${ZPOOL_CONFIG}+${ZPIOS_TEST_ARG}+${DATE} - mkdir -p ${PROFILE_ZPIOS_LOG} + mkdir -p ${PROFILE_DIR} zpios_profile_config - . ${PROFILE_ZPIOS_LOG}/zpios-config.sh + . ${PROFILE_DIR}/zpios-config.sh - ZPIOS_OPTIONS="${ZPIOS_OPTIONS} --log=${PROFILE_ZPIOS_LOG}" - ZPIOS_OPTIONS="${ZPIOS_OPTIONS} --prerun=${PROFILE_ZPIOS_PRE}" - ZPIOS_OPTIONS="${ZPIOS_OPTIONS} --postrun=${PROFILE_ZPIOS_POST}" + ZPIOS_OPTIONS="${ZPIOS_OPTIONS} --log=${PROFILE_DIR}" + ZPIOS_OPTIONS="${ZPIOS_OPTIONS} --prerun=${PROFILE_PRE}" + ZPIOS_OPTIONS="${ZPIOS_OPTIONS} --postrun=${PROFILE_POST}" /usr/bin/opcontrol --init - /usr/bin/opcontrol --setup --vmlinux=${OPROFILE_KERNEL_BIN} + /usr/bin/opcontrol --setup --vmlinux=${OPROFILE_KERNEL} } zpios_profile_stop() { From c0c0c27632d39e3a9e7d19a169956330d6e038a7 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 10 Mar 2009 21:45:50 -0700 Subject: [PATCH 42/45] Build system and packaging (RPM support) (Part 3) Complete support for dist install srpm and rpm make targets. --- configure.ac | 1 - module/Makefile.in | 1 + module/zpios/Makefile.in | 3 --- module/zpios/include/Makefile.in | 1 - 4 files changed, 1 insertion(+), 5 deletions(-) delete mode 100644 module/zpios/include/Makefile.in diff --git a/configure.ac b/configure.ac index 00962e2596..2903c36eda 100644 --- a/configure.ac +++ b/configure.ac @@ -76,7 +76,6 @@ AC_CONFIG_FILES([ module/zcommon/Makefile module/zfs/Makefile module/zpios/Makefile - module/zpios/include/Makefile scripts/Makefile scripts/zpool-config/Makefile scripts/zpios-test/Makefile diff --git a/module/Makefile.in b/module/Makefile.in index 2dfd043cb4..993b7fc3e9 100644 --- a/module/Makefile.in +++ b/module/Makefile.in @@ -3,6 +3,7 @@ subdir-m += nvpair subdir-m += unicode subdir-m += zcommon subdir-m += zfs +subdir-m += zpios modules clean: # Make the exported SPL symbols available to these modules. diff --git a/module/zpios/Makefile.in b/module/zpios/Makefile.in index c93e666da2..4924082a13 100644 --- a/module/zpios/Makefile.in +++ b/module/zpios/Makefile.in @@ -1,6 +1,3 @@ -subdir-m += include -DISTFILES = zpios.c - MODULE := zpios EXTRA_CFLAGS = -I@MODDIR@/zfs/include diff --git a/module/zpios/include/Makefile.in b/module/zpios/include/Makefile.in deleted file mode 100644 index 3aa71bfa19..0000000000 --- a/module/zpios/include/Makefile.in +++ /dev/null @@ -1 +0,0 @@ -DISTFILES = zpios-ctl.h zpios-internal.h From 071662bf322fb1b9ec70753233070ffa441fe7a3 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Wed, 11 Mar 2009 22:14:08 -0700 Subject: [PATCH 43/45] Remove unused variable --- cmd/zpios/zpios_main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd/zpios/zpios_main.c b/cmd/zpios/zpios_main.c index 6c1905201f..0505ad5db4 100644 --- a/cmd/zpios/zpios_main.c +++ b/cmd/zpios/zpios_main.c @@ -429,8 +429,6 @@ error: static int get_next(uint64_t *val, range_repeat_t *range) { - int i; - /* if low, incr, high is given */ if (range->val_count == 0) { *val = (range->val_low) + From b625eab8145882ccc0abeb393dfca7a5581e5837 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Thu, 12 Mar 2009 10:46:54 -0700 Subject: [PATCH 44/45] Move upcall after run_args are initialized. --- module/zpios/zpios.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/module/zpios/zpios.c b/module/zpios/zpios.c index 7d170d17ee..e710d910d6 100644 --- a/module/zpios/zpios.c +++ b/module/zpios/zpios.c @@ -270,6 +270,8 @@ zpios_setup_run(run_args_t **run_args, zpios_cmd_t *kcmd, struct file *file) mutex_init(&ra->lock_work, NULL, MUTEX_DEFAULT, NULL); mutex_init(&ra->lock_ctl, NULL, MUTEX_DEFAULT, NULL); + (void)zpios_upcall(ra->pre, PHASE_PRE_RUN, ra, 0); + rc = zpios_dmu_setup(ra); if (rc) { mutex_destroy(&ra->lock_ctl); @@ -799,7 +801,7 @@ static int zpios_do_one_run(struct file *file, zpios_cmd_t *kcmd, int data_size, void *data) { - run_args_t *run_args; + run_args_t *run_args = { 0 }; zpios_stats_t *stats = (zpios_stats_t *)data; int i, n, m, size, rc; @@ -843,8 +845,6 @@ zpios_do_one_run(struct file *file, zpios_cmd_t *kcmd, return -ENOSPC; } - (void)zpios_upcall(kcmd->cmd_pre, PHASE_PRE_RUN, run_args, 0); - rc = zpios_setup_run(&run_args, kcmd, file); if (rc) return rc; From 02424a268bcafd7148d342ac6a3af4fc06c18cae Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 17 Mar 2009 16:27:57 -0700 Subject: [PATCH 45/45] Use spl_device_* macro's for portability. --- module/zpios/zpios.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/zpios/zpios.c b/module/zpios/zpios.c index e710d910d6..fb508d7bbf 100644 --- a/module/zpios/zpios.c +++ b/module/zpios/zpios.c @@ -1263,7 +1263,7 @@ zpios_init(void) goto error; } - class_device_create(zpios_class, NULL, dev, NULL, "zpios"); + spl_device_create(zpios_class, NULL, dev, NULL, "zpios"); return 0; error: printk(KERN_ERR "ZPIOS: Error registering zpios device, %d\n", rc); @@ -1275,7 +1275,7 @@ zpios_fini(void) { dev_t dev = MKDEV(ZPIOS_MAJOR, 0); - class_device_destroy(zpios_class, dev); + spl_device_destroy(zpios_class, NULL, dev); class_destroy(zpios_class); cdev_del(&zpios_cdev);