Whamcloud - gitweb
LU-819 utils: Fix lfs getstripe -M
authorwangdi <di.wang@whamcloud.com>
Fri, 4 Nov 2011 06:00:05 +0000 (23:00 -0700)
committerOleg Drokin <green@whamcloud.com>
Thu, 23 Feb 2012 05:11:24 +0000 (00:11 -0500)
1. Fix lfs getstripe -M problem: some typo in llapi_file_fget_mdtidx.
2. Add lfs find -mdt and lfs mdts.
3. Add sanity test to check lfs getstripe -M and lfs find -mdt.

Signed-off-by: wangdi <di.wang@whamcloud.com>
Change-Id: I3b327d33c49009149dbed23728416efecb67691c
Reviewed-on: http://review.whamcloud.com/1646
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
14 files changed:
lustre/include/linux/lustre_lib.h
lustre/include/lustre/liblustreapi.h
lustre/include/lustre/lustre_user.h
lustre/include/lustre_lib.h
lustre/include/obd.h
lustre/llite/dir.c
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/lmv/lmv_obd.c
lustre/tests/sanity.sh
lustre/tests/test-framework.sh
lustre/utils/lfs.c
lustre/utils/liblustreapi.c

index 8c853ed..fb476f1 100644 (file)
 #endif
 #endif
 
+/* This macro is only for compatibility reasons with older Linux Lustre user
+ * tools. New ioctls should NOT use this macro as the ioctl "size". Instead
+ * the ioctl should get a "size" argument which is the actual data type used
+ * by the ioctl, to ensure the ioctl interface is versioned correctly. */
 #define OBD_IOC_DATA_TYPE               long
 
 #define LUSTRE_FATAL_SIGS (sigmask(SIGKILL) | sigmask(SIGINT) |                \
index 2cb4ad9..463f140 100644 (file)
@@ -126,6 +126,7 @@ struct find_param {
                         exclude_pattern:1,
                         exclude_type:1,
                         exclude_obd:1,
+                        exclude_mdt:1,
                         have_fileinfo:1,
                         exclude_gid:1,
                         exclude_uid:1,
@@ -139,6 +140,7 @@ struct find_param {
                         exclude_mtime:1,
                         exclude_ctime:1,
                         get_mdt_index:1,
+                        get_lmv:1,
                         raw:1;
 
         int     verbose;
@@ -149,11 +151,18 @@ struct find_param {
 
         char   *print_fmt;
 
-        struct  obd_uuid        *obduuid;
+        struct  obd_uuid       *obduuid;
         int                     num_obds;
         int                     num_alloc_obds;
         int                     obdindex;
-        int                     *obdindexes;
+        int                    *obdindexes;
+
+        struct  obd_uuid       *mdtuuid;
+        int                     num_mdts;
+        int                     num_alloc_mdts;
+        int                     mdtindex;
+        int                    *mdtindexes;
+        int                     file_mdtindex;
 
         int     lumlen;
         struct  lov_user_mds_data *lmd;
@@ -180,6 +189,7 @@ extern int llapi_catinfo(char *dir, char *keyword, char *node_name);
 extern int llapi_file_get_lov_uuid(const char *path, struct obd_uuid *lov_uuid);
 extern int llapi_file_fget_lov_uuid(int fd, struct obd_uuid *lov_uuid);
 extern int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp, int *ost_count);
+extern int llapi_lmv_get_uuids(int fd, struct obd_uuid *uuidp, int *mdt_count);
 extern int llapi_is_lustre_mnttype(const char *type);
 extern int llapi_search_ost(char *fsname, char *poolname, char *ostname);
 extern int llapi_get_obd_count(char *mnt, int *count, int is_mdt);
index 1b2176a..f2a52cb 100644 (file)
@@ -157,7 +157,7 @@ struct obd_statfs {
 /* see <lustre_lib.h> for ioctl numbers 177-210 */
 
 
-#define LL_STATFS_MDC           1
+#define LL_STATFS_LMV           1
 #define LL_STATFS_LOV           2
 
 #define IOC_MDC_TYPE            'i'
@@ -170,6 +170,9 @@ struct obd_statfs {
 #define LL_IOC_OBD_STATFS       IOC_OBD_STATFS
 #define IOC_MDC_GETSTRIPE       IOC_MDC_GETFILESTRIPE
 
+
+#define MAX_OBD_NAME 128 /* If this changes, a NEW ioctl must be added */
+
 #define O_LOV_DELAY_CREATE 0100000000  /* hopefully this does not conflict */
 
 #define LL_FILE_IGNORE_LOCK     0x00000001
index 37dd25d..2a7f3d5 100644 (file)
@@ -492,7 +492,10 @@ static inline void obd_ioctl_freedata(char *buf, int len)
 #define OBD_IOC_BRW_WRITE              _IOWR('f', 126, OBD_IOC_DATA_TYPE)
 #define OBD_IOC_NAME2DEV               _IOWR('f', 127, OBD_IOC_DATA_TYPE)
 #define OBD_IOC_UUID2DEV               _IOWR('f', 130, OBD_IOC_DATA_TYPE)
+
 #define OBD_IOC_GETNAME                _IOWR('f', 131, OBD_IOC_DATA_TYPE)
+#define OBD_IOC_GETMDNAME              _IOR('f', 131, char[MAX_OBD_NAME])
+#define OBD_IOC_GETDTNAME               OBD_IOC_GETNAME
 
 #define OBD_IOC_LOV_GET_CONFIG         _IOWR('f', 132, OBD_IOC_DATA_TYPE)
 #define OBD_IOC_CLIENT_RECOVER         _IOW ('f', 133, OBD_IOC_DATA_TYPE)
index 8f9d603..870c844 100644 (file)
@@ -1046,7 +1046,6 @@ struct obd_llog_group {
 };
 
 /* corresponds to one of the obd's */
-#define MAX_OBD_NAME 128
 #define OBD_DEVICE_MAGIC        0XAB5CD6EF
 #define OBD_DEV_BY_DEVNAME      0xffffd0de
 
index 392dce1..27edd96 100644 (file)
@@ -1477,15 +1477,9 @@ out_free:
                 OBD_FREE_PTR(qctl);
                 RETURN(rc);
         }
-        case OBD_IOC_GETNAME: {
-                struct obd_device *obd = class_exp2obd(sbi->ll_dt_exp);
-                if (!obd)
-                        RETURN(-EFAULT);
-                if (cfs_copy_to_user((void *)arg, obd->obd_name,
-                                     strlen(obd->obd_name) + 1))
-                        RETURN (-EFAULT);
-                RETURN(0);
-        }
+        case OBD_IOC_GETDTNAME:
+        case OBD_IOC_GETMDNAME:
+                RETURN(ll_get_obd_name(inode, cmd, arg));
         case LL_IOC_FLUSHCTX:
                 RETURN(ll_flush_ctx(inode));
 #ifdef CONFIG_FS_POSIX_ACL
index b4c0028..34ce73a 100644 (file)
@@ -1849,17 +1849,9 @@ int ll_file_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
                 RETURN(0);
         }
-        case OBD_IOC_GETNAME: {
-                struct obd_device *obd =
-                                class_exp2obd(ll_i2sbi(inode)->ll_dt_exp);
-                if (!obd)
-                        RETURN(-EFAULT);
-                if (cfs_copy_to_user((void *)arg, obd->obd_name,
-                                     strlen(obd->obd_name) + 1))
-                        RETURN(-EFAULT);
-                RETURN(0);
-        }
-
+        case OBD_IOC_GETDTNAME:
+        case OBD_IOC_GETMDNAME:
+                RETURN(ll_get_obd_name(inode, cmd, arg));
         default: {
                 int err;
 
index ef654c9..950856e 100644 (file)
@@ -815,6 +815,7 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data,
                                       const char *name, int namelen,
                                       int mode, __u32 opc, void *data);
 void ll_finish_md_op_data(struct md_op_data *op_data);
+int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg);
 
 /* llite/llite_nfs.c */
 extern struct export_operations lustre_export_operations;
index a17429d..4e49985 100644 (file)
@@ -2137,7 +2137,7 @@ int ll_obd_statfs(struct inode *inode, void *arg)
                 GOTO(out_statfs, rc = -EINVAL);
 
         memcpy(&type, data->ioc_inlbuf1, sizeof(__u32));
-        if (type == LL_STATFS_MDC)
+        if (type == LL_STATFS_LMV)
                 exp = sbi->ll_md_exp;
         else if (type == LL_STATFS_LOV)
                 exp = sbi->ll_dt_exp;
@@ -2272,3 +2272,29 @@ int ll_show_options(struct seq_file *seq, struct vfsmount *vfs)
 
         RETURN(0);
 }
+
+/**
+ * Get obd name by cmd, and copy out to user space
+ */
+int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg)
+{
+        struct ll_sb_info *sbi = ll_i2sbi(inode);
+        struct obd_device *obd;
+        ENTRY;
+
+        if (cmd == OBD_IOC_GETDTNAME)
+                obd = class_exp2obd(sbi->ll_dt_exp);
+        else if (cmd == OBD_IOC_GETMDNAME)
+                obd = class_exp2obd(sbi->ll_md_exp);
+        else
+                RETURN(-EINVAL);
+
+        if (!obd)
+                RETURN(-ENOENT);
+
+        if (cfs_copy_to_user((void *)arg, obd->obd_name,
+                             strlen(obd->obd_name) + 1))
+                RETURN(-EFAULT);
+
+        RETURN(0);
+}
index daefddd..d897826 100644 (file)
@@ -1110,10 +1110,11 @@ static int lmv_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
         lprocfs_obd_setup(obd, lvars.obd_vars);
 #ifdef LPROCFS
         {
-                rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd_status",
+                rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd",
                                         0444, &lmv_proc_target_fops, obd);
                 if (rc)
-                        CWARN("Error adding target_obd_stats file (%d)\n", rc);
+                        CWARN("%s: error adding LMV target_obd file: rc = %d\n",
+                               obd->obd_name, rc);
        }
 #endif
         rc = fld_client_init(&lmv->lmv_fld, obd->obd_name,
index cde9086..02f0d6f 100644 (file)
@@ -3375,9 +3375,9 @@ test_56i() {
        mkdir -p $DIR/$tdir
        UUID=$(ostuuid_from_index 0 $DIR/$tdir)
        OUT=$($LFIND -obd $UUID $DIR/$tdir)
-       [ "$OUT" ] && error "$LFIND returned directory '$OUT'" || true
+       [ "$OUT" ] && error "$LFIND -obd returned directory '$OUT'" || true
 }
-run_test 56i "check 'lfs find -ost UUID' skips directories ======="
+run_test 56i "check 'lfs find -obd UUID' skips directories ======="
 
 test_56j() {
        setup_56_special $NUMFILES $NUMDIRS
@@ -3538,6 +3538,22 @@ test_56r() {
 
 run_test 56r "check lfs find -size works =========================="
 
+test_56v() {
+    local FIND_MDT_IDX=0
+
+    TDIR=${tdir}g
+    rm -rf $TDIR
+    setup_56 $NUMFILES $NUMDIRS
+
+    UUID=$(mdtuuid_from_index $FIND_MDT_IDX $DIR/$TDIR)
+    for file in $($LFIND -mdt $UUID $DIR/$TDIR); do
+        file_mdt_idx=$($GETSTRIPE -M $file)
+        [ $file_mdt_idx -eq $FIND_MDT_IDX ] ||
+            error "wrong lfind -m not match getstripe -M"
+    done
+}
+run_test 56v "check 'lfs find -mdt match with lfs getstripe -M' ======="
+
 test_57a() {
        # note test will not do anything if MDS is not local
        remote_mds_nodsh && skip "remote MDS with nodsh" && return
index 4c52a29..ad6ad36 100644 (file)
@@ -3439,6 +3439,11 @@ index_from_ostuuid()
     $LFS osts $2 | sed -ne "/${1}/s/\(.*\): .* .*$/\1/p"
 }
 
+mdtuuid_from_index()
+{
+    $LFS mdts $2 | awk '/^'$1'/ { print $2 }'
+}
+
 remote_node () {
     local node=$1
     [ "$node" != "$(hostname)" ]
index 2bc71a1..c2f45eb 100644 (file)
@@ -85,6 +85,7 @@ static int lfs_setstripe(int argc, char **argv);
 static int lfs_find(int argc, char **argv);
 static int lfs_getstripe(int argc, char **argv);
 static int lfs_osts(int argc, char **argv);
+static int lfs_mdts(int argc, char **argv);
 static int lfs_df(int argc, char **argv);
 static int lfs_getname(int argc, char **argv);
 static int lfs_check(int argc, char **argv);
@@ -145,8 +146,9 @@ command_t cmdlist[] = {
          "usage: find <directory|filename> ...\n"
          "     [[!] --atime|-A [+-]N] [[!] --mtime|-M [+-]N] [[!] --ctime|-C [+-]N]\n"
          "     [--maxdepth|-D N] [[!] --name|-n <pattern>] [--print0|-P]\n"
-         "     [--print|-p] [[!] --obd|-O <uuid[s]>] [[!] --size|-s [+-]N[bkMGTP]]\n"
-         "     [[!] --type|-t <filetype>] [[!] --gid|-g|--group|-G <gid>|<gname>]\n"
+         "     [--print|-p] [[!] --obd|-O <uuid[s]>] [[!] --mdt|-m <uuid[s]]\n"
+         "     [[!] --size|-s [+-]N[bkMGTP]] [[!] --type|-t <filetype>]\n"
+         "     [[!] --gid|-g|--group|-G <gid>|<gname>]\n"
          "     [[!] --uid|-u|--user|-U <uid>|<uname>]\n"
          "     [[!] --pool <pool>]\n"
          "\t !: used before an option indicates 'NOT' the requested attribute\n"
@@ -166,6 +168,8 @@ command_t cmdlist[] = {
          "obsolete, HEAD does not support it anymore.\n"},
         {"osts", lfs_osts, 0, "list OSTs connected to client "
          "[for specified path only]\n" "usage: osts [path]"},
+        {"mdts", lfs_mdts, 0, "list MDTs connected to client "
+         "[for specified path only]\n" "usage: mdts [path]"},
         {"df", lfs_df, 0,
          "report filesystem disk space usage or inodes usage"
          "of each MDS and all OSDs or a batch belonging to a specific pool .\n"
@@ -506,6 +510,7 @@ static int lfs_find(int argc, char **argv)
                 {"gid",       required_argument, 0, 'g'},
                 {"group",     required_argument, 0, 'G'},
                 {"mtime",     required_argument, 0, 'M'},
+                {"mdt",       required_argument, 0, 'm'},
                 {"name",      required_argument, 0, 'n'},
                 /* --obd is considered as a new option. */
                 {"obd",       required_argument, 0, 'O'},
@@ -535,8 +540,8 @@ static int lfs_find(int argc, char **argv)
 
         optind = 0;
         /* when getopt_long_only() hits '!' it returns 1, puts "!" in optarg */
-        while ((c = getopt_long_only(argc,argv,"-A:C:D:g:G:M:n:O:Ppqrs:t:u:U:v",
-                                     long_opts, NULL)) >= 0) {
+        while ((c = getopt_long_only(argc, argv, "-A:C:D:g:G:M:m:n:O:"
+                                     "Ppqrs:t:u:U:v", long_opts, NULL)) >= 0) {
                 xtime = NULL;
                 xsign = NULL;
                 if (neg_opt)
@@ -659,6 +664,7 @@ static int lfs_find(int argc, char **argv)
                         param.pattern = (char *)optarg;
                         param.exclude_pattern = !!neg_opt;
                         break;
+                case 'm':
                 case 'O': {
                         char *buf, *token, *next, *p;
                         int len = 1;
@@ -680,29 +686,42 @@ static int lfs_find(int argc, char **argv)
                                         token++;
                                 }
                         }
-
-                        param.num_alloc_obds += len;
-                        tmp = realloc(param.obduuid,
-                                      param.num_alloc_obds *
-                                      sizeof(*param.obduuid));
-                        if (tmp == NULL) {
-                                ret = -ENOMEM;
-                                free(buf);
-                                goto err;
+                        if (c == 'O') {
+                                param.exclude_obd = !!neg_opt;
+                                param.num_alloc_obds += len;
+                                tmp = realloc(param.obduuid,
+                                              param.num_alloc_obds *
+                                              sizeof(*param.obduuid));
+                                if (tmp == NULL)
+                                        GOTO(err_free, ret = -ENOMEM);
+                                param.obduuid = tmp;
+                        } else {
+                                param.exclude_mdt = !!neg_opt;
+                                param.num_alloc_mdts += len;
+                                tmp = realloc(param.mdtuuid,
+                                              param.num_alloc_mdts *
+                                              sizeof(*param.mdtuuid));
+                                if (tmp == NULL)
+                                        GOTO(err_free, ret = -ENOMEM);
+                                param.mdtuuid = tmp;
                         }
-                        param.obduuid = tmp;
-
                         for (token = buf; token && *token; token = next) {
+                                char *uuid;
+                                if (c == 'O')
+                                        uuid =
+                                          param.obduuid[param.num_obds++].uuid;
+                                else
+                                        uuid =
+                                          param.mdtuuid[param.num_mdts++].uuid;
                                 p = strchr(token, ',');
                                 next = 0;
                                 if (p) {
                                         *p = 0;
                                         next = p+1;
                                 }
-                                strcpy((char *)&param.obduuid[param.num_obds++].uuid,
-                                       token);
+                                strcpy((char *)uuid, token);
                         }
-
+err_free:
                         if (buf)
                                 free(buf);
                         break;
@@ -812,6 +831,9 @@ err:
         if (param.obduuid && param.num_alloc_obds)
                 free(param.obduuid);
 
+        if (param.mdtuuid && param.num_alloc_mdts)
+                free(param.mdtuuid);
+
         return ret;
 }
 
@@ -894,6 +916,8 @@ static int lfs_getstripe(int argc, char **argv)
                         }
                         break;
                 case 'M':
+                        if (!(param.verbose & VERBOSE_DETAIL))
+                                param.maxdepth = 0;
                         param.get_mdt_index = 1;
                         break;
                 case 'R':
@@ -929,7 +953,7 @@ static int lfs_getstripe(int argc, char **argv)
         return rc;
 }
 
-static int lfs_osts(int argc, char **argv)
+static int lfs_tgts(int argc, char **argv)
 {
         char mntdir[PATH_MAX] = {'\0'}, path[PATH_MAX] = {'\0'};
         struct find_param param;
@@ -951,6 +975,9 @@ static int lfs_osts(int argc, char **argv)
                         continue;
 
                 memset(&param, 0, sizeof(param));
+                if (!strcmp(argv[0], "mdts"))
+                        param.get_lmv = 1;
+
                 rc = llapi_ostlist(mntdir, &param);
                 if (rc) {
                         fprintf(stderr, "error: %s: failed on %s\n",
@@ -964,6 +991,16 @@ static int lfs_osts(int argc, char **argv)
         return rc;
 }
 
+static int lfs_osts(int argc, char **argv)
+{
+        return lfs_tgts(argc, argv);
+}
+
+static int lfs_mdts(int argc, char **argv)
+{
+        return lfs_tgts(argc, argv);
+}
+
 #define COOK(value)                                                     \
 ({                                                                      \
         int radix = 0;                                                  \
@@ -1071,7 +1108,7 @@ static int mntdf(char *mntdir, char *fsname, char *pool, int ishow, int cooked)
         struct obd_statfs stat_buf, sum = { .os_bsize = 1 };
         struct obd_uuid uuid_buf;
         char *poolname = NULL;
-        struct ll_stat_type types[] = { { LL_STATFS_MDC, "MDT" },
+        struct ll_stat_type types[] = { { LL_STATFS_LMV, "MDT" },
                                         { LL_STATFS_LOV, "OST" },
                                         { 0, NULL } };
         struct ll_stat_type *tp;
@@ -1125,7 +1162,7 @@ static int mntdf(char *mntdir, char *fsname, char *pool, int ishow, int cooked)
                               ishow, cooked, tp->st_name, index, rc);
 
                         if (rc == 0) {
-                                if (tp->st_op == LL_STATFS_MDC) {
+                                if (tp->st_op == LL_STATFS_LMV) {
                                         sum.os_ffree += stat_buf.os_ffree;
                                         sum.os_files += stat_buf.os_files;
                                 } else /* if (tp->st_op == LL_STATFS_LOV) */ {
index f7e012b..719ab51 100644 (file)
@@ -1373,6 +1373,16 @@ int llapi_file_fget_lov_uuid(int fd, struct obd_uuid *lov_name)
         return rc;
 }
 
+int llapi_file_fget_lmv_uuid(int fd, struct obd_uuid *lov_name)
+{
+        int rc = ioctl(fd, OBD_IOC_GETMDNAME, lov_name);
+        if (rc) {
+                rc = -errno;
+                llapi_error(LLAPI_MSG_ERROR, rc, "error: can't get lmv name.");
+        }
+        return rc;
+}
+
 int llapi_file_get_lov_uuid(const char *path, struct obd_uuid *lov_uuid)
 {
         int fd, rc;
@@ -1390,27 +1400,38 @@ int llapi_file_get_lov_uuid(const char *path, struct obd_uuid *lov_uuid)
         return rc;
 }
 
+enum tgt_type {
+        LOV_TYPE = 1,
+        LMV_TYPE
+};
 /*
  * If uuidp is NULL, return the number of available obd uuids.
  * If uuidp is non-NULL, then it will return the uuids of the obds. If
  * there are more OSTs then allocated to uuidp, then an error is returned with
  * the ost_count set to number of available obd uuids.
  */
-int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp, int *ost_count)
+static int llapi_get_target_uuids(int fd, struct obd_uuid *uuidp,
+                                  int *ost_count, enum tgt_type type)
 {
-        struct obd_uuid lov_name;
+        struct obd_uuid name;
         char buf[1024];
         FILE *fp;
         int rc = 0, index = 0;
 
         /* Get the lov name */
-        rc = llapi_file_fget_lov_uuid(fd, &lov_name);
-        if (rc)
-                return rc;
+        if (type == LOV_TYPE) {
+                rc = llapi_file_fget_lov_uuid(fd, &name);
+                if (rc)
+                        return rc;
+        } else {
+                rc = llapi_file_fget_lmv_uuid(fd, &name);
+                if (rc)
+                        return rc;
+        }
 
         /* Now get the ost uuids from /proc */
-        snprintf(buf, sizeof(buf), "/proc/fs/lustre/lov/%s/target_obd",
-                 lov_name.uuid);
+        snprintf(buf, sizeof(buf), "/proc/fs/lustre/%s/%s/target_obd",
+                 type == LOV_TYPE ? "lov" : "lmv", name.uuid);
         fp = fopen(buf, "r");
         if (fp == NULL) {
                 rc = -errno;
@@ -1435,6 +1456,11 @@ int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp, int *ost_count)
         return rc;
 }
 
+int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp, int *ost_count)
+{
+        return llapi_get_target_uuids(fd, uuidp, ost_count, LOV_TYPE);
+}
+
 int llapi_get_obd_count(char *mnt, int *count, int is_mdt)
 {
         DIR *root;
@@ -1483,7 +1509,7 @@ int llapi_uuid_match(char *real_uuid, char *search_uuid)
  * returned in param->obdindex */
 static int setup_obd_uuid(DIR *dir, char *dname, struct find_param *param)
 {
-        struct obd_uuid lov_uuid;
+        struct obd_uuid obd_uuid;
         char uuid[sizeof(struct obd_uuid)];
         char buf[1024];
         FILE *fp;
@@ -1492,8 +1518,11 @@ static int setup_obd_uuid(DIR *dir, char *dname, struct find_param *param)
         if (param->got_uuids)
                 return rc;
 
-        /* Get the lov name */
-        rc = llapi_file_fget_lov_uuid(dirfd(dir), &lov_uuid);
+        /* Get the lov/lmv name */
+        if (param->get_lmv)
+                rc = llapi_file_fget_lmv_uuid(dirfd(dir), &obd_uuid);
+        else
+                rc = llapi_file_fget_lov_uuid(dirfd(dir), &obd_uuid);
         if (rc) {
                 if (rc != -ENOTTY) {
                         llapi_error(LLAPI_MSG_ERROR, rc,
@@ -1507,8 +1536,8 @@ static int setup_obd_uuid(DIR *dir, char *dname, struct find_param *param)
         param->got_uuids = 1;
 
         /* Now get the ost uuids from /proc */
-        snprintf(buf, sizeof(buf), "/proc/fs/lustre/lov/%s/target_obd",
-                 lov_uuid.uuid);
+        snprintf(buf, sizeof(buf), "/proc/fs/lustre/%s/%s/target_obd",
+                 param->get_lmv ? "lmv" : "lov", obd_uuid.uuid);
         fp = fopen(buf, "r");
         if (fp == NULL) {
                 rc = -errno;
@@ -1517,7 +1546,8 @@ static int setup_obd_uuid(DIR *dir, char *dname, struct find_param *param)
         }
 
         if (!param->obduuid && !param->quiet && !param->obds_printed)
-                llapi_printf(LLAPI_MSG_NORMAL, "OBDS:\n");
+                llapi_printf(LLAPI_MSG_NORMAL, "%s:\n",
+                             param->get_lmv ? "MDTS" : "OBDS:");
 
         while (fgets(buf, sizeof(buf), fp) != NULL) {
                 if (sscanf(buf, "%d: %s", &index, uuid) < 2)
@@ -1550,14 +1580,17 @@ static int setup_obd_uuid(DIR *dir, char *dname, struct find_param *param)
 /* In this case, param->obduuid will be an array of obduuids and
  * obd index for all these obduuids will be returned in
  * param->obdindexes */
-static int setup_obd_indexes(DIR *dir, char *path, struct find_param *param)
+static int setup_indexes(DIR *dir, char *path, struct obd_uuid *obduuids,
+                         int num_obds, int **obdindexes, int *obdindex,
+                         enum tgt_type type)
 {
         int ret, obdcount, obd_valid = 0, obdnum, i;
         struct obd_uuid *uuids = NULL;
         char buf[16];
+        int *indexes;
 
-        ret = get_param_obdvar(NULL, path, "lov", "numobd",
-                               buf, sizeof(buf));
+        ret = get_param_obdvar(NULL, path, type == LOV_TYPE ? "lov" : "lmv",
+                               "numobd", buf, sizeof(buf));
         if (ret)
                 return ret;
 
@@ -1568,8 +1601,7 @@ static int setup_obd_indexes(DIR *dir, char *path, struct find_param *param)
                 return -ENOMEM;
 
 retry_get_uuids:
-        ret = llapi_lov_get_uuids(dirfd(dir), uuids,
-                                  &obdcount);
+        ret = llapi_get_target_uuids(dirfd(dir), uuids, &obdcount, type);
         if (ret) {
                 struct obd_uuid *uuids_temp;
 
@@ -1583,39 +1615,63 @@ retry_get_uuids:
                 }
 
                 llapi_error(LLAPI_MSG_ERROR, ret, "get ost uuid failed");
-                return ret;
+                goto out_free;
         }
 
-        param->obdindexes = malloc(param->num_obds * sizeof(param->obdindex));
-        if (param->obdindexes == NULL)
-                return -ENOMEM;
+        indexes = malloc(num_obds * sizeof(*obdindex));
+        if (indexes == NULL) {
+                ret = -ENOMEM;
+                goto out_free;
+        }
 
-        for (obdnum = 0; obdnum < param->num_obds; obdnum++) {
+        for (obdnum = 0; obdnum < num_obds; obdnum++) {
                 for (i = 0; i < obdcount; i++) {
                         if (llapi_uuid_match(uuids[i].uuid,
-                                             param->obduuid[obdnum].uuid)) {
-                                param->obdindexes[obdnum] = i;
+                                             obduuids[obdnum].uuid)) {
+                                indexes[obdnum] = i;
                                 obd_valid++;
                                 break;
                         }
                 }
                 if (i >= obdcount) {
-                        param->obdindexes[obdnum] = OBD_NOT_FOUND;
+                        indexes[obdnum] = OBD_NOT_FOUND;
                         llapi_err_noerrno(LLAPI_MSG_ERROR,
                                           "error: %s: unknown obduuid: %s",
-                                          __func__,
-                                          param->obduuid[obdnum].uuid);
+                                          __func__, obduuids[obdnum].uuid);
                         ret = -EINVAL;
                 }
         }
 
         if (obd_valid == 0)
-                param->obdindex = OBD_NOT_FOUND;
+                *obdindex = OBD_NOT_FOUND;
         else
-                param->obdindex = obd_valid;
+                *obdindex = obd_valid;
 
-        param->got_uuids = 1;
+        *obdindexes = indexes;
+out_free:
+        if (uuids)
+                free(uuids);
+
+        return ret;
+}
+
+static int setup_target_indexes(DIR *dir, char *path, struct find_param *param)
+{
+        int ret = 0;
 
+        if (param->mdtuuid) {
+                ret = setup_indexes(dir, path, param->mdtuuid, param->num_mdts,
+                              &param->mdtindexes, &param->mdtindex, LMV_TYPE);
+                if (ret)
+                        return ret;
+        }
+        if (param->obduuid) {
+                ret = setup_indexes(dir, path, param->obduuid, param->num_obds,
+                              &param->obdindexes, &param->obdindex, LOV_TYPE);
+                if (ret)
+                        return ret;
+        }
+        param->got_uuids = 1;
         return ret;
 }
 
@@ -2154,6 +2210,104 @@ static int find_time_check(lstat_t *st, struct find_param *param, int mds)
         return rc;
 }
 
+/**
+ * Check whether the stripes matches the indexes user provided
+ *       1   : matched
+ *       0   : Unmatched
+ */
+static int check_obd_match(struct find_param *param)
+{
+        lstat_t *st = &param->lmd->lmd_st;
+        struct lov_user_ost_data_v1 *lmm_objects;
+        int i, j;
+
+        if (param->obduuid && param->obdindex == OBD_NOT_FOUND)
+                return 0;
+
+        if (!S_ISREG(st->st_mode))
+                return 0;
+
+        /* Only those files should be accepted, which have a
+         * stripe on the specified OST. */
+        if (!param->lmd->lmd_lmm.lmm_stripe_count)
+                return 0;
+
+        if (param->lmd->lmd_lmm.lmm_magic ==
+            LOV_USER_MAGIC_V3) {
+                struct lov_user_md_v3 *lmmv3 = (void *)&param->lmd->lmd_lmm;
+
+                lmm_objects = lmmv3->lmm_objects;
+        } else if (param->lmd->lmd_lmm.lmm_magic ==  LOV_USER_MAGIC_V1) {
+                lmm_objects = param->lmd->lmd_lmm.lmm_objects;
+        } else {
+                llapi_err_noerrno(LLAPI_MSG_ERROR, "%s:Unknown magic: 0x%08X\n",
+                                  __func__, param->lmd->lmd_lmm.lmm_magic);
+                return -EINVAL;
+        }
+
+        for (i = 0; i < param->lmd->lmd_lmm.lmm_stripe_count; i++) {
+                for (j = 0; j < param->num_obds; j++) {
+                        if (param->obdindexes[j] ==
+                            lmm_objects[i].l_ost_idx) {
+                                if (param->exclude_obd)
+                                        return 0;
+                                return 1;
+                        }
+                }
+        }
+
+        if (param->exclude_obd)
+                return 1;
+        return 0;
+}
+
+static int check_mdt_match(struct find_param *param)
+{
+        int i;
+
+        if (param->mdtuuid && param->mdtindex == OBD_NOT_FOUND)
+                return 0;
+
+        /* FIXME: For striped dir, we should get stripe information and check */
+        for (i = 0; i < param->num_mdts; i++) {
+                if (param->mdtindexes[i] == param->file_mdtindex)
+                        if (param->exclude_mdt)
+                                return 0;
+                        return 1;
+        }
+
+        if (param->exclude_mdt)
+                return 1;
+        return 0;
+}
+
+/**
+ * Check whether the obd is active or not, if it is
+ * not active, just print the object affected by this
+ * failed target
+ **/
+static int print_failed_tgt(struct find_param *param, char *path, int type)
+{
+        struct obd_statfs stat_buf;
+        struct obd_uuid uuid_buf;
+        int ret;
+
+        LASSERT(type == LL_STATFS_LOV || type == LL_STATFS_LMV);
+
+        memset(&stat_buf, 0, sizeof(struct obd_statfs));
+        memset(&uuid_buf, 0, sizeof(struct obd_uuid));
+        ret = llapi_obd_statfs(path, type,
+                               param->obdindex, &stat_buf,
+                               &uuid_buf);
+        if (ret) {
+                llapi_printf(LLAPI_MSG_NORMAL,
+                             "obd_uuid: %s failed %s ",
+                             param->obduuid->uuid,
+                             strerror(errno));
+        }
+        return ret;
+}
+
 static int cb_find_init(char *path, DIR *parent, DIR *dir,
                         void *data, cfs_dirent_t *de)
 {
@@ -2192,21 +2346,56 @@ static int cb_find_init(char *path, DIR *parent, DIR *dir,
                 }
         }
 
-
         ret = 0;
 
         /* Request MDS for the stat info if some of these parameters need
          * to be compared. */
-        if (param->obduuid    || param->check_uid || param->check_gid ||
-            param->check_pool || param->atime     || param->ctime     ||
-            param->mtime      || param->check_size)
+        if (param->obduuid    || param->mdtuuid || param->check_uid ||
+            param->check_gid || param->check_pool || param->atime   ||
+            param->ctime     || param->mtime || param->check_size)
                 decision = 0;
+
         if (param->type && checked_type == 0)
                 decision = 0;
 
         if (param->have_fileinfo == 0 && decision == 0) {
                 ret = get_lmd_info(path, parent, dir, param->lmd,
-                                        param->lumlen);
+                                   param->lumlen);
+                if (ret == 0) {
+                        if (dir) {
+                                ret = llapi_file_fget_mdtidx(dirfd(dir),
+                                                     &param->file_mdtindex);
+                        } else {
+                                int fd;
+                                lstat_t tmp_st;
+
+                                ret = lstat_f(path, &tmp_st);
+                                if (ret) {
+                                        ret = -errno;
+                                        llapi_error(LLAPI_MSG_ERROR, ret,
+                                                    "error: %s: lstat failed"
+                                                    "for %s", __func__, path);
+                                        return ret;
+                                }
+                                if (S_ISREG(tmp_st.st_mode)) {
+                                        fd = open(path, O_RDONLY);
+                                        if (fd > 0) {
+                                                ret = llapi_file_fget_mdtidx(fd,
+                                                         &param->file_mdtindex);
+                                                close(fd);
+                                        } else {
+                                                ret = fd;
+                                        }
+                                } else {
+                                        /* For special inode, it assumes to
+                                         * reside on the same MDT with the
+                                         * parent */
+                                        fd = dirfd(parent);
+                                        ret = llapi_file_fget_mdtidx(fd,
+                                                        &param->file_mdtindex);
+                                }
+                        }
+                }
                 if (ret) {
                         if (ret == -ENOTTY)
                                 lustre_fs = 0;
@@ -2227,18 +2416,18 @@ static int cb_find_init(char *path, DIR *parent, DIR *dir,
         }
 
         /* Prepare odb. */
-        if (param->obduuid) {
+        if (param->obduuid || param->mdtuuid) {
                 if (lustre_fs && param->got_uuids &&
                     param->st_dev != st->st_dev) {
                         /* A lustre/lustre mount point is crossed. */
                         param->got_uuids = 0;
                         param->obds_printed = 0;
-                        param->obdindex = OBD_NOT_FOUND;
+                        param->obdindex = param->mdtindex = OBD_NOT_FOUND;
                 }
 
                 if (lustre_fs && !param->got_uuids) {
-                        ret = setup_obd_indexes(dir ? dir : parent, path,
-                                                param);
+                        ret = setup_target_indexes(dir ? dir : parent, path,
+                                                   param);
                         if (ret)
                                 return ret;
 
@@ -2246,59 +2435,36 @@ static int cb_find_init(char *path, DIR *parent, DIR *dir,
                 } else if (!lustre_fs && param->got_uuids) {
                         /* A lustre/non-lustre mount point is crossed. */
                         param->got_uuids = 0;
-                        param->obdindex = OBD_NOT_FOUND;
+                        param->obdindex = param->mdtindex = OBD_NOT_FOUND;
                 }
         }
 
-        /* If an OBD UUID is specified but no one matches, skip this file. */
-        if (param->obduuid && param->obdindex == OBD_NOT_FOUND)
+        if ((param->obduuid && param->obdindex == OBD_NOT_FOUND) ||
+            (param->mdtuuid && param->mdtindex == OBD_NOT_FOUND))
                 goto decided;
 
-        /* If a OST UUID is given, and some OST matches, check it here. */
-        if (param->obdindex != OBD_NOT_FOUND) {
-                if (!S_ISREG(st->st_mode))
-                        goto decided;
-
-                /* Only those files should be accepted, which have a
-                 * stripe on the specified OST. */
-                if (!param->lmd->lmd_lmm.lmm_stripe_count) {
-                        goto decided;
-                } else {
-                        int i, j;
-                        struct lov_user_ost_data_v1 *lmm_objects;
-
-                        if (param->lmd->lmd_lmm.lmm_magic ==
-                            LOV_USER_MAGIC_V3) {
-                                struct lov_user_md_v3 *lmmv3 =
-                                        (void *)&param->lmd->lmd_lmm;
-
-                                lmm_objects = lmmv3->lmm_objects;
+        /* If a OST or MDT UUID is given, and some OST matches,
+         * check it here. */
+        if (param->obdindex != OBD_NOT_FOUND ||
+            param->mdtindex != OBD_NOT_FOUND) {
+                if (param->obduuid) {
+                        if (check_obd_match(param)) {
+                                /* If no mdtuuid is given, we are done.
+                                 * Otherwise, fall through to the mdtuuid
+                                 * check below. */
+                                if (!param->mdtuuid)
+                                        goto obd_matches;
                         } else {
-                                lmm_objects = param->lmd->lmd_lmm.lmm_objects;
-                        }
-
-                        for (i = 0;
-                             i < param->lmd->lmd_lmm.lmm_stripe_count; i++) {
-                                for (j = 0; j < param->num_obds; j++) {
-                                        if (param->obdindexes[j] ==
-                                            lmm_objects[i].l_ost_idx) {
-                                                if (param->exclude_obd)
-                                                        goto decided;
-                                                break;
-                                        }
-                                }
-                                /* If an OBD matches, just break */
-                                if (j != param->num_obds)
-                                        break;
-                        }
-
-                        if (i == param->lmd->lmd_lmm.lmm_stripe_count) {
-                                if (!param->exclude_obd)
-                                        goto decided;
+                                goto decided;
                         }
                 }
+                if (param->mdtuuid) {
+                        if (check_mdt_match(param))
+                                goto obd_matches;
+                        goto decided;
+                }
         }
-
+obd_matches:
         if (param->check_uid) {
                 if (st->st_uid == param->uid) {
                         if (param->exclude_uid)
@@ -2362,30 +2528,16 @@ static int cb_find_init(char *path, DIR *parent, DIR *dir,
         while (!decision) {
                 /* For regular files with the stripe the decision may have not
                  * been taken yet if *time or size is to be checked. */
-                LASSERT(S_ISREG(st->st_mode) &&
-                        param->lmd->lmd_lmm.lmm_stripe_count);
-
-                if (param->obdindex != OBD_NOT_FOUND) {
-                        /* Check whether the obd is active or not, if it is
-                         * not active, just print the object affected by this
-                         * failed ost
-                         * */
-                        struct obd_statfs stat_buf;
-                        struct obd_uuid uuid_buf;
-
-                        memset(&stat_buf, 0, sizeof(struct obd_statfs));
-                        memset(&uuid_buf, 0, sizeof(struct obd_uuid));
-                        ret = llapi_obd_statfs(path, LL_STATFS_LOV,
-                                               param->obdindex, &stat_buf,
-                                               &uuid_buf);
-                        if (ret) {
-                                llapi_printf(LLAPI_MSG_NORMAL,
-                                             "obd_uuid: %s failed %s ",
-                                             param->obduuid->uuid,
-                                             strerror(errno));
-                                break;
-                        }
-                }
+                LASSERT((S_ISREG(st->st_mode) &&
+                        param->lmd->lmd_lmm.lmm_stripe_count) ||
+                        param->mdtindex != OBD_NOT_FOUND);
+
+                if (param->obdindex != OBD_NOT_FOUND)
+                        print_failed_tgt(param, path, LL_STATFS_LOV);
+
+                if (param->mdtindex != OBD_NOT_FOUND)
+                        print_failed_tgt(param, path, LL_STATFS_LMV);
+
                 if (dir) {
                         ret = ioctl(dirfd(dir), IOC_LOV_GETINFO,
                                     (void *)param->lmd);
@@ -2451,7 +2603,7 @@ int llapi_find(char *path, struct find_param *param)
  */
 int llapi_file_fget_mdtidx(int fd, int *mdtidx)
 {
-        if (ioctl(fd, LL_IOC_GET_MDTIDX, &mdtidx) < 0)
+        if (ioctl(fd, LL_IOC_GET_MDTIDX, mdtidx) < 0)
                 return -errno;
         return 0;
 }
@@ -2502,7 +2654,7 @@ static int cb_get_mdt_index(char *path, DIR *parent, DIR *d, void *data,
                 return ret;
         }
 
-        if (param->quiet)
+        if (param->quiet || !(param->verbose & VERBOSE_DETAIL))
                 llapi_printf(LLAPI_MSG_NORMAL, "%d\n", mdtidx);
         else
                 llapi_printf(LLAPI_MSG_NORMAL, "%s MDT index: %d\n",