+/**
+ * return a parameter string for a specific device type or mountpoint
+ *
+ * \param param_path the path to the file containing parameter data
+ * \param result buffer for parameter value string
+ * \param result_size size of buffer for return value
+ *
+ * The \param param_path is appended to /proc/{fs,sys}/{lnet,lustre} to
+ * complete the absolute path to the file containing the parameter data
+ * the user is requesting. If that file exist then the data is read from
+ * the file and placed into the \param result buffer that is passed by
+ * the user. Data is only copied up to the \param result_size to prevent
+ * overflow of the array.
+ *
+ * Return 0 for success, with a NUL-terminated string in \param result.
+ * Return -ve value for error.
+ */
+static int get_param(const char *param_path, char *result,
+ unsigned int result_size)
+{
+ char file[PATH_MAX + 1], pattern[PATH_MAX + 1], buf[result_size];
+ FILE *fp = NULL;
+ int rc = 0;
+
+ snprintf(pattern, PATH_MAX, "/proc/{fs,sys}/{lnet,lustre}/%s",
+ param_path);
+ rc = first_match(pattern, file);
+ if (rc)
+ return rc;
+
+ fp = fopen(file, "r");
+ if (fp != NULL) {
+ while (fgets(buf, result_size, fp) != NULL)
+ strcpy(result, buf);
+ fclose(fp);
+ } else {
+ rc = -errno;
+ }
+ return rc;
+}
+
+#define DEVICES_LIST "/proc/fs/lustre/devices"
+
+/**
+ * return a parameter string for a specific device type or mountpoint
+ *
+ * \param fsname Lustre filesystem name (optional)
+ * \param file_path path to file in filesystem (optional, if fsname unset)
+ * \param obd_type Lustre OBD device type
+ * \param param_name parameter name to fetch
+ * \param value return buffer for parameter value string
+ * \param val_len size of buffer for return value
+ *
+ * If fsname is specified then the parameter will be from that filesystem
+ * (if it exists). If file_path is given and it is in a mounted Lustre
+ * filesystem, then the parameter will be otherwise the value may be
+ * from any mounted filesystem (if there is more than one).
+ *
+ * If "obd_type" matches a Lustre device then the first matching device
+ * (as with "lctl dl", constrained by \param fsname or \param mount_path)
+ * will be used to provide the return value, otherwise the first such
+ * device found will be used.
+ *
+ * Return 0 for success, with a NUL-terminated string in \param buffer.
+ * Return -ve value for error.
+ */
+static int get_param_obdvar(const char *fsname, const char *file_path,
+ const char *obd_type, const char *param_name,
+ char *value, unsigned int val_len)
+{
+ char devices[PATH_MAX + 1], dev[PATH_MAX + 1] = "*", fs[PATH_MAX + 1];
+ FILE *fp = fopen(DEVICES_LIST, "r");
+ int rc = 0;
+
+ if (!fsname && file_path) {
+ rc = llapi_search_fsname(file_path, fs);
+ if (rc) {
+ llapi_error(LLAPI_MSG_ERROR, rc,
+ "'%s' is not on a Lustre filesystem",
+ file_path);
+ return rc;
+ }
+ } else if (fsname) {
+ strcpy(fs, fsname);
+ }
+
+ if (fp == NULL) {
+ rc = -errno;
+ llapi_error(LLAPI_MSG_ERROR, rc, "error: opening "DEVICES_LIST);
+ return rc;
+ }
+
+ while (fgets(devices, sizeof(devices), fp) != NULL) {
+ char *bufp = devices, *tmp;
+
+ while (bufp[0] == ' ')
+ ++bufp;
+
+ tmp = strstr(bufp, obd_type);
+ if (tmp) {
+ tmp += strlen(obd_type) + 1;
+ if (strcmp(tmp, fs))
+ continue;
+ strcpy(dev, tmp);
+ tmp = strchr(dev, ' ');
+ *tmp = '\0';
+ break;
+ }
+ }
+
+ if (dev[0] == '*' && strlen(fs))
+ snprintf(dev, PATH_MAX, "%s-*", fs);
+ snprintf(devices, PATH_MAX, "%s/%s/%s", obd_type, dev, param_name);
+ fclose(fp);
+ return get_param(devices, value, val_len);
+}
+
+static int get_mds_md_size(char *path)
+{
+ int lumlen = lov_mds_md_size(LOV_MAX_STRIPE_COUNT, LOV_MAGIC_V3);
+ char buf[16];
+
+ /* Now get the maxea from llite proc */
+ if (!get_param_obdvar(NULL, path, "llite", "max_easize",
+ buf, sizeof(buf)))
+ lumlen = atoi(buf);
+ return lumlen;
+}
+