+ "error: %s: string buffer is too small",
+ __func__);
+ break;
+ }
+ strcat(path, "/");
+ strcat(path, dent->d_name);
+
+ if (dent->d_type == DT_UNKNOWN) {
+ lstat_t *st = &((struct find_param *)data)->lmd->lmd_st;
+
+ ret = llapi_mds_getfileinfo(path, d,
+ ((struct find_param *)data)->lmd);
+ if (ret == 0) {
+ ((struct find_param *)data)->have_fileinfo = 1;
+ dent->d_type =
+ llapi_filetype_dir_table[st->st_mode &
+ S_IFMT];
+ }
+ if (ret == -ENOENT)
+ continue;
+ }
+
+ switch (dent->d_type) {
+ case DT_UNKNOWN:
+ llapi_err(LLAPI_MSG_ERROR,
+ "error: %s: '%s' is UNKNOWN type %d",
+ __func__, dent->d_name, dent->d_type);
+ break;
+ case DT_DIR:
+ ret = llapi_semantic_traverse(path, size, d, sem_init,
+ sem_fini, data, dent);
+ if (ret < 0)
+ goto out;
+ break;
+ default:
+ ret = 0;
+ if (sem_init) {
+ ret = sem_init(path, d, NULL, data, dent);
+ if (ret < 0)
+ goto out;
+ }
+ if (sem_fini && ret == 0)
+ sem_fini(path, d, NULL, data, dent);
+ }
+ }
+
+out:
+ path[len] = 0;
+
+ if (sem_fini)
+ sem_fini(path, parent, d, data, de);
+err:
+ if (d)
+ closedir(d);
+ if (p)
+ closedir(p);
+ return ret;
+}
+
+static int param_callback(char *path, semantic_func_t sem_init,
+ semantic_func_t sem_fini, struct find_param *param)
+{
+ int ret, len = strlen(path);
+ char *buf;
+
+ if (len > PATH_MAX) {
+ llapi_err(LLAPI_MSG_ERROR, "Path name '%s' is too long", path);
+ return -EINVAL;
+ }
+
+ buf = (char *)malloc(PATH_MAX + 1);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = common_param_init(param);
+ if (ret)
+ goto out;
+ param->depth = 0;
+
+ strncpy(buf, path, PATH_MAX + 1);
+ ret = llapi_semantic_traverse(buf, PATH_MAX + 1, NULL, sem_init,
+ sem_fini, param, NULL);
+out:
+ find_param_fini(param);
+ free(buf);
+ return ret < 0 ? ret : 0;
+}
+
+int llapi_file_fget_lov_uuid(int fd, struct obd_uuid *lov_name)
+{
+ int rc = ioctl(fd, OBD_IOC_GETNAME, lov_name);
+ if (rc) {
+ rc = errno;
+ llapi_err(LLAPI_MSG_ERROR, "error: can't get lov name.");
+ }
+ return rc;
+}
+
+int llapi_file_get_lov_uuid(const char *path, struct obd_uuid *lov_uuid)
+{
+ int fd, rc;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ rc = errno;
+ llapi_err(LLAPI_MSG_ERROR, "error opening %s", path);
+ return rc;
+ }
+
+ rc = llapi_file_fget_lov_uuid(fd, lov_uuid);
+
+ close(fd);
+
+ return rc;
+}
+
+/*
+ * 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)
+{
+ struct obd_uuid lov_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;
+
+ /* Now get the ost uuids from /proc */
+ snprintf(buf, sizeof(buf), "/proc/fs/lustre/lov/%s/target_obd",
+ lov_name.uuid);
+ fp = fopen(buf, "r");
+ if (fp == NULL) {
+ rc = errno;
+ llapi_err(LLAPI_MSG_ERROR, "error: opening '%s'", buf);
+ return rc;
+ }
+
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ if (uuidp && (index < *ost_count)) {
+ if (sscanf(buf, "%d: %s", &index, uuidp[index].uuid) <2)
+ break;
+ }
+ index++;
+ }
+
+ fclose(fp);
+
+ if (uuidp && (index >= *ost_count))
+ return -EOVERFLOW;
+
+ *ost_count = index;
+ return rc;
+}
+
+int llapi_get_obd_count(char *mnt, int *count, int is_mdt)
+{
+ DIR *root;
+ int rc;
+
+ root = opendir(mnt);
+ if (!root) {
+ llapi_err(LLAPI_MSG_ERROR, "open %s failed", mnt);
+ return -1;
+ }
+
+ *count = is_mdt;
+ rc = ioctl(dirfd(root), LL_IOC_GETOBDCOUNT, count);
+
+ closedir(root);
+ 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);
+ int searchlen = strlen(search_uuid);
+
+ if (cmplen > 5 && strcmp(real_uuid + cmplen - 5, "_UUID") == 0)
+ cmplen -= 5;
+ if (searchlen > 5 && strcmp(search_uuid + searchlen - 5, "_UUID") == 0)
+ searchlen -= 5;
+
+ /* The UUIDs may legitimately be different lengths, if
+ * the system was upgraded from an older version. */
+ if (cmplen != searchlen)
+ 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)
+{
+ struct obd_uuid lov_uuid;
+ char uuid[sizeof(struct obd_uuid)];
+ char buf[1024];
+ FILE *fp;
+ int rc = 0, index;
+
+ if (param->got_uuids)
+ return rc;
+
+ /* Get the lov name */
+ rc = llapi_file_fget_lov_uuid(dirfd(dir), &lov_uuid);
+ if (rc) {
+ if (errno != ENOTTY) {
+ rc = errno;
+ llapi_err(LLAPI_MSG_ERROR,
+ "error: can't get lov name: %s", dname);