Whamcloud - gitweb
LU-11743 utils: allow lctl pool_list on separate MGS 95/35895/9
authorEmoly Liu <emoly@whamcloud.com>
Sun, 22 Sep 2019 12:06:07 +0000 (20:06 +0800)
committerOleg Drokin <green@whamcloud.com>
Fri, 27 Sep 2019 23:12:51 +0000 (23:12 +0000)
Change lctl pool_list command to parse the configuration log directly
when run on a standalone MGS node.  This also allows the pool commands
to be run when only the MGS is started.

Also, those test scripts from the patch of LU-9899 to mount a client
on the standalone MGS to allow OST pools to work properly are cleared.

Change-Id: Ic25931d49c2cf747da2a3f2ac3c25a21f6878991
Test-Parameters: standalonemgs=true testlist=ost-pools.sh,sanity.sh,conf-sanity.sh
Signed-off-by: Emoly Liu <emoly@whamcloud.com>
Signed-off-by: Vladimir Saveliev <c17830@cray.com>
Reviewed-on: https://review.whamcloud.com/35895
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Li Xi <lixi@ddn.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
lustre/include/uapi/linux/lustre/lustre_cfg.h
lustre/obdclass/obd_config.c
lustre/tests/conf-sanity.sh
lustre/tests/ost-pools.sh
lustre/tests/replay-single.sh
lustre/tests/sanity.sh [changed mode: 0755->0644]
lustre/tests/test-framework.sh
lustre/utils/obd.c

index af78b57..93884d7 100644 (file)
@@ -172,6 +172,57 @@ struct lustre_cfg {
        __u32 lcfg_buflens[0];
 };
 
+struct lcfg_type_data {
+       __u32    ltd_type;
+       char    *ltd_name;
+       char    *ltd_bufs[4];
+};
+
+static struct lcfg_type_data lcfg_data_table[] = {
+       { LCFG_ATTACH, "attach", { "type", "UUID", "3", "4" } },
+       { LCFG_DETACH, "detach", { "1", "2", "3", "4" } },
+       { LCFG_SETUP, "setup", { "UUID", "node", "options", "failout" } },
+       { LCFG_CLEANUP, "cleanup", { "1", "2", "3", "4" } },
+       { LCFG_ADD_UUID, "add_uuid", { "node", "2", "3", "4" }  },
+       { LCFG_DEL_UUID, "del_uuid", { "1", "2", "3", "4" }  },
+       { LCFG_MOUNTOPT, "new_profile", { "name", "lov", "lmv", "4" }  },
+       { LCFG_DEL_MOUNTOPT, "del_mountopt", { "1", "2", "3", "4" }  },
+       { LCFG_SET_TIMEOUT, "set_timeout", { "parameter", "2", "3", "4" }  },
+       { LCFG_SET_UPCALL, "set_upcall", { "1", "2", "3", "4" }  },
+       { LCFG_ADD_CONN, "add_conn", { "node", "2", "3", "4" }  },
+       { LCFG_DEL_CONN, "del_conn", { "1", "2", "3", "4" }  },
+       { LCFG_LOV_ADD_OBD, "add_osc", { "ost", "index", "gen", "UUID" } },
+       { LCFG_LOV_DEL_OBD, "del_osc", { "1", "2", "3", "4" } },
+       { LCFG_PARAM, "conf_param", { "parameter", "value", "3", "4" } },
+       { LCFG_MARKER, "marker", { "1", "2", "3", "4" } },
+       { LCFG_LOG_START, "log_start", { "1", "2", "3", "4" } },
+       { LCFG_LOG_END, "log_end", { "1", "2", "3", "4" } },
+       { LCFG_LOV_ADD_INA, "add_osc_inactive", { "1", "2", "3", "4" }  },
+       { LCFG_ADD_MDC, "add_mdc", { "mdt", "index", "gen", "UUID" } },
+       { LCFG_DEL_MDC, "del_mdc", { "1", "2", "3", "4" } },
+       { LCFG_SPTLRPC_CONF, "security", { "parameter", "2", "3", "4" } },
+       { LCFG_POOL_NEW, "new_pool", { "fsname", "pool", "3", "4" }  },
+       { LCFG_POOL_ADD, "add_pool", { "fsname", "pool", "ost", "4" } },
+       { LCFG_POOL_REM, "remove_pool", { "fsname", "pool", "ost", "4" } },
+       { LCFG_POOL_DEL, "del_pool", { "fsname", "pool", "3", "4" } },
+       { LCFG_SET_LDLM_TIMEOUT, "set_ldlm_timeout",
+         { "parameter", "2", "3", "4" } },
+       { LCFG_SET_PARAM, "set_param", { "parameter", "value", "3", "4" } },
+       { 0, NULL, { NULL, NULL, NULL, NULL } }
+};
+
+static inline struct lcfg_type_data *lcfg_cmd2data(__u32 cmd)
+{
+       int i = 0;
+
+       while (lcfg_data_table[i].ltd_type != 0) {
+               if (lcfg_data_table[i].ltd_type == cmd)
+                       return &lcfg_data_table[i];
+               i++;
+       }
+       return NULL;
+}
+
 enum cfg_record_type {
        PORTALS_CFG_TYPE        = 1,
        LUSTRE_CFG_TYPE         = 123,
index 5cb44e7..a54308d 100644 (file)
@@ -1854,55 +1854,6 @@ parse_out:
 }
 EXPORT_SYMBOL(class_config_parse_llog);
 
-static struct lcfg_type_data {
-       __u32    ltd_type;
-       char    *ltd_name;
-       char    *ltd_bufs[4];
-} lcfg_data_table[] = {
-       { LCFG_ATTACH, "attach", { "type", "UUID", "3", "4" } },
-       { LCFG_DETACH, "detach", { "1", "2", "3", "4" } },
-       { LCFG_SETUP, "setup", { "UUID", "node", "options", "failout" } },
-       { LCFG_CLEANUP, "cleanup", { "1", "2", "3", "4" } },
-       { LCFG_ADD_UUID, "add_uuid", { "node", "2", "3", "4" }  },
-       { LCFG_DEL_UUID, "del_uuid", { "1", "2", "3", "4" }  },
-       { LCFG_MOUNTOPT, "new_profile", { "name", "lov", "lmv", "4" }  },
-       { LCFG_DEL_MOUNTOPT, "del_mountopt", { "1", "2", "3", "4" } , },
-       { LCFG_SET_TIMEOUT, "set_timeout", { "parameter", "2", "3", "4" }  },
-       { LCFG_SET_UPCALL, "set_upcall", { "1", "2", "3", "4" }  },
-       { LCFG_ADD_CONN, "add_conn", { "node", "2", "3", "4" }  },
-       { LCFG_DEL_CONN, "del_conn", { "1", "2", "3", "4" }  },
-       { LCFG_LOV_ADD_OBD, "add_osc", { "ost", "index", "gen", "UUID" } },
-       { LCFG_LOV_DEL_OBD, "del_osc", { "1", "2", "3", "4" } },
-       { LCFG_PARAM, "conf_param", { "parameter", "value", "3", "4" } },
-       { LCFG_MARKER, "marker", { "1", "2", "3", "4" } },
-       { LCFG_LOG_START, "log_start", { "1", "2", "3", "4" } },
-       { LCFG_LOG_END, "log_end", { "1", "2", "3", "4" } },
-       { LCFG_LOV_ADD_INA, "add_osc_inactive", { "1", "2", "3", "4" }  },
-       { LCFG_ADD_MDC, "add_mdc", { "mdt", "index", "gen", "UUID" } },
-       { LCFG_DEL_MDC, "del_mdc", { "1", "2", "3", "4" } },
-       { LCFG_SPTLRPC_CONF, "security", { "parameter", "2", "3", "4" } },
-       { LCFG_POOL_NEW, "new_pool", { "fsname", "pool", "3", "4" }  },
-       { LCFG_POOL_ADD, "add_pool", { "fsname", "pool", "ost", "4" } },
-       { LCFG_POOL_REM, "remove_pool", { "fsname", "pool", "ost", "4" } },
-       { LCFG_POOL_DEL, "del_pool", { "fsname", "pool", "3", "4" } },
-       { LCFG_SET_LDLM_TIMEOUT, "set_ldlm_timeout",
-         { "parameter", "2", "3", "4" } },
-       { LCFG_SET_PARAM, "set_param", { "parameter", "value", "3", "4" } },
-       { 0, NULL, { NULL, NULL, NULL, NULL } }
-};
-
-static struct lcfg_type_data *lcfg_cmd2data(__u32 cmd)
-{
-       int i = 0;
-
-       while (lcfg_data_table[i].ltd_type != 0) {
-               if (lcfg_data_table[i].ltd_type == cmd)
-                       return &lcfg_data_table[i];
-               i++;
-       }
-       return NULL;
-}
-
 /**
  * Parse config record and output dump in supplied buffer.
  *
index 898c7ca..7b3f25a 100644 (file)
@@ -6012,9 +6012,6 @@ cleanup_82b() {
        # Remove OSTs from a pool and destroy the pool.
        destroy_pool $ost_pool || true
 
-       if ! combined_mgs_mds ; then
-               umount_mgs_client
-       fi
        restore_ostindex
 }
 
@@ -6054,9 +6051,6 @@ test_82b() { # LU-4665
        done
 
        mount_client $MOUNT || error "mount client $MOUNT failed"
-       if ! combined_mgs_mds ; then
-               mount_mgs_client
-       fi
 
        wait_osts_up
        $LFS df $MOUNT || error "$LFS df $MOUNT failed"
@@ -7485,9 +7479,6 @@ test_103() {
        cp $LUSTRE/tests/test-framework.sh $DIR/$tdir ||
                error "(2) Fail to copy test-framework.sh"
 
-       if ! combined_mgs_mds ; then
-               mount_mgs_client
-       fi
        do_facet mgs $LCTL pool_new $FSNAME.pool1 ||
                error "(3) Fail to create $FSNAME.pool1"
        # name the pool name as the fsname
@@ -7499,9 +7490,6 @@ test_103() {
        $LFS setstripe -p $FSNAME $DIR/$tdir/d0 ||
                error "(6) Fail to setstripe on $DIR/$tdir/d0"
 
-       if ! combined_mgs_mds ; then
-               umount_mgs_client
-       fi
        KEEP_ZPOOL=true
        stopall
 
@@ -7511,9 +7499,6 @@ test_103() {
        FSNAME="mylustre"
        setupall
 
-       if ! combined_mgs_mds ; then
-               mount_mgs_client
-       fi
        test_103_check_pool $save_fsname 7
 
        if [ $OSTCOUNT -ge 2 ]; then
@@ -7522,9 +7507,6 @@ test_103() {
 
        $LFS setstripe -p $save_fsname $DIR/$tdir/f0 ||
                error "(16) Fail to setstripe on $DIR/$tdir/f0"
-       if ! combined_mgs_mds ; then
-               umount_mgs_client
-       fi
 
        stopall
 
@@ -7533,14 +7515,8 @@ test_103() {
        FSNAME="tfs"
        setupall
 
-       if ! combined_mgs_mds ; then
-               mount_mgs_client
-       fi
        test_103_check_pool $save_fsname 17
 
-       if ! combined_mgs_mds ; then
-               umount_mgs_client
-       fi
        stopall
 
        test_renamefs $save_fsname
@@ -8014,18 +7990,12 @@ test_109a()
        reformat
        setup_noconfig
        client_up || error "client_up failed"
-       #pool commands requires a client on MGS for procfs interfaces
-       if ! combined_mgs_mds ; then
-               mount_mgs_client
-               stack_trap umount_mgs_client EXIT
-       fi
 
        #
        # set number of permanent parameters
        #
        test_109_set_params $FSNAME
 
-       combined_mgs_mds || umount_mgs_client
        umount_client $MOUNT || error "umount_client failed"
        stop_ost || error "stop_ost failed"
        stop_mds || error "stop_mds failed"
@@ -8040,7 +8010,6 @@ test_109a()
                error "failed to clear client config"
 
        setup_noconfig
-       combined_mgs_mds || mount_mgs_client
 
        #
        # check that configurations are intact
@@ -8052,7 +8021,6 @@ test_109a()
        #
        destroy_test_pools || error "destroy test pools failed"
 
-       combined_mgs_mds || umount_mgs_client
        cleanup
 }
 run_test 109a "test lctl clear_conf fsname"
@@ -8068,18 +8036,12 @@ test_109b()
        reformat
        setup_noconfig
        client_up || error "client_up failed"
-       #pool commands requires a client on MGS for procfs interfaces
-       if ! combined_mgs_mds ; then
-               mount_mgs_client
-               stack_trap umount_mgs_client EXIT
-       fi
 
        #
        # set number of permanent parameters
        #
        test_109_set_params $FSNAME
 
-       combined_mgs_mds || umount_mgs_client
        umount_client $MOUNT || error "umount_client failed"
        stop_ost || error "stop_ost failed"
        stop_mds || error "stop_mds failed"
@@ -8094,7 +8056,6 @@ test_109b()
                error "failed to clear client config"
 
        setup_noconfig
-       combined_mgs_mds || mount_mgs_client
        #
        # check that configurations are intact
        #
@@ -8105,7 +8066,6 @@ test_109b()
        #
        destroy_test_pools || error "destroy test pools failed"
 
-       combined_mgs_mds || umount_mgs_client
        cleanup
 }
 run_test 109b "test lctl clear_conf one config"
index b77c639..bdfe65e 100755 (executable)
@@ -415,10 +415,11 @@ test_2e() {
 
        create_pool_nofail $POOL
 
-       TGT="$FSNAME-OST0000_UUID "
+       TGT="$FSNAME-OST0000_UUID"
        do_facet mgs 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"
+       wait_update_facet $SINGLEMDS \
+               "lctl pool_list $FSNAME.$POOL | sed '1d'" "$TGT" ||
+               error "Add $TGT to $FSNAME.$POOL failed"
        RESULT=$(do_facet mgs \
                "LOCALE=C $LCTL pool_add $FSNAME.$POOL $TGT 2>&1")
        RC=$?
index 69cda14..d588042 100755 (executable)
@@ -3110,10 +3110,6 @@ test_85b() { #bug 16774
 
        lctl set_param -n ldlm.cancel_unused_locks_before_replay "1"
 
-       if ! combined_mgs_mds ; then
-               mount_mgs_client
-       fi
-
        $LFS setstripe -c 1 -i 0 $DIR/$tdir
 
        for i in $(seq 100); do
@@ -3141,10 +3137,6 @@ test_85b() { #bug 16774
                 -n ldlm.namespaces.*OST0000*$addr.lock_unused_count)
        echo "after recovery: unused locks count = $count2"
 
-       if ! combined_mgs_mds ; then
-               umount_mgs_client
-       fi
-
        if [ $count2 -ge $count ]; then
                error "unused locks are not canceled"
        fi
old mode 100755 (executable)
new mode 100644 (file)
index 46ae2a1..fe7c46d
@@ -2458,10 +2458,6 @@ test_27D() {
        local ost_list=$(seq $first_ost $ost_step $last_ost)
        local ost_range="$first_ost $last_ost $ost_step"
 
-       if ! combined_mgs_mds ; then
-               mount_mgs_client
-       fi
-
        test_mkdir $DIR/$tdir
        pool_add $POOL || error "pool_add failed"
        pool_add_targets $POOL $ost_range || error "pool_add_targets failed"
@@ -2481,10 +2477,6 @@ test_27D() {
                error "llapi_layout_test failed"
 
        destroy_test_pools || error "destroy test pools failed"
-
-       if ! combined_mgs_mds ; then
-               umount_mgs_client
-       fi
 }
 run_test 27D "validate llapi_layout API"
 
@@ -2815,11 +2807,6 @@ test_27L() {
 
        local POOL=${POOL:-$TESTNAME}
 
-       if ! combined_mgs_mds ; then
-               mount_mgs_client
-               trap umount_mgs_client EXIT
-       fi
-
        pool_add $POOL || error "pool_add failed"
 
        lfs pool_list $MOUNT | grep -Fx "${FSNAME}.${POOL}" ||
@@ -2964,6 +2951,16 @@ test_27M() {
 }
 run_test 27M "test O_APPEND striping"
 
+test_27N() {
+       combined_mgs_mds && skip "needs separate MGS/MDT"
+
+       pool_add $TESTNAME || error "pool_add failed"
+       do_facet mgs "$LCTL pool_list $FSNAME" |
+               grep -Fx "${FSNAME}.${TESTNAME}" ||
+               error "lctl pool_list on MGS failed"
+}
+run_test 27N "lctl pool_list on separate MGS gives correct pool name"
+
 # createtest also checks that device nodes are created and
 # then visible correctly (#2091)
 test_28() { # bug 2091
@@ -15113,10 +15110,6 @@ test_200() {
        local subdir=$test_path/subdir
        local rc=0
 
-       if ! combined_mgs_mds ; then
-               mount_mgs_client
-       fi
-
        while : ; do
                # former test_200a test_200b
                pool_add $POOL                          || { rc=$? ; break; }
@@ -15150,9 +15143,6 @@ test_200() {
 
        destroy_test_pools
 
-       if ! combined_mgs_mds ; then
-               umount_mgs_client
-       fi
        return $rc
 }
 run_test 200 "OST pools"
@@ -15834,10 +15824,6 @@ test_220() { #LU-325
 
        $LFS df -i
 
-       if ! combined_mgs_mds ; then
-               mount_mgs_client
-       fi
-
        do_facet ost$((OSTIDX + 1)) lctl set_param fail_val=-1
        #define OBD_FAIL_OST_ENOINO              0x229
        do_facet ost$((OSTIDX + 1)) lctl set_param fail_loc=0x229
@@ -15874,10 +15860,6 @@ test_220() { #LU-325
                error "$LCTL pool_destroy $FSNAME.$TESTNAME failed"
        echo "unlink $MDSOBJS files @$next_id..."
        unlinkmany $DIR/$tdir/f $MDSOBJS || error "unlinkmany failed"
-
-       if ! combined_mgs_mds ; then
-               umount_mgs_client
-       fi
 }
 run_test 220 "preallocated MDS objects still used if ENOSPC from OST"
 
@@ -17558,9 +17540,6 @@ test_253() {
        wait_delete_completed
        mkdir $DIR/$tdir
 
-       if ! combined_mgs_mds ; then
-               mount_mgs_client
-       fi
        pool_add $TESTNAME || error "Pool creation failed"
        pool_add_targets $TESTNAME 0 || error "Pool add targets failed"
 
@@ -17606,10 +17585,6 @@ test_253() {
        if (( oa_status != 0 )); then
                error "Object allocation still disable after rm"
        fi
-
-       if ! combined_mgs_mds ; then
-               umount_mgs_client
-       fi
 }
 run_test 253 "Check object allocation limit"
 
@@ -20532,9 +20507,6 @@ test_406() {
        local def_stripe_size=$($LFS getstripe -S $MOUNT)
        local test_pool=$TESTNAME
 
-       if ! combined_mgs_mds ; then
-               mount_mgs_client
-       fi
        pool_add $test_pool || error "pool_add failed"
        pool_add_targets $test_pool 0 $(($OSTCOUNT - 1)) 1 ||
                error "pool_add_targets failed"
@@ -20587,10 +20559,6 @@ test_406() {
        local f=$DIR/$tdir/$tfile
        pool_remove_all_targets $test_pool $f
        pool_remove $test_pool $f
-
-       if ! combined_mgs_mds ; then
-               umount_mgs_client
-       fi
 }
 run_test 406 "DNE support fs default striping"
 
index 9b78323..17274af 100755 (executable)
@@ -2320,19 +2320,6 @@ zconf_umount() {
        fi
 }
 
-# Mount the file system on the MGS
-mount_mgs_client() {
-       do_facet mgs "mkdir -p $MOUNT"
-       zconf_mount $mgs_HOST $MOUNT $MOUNT_OPTS ||
-               error "unable to mount $MOUNT on MGS"
-}
-
-# Unmount the file system on the MGS
-umount_mgs_client() {
-       zconf_umount $mgs_HOST $MOUNT
-       do_facet mgs "rm -rf $MOUNT"
-}
-
 # nodes is comma list
 sanity_mount_check_nodes () {
     local nodes=$1
index e82bdf7..123a5f9 100644 (file)
@@ -3216,6 +3216,37 @@ static long llog_last_index(char *logname)
        return rc;
 }
 
+static char *get_llog_event_name(__u32 cmd)
+{
+       struct lcfg_type_data *data;
+
+       data = lcfg_cmd2data(cmd);
+       if (data)
+               return data->ltd_name;
+       return NULL;
+}
+
+static char *get_event_filter(__u32 cmd)
+{
+       char *event_name;
+       char *filter = NULL;
+       int len;
+
+       event_name = get_llog_event_name(cmd);
+       if (event_name) {
+               /* 9 bytes for "event: , " */
+               len = 9 + strlen(event_name);
+               filter = malloc(len + 1);
+               if (!filter)
+                       return NULL;
+               memset(filter, 0, len + 1);
+               snprintf(filter, len, "event: %s, ", event_name);
+               return filter;
+       }
+
+       return NULL;
+}
+
 /**
  * Callback to search ostname in llog
  * - { index: 23, event: attach, device: lustre-OST0000-osc, type: osc,
@@ -3236,19 +3267,30 @@ static int llog_search_ost_cb(const char *record, void *data)
 {
        char *ostname = data;
        char ost_filter[MAX_STRING_SIZE] = {'\0'};
+       char *add_osc, *del_osc, *setup, *cleanup;
+
+       add_osc = get_event_filter(LCFG_LOV_ADD_OBD);
+       del_osc = get_event_filter(LCFG_LOV_DEL_OBD);
+       setup = get_event_filter(LCFG_SETUP);
+       cleanup = get_event_filter(LCFG_CLEANUP);
+       if (!add_osc || !del_osc || !setup || !cleanup)
+               return -ENOMEM;
 
        if (ostname && ostname[0])
                snprintf(ost_filter, sizeof(ost_filter), " %s,", ostname);
 
        if (strstr(record, ost_filter)) {
-               if (strstr(record, "event: add_osc, ") ||
-                   strstr(record, "event: setup, "))
+               if (strstr(record, add_osc) || strstr(record, setup))
                        return 1;
-               if (strstr(record, "event: del_osc, ") ||
-                   strstr(record, "event: cleanup, "))
+               if (strstr(record, del_osc) || strstr(record, cleanup))
                        return -ENOENT;
        }
 
+       free(add_osc);
+       free(del_osc);
+       free(setup);
+       free(cleanup);
+
        return 0;
 }
 
@@ -3308,8 +3350,18 @@ static int llog_search_pool_cb(const char *record, void *data)
 {
        struct llog_pool_data *lpd = data;
        char pool_filter[MAX_STRING_SIZE] = "";
+       char *new_pool, *del_pool, *add_pool, *rem_pool;
        char *found = NULL;
-       int fs_pool_len = 0;
+       int fs_pool_len = 0, rc = 0;
+
+       new_pool = get_event_filter(LCFG_POOL_NEW);
+       del_pool = get_event_filter(LCFG_POOL_DEL);
+       add_pool = get_event_filter(LCFG_POOL_ADD);
+       rem_pool = get_event_filter(LCFG_POOL_REM);
+       if (!new_pool || !del_pool || !add_pool || !rem_pool) {
+               rc = -ENOMEM;
+               goto out;
+       }
 
        fs_pool_len = 16 + strlen(lpd->lpd_fsname) + strlen(lpd->lpd_poolname);
        snprintf(pool_filter, fs_pool_len + 1, "fsname: %s, pool: %s",
@@ -3319,37 +3371,50 @@ static int llog_search_pool_cb(const char *record, void *data)
        found = strstr(record, pool_filter);
        if (found &&
            (found[fs_pool_len] == ' ' || found[fs_pool_len] == ',')) {
-               if (strstr(record, "event: new_pool,")) {
+               if (strstr(record, new_pool)) {
                        lpd->lpd_pool_exists = true;
-                       return 1;
+                       rc = 1;
+                       goto out;
                }
-               if (strstr(record, "event: del_pool,")) {
+               if (strstr(record, del_pool)) {
                        lpd->lpd_pool_exists = false;
-                       return -ENOENT;
+                       rc = -ENOENT;
+                       goto out;
                }
 
                if (lpd->lpd_cmd_type == LCFG_POOL_NEW ||
                    lpd->lpd_cmd_type == LCFG_POOL_DEL) {
-                       if (strstr(record, "event: add_pool,"))
+                       if (strstr(record, add_pool))
                                lpd->lpd_ost_num++;
-                       if (strstr(record, "event: remove_pool,"))
+                       if (strstr(record, rem_pool))
                                lpd->lpd_ost_num--;
                } else if (lpd->lpd_ostname && lpd->lpd_ostname[0]) {
                        if (strstr(record, lpd->lpd_ostname)) {
                                lpd->lpd_pool_exists = true;
-                               if (strstr(record, "event: add_pool,")) {
+                               if (strstr(record, add_pool)) {
                                        lpd->lpd_ost_num = 1;
-                                       return 1;
+                                       rc = 1;
+                                       goto out;
                                }
-                               if (strstr(record, "event: remove_pool,")) {
+                               if (strstr(record, rem_pool)) {
                                        lpd->lpd_ost_num = 0;
-                                       return -ENOENT;
+                                       rc = -ENOENT;
+                                       goto out;
                                }
                        }
                }
        }
+out:
+       if (new_pool)
+               free(new_pool);
+       if (del_pool)
+               free(del_pool);
+       if (add_pool)
+               free(add_pool);
+       if (rem_pool)
+               free(rem_pool);
 
-       return 0;
+       return rc;
 }
 
 /* Search pool and its ost in llog
@@ -4546,15 +4611,192 @@ err:
        return 0;
 }
 
-static int extract_fsname_poolname(const char *arg, char *fsname,
+struct llog_pool_name {
+       char lpn_name[UUID_MAX];
+       struct list_head lpn_list;
+};
+
+struct llog_pool_list_data {
+       char lpld_fsname[LUSTRE_MAXFSNAME + 1];
+       char lpld_poolname[LOV_MAXPOOLNAME + 1];
+       bool lpld_exists;
+       struct list_head lpld_list_head;
+};
+
+/**
+ * Callback to list pool information in llog
+ * - { index: 74, event: new_pool, device: tfs-clilov, fsname: tfs, pool: tmp }
+ * - { index: 77, event: add_pool, device: tfs-clilov, fsname: tfs, pool: tmp,
+ *     ost: tfs-OST0000_UUID }
+ * - { index: 224, event: remove_pool, device: tfs-clilov, fsname: tfs,
+ *     pool: tmp, ost: tfs-OST0003_UUID }
+ * - { index: 227, event: del_pool, device: tfs-clilov, fsname: tfs, pool: tmp }
+ *
+ * \param record[in]   pointer to llog record
+ * \param data[in]     pointer to struct llog_pool_list_data
+ *
+ * \retval             0 on success
+ *                     <0 on error
+ */
+static int llog_poollist_cb(const char *record, void *data)
+{
+       struct llog_pool_list_data *lpld = data;
+       char pool_filter[MAX_STRING_SIZE] = "";
+       char *new_record, *del_record, *del_pool, *found;
+       char type[10] = "";
+       int filter_len, rc = 0;
+
+       filter_len = snprintf(pool_filter, sizeof(pool_filter), " fsname: %s,",
+                             lpld->lpld_fsname);
+       if (lpld->lpld_poolname[0] == '\0') {
+               new_record = get_event_filter(LCFG_POOL_NEW);
+               del_record = get_event_filter(LCFG_POOL_DEL);
+               strncpy(type, " pool: ", sizeof(type));
+       } else {
+               filter_len += snprintf(pool_filter + filter_len,
+                                      sizeof(pool_filter) - filter_len,
+                                      " pool: %s", lpld->lpld_poolname);
+               new_record = get_event_filter(LCFG_POOL_ADD);
+               del_record = get_event_filter(LCFG_POOL_REM);
+               strncpy(type, " ost: ", sizeof(type));
+       }
+       del_pool = get_event_filter(LCFG_POOL_DEL);
+
+       if (!new_record || !del_record || !del_pool) {
+               rc = -ENOMEM;
+               goto out;
+       }
+
+       found = strstr(record, pool_filter);
+       if (found &&
+           (found[filter_len] == ' ' || found[filter_len] == ',')) {
+               struct llog_pool_name *tmp = NULL;
+               struct list_head *head = &lpld->lpld_list_head;
+               char *name;
+               int name_len, type_len = strlen(type);
+
+               lpld->lpld_exists = true;
+               if (strstr(record, new_record)) {
+                       name = strstr(record, type);
+                       /* 2 bytes for " }" */
+                       name_len = strlen(name) - type_len - 2;
+                       if (name_len <= 0 || name_len > sizeof(tmp->lpn_name))
+                               return -EINVAL;
+                       tmp = malloc(sizeof(struct llog_pool_name));
+                       if (tmp == NULL) {
+                               rc = -ENOMEM;
+                               goto out;
+                       }
+                       memset(tmp, 0, sizeof(struct llog_pool_name));
+                       strncpy(tmp->lpn_name, name + type_len, name_len);
+                       list_add_tail(&tmp->lpn_list, &lpld->lpld_list_head);
+               } else if (strstr(record, del_record)) {
+                       name = strstr(record, type);
+                       name_len = strlen(name) - type_len - 2;
+                       list_for_each_entry(tmp, head, lpn_list) {
+                               if (strncmp(tmp->lpn_name, name + type_len,
+                                           name_len) == 0 &&
+                                           tmp->lpn_name[name_len] == '\0') {
+                                       list_del(&tmp->lpn_list);
+                                       free(tmp);
+                                       break;
+                               }
+                       }
+               }
+               /* verify if the specified pool still exists */
+               if (lpld->lpld_poolname[0] && strstr(record, del_pool))
+                       lpld->lpld_exists = false;
+       }
+out:
+       if (new_record)
+               free(new_record);
+       if (del_record)
+               free(del_record);
+       if (del_pool)
+               free(del_pool);
+
+       return rc;
+}
+
+/**
+ * List pool information by config log
+ *
+ * \param fsname[in]   pointer to filesystem name
+ * \param poolname[in] pointer to pool name
+ *
+ * \retval             0 on success
+ *                     < 0 on error
+ */
+int llog_poollist(char *fsname, char *poolname)
+{
+       char logname[MAX_OBD_NAME] = {'\0'};
+       struct llog_pool_list_data lpld;
+       struct llog_pool_name *tmp;
+       struct list_head *head;
+       int rc = 0;
+
+       if (fsname && fsname[0] == '\0')
+               fsname = NULL;
+       if (!fsname)
+               return -EINVAL;
+
+       memset(&lpld, 0, sizeof(lpld));
+       INIT_LIST_HEAD(&lpld.lpld_list_head);
+       lpld.lpld_exists = false;
+       strncpy(lpld.lpld_fsname, fsname, sizeof(lpld.lpld_fsname) - 1);
+       if (poolname && poolname[0])
+               strncpy(lpld.lpld_poolname, poolname,
+                       sizeof(lpld.lpld_poolname) - 1);
+       snprintf(logname, sizeof(logname), "%s-client", fsname);
+       rc = jt_llog_print_iter(logname, 0, -1, llog_poollist_cb, &lpld, false);
+
+       if (poolname && poolname[0])
+               printf("Pool: %s.%s\n", fsname, poolname);
+       else
+               printf("Pools from %s:\n", fsname);
+
+       head = &lpld.lpld_list_head;
+       if (poolname && poolname[0] && !lpld.lpld_exists && list_empty(head))
+               return -ENOENT;
+
+       list_for_each_entry(tmp, head, lpn_list) {
+               if (poolname && poolname[0])
+                       printf("%s\n", tmp->lpn_name);
+               else
+                       printf("%s.%s\n", fsname, tmp->lpn_name);
+               list_del(&tmp->lpn_list);
+               free(tmp);
+       }
+
+       return rc;
+}
+
+static bool get_pools_path(char *fsname)
+{
+       glob_t path;
+       int rc;
+
+       rc = cfs_get_param_paths(&path, "lov/%s-*/pools", fsname);
+       if (!rc)
+               cfs_free_param_data(&path);
+
+       return (rc == 0);
+}
+
+static int extract_fsname_poolname(char **argv, char *fsname,
                                   char *poolname)
 {
+       char *cmd = argv[0], *param = argv[1];
        char *ptr;
        int rc;
 
-       snprintf(fsname, PATH_MAX + 1, "%s", arg);
+       snprintf(fsname, PATH_MAX + 1, "%s", param);
        ptr = strchr(fsname, '.');
        if (ptr == NULL) {
+               if (strcmp(cmd, "pool_list") == 0) {
+                       poolname = NULL;
+                       goto out;
+               }
                fprintf(stderr, ". is missing in %s\n", fsname);
                rc = -EINVAL;
                goto err;
@@ -4582,63 +4824,71 @@ static int extract_fsname_poolname(const char *arg, char *fsname,
                fprintf(stderr, "poolname cannot be 'none'\n");
                return -EINVAL;
        }
+out:
        return 0;
 
 err:
-       fprintf(stderr, "argument %s must be <fsname>.<poolname>\n", arg);
+       fprintf(stderr, "argument %s must be <fsname>.<poolname>\n", param);
        return rc;
 }
 
 int jt_pool_cmd(int argc, char **argv)
 {
-        enum lcfg_command_type cmd;
-        char fsname[PATH_MAX + 1];
-        char poolname[LOV_MAXPOOLNAME + 1];
-        char *ostnames_buf = NULL;
-        int i, rc;
-        int *array = NULL, array_sz;
-        struct {
-                int     rc;
-                char   *ostname;
-        } *cmds = NULL;
-
-        switch (argc) {
-        case 0:
-        case 1: return CMD_HELP;
-        case 2: {
-                if (strcmp("pool_new", argv[0]) == 0)
-                        cmd = LCFG_POOL_NEW;
-                else if (strcmp("pool_destroy", argv[0]) == 0)
-                        cmd = LCFG_POOL_DEL;
-                else if (strcmp("pool_list", argv[0]) == 0)
-                         return llapi_poollist(argv[1]);
-                else return CMD_HELP;
-
-                rc = extract_fsname_poolname(argv[1], fsname, poolname);
-                if (rc)
-                        break;
+       enum lcfg_command_type cmd;
+       char fsname[PATH_MAX + 1];
+       char poolname[LOV_MAXPOOLNAME + 1];
+       char *ostnames_buf = NULL;
+       int i, rc;
+       int *array = NULL, array_sz;
+       struct {
+               int     rc;
+               char   *ostname;
+       } *cmds = NULL;
+
+       switch (argc) {
+       case 0:
+       case 1: return CMD_HELP;
+       case 2: {
+               rc = extract_fsname_poolname(argv, fsname, poolname);
+               if (rc)
+                       break;
 
-                rc = pool_cmd(cmd, argv[0], argv[1], fsname, poolname, NULL);
-                if (rc)
-                        break;
+               if (strcmp("pool_new", argv[0]) == 0) {
+                       cmd = LCFG_POOL_NEW;
+               } else if (strcmp("pool_destroy", argv[0]) == 0) {
+                       cmd = LCFG_POOL_DEL;
+               } else if (strcmp("pool_list", argv[0]) == 0) {
+                       if (get_pools_path(fsname))
+                               return llapi_poollist(argv[1]);
+                       if (get_mgs_device() > 0)
+                               return llog_poollist(fsname, poolname);
+                       fprintf(stderr, "Cannot run pool_list command "
+                               "since there is no local MGS/MDT or client\n");
+                       return CMD_HELP;
+               } else {
+                       return CMD_HELP;
+               }
 
-                check_pool_cmd_result(cmd, fsname, poolname, NULL);
-                break;
-        }
-        default: {
-                char format[2*MAX_OBD_NAME];
+               rc = pool_cmd(cmd, argv[0], argv[1], fsname, poolname, NULL);
+               if (rc)
+                       break;
 
-                if (strcmp("pool_remove", argv[0]) == 0) {
-                        cmd = LCFG_POOL_REM;
-                } else if (strcmp("pool_add", argv[0]) == 0) {
-                        cmd = LCFG_POOL_ADD;
-                } else {
-                        return CMD_HELP;
-                }
+               check_pool_cmd_result(cmd, fsname, poolname, NULL);
+               break;
+       }
+       default: {
+               char format[2 * MAX_OBD_NAME];
 
-                rc = extract_fsname_poolname(argv[1], fsname, poolname);
-                if (rc)
-                        break;
+               if (strcmp("pool_remove", argv[0]) == 0)
+                       cmd = LCFG_POOL_REM;
+               else if (strcmp("pool_add", argv[0]) == 0)
+                       cmd = LCFG_POOL_ADD;
+               else
+                       return CMD_HELP;
+
+               rc = extract_fsname_poolname(argv, fsname, poolname);
+               if (rc)
+                       break;
 
                 for (i = 2; i < argc; i++) {
                         int j;