ndevs=$((ndevs+1))
done
if [ $case == "netdisk" ]; then
- if [ "$targets" ]; then
- for ((i = 0; i < $ndevs; i++)); do
- setup_osc_for_remote_ost ${host_names[$i]} ${client_names[$i]} $i
- cleanup_oscs="$cleanup_oscs ${client_names[$i]}_osc"
- host_names[$i]=localhost
- done
- fi
- declare -a osc_names
- declare -a osc_uuids
- osc_names_str=$(lctl dl |grep osc | awk "{if (\$2 == \"UP\" && \$3 == \"osc\") {print \$4} }")
- count=0;
- for name in $osc_names_str; do
- osc_names[$count]=$name
- count=$((count+1))
- done
- osc_uuid_str=$(lctl dl |grep osc | awk "{if (\$2 == \"UP\" && \$3 == \"osc\") {print \$5} }")
- count=0;
- for uuid in $osc_uuid_str; do
- osc_uuids[$count]=$uuid
- count=$((count+1))
- done
- for (( i = 0; i < $count; i++ ))
- do
- ec_using_osc ${osc_names[$i]}
- done
- echo_clients=$(lctl dl | grep echo_client | awk "{if (\$2 == \"UP\" && \$3 == \"echo_client\") {print \$4} }")
+ if [ "$targets" ]; then
+ for ((i = 0; i < $ndevs; i++)); do
+ setup_osc_for_remote_ost ${host_names[$i]} \
+ ${client_names[$i]} $i
+ osc_name=${client_names[$i]}_osc
+ ec_using_osc $osc_name
+ cleanup_oscs="$cleanup_oscs $osc_name"
+ done
+ else
+ client_names_str=$($lctl dl | grep -v mdt | \
+ awk '{if ($2 == "UP" && $3 == "osc") {print $4} }')
+ count=0;
+ for name in $client_names_str; do
+ client_names[$count]=`echo $name | sed 's/-osc-.*$//'`
+ count=$((count+1))
+ done
+
+ host_names_str=$($lctl dl -t | grep -v mdt | \
+ awk '{if ($2 == "UP" && $3 == "osc") {print $7} }')
+ count=0;
+ for name in $host_names_str; do
+ host_names[$count]=`echo $name | sed 's/@.*$//'`
+ count=$((count+1))
+ done
+
+ for (( i = 0; i < $count; i++ )) do
+ setup_osc_for_remote_ost ${host_names[$i]} \
+ ${client_names[$i]} $i
+ osc_name=${client_names[$i]}_osc
+ ec_using_osc $osc_name
+ cleanup_oscs="$cleanup_oscs $osc_name"
+ done
+ fi
+
+ echo_clients=$($lctl dl | grep echo_client | awk "{if (\$2 == \"UP\" && \$3 == \"echo_client\") {print \$4} }")
cnt=0;
for name in $echo_clients; do
client_names[$cnt]=$name
fi
# Now do the server setup
setup_srv_obd $server_nid "echo_srv"
- oss_on_srv=`dsh $server_nid root "lctl dl | grep OSS" | awk '{ print $4 }'`
+ oss_on_srv=`dsh $server_nid root "$lctl dl | grep OSS" | awk '{ print $4 }'`
if [ -z $oss_on_srv ]; then
setup_OSS $server_nid
clean_srv_OSS=1
fi
- if ! dsh $server_nid root "lctl dl | grep obdecho > /dev/null 2>&1"; then
+ if ! dsh $server_nid root "$lctl dl | grep obdecho > /dev/null 2>&1"; then
echo "obdecho not setup on server"
exit 1
fi
- if ! dsh $server_nid root "lctl dl | grep ost > /dev/null 2>&1"; then
+ if ! dsh $server_nid root "$lctl dl | grep ost > /dev/null 2>&1"; then
echo "ost not setup on server"
exit 1
fi
# Now start client setup
- osc_names_str=$(lctl dl)
+ osc_names_str=$($lctl dl| grep osc | grep -v mdt | grep UP)
if [ -n "$osc_names_str" ]; then
echo "The existing setup must be cleaned";
exit 0;
actual_size=$((actual_rsz*count*thr))
total_size=$((actual_size*ndevs))
# show computed parameters
- str=`printf 'ost %2d sz %8dK rsz %4d obj %4d thr %4d ' \
+ str=`printf 'ost %2d sz %8dK rsz %4dK obj %4d thr %4d ' \
$ndevs $total_size $actual_rsz $total_nobj $total_thr`
echo "=======================> $str" >> $workf
print_summary -n "$str"
for host in ${unique_hosts[@]}; do
rm ${cmdsf}_${host}
done
+
# compute bandwidth from total data / elapsed time
str=`awk "BEGIN {printf \"%7.2f \",\
$total_size / (( $t1 - $t0 ) * 1024)}"`
struct list_head el_chain;
struct echo_object *el_object;
__u64 el_cookie;
+ atomic_t el_refcount;
};
struct echo_io {
cl_lock_slice_add(lock, &el->el_cl, obj, &echo_lock_ops);
el->el_object = cl2echo_obj(obj);
CFS_INIT_LIST_HEAD(&el->el_chain);
+ atomic_set(&el->el_refcount, 0);
}
RETURN(el == NULL ? -ENOMEM : 0);
}
return NULL;
}
+static void echo_lock_release(const struct lu_env *env,
+ struct echo_lock *ecl,
+ int still_used)
+{
+ struct cl_lock *clk = echo_lock2cl(ecl);
+
+ cl_lock_get(clk);
+ cl_unuse(env, clk);
+ cl_lock_release(env, clk, "ec enqueue", ecl->el_object);
+ if (!still_used) {
+ cl_lock_mutex_get(env, clk);
+ cl_lock_cancel(env, clk);
+ cl_lock_delete(env, clk);
+ cl_lock_mutex_put(env, clk);
+ }
+ cl_lock_put(env, clk);
+}
+
static struct lu_device *echo_device_free(const struct lu_env *env,
struct lu_device *d)
{
while (!list_empty(&ec->ec_locks)) {
struct echo_lock *ecl = list_entry(ec->ec_locks.next,
struct echo_lock, el_chain);
- struct cl_lock *lock = echo_lock2cl(ecl);
+ int still_used = 0;
- list_del_init(&ecl->el_chain);
+ if (atomic_dec_and_test(&ecl->el_refcount))
+ list_del_init(&ecl->el_chain);
+ else
+ still_used = 1;
spin_unlock(&ec->ec_lock);
- CERROR("echo client: pending lock %p\n", ecl);
-
- cl_lock_get(lock);
- cl_unuse(env, lock);
- cl_lock_release(env, lock, "ec enqueue", ecl->el_object);
-
- cl_lock_mutex_get(env, lock);
- cl_lock_cancel(env, lock);
- cl_lock_delete(env, lock);
- cl_lock_mutex_put(env, lock);
- cl_lock_put(env, lock);
+ CERROR("echo client: pending lock %p refs %d\n",
+ ecl, atomic_read(&ecl->el_refcount));
+ echo_lock_release(env, ecl, still_used);
spin_lock(&ec->ec_lock);
}
spin_unlock(&ec->ec_lock);
RETURN(0);
}
-static int cl_echo_enqueue(struct echo_object *eco, obd_off start, obd_off end,
- int mode, __u64 *cookie)
+static int cl_echo_enqueue0(struct lu_env *env, struct echo_object *eco,
+ obd_off start, obd_off end, int mode,
+ __u64 *cookie , __u32 enqflags)
{
- struct lu_env *env;
- struct cl_lock *lck;
- struct echo_thread_info *info;
struct cl_io *io;
+ struct cl_lock *lck;
+ struct cl_object *obj;
struct cl_lock_descr *descr;
- struct cl_object *obj = echo_obj2cl(eco);
- int refcheck;
- int result;
+ struct echo_thread_info *info;
+ int rc = -ENOMEM;
ENTRY;
- env = cl_env_get(&refcheck);
- if (IS_ERR(env))
- RETURN(PTR_ERR(env));
-
info = echo_env_info(env);
+ io = &info->eti_io;
descr = &info->eti_descr;
+ obj = echo_obj2cl(eco);
+
descr->cld_obj = obj;
descr->cld_start = cl_index(obj, start);
descr->cld_end = cl_index(obj, end);
descr->cld_mode = mode == LCK_PW ? CLM_WRITE : CLM_READ;
-
- io = &info->eti_io;
io->ci_obj = obj;
- result = cl_io_init(env, io, CIT_MISC, obj);
- if (result < 0)
- GOTO(out, result);
- LASSERT(result == 0);
- result = -ENOMEM;
- lck = cl_lock_request(env, io, descr, CEF_ASYNC, "ec enqueue", eco);
+ lck = cl_lock_request(env, io, descr, CEF_ASYNC | enqflags,
+ "ec enqueue", eco);
if (lck) {
struct echo_client_obd *ec = eco->eo_dev->ed_ec;
struct echo_lock *el;
- result = cl_wait(env, lck);
- if (result == 0) {
+ rc = cl_wait(env, lck);
+ if (rc == 0) {
el = cl2echo_lock(cl_lock_at(lck, &echo_device_type));
spin_lock(&ec->ec_lock);
- list_add(&el->el_chain, &ec->ec_locks);
- *cookie = el->el_cookie = ++ec->ec_unique;
+ if (list_empty(&el->el_chain)) {
+ list_add(&el->el_chain, &ec->ec_locks);
+ el->el_cookie = ++ec->ec_unique;
+ }
+ atomic_inc(&el->el_refcount);
+ *cookie = el->el_cookie;
spin_unlock(&ec->ec_lock);
} else
cl_lock_release(env, lck, "ec enqueue", cfs_current());
}
+ RETURN(rc);
+}
+
+static int cl_echo_enqueue(struct echo_object *eco, obd_off start, obd_off end,
+ int mode, __u64 *cookie)
+{
+ struct echo_thread_info *info;
+ struct lu_env *env;
+ struct cl_io *io;
+ int refcheck;
+ int result;
+ ENTRY;
+
+ env = cl_env_get(&refcheck);
+ if (IS_ERR(env))
+ RETURN(PTR_ERR(env));
+
+ info = echo_env_info(env);
+ io = &info->eti_io;
+
+ result = cl_io_init(env, io, CIT_MISC, echo_obj2cl(eco));
+ if (result < 0)
+ GOTO(out, result);
+ LASSERT(result == 0);
+
+ result = cl_echo_enqueue0(env, eco, start, end, mode, cookie, 0);
cl_io_fini(env, io);
EXIT;
return result;
}
-static int cl_echo_cancel(struct echo_device *ed, __u64 cookie)
+static int cl_echo_cancel0(struct lu_env *env, struct echo_device *ed,
+ __u64 cookie)
{
struct echo_client_obd *ec = ed->ed_ec;
struct echo_lock *ecl = NULL;
struct list_head *el;
- int found = 0;
- int result;
-
- struct lu_env *env;
- int refcheck;
+ int found = 0, still_used = 0;
ENTRY;
- env = cl_env_get(&refcheck);
- if (IS_ERR(env))
- RETURN(PTR_ERR(env));
-
+ LASSERT(ec != NULL);
spin_lock (&ec->ec_lock);
list_for_each (el, &ec->ec_locks) {
ecl = list_entry (el, struct echo_lock, el_chain);
CDEBUG(D_INFO, "ecl: %p, cookie: %llx\n", ecl, ecl->el_cookie);
found = (ecl->el_cookie == cookie);
if (found) {
- list_del_init(&ecl->el_chain);
+ if (atomic_dec_and_test(&ecl->el_refcount))
+ list_del_init(&ecl->el_chain);
+ else
+ still_used = 1;
break;
}
}
spin_unlock (&ec->ec_lock);
- result = -ENOENT;
- if (found) {
- struct cl_lock *clk = echo_lock2cl(ecl);
+ if (!found)
+ RETURN(-ENOENT);
- cl_lock_get(clk);
- cl_unuse(env, clk);
- cl_lock_release(env, clk, "ec enqueue", ecl->el_object);
+ echo_lock_release(env, ecl, still_used);
+ RETURN(0);
+}
+
+static int cl_echo_cancel(struct echo_device *ed, __u64 cookie)
+{
+ struct lu_env *env;
+ int refcheck;
+ int rc;
+ ENTRY;
+
+ env = cl_env_get(&refcheck);
+ if (IS_ERR(env))
+ RETURN(PTR_ERR(env));
+
+ rc = cl_echo_cancel0(env, ed, cookie);
- cl_lock_mutex_get(env, clk);
- cl_lock_cancel(env, clk);
- cl_lock_delete(env, clk);
- cl_lock_mutex_put(env, clk);
- cl_lock_put(env, clk);
- result = 0;
- }
cl_env_put(env, &refcheck);
- RETURN(result);
+ RETURN(rc);
}
static int cl_echo_async_brw(const struct lu_env *env, struct cl_io *io,
struct cl_2queue *queue;
struct cl_io *io;
struct cl_page *clp;
-
+ struct lustre_handle lh = { 0 };
int page_size = cl_page_size(obj);
int refcheck;
int rc;
int i;
ENTRY;
+ LASSERT((offset & ~CFS_PAGE_MASK) == 0);
LASSERT(ed->ed_next != NULL);
env = cl_env_get(&refcheck);
if (IS_ERR(env))
GOTO(out, rc);
LASSERT(rc == 0);
+
+ rc = cl_echo_enqueue0(env, eco, offset,
+ offset + npages * CFS_PAGE_SIZE - 1,
+ rw == READ ? LCK_PW : LCK_PW, &lh.cookie,
+ CILR_NEVER);
+ if (rc < 0)
+ GOTO(error_lock, rc);
+
for (i = 0; i < npages; i++) {
LASSERT(pages[i]);
clp = cl_page_find(env, obj, cl_index(obj, offset),
/* drop the reference count for cl_page_find, so that the page
* will be freed in cl_2queue_fini. */
cl_page_put(env, clp);
+ cl_page_clip(env, clp, 0, page_size);
+
offset += page_size;
}
async ? "async" : "sync", rc);
}
+ cl_echo_cancel0(env, ed, lh.cookie);
+ EXIT;
+error_lock:
cl_2queue_discard(env, io, queue);
cl_2queue_disown(env, io, queue);
cl_2queue_fini(env, queue);
cl_io_fini(env, io);
-
- EXIT;
out:
cl_env_put(env, &refcheck);
return rc;
}
run_test 170 "test lctl df to handle corrupted log ====================="
+# it would be good to share it with obdfilter-survey/libecho code
+setup_obdecho_osc () {
+ local rc=0
+ local ost_nid=$1
+ local obdfilter_name=$2
+ [ $rc -eq 0 ] && { $LCTL attach osc ${obdfilter_name}_osc \
+ ${obdfilter_name}_osc_UUID || rc=2; }
+ [ $rc -eq 0 ] && { $LCTL --device ${obdfilter_name}_osc setup \
+ ${obdfilter_name}_UUID $ost_nid || rc=3; }
+ return $rc
+}
+
+cleaup_obdecho_osc () {
+ local obdfilter_name=$1
+ $LCTL --device ${obdfilter_name}_osc cleanup >/dev/null
+ $LCTL --device ${obdfilter_name}_osc detach >/dev/null
+ return 0
+}
+
+obdecho_create_test() {
+ local OBD=$1
+ local node=ost
+ local rc=0
+ do_facet $node "$LCTL attach echo_client ec ec_uuid" || rc=1
+ [ $rc -eq 0 ] && { do_facet $node "$LCTL --device ec setup $OBD" || \
+ rc=2; }
+ [ $rc -eq 0 ] && { do_facet $node "$LCTL --device ec create 1" || \
+ rc=3; }
+ [ $rc -eq 0 ] && { do_facet $node "$LCTL --device ec test_brw 0 w 1" ||\
+ rc=4; }
+ [ $rc -eq 0 -o $rc -gt 2 ] && { do_facet $node "$LCTL --device ec " \
+ "cleanup" || rc=5; }
+ [ $rc -eq 0 -o $rc -gt 1 ] && { do_facet $node "$LCTL --device ec " \
+ "detach" || rc=6; }
+ return $rc
+}
+
+test_180() {
+ local rc=0
+ local rmmod_local=0
+ local rmmod_remote=0
+
+ lsmod | grep -q obdecho || \
+ { load_module obdecho/obdecho && rmmod_local=1; }
+ OBD=$($LCTL dl | grep -v mdt | grep osc | awk '{print $4;exit}')
+ HOST=$($LCTL dl -t | grep -v mdt | grep osc | awk '{print $7;exit}')
+ OBD=`echo $OBD | sed 's/-osc-.*$//'`
+ [ "x$OBD" != "x" ] && { setup_obdecho_osc $HOST $OBD || rc=1; } || rc=1
+ [ $rc -eq 0 ] && { obdecho_create_test ${OBD}_osc || rc=2; }
+ [ "x$OBD" != "x" ] && cleaup_obdecho_osc $OBD
+ [ $rmmod_local -eq 1 ] && rmmod obdecho
+ [ $rc -eq 0 ] || return $rc
+
+ do_facet ost "lsmod | grep -q obdecho || " \
+ "{ insmod ${LUSTRE}/obdecho/obdecho.ko || " \
+ "modprobe obdecho; }" && rmmod_remote=1
+ OBD=$(do_facet ost $LCTL dl | awk '/obdfilter/ {print $4;exit}')
+ [ "x$OBD" != "x" ] && { obdecho_create_test $OBD || rc=3; }
+ [ $rmmod_remote -eq 1 ] && do_facet ost "rmmod obdecho"
+ [ $rc -eq 0 ] || return $rc
+
+ true
+}
+run_test 180 "test obdecho ============================================"
+
# OST pools tests
POOL=${POOL:-cea1}
TGT_COUNT=$OSTCOUNT