Whamcloud - gitweb
LU-11607 tests: replace version/fstype in sanity-dom/quota
[fs/lustre-release.git] / lustre / utils / liblustreapi_util.c
index efd9d3c..59f7e98 100644 (file)
@@ -5,6 +5,8 @@
  *
  * (C) Copyright (c) 2015, Cray Inc, all rights reserved.
  *
+ * Copyright (c) 2016, 2017, Intel Corporation.
+ *
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the GNU Lesser General Public License
  * LGPL version 2.1 or (at your discretion) any later version.
  * Author: Frank Zago <fzago@cray.com>
  */
 
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
 #include <stdlib.h>
+#include <sys/ioctl.h>
+#include <string.h>
 #include <unistd.h>
-#include <stdbool.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <fcntl.h>
 #include <sys/syscall.h>
+#include <lustre/lustreapi.h>
+#include <linux/lustre/lustre_ver.h>   /* only until LUSTRE_VERSION_CODE is gone */
+#include "lustreapi_internal.h"
 
 /*
  * Indicate whether the liblustreapi_init() constructor below has run or not.
  *
- * This can be used by external programs to ensure if the initialization
+ * This can be used by external programs to ensure that the initialization
  * mechanism has actually worked.
  */
 bool liblustreapi_initialized;
 
-
-/*
- * Initializes the library
+/**
+ * Initialize the library once at startup.
+ *
+ * Initializes the random number generator (random()). Get
+ * data from different places in case one of them fails. This
+ * is enough to get reasonably random numbers, but is not
+ * strong enough to be used for cryptography.
  */
 static __attribute__ ((constructor)) void liblustreapi_init(void)
 {
@@ -53,10 +67,6 @@ static __attribute__ ((constructor)) void liblustreapi_init(void)
        struct timeval  tv;
        int             fd;
 
-       /* Initializes the random number generator (random()). Get
-        * data from different places in case one of them fails. This
-        * is enough to get reasonably random numbers, but is not
-        * strong enough to be used for cryptography. */
        seed = syscall(SYS_gettid);
 
        if (gettimeofday(&tv, NULL) == 0) {
@@ -77,3 +87,227 @@ static __attribute__ ((constructor)) void liblustreapi_init(void)
        srandom(seed);
        liblustreapi_initialized = true;
 }
+
+/**
+ * Return the release version for the Lustre modules, e.g. 2.6.92.
+ *
+ * The "version" file in /proc currently returns only the line:
+ * lustre: 2.8.52
+ *
+ * but in the past it also returned more lines that should be ignored:
+ * kernel: patchless_client
+ * build: v2_6_92_0-gadb3ee4-2.6.32-431.29.2.el6_lustre.g36cd22b.x86_64
+ *
+ * \param version[in,out]      buffer to store build version string
+ * \param version_size[in]     size of \a version
+ *
+ * \retval                     0 on success
+ * \retval                     -1 on failure, errno set
+ */
+int llapi_get_version_string(char *version, unsigned int version_size)
+{
+       char buffer[4096];
+       char *ptr;
+       int rc;
+
+       if (version == NULL || version_size == 0) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       rc = get_lustre_param_value(NULL, NULL, FILTER_BY_NONE, buffer,
+                                   "version", sizeof(buffer));
+       if (rc < 0) {
+               errno = -rc;
+               return -1;
+       }
+
+       ptr = strstr(buffer, "lustre:");
+       if (ptr) {
+               ptr += strlen("lustre:");
+               while (*ptr == ' ' || *ptr == '\t')
+                       ptr++;
+       } else {
+               ptr = buffer;
+       }
+       llapi_chomp_string(ptr);
+
+       if (ptr[0] == '\0') {
+               errno = ENODATA;
+               return -1;
+       }
+
+       if (snprintf(version, version_size, "%s", ptr) >= version_size) {
+               errno = EOVERFLOW;
+               return -1;
+       }
+       return 0;
+}
+
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 4, 53, 0)
+/**
+ * Return the build version of the Lustre code.
+ *
+ * The **version argument is pointless, so llapi_get_version_string() is
+ * better to use in the future, but give users a few versions to fix * it.
+ *
+ * \param buffer[in]           temporary buffer to hold version string
+ * \param buffer_size[in]      length of the \a buffer
+ * \param version[out]         pointer to the start of build version string
+ *
+ * \retval                     0 on success
+ * \retval                     -ve errno on failure
+ */
+int llapi_get_version(char *buffer, int buffer_size, char **version)
+{
+       int rc;
+#if LUSTRE_VERSION_CODE > OBD_OCD_VERSION(2, 8, 53, 0)
+       static bool printed;
+       if (!printed) {
+               fprintf(stderr,
+                       "%s deprecated, use llapi_get_version_string()\n",
+                       __func__);
+               printed = true;
+       }
+#endif
+
+       rc = llapi_get_version_string(buffer, buffer_size);
+       /* keep old return style for this legacy function */
+       if (rc == -1)
+               rc = -errno;
+       else
+               *version = buffer;
+
+       return rc;
+}
+#endif /* LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 4, 53, 0) */
+
+/*
+ * fsname must be specified
+ * if poolname is NULL, search tgtname in fsname
+ * if poolname is not NULL:
+ *  if poolname not found returns errno < 0
+ *  if tgtname is NULL, returns 1 if pool is not empty and 0 if pool empty
+ *  if tgtname is not NULL, returns 1 if target is in pool and 0 if not
+ */
+int llapi_search_tgt(const char *fsname, const char *poolname,
+                    const char *tgtname, bool is_mdt)
+{
+       char buffer[PATH_MAX];
+       size_t len = 0;
+       glob_t param;
+       FILE *fd;
+       int rc;
+
+       if (fsname && fsname[0] == '\0')
+               fsname = NULL;
+       if (!fsname) {
+               rc = -EINVAL;
+               goto out;
+       }
+
+       if (poolname && poolname[0] == '\0')
+               poolname = NULL;
+       if (tgtname) {
+               if (tgtname[0] == '\0')
+                       tgtname = NULL;
+               else
+                       len = strlen(tgtname);
+       }
+
+       /* You need one or the other to have something in it */
+       if (!poolname && !tgtname) {
+               rc = -EINVAL;
+               goto out;
+       }
+
+       if (poolname) {
+               rc = poolpath(&param, fsname, NULL);
+               if (!rc) {
+                       snprintf(buffer, sizeof(buffer) - 1, "%s/%s",
+                                param.gl_pathv[0], poolname);
+                       buffer[sizeof(buffer) - 1] = '\0';
+               }
+       } else {
+               rc = get_lustre_param_path(is_mdt ? "lmv" : "lov", fsname,
+                                          FILTER_BY_FS_NAME,
+                                          "target_obd", &param);
+               if (!rc) {
+                       strncpy(buffer, param.gl_pathv[0],
+                               sizeof(buffer) - 1);
+                       buffer[sizeof(buffer) - 1] = '\0';
+               }
+       }
+       cfs_free_param_data(&param);
+       if (rc)
+               goto out;
+
+       fd = fopen(buffer, "r");
+       if (!fd) {
+               rc = -errno;
+               goto out;
+       }
+
+       while (fgets(buffer, sizeof(buffer), fd)) {
+               if (!poolname) {
+                       char *ptr;
+                       /* Search for an tgtname in the list of all targets
+                        * Line format is IDX: fsname-OST/MDTxxxx_UUID STATUS */
+                       ptr = strchr(buffer, ' ');
+                       if (ptr && strncmp(ptr + 1, tgtname, len) == 0) {
+                               rc = 1;
+                               goto out_close;
+                       }
+               } else {
+                       /* Search for an tgtname in a pool,
+                        * (or an existing non-empty pool if no tgtname) */
+                       if (!tgtname || strncmp(buffer, tgtname, len) == 0) {
+                               rc = 1;
+                               goto out_close;
+                       }
+               }
+       }
+out_close:
+       fclose(fd);
+out:
+       if (rc < 0)
+               errno = -rc;
+       return rc;
+}
+
+int llapi_search_mdt(const char *fsname, const char *poolname,
+                    const char *mdtname)
+{
+       return llapi_search_tgt(fsname, poolname, mdtname, true);
+}
+
+int llapi_search_ost(const char *fsname, const char *poolname,
+                    const char *ostname)
+{
+       return llapi_search_tgt(fsname, poolname, ostname, false);
+}
+
+int llapi_rmfid(const char *path, struct fid_array *fa)
+{
+       char rootpath[PATH_MAX];
+       int fd, rc;
+
+retry_open:
+       fd = open(path, O_RDONLY | O_NONBLOCK | O_NOFOLLOW);
+       if (fd < 0) {
+               if (errno == ENOENT && path != rootpath) {
+                       rc = llapi_search_rootpath(rootpath, path);
+                       if (!rc) {
+                               path = rootpath;
+                               goto retry_open;
+                       }
+               } else {
+                       return -errno;
+               }
+       }
+
+       rc = ioctl(fd, LL_IOC_RMFID, fa);
+       close(fd);
+
+       return rc ? -errno : 0;
+}