From e7953d2cee5c273f5a4411231090825b4388256c Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 9 Nov 2009 23:20:09 +0000 Subject: [PATCH] b=19919 i=manoj i=adilger Make sure there is a valid pool when creating a new file with llapi Fixes for 19406 Various pools test cleanups and fixes b=19027 i=brian i=rread Don't be so anal about using _UUID in user interface; e.g. accept lustre-OST0000, lustre-OST0000-osc-4ba41334 as well as lustre-OST0000_UUID. --- lustre/include/lustre/liblustreapi.h | 4 +- lustre/tests/ost-pools.sh | 198 ++++++------ lustre/tests/sanity.sh | 69 ++-- lustre/utils/liblustreapi.c | 612 ++++++++++++++++++++++++++--------- lustre/utils/obd.c | 97 +----- 5 files changed, 615 insertions(+), 365 deletions(-) diff --git a/lustre/include/lustre/liblustreapi.h b/lustre/include/lustre/liblustreapi.h index 4594968..59f4216 100644 --- a/lustre/include/lustre/liblustreapi.h +++ b/lustre/include/lustre/liblustreapi.h @@ -81,7 +81,7 @@ extern int llapi_file_open_pool(const char *name, int flags, int mode, unsigned long long stripe_size, int stripe_offset, int stripe_count, int stripe_pattern, char *pool_name); -extern int llapi_poollist(char *name); +extern int llapi_poollist(const char *name); extern int llapi_file_get_stripe(const char *path, struct lov_user_md *lum); #define HAVE_LLAPI_FILE_LOOKUP extern int llapi_file_lookup(int dirfd, const char *name); @@ -164,8 +164,10 @@ extern int llapi_is_lustre_mnttype(const char *type); extern int llapi_search_ost(char *fsname, char *poolname, char *ostname); extern int llapi_search_mounts(const char *pathname, int index, char *mntdir, char *fsname); +extern int llapi_search_fsname(const char *pathname, char *fsname); extern int parse_size(char *optarg, unsigned long long *size, unsigned long long *size_units, int bytes_spec); + extern void llapi_ping_target(char *obd_type, char *obd_name, char *obd_uuid, void *args); extern int llapi_path2fid(const char *path, lustre_fid *fid); diff --git a/lustre/tests/ost-pools.sh b/lustre/tests/ost-pools.sh index 3f3a1e9..47b6973 100644 --- a/lustre/tests/ost-pools.sh +++ b/lustre/tests/ost-pools.sh @@ -1,4 +1,6 @@ #!/bin/bash +# -*- mode: Bash; tab-width: 4; indent-tabs-mode: t; -*- +# vim:autoindent:shiftwidth=4:tabstop=4: # # Run select tests by setting ONLY, or as arguments to the script. # Skip specific tests by setting EXCEPT. @@ -40,6 +42,7 @@ LCTL=${LCTL:-lctl} SETSTRIPE=${SETSTRIPE:-"$LFS setstripe"} GETSTRIPE=${GETSTRIPE:-"$LFS getstripe"} +SINGLEMDS=mds TSTUSR=${TSTUSR:-"quota_usr"} TSTID=${TSTID:-60000} @@ -95,8 +98,8 @@ create_file() { osts_in_pool() { local pool=$1 local res - for i in $(do_facet mds lctl pool_list $FSNAME.$pool | grep -v "^Pool:" \ - | sed -e 's/_UUID$//;s/^.*-OST//'); do + for i in $(do_facet $SINGLEMDS lctl pool_list $FSNAME.$pool | \ + grep -v "^Pool:" | sed -e 's/_UUID$//;s/^.*-OST//'); do res="$res $(printf "%d" 0x$i)" done echo $res @@ -140,7 +143,7 @@ check_file_in_osts() { local ost_count=$($GETSTRIPE $file | grep 0x | wc -l) [[ -n "$count" ]] && [[ $ost_count -ne $count ]] && \ - error "Stripe count $count expected; got $ost_count" + { error "Stripe count $count expected; got $ost_count" && return 1; } return 0 } @@ -160,7 +163,8 @@ check_file_not_in_pool() { check_dir_not_in_pool() { local dir=$1 local pool=$2 - local res=$($GETSTRIPE -v $dir | grep "^stripe_count" | head -1 | cut -f 8 -d ' ') + local res=$($GETSTRIPE -v $dir | grep "^stripe_count" | head -1 | \ + cut -f 8 -d ' ') if [[ "$res" == "$pool" ]]; then error "File $dir is in pool: $res" return 1 @@ -170,7 +174,7 @@ check_dir_not_in_pool() { } create_pool() { - do_facet mds lctl pool_new $FSNAME.$1 + do_facet $SINGLEMDS lctl pool_new $FSNAME.$1 local RC=$? # get param should return err until pool is created [[ $RC -ne 0 ]] && return $RC @@ -190,13 +194,15 @@ drain_pool() { add_pool() { local pool=$1 local osts=$2 - local tgt="${3}$(lctl get_param -n lov.$FSNAME-*.pools.$pool | sort -u | tr '\n' ' ')" + local tgt="${3}$(lctl get_param -n lov.$FSNAME-*.pools.$pool | \ + sort -u | tr '\n' ' ')" - do_facet mds lctl pool_add $FSNAME.$pool $osts + do_facet $SINGLEMDS lctl pool_add $FSNAME.$pool $osts local RC=$? [[ $RC -ne 0 ]] && return $RC - wait_update $HOSTNAME "lctl get_param -n lov.$FSNAME-*.pools.$pool | sort -u | tr '\n' ' ' " "$tgt" || RC=1 + wait_update $HOSTNAME "lctl get_param -n lov.$FSNAME-*.pools.$pool | \ + sort -u | tr '\n' ' ' " "$tgt" || RC=1 [[ $RC -ne 0 ]] && error "pool_add failed: $1; $2" return $RC } @@ -219,7 +225,8 @@ create_pool_fail() { cleanup_tests() { # Destroy pools from previous test runs - for p in $(do_facet mds lctl pool_list $FSNAME | grep $FSNAME.pool[0-$OSTCOUNT]); do + for p in $(do_facet $SINGLEMDS lctl pool_list $FSNAME | \ + grep $FSNAME.pool[0-$OSTCOUNT]); do destroy_pool_int $p; done rm -rf $DIR/d0.${TESTSUITE} @@ -258,27 +265,27 @@ test_1() { create_pool_fail $NAME echo "pool_new should fail if fs-name or poolname are missing." - do_facet mds lctl pool_new .pool1 + do_facet $SINGLEMDS lctl pool_new .pool1 2>/dev/null [[ $? -ne 0 ]] || \ error "pool_new did not fail even though fs-name was missing." - do_facet mds lctl pool_new pool1 + do_facet $SINGLEMDS lctl pool_new pool1 2>/dev/null [[ $? -ne 0 ]] || \ error "pool_new did not fail even though fs-name was missing." - do_facet mds lctl pool_new ${FSNAME}. + do_facet $SINGLEMDS lctl pool_new ${FSNAME}. 2>/dev/null [[ $? -ne 0 ]] || \ error "pool_new did not fail even though pool name was missing." - do_facet mds lctl pool_new . + do_facet $SINGLEMDS lctl pool_new . 2>/dev/null [[ $? -ne 0 ]] || \ error "pool_new did not fail even though pool name and fs-name " \ "were missing." - do_facet mds lctl pool_new ${FSNAME},pool1 + do_facet $SINGLEMDS lctl pool_new ${FSNAME},pool1 2>/dev/null [[ $? -ne 0 ]] || \ error "pool_new did not fail even though pool name format was wrong" - do_facet mds lctl pool_new ${FSNAME}/pool1 + do_facet $SINGLEMDS lctl pool_new ${FSNAME}/pool1 2>/dev/null [[ $? -ne 0 ]] || \ error "pool_new did not fail even though pool name format was wrong" - do_facet mds lctl pool_new ${FSNAME}.p + do_facet $SINGLEMDS lctl pool_new ${FSNAME}.p 2>/dev/null [[ $? -ne 0 ]] || \ error "pool_new did not fail even though pool1 existed" destroy_pool p @@ -289,7 +296,7 @@ run_test 1 "Test lctl pool_new =========================================" test_2a() { destroy_pool $POOL - do_facet mds lctl pool_add $FSNAME.$POOL $FSNAME-OST0000 + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL $FSNAME-OST0000 2>/dev/null [[ $? -ne 0 ]] || \ error " pool_add did not fail even though pool did " \ " not exist." @@ -297,7 +304,8 @@ test_2a() { run_test 2a "pool_add: non-existant pool" test_2b() { - do_facet mds lctl pool_add $FSNAME.p1234567891234567890 $FSNAME-OST0000 + do_facet $SINGLEMDS lctl pool_add $FSNAME.p1234567891234567890 \ + $FSNAME-OST0000 2>/dev/null [[ $? -ne 0 ]] || \ error "pool_add did not fail even though pool name was invalid." } @@ -315,43 +323,43 @@ test_2c() { create_pool_nofail $POOL # 1. OST0000 - do_facet mds lctl pool_add $FSNAME.$POOL OST0000 + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL OST0000 RC=$?; [[ $RC -eq 0 ]] || \ error "pool_add failed. $FSNAME $POOL OST0000: $RC" - do_facet mds lctl pool_remove $FSNAME.$POOL OST0000 + do_facet $SINGLEMDS lctl pool_remove $FSNAME.$POOL OST0000 drain_pool $POOL # 2. lustre-OST0000 - do_facet mds lctl pool_add $FSNAME.$POOL $FSNAME-OST0000 + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL $FSNAME-OST0000 RC=$?; [[ $RC -eq 0 ]] || \ error "pool_add failed. $FSNAME $POOL $FSNAME-OST0000: $RC" - do_facet mds lctl pool_remove $FSNAME.$POOL $FSNAME-OST0000 + do_facet $SINGLEMDS lctl pool_remove $FSNAME.$POOL $FSNAME-OST0000 drain_pool $POOL # 3. lustre-OST0000_UUID - do_facet mds lctl pool_add $FSNAME.$POOL $FSNAME-OST0000_UUID + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL $FSNAME-OST0000_UUID RC=$?; [[ $RC -eq 0 ]] || \ error "pool_add failed. $FSNAME $POOL $FSNAME-OST0000_UUID: $RC" - do_facet mds lctl pool_remove $FSNAME.$POOL $FSNAME-OST0000_UUID + do_facet $SINGLEMDS lctl pool_remove $FSNAME.$POOL $FSNAME-OST0000_UUID drain_pool $POOL # 4. lustre-OST[0,1,2,3,] TGT="$FSNAME-OST[" for i in $TGT_LIST; do TGT=${TGT}$(printf "$i," $i); done TGT="${TGT}]" - do_facet mds lctl pool_add $FSNAME.$POOL $TGT + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL $TGT [[ $? -eq 0 ]] || \ error "pool_add failed. $FSNAME.$POOL $TGT. $RC" - do_facet mds lctl pool_remove $FSNAME.$POOL $TGT + do_facet $SINGLEMDS lctl pool_remove $FSNAME.$POOL $TGT drain_pool $POOL # 5. lustre-OST[0-5/1] - do_facet mds lctl pool_add $FSNAME.$POOL $TGT_ALL + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL $TGT_ALL RC=$?; [[ $RC -eq 0 ]] || \ error "pool_add failed. $FSNAME $POOL" "$TGT_ALL $RC" wait_update $HOSTNAME "lctl get_param -n lov.$FSNAME-*.pools.$POOL | \ sort -u | tr '\n' ' ' " "$TGT_UUID" || error "Add to pool failed" - do_facet mds lctl pool_remove $FSNAME.$POOL $TGT_ALL + do_facet $SINGLEMDS lctl pool_remove $FSNAME.$POOL $TGT_ALL drain_pool $POOL destroy_pool $POOL @@ -369,7 +377,7 @@ test_2d() { create_pool_nofail $POOL TGT=$(printf "$FSNAME-OST%04x_UUID " $OSTCOUNT) - do_facet mds lctl pool_add $FSNAME.$POOL $TGT + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL $TGT RC=$?; [[ $RC -ne 0 ]] || \ error "pool_add succeeded for an OST ($TGT) that does not exist." @@ -389,10 +397,11 @@ test_2e() { create_pool_nofail $POOL TGT="$FSNAME-OST0000_UUID " - do_facet mds lctl pool_add $FSNAME.$POOL $TGT + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL $TGT wait_update $HOSTNAME "lctl get_param -n lov.$FSNAME-*.pools.$POOL | \ sort -u | tr '\n' ' ' " "$TGT" || error "Add to pool failed" - RESULT=$(do_facet mds "LOCALE=C $LCTL pool_add $FSNAME.$POOL $TGT 2>&1") + RESULT=$(do_facet $SINGLEMDS \ + "LOCALE=C $LCTL pool_add $FSNAME.$POOL $TGT 2>&1") RC=$? echo $RESULT @@ -411,28 +420,27 @@ test_3a() { [[ $? -ne 0 ]] || \ destroy_pool $POOL - do_facet mds lctl pool_remove $FSNAME.$POOL $FSNAME-OST0000 + do_facet $SINGLEMDS lctl pool_remove $FSNAME.$POOL $FSNAME-OST0000 2>/dev/null [[ $? -ne 0 ]] || \ - error "pool_remove did not fail even though" \ - "pool did not exist." + error "pool_remove did not fail even though pool did not exist." } run_test 3a "pool_remove: non-existant pool" test_3b() { - do_facet mds lctl pool_remove ${NON_EXISTANT_FS}.$POOL OST0000 + do_facet $SINGLEMDS lctl pool_remove ${NON_EXISTANT_FS}.$POOL OST0000 2>/dev/null [[ $? -ne 0 ]] || \ error "pool_remove did not fail even though fsname did not exist." } run_test 3b "pool_remove: non-existant fsname" test_3c() { - do_facet mds lctl pool_remove $FSNAME.p1234567891234567890 $FSNAME-OST0000 + do_facet $SINGLEMDS lctl pool_remove $FSNAME.p1234567891234567890 \ + $FSNAME-OST0000 2>/dev/null [[ $? -ne 0 ]] || \ error "pool_remove did not fail even though pool name was invalid." } run_test 3c "pool_remove: Invalid pool name" - # Testing various combinations of OST name list test_3d() { lctl get_param -n lov.$FSNAME-*.pools.$POOL 2>/dev/null @@ -440,26 +448,26 @@ test_3d() { destroy_pool $POOL create_pool_nofail $POOL - do_facet mds lctl pool_add $FSNAME.$POOL OST0000 - do_facet mds lctl pool_remove $FSNAME.$POOL OST0000 + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL OST0000 + do_facet $SINGLEMDS lctl pool_remove $FSNAME.$POOL OST0000 [[ $? -eq 0 ]] || \ error "pool_remove failed. $FSNAME $POOL OST0000" drain_pool $POOL - do_facet mds lctl pool_add $FSNAME.$POOL $FSNAME-OST0000 - do_facet mds lctl pool_remove $FSNAME.$POOL $FSNAME-OST0000 + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL $FSNAME-OST0000 + do_facet $SINGLEMDS lctl pool_remove $FSNAME.$POOL $FSNAME-OST0000 [[ $? -eq 0 ]] || \ error "pool_remove failed. $FSNAME $POOL $FSNAME-OST0000" drain_pool $POOL - do_facet mds lctl pool_add $FSNAME.$POOL $FSNAME-OST0000_UUID - do_facet mds lctl pool_remove $FSNAME.$POOL $FSNAME-OST0000_UUID + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL $FSNAME-OST0000_UUID + do_facet $SINGLEMDS lctl pool_remove $FSNAME.$POOL $FSNAME-OST0000_UUID [[ $? -eq 0 ]] || \ error "pool_remove failed. $FSNAME $POOL $FSNAME-OST0000_UUID" drain_pool $POOL add_pool $POOL $TGT_ALL "$TGT_UUID" - do_facet mds lctl pool_remove $FSNAME.$POOL $TGT_ALL + do_facet $SINGLEMDS lctl pool_remove $FSNAME.$POOL $TGT_ALL [[ $? -eq 0 ]] || \ error "pool_remove failed. $FSNAME $POOL" $TGT_ALL drain_pool $POOL @@ -473,14 +481,14 @@ test_4a() { [[ $? -ne 0 ]] || \ destroy_pool $POOL - do_facet mds lctl pool_destroy $FSNAME.$POOL + do_facet $SINGLEMDS lctl pool_destroy $FSNAME.$POOL 2>/dev/null [[ $? -ne 0 ]] || \ error "pool_destroy did not fail even though pool did not exist." } run_test 4a "pool_destroy: non-existant pool" test_4b() { - do_facet mds lctl pool_destroy ${NON_EXISTANT_FS}.$POOL + do_facet $SINGLEMDS lctl pool_destroy ${NON_EXISTANT_FS}.$POOL 2>/dev/null [[ $? -ne 0 ]] || \ error "pool_destroy did not fail even though the filesystem did not exist." } @@ -490,9 +498,9 @@ test_4c() { create_pool_nofail $POOL add_pool $POOL "OST0000" "$FSNAME-OST0000_UUID " - do_facet mds lctl pool_destroy ${FSNAME}.$POOL + do_facet $SINGLEMDS lctl pool_destroy ${FSNAME}.$POOL [[ $? -ne 0 ]] || \ - error "pool_destroy succeeded with a non-empty pool name." + error "pool_destroy succeeded with a non-empty pool." destroy_pool $POOL } run_test 4c "pool_destroy: non-empty pool ===============================" @@ -500,12 +508,12 @@ run_test 4c "pool_destroy: non-empty pool ===============================" sub_test_5() { local LCMD=$1 - $LCMD pool_list + $LCMD pool_list 2>/dev/null [[ $? -ne 0 ]] || \ error "pool_list did not fail even though fsname was not mentioned." - destroy_pool $POOL - destroy_pool $POOL2 + destroy_pool $POOL 2>/dev/null + destroy_pool $POOL2 2>/dev/null create_pool_nofail $POOL create_pool_nofail $POOL2 @@ -513,21 +521,21 @@ sub_test_5() { [[ $? -eq 0 ]] || \ error "pool_list $FSNAME failed." - do_facet mds lctl pool_add $FSNAME.$POOL $TGT_ALL + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL $TGT_ALL $LCMD pool_list $FSNAME.$POOL [[ $? -eq 0 ]] || \ error "pool_list $FSNAME.$POOL failed." - $LCMD pool_list ${NON_EXISTANT_FS} + $LCMD pool_list ${NON_EXISTANT_FS} 2>/dev/null [[ $? -ne 0 ]] || \ error "pool_list did not fail for a non-existant fsname $NON_EXISTANT_FS" - $LCMD pool_list ${FSNAME}.$NON_EXISTANT_POOL + $LCMD pool_list ${FSNAME}.$NON_EXISTANT_POOL 2>/dev/null [[ $? -ne 0 ]] || \ error "pool_list did not fail for a non-existant pool $NON_EXISTANT_POOL" - if [[ ! $(grep mds <<< $LCMD) ]]; then + if [[ ! $(grep $SINGLEMDS <<< $LCMD) ]]; then echo $LCMD pool_list $DIR $LCMD pool_list $DIR [[ $? -eq 0 ]] || \ @@ -540,7 +548,7 @@ sub_test_5() { fi rm -rf ${DIR}nonexistant - $LCMD pool_list ${DIR}nonexistant + $LCMD pool_list ${DIR}nonexistant 2>/dev/null [[ $? -ne 0 ]] || \ error "pool_list did not fail for invalid mountpoint ${DIR}nonexistant" @@ -554,8 +562,8 @@ test_5() { sub_test_5 $LFS # Issue commands from MDS - sub_test_5 "do_facet mds lctl" - sub_test_5 "do_facet mds lfs" + sub_test_5 "do_facet $SINGLEMDS lctl" + sub_test_5 "do_facet $SINGLEMDS lfs" } run_test 5 "lfs/lctl pool_list" @@ -567,11 +575,11 @@ test_6() { create_pool_nofail $POOL - do_facet mds lctl pool_list $FSNAME + do_facet $SINGLEMDS lctl pool_list $FSNAME [[ $? -eq 0 ]] || \ error "pool_list $FSNAME failed." - do_facet mds lctl pool_add $FSNAME.$POOL $TGT_ALL + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL $TGT_ALL mkdir -p $POOL_DIR $SETSTRIPE -c -1 -p $POOL $POOL_DIR @@ -580,14 +588,14 @@ test_6() { check_dir_in_pool $POOL_DIR $POOL # If an invalid pool name is specified, the command should fail - $SETSTRIPE -c 2 -p $INVALID_POOL $POOL_DIR + $SETSTRIPE -c 2 -p $INVALID_POOL $POOL_DIR 2>/dev/null [[ $? -ne 0 ]] || \ - error_ignore 19919 "setstripe to invalid pool did not fail." + error "setstripe to invalid pool did not fail." # If the pool name does not exist, the command should fail - $SETSTRIPE -c 2 -p $NON_EXISTANT_POOL $POOL_DIR + $SETSTRIPE -c 2 -p $NON_EXISTANT_POOL $POOL_DIR 2>/dev/null [[ $? -ne 0 ]] || \ - error_ignore 19919 "setstripe to non-existant pool did not fail." + error "setstripe to non-existant pool did not fail." # lfs setstripe should work as before if a pool name is not specified. $SETSTRIPE -c -1 $POOL_DIR @@ -601,7 +609,7 @@ test_6() { # pool is specified. create_pool_nofail $POOL2 add_pool $POOL2 "OST0000" "$FSNAME-OST0000_UUID " - $SETSTRIPE -o 1 -p $POOL2 $ROOT_POOL/$tfile + $SETSTRIPE -o 1 -p $POOL2 $ROOT_POOL/$tfile 2>/dev/null [[ $? -ne 0 ]] || \ error "$SETSTRIPE with start index outside the pool did not fail." @@ -618,10 +626,10 @@ test_11() { create_pool_nofail $POOL create_pool_nofail $POOL2 - do_facet mds lctl pool_add $FSNAME.$POOL \ + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL \ $FSNAME-OST[$TGT_FIRST-$TGT_MAX/2] local start=$((TGT_FIRST+1)) - do_facet mds lctl pool_add $FSNAME.$POOL2 \ + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL2 \ $FSNAME-OST[$start-$TGT_MAX/2] create_dir $POOL_ROOT/dir1 $POOL @@ -660,10 +668,10 @@ test_12() { create_pool_nofail $POOL create_pool_nofail $POOL2 - do_facet mds lctl pool_add $FSNAME.$POOL \ + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL \ $FSNAME-OST[$TGT_FIRST-$TGT_MAX/2] local start=$((TGT_FIRST+1)) - do_facet mds lctl pool_add $FSNAME.$POOL2 \ + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL2 \ $FSNAME-OST[$start-$TGT_MAX/2] echo creating some files in $POOL and $POOL2 @@ -680,10 +688,10 @@ test_12() { check_file_in_pool $POOL_ROOT/file2 $POOL2 echo Changing the pool membership - do_facet mds lctl pool_remove $FSNAME.$POOL $FSNAME-OST[$TGT_FIRST] - do_facet mds lctl pool_list $FSNAME.$POOL - do_facet mds lctl pool_add $FSNAME.$POOL2 $FSNAME-OST[$TGT_FIRST] - do_facet mds lctl pool_list $FSNAME.$POOL2 + do_facet $SINGLEMDS lctl pool_remove $FSNAME.$POOL $FSNAME-OST[$TGT_FIRST] + do_facet $SINGLEMDS lctl pool_list $FSNAME.$POOL + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL2 $FSNAME-OST[$TGT_FIRST] + do_facet $SINGLEMDS lctl pool_list $FSNAME.$POOL2 echo Checking the files again check_dir_in_pool $POOL_ROOT/dir1 $POOL @@ -716,7 +724,7 @@ test_13() { local count=3 create_pool_nofail $POOL - do_facet mds lctl pool_add $FSNAME.$POOL $TGT_ALL + do_facet $SINGLEMDS lctl pool_add $FSNAME.$POOL $TGT_ALL create_dir $POOL_ROOT/dir1 $POOL -1 createmany -o $POOL_ROOT/dir1/$tfile $numfiles || \ @@ -1106,22 +1114,26 @@ add_loop() { for c in $(seq 1 10); do echo "Pool $pool, iteration $c" - create_pool_nofail $pool - local TGT=$(for i in `seq $TGT_FIRST $step $TGT_MAX`; \ - do printf "$FSNAME-OST%04x_UUID " $i; done) - add_pool $pool "$FSNAME-OST[$TGT_FIRST-$TGT_MAX/$step]" "$TGT" - destroy_pool $pool - do_facet mds lctl pool_list $FSNAME + do_facet $SINGLEMDS lctl pool_add $FSNAME.$pool OST[$TGT_FIRST-$TGT_MAX/$step] 2>/dev/null + local TGT_SECOND=$(($TGT_FIRST+$step)) + if [ "$TGT_SECOND" -le "$TGT_MAX" ]; then + do_facet $SINGLEMDS lctl pool_remove $FSNAME.$pool OST[$TGT_SECOND-$TGT_MAX/$step] + fi done echo loop for $pool complete } test_22() { local POOL_ROOT=${POOL_ROOT:-$DIR/$tdir} - [[ $OSTCOUNT -le 1 ]] && skip "Need atleast 2 OSTs" && return + [[ $OSTCOUNT -le 1 ]] && skip "Need at least 2 OSTs" && return local numfiles=100 + create_pool_nofail $POOL + add_pool $POOL "OST0000" "$FSNAME-OST0000_UUID " + create_pool_nofail $POOL2 + add_pool $POOL2 "OST0000" "$FSNAME-OST0000_UUID " + add_loop $POOL 1 & add_loop $POOL2 2 & sleep 5 @@ -1130,6 +1142,9 @@ test_22() { error "createmany $POOL_ROOT/${tfile} failed!" wait + destroy_pool $POOL + destroy_pool $POOL2 + return 0 } run_test 22 "Simultaneous manipulation of a pool" @@ -1293,21 +1308,22 @@ test_25() { mkdir -p $POOL_ROOT for i in $(seq 10); do - create_pool_nofail pool$i - stop mds || return 1 - sleep 10 - start mds $MDSDEV $MDS_MOUNT_OPTS || \ - error "Failed to start MDS after stopping" + create_pool_nofail pool$i + do_facet $SINGLEMDS lctl pool_add $FSNAME.pool$i OST0000 + stop $SINGLEMDS || return 1 + start $SINGLEMDS $MDSDEV $MDS_MOUNT_OPTS || \ + { error "Failed to start $SINGLEMDS after stopping" && break; } + client_df # Veriy that the pool got created and is usable - echo "Creating a file in pool$i" - create_file $POOL_ROOT/file$i pool$i - check_file_in_pool $POOL_ROOT/file$i pool$i - done + echo "Creating a file in pool$i" + create_file $POOL_ROOT/file$i pool$i || break + check_file_in_pool $POOL_ROOT/file$i pool$i || break + done rm -rf $POOL_ROOT for i in $(seq 10); do - destroy_pool pool$i + destroy_pool pool$i done } run_test 25 "Create new pool and restart MDS =======================" diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index d070ba1..ad6a1f7 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -1,4 +1,6 @@ #!/bin/bash +# -*- mode: Bash; tab-width: 4; indent-tabs-mode: t; -*- +# vim:autoindent:shiftwidth=4:tabstop=4: # # Run select tests by setting ONLY, or as arguments to the script. # Skip specific tests by setting EXCEPT. @@ -6352,43 +6354,56 @@ test_200f() { run_test 200f "Create files in a pool ===================================" test_200g() { - test_pools || return 0 + test_pools || return 0 - TGT=$($LCTL get_param -n lov.$FSNAME-*.pools.$POOL | head -1) - res=$(lfs df --pool $FSNAME.$POOL | awk '{print $1}' | grep "$FSNAME-OST") - [ "$res" = "$TGT" ] || echo "Pools OSTS $TGT is not $res that lfs df reports" + TGT=$($LCTL get_param -n lov.$FSNAME-*.pools.$POOL | head -1) + res=$($LFS df --pool $FSNAME.$POOL | awk '{print $1}' | grep "$FSNAME-OST") + [ "$res" = "$TGT" ] || error "Pools OSTS '$TGT' is not '$res' that lfs df reports" } run_test 200g "lfs df a pool ============================================" -test_201a() { # was 200g - test_pools || return 0 - TGT=$($LCTL get_param -n lov.$FSNAME-*.pools.$POOL | head -1) - do_facet mgs $LCTL pool_remove $FSNAME.$POOL $TGT - wait_update $HOSTNAME "lctl get_param -n lov.$FSNAME-*.pools.$POOL | grep $TGT" "" || error "$TGT not removed from $FSNAME.$POOL" +test_201a() { + test_pools || return 0 + + TGT=$($LCTL get_param -n lov.$FSNAME-*.pools.$POOL | head -1) + do_facet mgs $LCTL pool_remove $FSNAME.$POOL $TGT + wait_update $HOSTNAME "lctl get_param -n lov.$FSNAME-*.pools.$POOL | grep $TGT" "" || error "$TGT not removed from $FSNAME.$POOL" } run_test 201a "Remove a target from a pool =============================" -test_201b() { # was 200h - test_pools || return 0 - for TGT in $($LCTL get_param -n lov.$FSNAME-*.pools.$POOL | sort -u) - do - do_facet mgs $LCTL pool_remove $FSNAME.$POOL $TGT - done - wait_update $HOSTNAME "lctl get_param -n lov.$FSNAME-*.pools.$POOL" ""\ - || error "Pool $FSNAME.$POOL cannot be drained" - # striping on an empty pool should fall back to "pool of everything" - $SETSTRIPE -p $POOL ${POOL_FILE}/$tfile || \ - error "failed to create file with empty pool" +test_201b() { + test_pools || return 0 + + for TGT in $($LCTL get_param -n lov.$FSNAME-*.pools.$POOL | sort -u) + do + do_facet mgs $LCTL pool_remove $FSNAME.$POOL $TGT + done + wait_update $HOSTNAME "lctl get_param -n lov.$FSNAME-*.pools.$POOL" ""\ + || error "Pool $FSNAME.$POOL cannot be drained" + # striping on an empty/nonexistant pool should fall back to "pool of everything" + touch ${POOL_DIR}/$tfile || error "failed to use fallback striping for empty pool" + # setstripe on an empty pool should fail + $SETSTRIPE -p $POOL ${POOL_FILE}/$tfile 2>/dev/null && \ + error "expected failure when creating file with empty pool" + return 0 } run_test 201b "Remove all targets from a pool ==========================" -test_201c() { # was 200i - test_pools || return 0 - do_facet mgs $LCTL pool_destroy $FSNAME.$POOL - # get param should return err once pool is gone - wait_update $HOSTNAME "lctl get_param -n lov.$FSNAME-*.pools.$POOL 2>/dev/null || - echo foo" "foo" && unset CLEANUP_200 && trap 0 && return 0 - error "Pool $FSNAME.$POOL is not destroyed" +test_201c() { + test_pools || return 0 + + do_facet mgs $LCTL pool_destroy $FSNAME.$POOL + + sleep 2 + # striping on an empty/nonexistant pool should fall back to "pool of everything" + touch ${POOL_DIR}/$tfile || error "failed to use fallback striping for missing pool" + # setstripe on an empty pool should fail + $SETSTRIPE -p $POOL ${POOL_FILE}/$tfile 2>/dev/null && \ + error "expected failure when creating file with missing pool" + + # get param should return err once pool is gone + wait_update $HOSTNAME "lctl get_param -n lov.$FSNAME-*.pools.$POOL 2>/dev/null || echo foo" "foo" && unset CLEANUP_200 && trap 0 && return 0 + error "Pool $FSNAME.$POOL is not destroyed" } run_test 201c "Remove a pool ============================================" diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index 9653cfe..5dcc68b 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -262,7 +263,98 @@ int llapi_stripe_limit_check(unsigned long long stripe_size, int stripe_offset, return 0; } -static int poolpath(char *fsname, char *pathname, char *pool_pathname); +static int find_target_obdpath(char *fsname, char *path) +{ + glob_t glob_info; + char pattern[PATH_MAX + 1]; + int rc; + + snprintf(pattern, PATH_MAX, + "/proc/fs/lustre/lov/%s-*/target_obd", + fsname); + rc = glob(pattern, GLOB_BRACE, NULL, &glob_info); + if (rc == GLOB_NOMATCH) + return -ENODEV; + else if (rc) + return -EINVAL; + + strcpy(path, glob_info.gl_pathv[0]); + globfree(&glob_info); + return 0; +} + +static int find_poolpath(char *fsname, char *poolname, char *poolpath) +{ + glob_t glob_info; + char pattern[PATH_MAX + 1]; + int rc; + + snprintf(pattern, PATH_MAX, + "/proc/fs/lustre/lov/%s-*/pools/%s", + fsname, poolname); + rc = glob(pattern, GLOB_BRACE, NULL, &glob_info); + /* If no pools, make sure the lov is available */ + if ((rc == GLOB_NOMATCH) && + (find_target_obdpath(fsname, poolpath) == -ENODEV)) + return -ENODEV; + if (rc) + return -EINVAL; + + strcpy(poolpath, glob_info.gl_pathv[0]); + globfree(&glob_info); + return 0; +} + +/* + * if pool is NULL, search ostname in target_obd + * if pool is not NULL: + * if pool not found returns errno < 0 + * if ostname is NULL, returns 1 if pool is not empty and 0 if pool empty + * if ostname is not NULL, returns 1 if OST is in pool and 0 if not + */ +int llapi_search_ost(char *fsname, char *poolname, char *ostname) +{ + FILE *fd; + char buffer[PATH_MAX + 1]; + int len = 0, rc; + + if (ostname != NULL) + len = strlen(ostname); + + if (poolname == NULL) + rc = find_target_obdpath(fsname, buffer); + else + rc = find_poolpath(fsname, poolname, buffer); + if (rc) + return rc; + + if ((fd = fopen(buffer, "r")) == NULL) + return -EINVAL; + + while (fgets(buffer, sizeof(buffer), fd) != NULL) { + if (poolname == NULL) { + char *ptr; + /* Search for an ostname in the list of OSTs + Line format is IDX: fsname-OSTxxxx_UUID STATUS */ + ptr = strchr(buffer, ' '); + if ((ptr != NULL) && + (strncmp(ptr + 1, ostname, len) == 0)) { + fclose(fd); + return 1; + } + } else { + /* Search for an ostname in a pool, + (or an existing non-empty pool if no ostname) */ + if ((ostname == NULL) || + (strncmp(buffer, ostname, len) == 0)) { + fclose(fd); + return 1; + } + } + } + fclose(fd); + return 0; +} int llapi_file_open_pool(const char *name, int flags, int mode, unsigned long long stripe_size, int stripe_offset, @@ -271,7 +363,40 @@ int llapi_file_open_pool(const char *name, int flags, int mode, struct lov_user_md_v3 lum = { 0 }; int fd, rc = 0; int isdir = 0; - char fsname[MAX_OBD_NAME + 1], *ptr; + + /* Make sure we have a good pool */ + if (pool_name != NULL) { + char fsname[MAX_OBD_NAME + 1], *ptr; + + if (llapi_search_fsname(name, fsname)) { + llapi_err(LLAPI_MSG_ERROR | LLAPI_MSG_NO_ERRNO, + "'%s' is not on a Lustre filesystem", name); + return -EINVAL; + } + + /* in case user gives the full pool name ., + * strip the fsname */ + ptr = strchr(pool_name, '.'); + if (ptr != NULL) { + *ptr = '\0'; + if (strcmp(pool_name, fsname) != 0) { + *ptr = '.'; + llapi_err(LLAPI_MSG_ERROR | LLAPI_MSG_NO_ERRNO, + "Pool '%s' is not on filesystem '%s'", + pool_name, fsname); + return -EINVAL; + } + pool_name = ptr + 1; + } + + /* Make sure the pool exists and is non-empty */ + if ((rc = llapi_search_ost(fsname, pool_name, NULL)) < 1) { + llapi_err(LLAPI_MSG_ERROR | LLAPI_MSG_NO_ERRNO, + "pool '%s.%s' %s", fsname, pool_name, + rc == 0 ? "has no OSTs" : "does not exist"); + return -EINVAL; + } + } fd = open(name, flags | O_LOV_DELAY_CREATE, mode); if (fd < 0 && errno == EISDIR) { @@ -297,19 +422,7 @@ int llapi_file_open_pool(const char *name, int flags, int mode, lum.lmm_stripe_size = stripe_size; lum.lmm_stripe_count = stripe_count; lum.lmm_stripe_offset = stripe_offset; - - /* in case user give the full pool name ., skip - * the fsname */ if (pool_name != NULL) { - ptr = strchr(pool_name, '.'); - if (ptr != NULL) { - strncpy(fsname, pool_name, ptr - pool_name); - fsname[ptr - pool_name] = '\0'; - /* if fsname matches a filesystem skip it - * if not keep the poolname as is */ - if (poolpath(fsname, NULL, NULL) == 0) - pool_name = ptr + 1; - } strncpy(lum.lmm_pool_name, pool_name, LOV_MAXPOOLNAME); } else { /* If no pool is specified at all, use V1 request */ @@ -375,24 +488,93 @@ int llapi_file_create_pool(const char *name, unsigned long long stripe_size, return 0; } - -static int print_pool_members(char *fs, char *pool_dir, char *pool_file) +/* + * Find the fsname, the full path, and/or an open fd. + * Either the fsname or path must not be NULL + */ +#define WANT_PATH 0x1 +#define WANT_FSNAME 0x2 +#define WANT_FD 0x4 +#define WANT_INDEX 0x8 +#define WANT_ERROR 0x10 +static int get_root_path(int want, char *fsname, int *outfd, char *path, + int index) { - char path[MAXPATHLEN + 1]; - char buf[1024]; - FILE *fd; + struct mntent mnt; + char buf[PATH_MAX], mntdir[PATH_MAX]; + char *ptr; + FILE *fp; + int idx = 0, len = 0, mntlen, fd; + int rc = -ENODEV; - llapi_printf(LLAPI_MSG_NORMAL, "Pool: %s.%s\n", fs, pool_file); - sprintf(path, "%s/%s", pool_dir, pool_file); - if ((fd = fopen(path, "r")) == NULL) { - llapi_err(LLAPI_MSG_ERROR, "Cannot open %s\n", path); - return -EINVAL; + /* get the mount point */ + fp = setmntent(MOUNTED, "r"); + if (fp == NULL) { + llapi_err(LLAPI_MSG_ERROR, + "setmntent(%s) failed: %s:", MOUNTED, + strerror (errno)); + return -EIO; } - while (fgets(buf, sizeof(buf), fd) != NULL) - llapi_printf(LLAPI_MSG_NORMAL, buf); + while (1) { + if (getmntent_r(fp, &mnt, buf, sizeof(buf)) == NULL) + break; - fclose(fd); - return 0; + if (!llapi_is_lustre_mnt(&mnt)) + continue; + + mntlen = strlen(mnt.mnt_dir); + ptr = strrchr(mnt.mnt_fsname, '/'); + if (!ptr && !len) { + rc = -EINVAL; + break; + } + ptr++; + + if ((want & WANT_INDEX) && (idx++ != index)) + continue; + + /* Check the fsname for a match, if given */ + if (!(want & WANT_FSNAME) && fsname != NULL && + (strlen(fsname) > 0) && (strcmp(ptr, fsname) != 0)) + continue; + + /* If the path isn't set return the first one we find */ + if (path == NULL || strlen(path) == 0) { + strcpy(mntdir, mnt.mnt_dir); + if ((want & WANT_FSNAME) && fsname != NULL) + strcpy(fsname, ptr); + rc = 0; + break; + /* Otherwise find the longest matching path */ + } else if ((strlen(path) >= mntlen) && (mntlen >= len) && + (strncmp(mnt.mnt_dir, path, mntlen) == 0)) { + strcpy(mntdir, mnt.mnt_dir); + len = mntlen; + if ((want & WANT_FSNAME) && fsname != NULL) + strcpy(fsname, ptr); + rc = 0; + } + } + endmntent(fp); + + /* Found it */ + if (rc == 0) { + if ((want & WANT_PATH) && path != NULL) + strcpy(path, mntdir); + if (want & WANT_FD) { + fd = open(mntdir, O_RDONLY | O_DIRECTORY | O_NONBLOCK); + if (fd < 0) { + perror("open"); + rc = -errno; + } else { + *outfd = fd; + } + } + } else if (want & WANT_ERROR) + llapi_err(LLAPI_MSG_ERROR | LLAPI_MSG_NO_ERRNO, + "can't find fs root for '%s': %d", + (want & WANT_PATH) ? fsname : path, rc); + return rc; } /* @@ -404,60 +586,48 @@ static int print_pool_members(char *fs, char *pool_dir, char *pool_file) * The user inputs are pathname and index. If the pathname is supplied then * the value of the index will be ignored. The pathname will return data if * the pathname is located on a lustre mount. Index is used to pick which - * mount point you want in the case of multiple mounted lustre file systems. + * mount point you want in the case of multiple mounted lustre file systems. * See function lfs_osts in lfs.c for a example of the index use. */ -int llapi_search_mounts(const char *pathname, int index, char *mntdir, +int llapi_search_mounts(const char *pathname, int index, char *mntdir, char *fsname) { - int len = 0, idx = 0, rc = -ENOENT; - char *ptr; - FILE *fp; - struct mntent *mnt = NULL; + int want = WANT_PATH, idx = -1; - /* get the mount point */ - fp = setmntent(MOUNTED, "r"); - if (fp == NULL) { - llapi_err(LLAPI_MSG_ERROR, - "setmntent(%s) failed: %s:", MOUNTED, - strerror (errno)); - return -EIO; - } - mnt = getmntent(fp); - while ((feof(fp) == 0) && ferror(fp) == 0) { - if (llapi_is_lustre_mnt(mnt)) { - int mntlen = strlen(mnt->mnt_dir); + if (!pathname) { + want |= WANT_INDEX; + idx = index; + } else + strcpy(mntdir, pathname); - ptr = strchr(mnt->mnt_fsname, '/'); - if (ptr == NULL && !len) { - rc = -EINVAL; - continue; - } + if (fsname) + want |= WANT_FSNAME; + return get_root_path(want, fsname, NULL, mntdir, idx); +} - /* search by pathname */ - if (pathname) { - if ((mntlen >= len) && (strncmp(mnt->mnt_dir, - pathname, mntlen) == 0)) { - strcpy(mntdir, mnt->mnt_dir); - if (fsname) - strcpy(fsname, ++ptr); - len = mntlen; - rc = 0; - } - } else if (idx == index) { - strcpy(mntdir, mnt->mnt_dir); - if (fsname) - strcpy(fsname, ++ptr); - rc = 0; - break; - } - idx++; - } - mnt = getmntent(fp); +int llapi_search_fsname(const char *pathname, char *fsname) +{ + return get_root_path(WANT_FSNAME | WANT_ERROR, fsname, NULL, + (char *)pathname, -1); +} + +/* return the first file matching this pattern */ +static int first_match(char *pattern, char *buffer) +{ + glob_t glob_info; + + if (glob(pattern, GLOB_BRACE, NULL, &glob_info)) + return -ENOENT; + + if (glob_info.gl_pathc < 1) { + globfree(&glob_info); + return -ENOENT; } - endmntent(fp); - return rc; + strcpy(buffer, glob_info.gl_pathv[0]); + + globfree(&glob_info); + return 0; } /* @@ -467,44 +637,131 @@ int llapi_search_mounts(const char *pathname, int index, char *mntdir, static int poolpath(char *fsname, char *pathname, char *pool_pathname) { int rc = 0; - glob_t glob_info; - char pattern[MAXPATHLEN + 1]; - char buffer[MAXPATHLEN]; + char pattern[PATH_MAX + 1]; + char buffer[PATH_MAX]; if (fsname == NULL) { - rc = llapi_search_mounts(pathname, 0, pattern, buffer); + rc = llapi_search_fsname(pathname, buffer); if (rc != 0) return rc; fsname = buffer; strcpy(pathname, fsname); } - snprintf(pattern, MAXPATHLEN, - "/proc/fs/lustre/lov/%s-*/pools", - fsname); - rc = glob(pattern, GLOB_BRACE, NULL, &glob_info); + snprintf(pattern, PATH_MAX, "/proc/fs/lustre/lov/%s-*/pools", fsname); + rc = first_match(pattern, buffer); if (rc) - return -ENOENT; - - if (glob_info.gl_pathc == 0) { - globfree(&glob_info); - return -ENOENT; - } + return rc; /* in fsname test mode, pool_pathname is NULL */ if (pool_pathname != NULL) - strcpy(pool_pathname, glob_info.gl_pathv[0]); + strcpy(pool_pathname, buffer); return 0; } -int llapi_poollist(char *name) +/** + * Get the list of pool members. + * \param poolname string of format \.\ + * \param members caller-allocated array of char* + * \param list_size size of the members array + * \param buffer caller-allocated buffer for storing OST names + * \param buffer_size size of the buffer + * + * \return number of members retrieved for this pool + * \retval -error failure + */ +int llapi_get_poolmembers(const char *poolname, char **members, + int list_size, char *buffer, int buffer_size) +{ + char fsname[PATH_MAX + 1]; + char *pool, *tmp; + char pathname[PATH_MAX + 1]; + char path[PATH_MAX + 1]; + char buf[1024]; + FILE *fd; + int rc = 0; + int nb_entries = 0; + int used = 0; + + /* name is FSNAME.POOLNAME */ + if (strlen(poolname) > PATH_MAX) + return -EOVERFLOW; + strcpy(fsname, poolname); + pool = strchr(fsname, '.'); + if (pool == NULL) + return -EINVAL; + + *pool = '\0'; + pool++; + + rc = poolpath(fsname, NULL, pathname); + if (rc != 0) { + errno = -rc; + llapi_err(LLAPI_MSG_ERROR, "Lustre filesystem '%s' not found", + fsname); + return rc; + } + + llapi_printf(LLAPI_MSG_NORMAL, "Pool: %s.%s\n", fsname, pool); + sprintf(path, "%s/%s", pathname, pool); + if ((fd = fopen(path, "r")) == NULL) { + llapi_err(LLAPI_MSG_ERROR, "Cannot open %s", path); + return -EINVAL; + } + + rc = 0; + while (fgets(buf, sizeof(buf), fd) != NULL) { + if (nb_entries >= list_size) { + rc = -EOVERFLOW; + break; + } + /* remove '\n' */ + if ((tmp = strchr(buf, '\n')) != NULL) + *tmp='\0'; + if (used + strlen(buf) + 1 > buffer_size) { + rc = -EOVERFLOW; + break; + } + + strcpy(buffer + used, buf); + members[nb_entries] = buffer + used; + used += strlen(buf) + 1; + nb_entries++; + rc = nb_entries; + } + + fclose(fd); + return rc; +} + +/** + * Get the list of pools in a filesystem. + * \param name filesystem name or path + * \param poollist caller-allocated array of char* + * \param list_size size of the poollist array + * \param buffer caller-allocated buffer for storing pool names + * \param buffer_size size of the buffer + * + * \return number of pools retrieved for this filesystem + * \retval -error failure + */ +int llapi_get_poollist(const char *name, char **poollist, int list_size, + char *buffer, int buffer_size) { - char *poolname; - char *fsname; - char rname[MAXPATHLEN + 1], pathname[MAXPATHLEN + 1]; + char fsname[PATH_MAX + 1], rname[PATH_MAX + 1], pathname[PATH_MAX + 1]; char *ptr; + DIR *dir; + struct dirent pool; + struct dirent *cookie = NULL; int rc = 0; + unsigned int nb_entries = 0; + unsigned int used = 0; + unsigned int i; + + /* initilize output array */ + for (i = 0; i < list_size; i++) + poollist[i] = NULL; /* is name a pathname ? */ ptr = strchr(name, '/'); @@ -514,72 +771,100 @@ int llapi_poollist(char *name) return -EINVAL; if (!realpath(name, rname)) { rc = -errno; - llapi_err(LLAPI_MSG_ERROR, - "llapi_poollist: invalid path '%s'", - name); + llapi_err(LLAPI_MSG_ERROR, "invalid path '%s'", name); return rc; } rc = poolpath(NULL, rname, pathname); if (rc != 0) { errno = -rc; - llapi_err(LLAPI_MSG_ERROR, - "llapi_poollist: '%s' is not" - " a Lustre filesystem", - name); + llapi_err(LLAPI_MSG_ERROR, "'%s' is not" + " a Lustre filesystem", name); return rc; } - fsname = rname; - poolname = NULL; + strcpy(fsname, rname); } else { - /* name is FSNAME[.POOLNAME] */ - fsname = name; - poolname = strchr(name, '.'); - if (poolname != NULL) { - *poolname = '\0'; - poolname++; - } + /* name is FSNAME */ + strcpy(fsname, name); rc = poolpath(fsname, NULL, pathname); - if (rc != 0) { - errno = -rc; - llapi_err(LLAPI_MSG_ERROR, - "llapi_poollist: Lustre filesystem '%s'" - " not found", name); - return rc; - } } if (rc != 0) { errno = -rc; - llapi_err(LLAPI_MSG_ERROR, - "llapi_poollist: Lustre filesystem '%s' not found", + llapi_err(LLAPI_MSG_ERROR, "Lustre filesystem '%s' not found", name); return rc; } - if (poolname != NULL) { - rc = print_pool_members(fsname, pathname, poolname); - poolname--; - *poolname = '.'; - } else { - DIR *dir; - struct dirent *pool; + llapi_printf(LLAPI_MSG_NORMAL, "Pools from %s:\n", fsname); + if ((dir = opendir(pathname)) == NULL) { + llapi_err(LLAPI_MSG_ERROR, "Could not open pool list for '%s'", + name); + return -errno; + } - llapi_printf(LLAPI_MSG_NORMAL, "Pools from %s:\n", fsname); - if ((dir = opendir(pathname)) == NULL) { - return -EINVAL; - } - while ((pool = readdir(dir)) != NULL) { - if (!((pool->d_name[0] == '.') && - (pool->d_name[1] == '\0')) && - !((pool->d_name[0] == '.') && - (pool->d_name[1] == '.') && - (pool->d_name[2] == '\0'))) - llapi_printf(LLAPI_MSG_NORMAL, " %s.%s\n", - fsname, pool->d_name); - } - closedir(dir); + while(1) { + rc = readdir_r(dir, &pool, &cookie); + + if (rc != 0) { + llapi_err(LLAPI_MSG_ERROR, + "Error reading pool list for '%s'", name); + return -errno; + } else if ((rc == 0) && (cookie == NULL)) + /* end of directory */ + break; + + /* ignore . and .. */ + if (!strcmp(pool.d_name, ".") || !strcmp(pool.d_name, "..")) + continue; + + /* check output bounds */ + if (nb_entries >= list_size) + return -EOVERFLOW; + + /* +2 for '.' and final '\0' */ + if (used + strlen(pool.d_name) + strlen(fsname) + 2 + > buffer_size) + return -EOVERFLOW; + + sprintf(buffer + used, "%s.%s", fsname, pool.d_name); + poollist[nb_entries] = buffer + used; + used += strlen(pool.d_name) + strlen(fsname) + 2; + nb_entries++; } - return rc; + + closedir(dir); + return nb_entries; +} + +/* wrapper for lfs.c and obd.c */ +int llapi_poollist(const char *name) +{ + /* list of pool names (assume that pool count is smaller + than OST count) */ + char *list[FIND_MAX_OSTS]; + char *buffer; + /* fsname-OST0000_UUID < 32 char, 1 per OST */ + int bufsize = FIND_MAX_OSTS * 32; + int i, nb; + + buffer = malloc(bufsize); + if (buffer == NULL) + return -ENOMEM; + + if ((name[0] == '/') || (strchr(name, '.') == NULL)) + /* name is a path or fsname */ + nb = llapi_get_poollist(name, list, FIND_MAX_OSTS, buffer, + bufsize); + else + /* name is a pool name (.) */ + nb = llapi_get_poolmembers(name, list, FIND_MAX_OSTS, buffer, + bufsize); + + for (i = 0; i < nb; i++) + llapi_printf(LLAPI_MSG_NORMAL, "%s\n", list[i]); + + free(buffer); + return (nb < 0 ? nb : 0); } typedef int (semantic_func_t)(char *path, DIR *parent, DIR *d, @@ -686,6 +971,24 @@ int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp, int *ost_count) return rc; } +/* Check if user specified value matches a real uuid. Ignore _UUID, + * -osc-4ba41334, other trailing gunk in comparison. + * @param real_uuid ends in "_UUID" + * @param search_uuid may or may not end in "_UUID" + */ +int llapi_uuid_match(char *real_uuid, char *search_uuid) +{ + int cmplen = strlen(real_uuid) - 5; + + if ((strlen(search_uuid) > cmplen) && isxdigit(search_uuid[cmplen])) { + /* OST00000003 doesn't match OST0000 */ + llapi_err(LLAPI_MSG_ERROR, "Bad UUID format '%s'", search_uuid); + return 0; + } + + return (strncmp(search_uuid, real_uuid, cmplen) == 0); +} + /* Here, param->obduuid points to a single obduuid, the index of which is * returned in param->obdindex */ static int setup_obd_uuid(DIR *dir, char *dname, struct find_param *param) @@ -729,8 +1032,7 @@ static int setup_obd_uuid(DIR *dir, char *dname, struct find_param *param) break; if (param->obduuid) { - if (strncmp((char *)param->obduuid->uuid, uuid, - sizeof(uuid)) == 0) { + if (llapi_uuid_match(uuid, param->obduuid->uuid)) { param->obdindex = index; break; } @@ -745,10 +1047,10 @@ static int setup_obd_uuid(DIR *dir, char *dname, struct find_param *param) if (!param->quiet && param->obduuid && (param->obdindex == OBD_NOT_FOUND)) { - llapi_err_noerrno(LLAPI_MSG_ERROR, + llapi_err_noerrno(LLAPI_MSG_ERROR, "error: %s: unknown obduuid: %s", __FUNCTION__, param->obduuid->uuid); - //rc = EINVAL; + rc = -EINVAL; } return (rc); @@ -792,16 +1094,22 @@ retry_get_uuids: return -ENOMEM; for (obdnum = 0; obdnum < param->num_obds; obdnum++) { - for (i = 0; i <= obdcount; i++) { - if (strcmp((char *)¶m->obduuid[obdnum].uuid, - (char *)&uuids[i]) == 0) { + for (i = 0; i < obdcount; i++) { + if (llapi_uuid_match(uuids[i].uuid, + param->obduuid[obdnum].uuid)) { param->obdindexes[obdnum] = i; obd_valid++; break; } } - if (i == obdcount) + if (i >= obdcount) { param->obdindexes[obdnum] = OBD_NOT_FOUND; + llapi_err_noerrno(LLAPI_MSG_ERROR, + "error: %s: unknown obduuid: %s", + __FUNCTION__, + param->obduuid[obdnum].uuid); + ret = -EINVAL; + } } if (obd_valid == 0) @@ -811,7 +1119,7 @@ retry_get_uuids: param->got_uuids = 1; - return 0; + return ret; } static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, @@ -1117,8 +1425,8 @@ int llapi_mds_getfileinfo(char *path, DIR *parent, fname = (fname == NULL ? path : fname + 1); /* retrieve needed file info */ - strncpy((char *)lmd, fname, lov_mds_md_size(MAX_LOV_UUID_COUNT, - LOV_MAGIC)); + strncpy((char *)lmd, fname, + lov_mds_md_size(MAX_LOV_UUID_COUNT, LOV_MAGIC)); ret = ioctl(dirfd(parent), IOC_MDC_GETFILEINFO, (void *)lmd); if (ret) { @@ -1874,7 +2182,9 @@ static void do_target_check(char *obd_type_name, char *obd_name, int rc; rc = llapi_ping(obd_type_name, obd_name); - if (rc) { + if (rc == ENOTCONN) { + llapi_printf(LLAPI_MSG_NORMAL, "%s inactive.\n", obd_name); + } else if (rc) { llapi_err(LLAPI_MSG_ERROR, "error: check '%s'", obd_name); } else { llapi_printf(LLAPI_MSG_NORMAL, "%s active.\n", obd_name); diff --git a/lustre/utils/obd.c b/lustre/utils/obd.c index 96783ca..0479315 100644 --- a/lustre/utils/obd.c +++ b/lustre/utils/obd.c @@ -2537,106 +2537,13 @@ void obd_finalize(int argc, char **argv) do_disconnect(argv[0], 1); } -static int find_target_obdpath(char *fsname, char *path) -{ - glob_t glob_info; - char pattern[MAXPATHLEN + 1]; - int rc; - - snprintf(pattern, MAXPATHLEN, - "/proc/fs/lustre/lov/%s-*/target_obd", - fsname); - rc = glob(pattern, GLOB_BRACE, NULL, &glob_info); - if (rc == GLOB_NOMATCH) - return -ENODEV; - else if (rc) - return -EINVAL; - - strcpy(path, glob_info.gl_pathv[0]); - globfree(&glob_info); - return 0; -} - -static int find_poolpath(char *fsname, char *poolname, char *poolpath) -{ - glob_t glob_info; - char pattern[MAXPATHLEN + 1]; - int rc; - - snprintf(pattern, MAXPATHLEN, - "/proc/fs/lustre/lov/%s-*/pools/%s", - fsname, poolname); - rc = glob(pattern, GLOB_BRACE, NULL, &glob_info); - /* If no pools, make sure the lov is available */ - if ((rc == GLOB_NOMATCH) && - (find_target_obdpath(fsname, poolpath) == -ENODEV)) - return -ENODEV; - if (rc) - return -EINVAL; - - strcpy(poolpath, glob_info.gl_pathv[0]); - globfree(&glob_info); - return 0; -} - -/* - * if pool is NULL, search ostname in target_obd - * if pool is no NULL - * if pool not found returns errno < 0 - * if ostname is NULL, returns 1 if pool is not empty and 0 if pool empty - * if ostname is not NULL, returns 1 if OST is in pool and 0 if not - */ -int llapi_search_ost(char *fsname, char *poolname, char *ostname) -{ - FILE *fd; - char buffer[MAXPATHLEN + 1]; - int len = 0, rc; - - if (ostname != NULL) - len = strlen(ostname); - - if (poolname == NULL) - rc = find_target_obdpath(fsname, buffer); - else - rc = find_poolpath(fsname, poolname, buffer); - if (rc) - return rc; - - if ((fd = fopen(buffer, "r")) == NULL) - return -EINVAL; - - while (fgets(buffer, sizeof(buffer), fd) != NULL) { - if (poolname == NULL) { - char *ptr; - /* Search for an ostname in the list of OSTs - Line format is IDX: fsname-OSTxxxx_UUID STATUS */ - ptr = strchr(buffer, ' '); - if ((ptr != NULL) && - (strncmp(ptr + 1, ostname, len) == 0)) { - fclose(fd); - return 1; - } - } else { - /* Search for an ostname in a pool, - (or an existing non-empty pool if no ostname) */ - if ((ostname == NULL) || - (strncmp(buffer, ostname, len) == 0)) { - fclose(fd); - return 1; - } - } - } - fclose(fd); - return 0; -} - static int check_pool_cmd(enum lcfg_command_type cmd, char *fsname, char *poolname, char *ostname) { int rc; - rc = llapi_search_ost(fsname, poolname, NULL); + rc = llapi_search_ost(fsname, poolname, ostname); if (rc < 0 && (cmd != LCFG_POOL_NEW)) { fprintf(stderr, "Pool %s.%s not found\n", fsname, poolname); @@ -3017,7 +2924,7 @@ err: int jt_pool_cmd(int argc, char **argv) { enum lcfg_command_type cmd; - char fsname[MAXPATHLEN + 1]; + char fsname[PATH_MAX + 1]; char poolname[LOV_MAXPOOLNAME + 1]; char *ostnames_buf = NULL; int i, rc; -- 1.8.3.1