Whamcloud - gitweb
b=15699
[fs/lustre-release.git] / lustre / utils / lustre_cfg.c
index b938ed8..69f734b 100644 (file)
@@ -1,35 +1,52 @@
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
- *  Copyright (C) 2002 Cluster File Systems, Inc.
- *   Author: Peter J. Braam <braam@clusterfs.com>
- *   Author: Phil Schwan <phil@clusterfs.com>
- *   Author: Andreas Dilger <adilger@clusterfs.com>
- *   Author: Robert Read <rread@clusterfs.com>
+ * GPL HEADER START
  *
- *   This file is part of Lustre, http://www.lustre.org.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- *   Lustre is free software; you can redistribute it and/or
- *   modify it under the terms of version 2 of the GNU General Public
- *   License as published by the Free Software Foundation.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
  *
- *   Lustre is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
  *
- *   You should have received a copy of the GNU General Public License
- *   along with Lustre; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
  *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright  2008 Sun Microsystems, Inc. All rights reserved
+ * Use is subject to license terms.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
+ *
+ * lustre/utils/lustre_cfg.c
+ *
+ * Author: Peter J. Braam <braam@clusterfs.com>
+ * Author: Phil Schwan <phil@clusterfs.com>
+ * Author: Andreas Dilger <adilger@clusterfs.com>
+ * Author: Robert Read <rread@clusterfs.com>
  */
-
 
 #include <stdlib.h>
 #include <sys/ioctl.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <ctype.h>
+#include <glob.h>
 
 #ifndef __KERNEL__
 #include <liblustre.h>
@@ -52,7 +69,7 @@
 
 #include "obdctl.h"
 #include <lnet/lnetctl.h>
-#include "parser.h"
+#include <libcfs/libcfsutil.h>
 #include <stdio.h>
 
 static char * lcfg_devname;
@@ -65,7 +82,7 @@ int lcfg_set_devname(char *name)
                 /* quietly strip the unnecessary '$' */
                 if (*name == '$' || *name == '%')
                         name++;
-                if (isdigit(*name)) { 
+                if (isdigit(*name)) {
                         /* We can't translate from dev # to name */
                         lcfg_devname = NULL;
                 } else {
@@ -73,7 +90,7 @@ int lcfg_set_devname(char *name)
                 }
         } else {
                 lcfg_devname = NULL;
-        } 
+        }
         return 0;
 }
 
@@ -137,8 +154,8 @@ int jt_lcfg_setup(int argc, char **argv)
 
         if (lcfg_devname == NULL) {
                 fprintf(stderr, "%s: please use 'device name' to set the "
-                        "device name for config commands.\n", 
-                        jt_cmdname(argv[0])); 
+                        "device name for config commands.\n",
+                        jt_cmdname(argv[0]));
                 return -EINVAL;
         }
 
@@ -169,8 +186,8 @@ int jt_obd_detach(int argc, char **argv)
 
         if (lcfg_devname == NULL) {
                 fprintf(stderr, "%s: please use 'device name' to set the "
-                        "device name for config commands.\n", 
-                        jt_cmdname(argv[0])); 
+                        "device name for config commands.\n",
+                        jt_cmdname(argv[0]));
                 return -EINVAL;
         }
 
@@ -201,8 +218,8 @@ int jt_obd_cleanup(int argc, char **argv)
 
         if (lcfg_devname == NULL) {
                 fprintf(stderr, "%s: please use 'device name' to set the "
-                        "device name for config commands.\n", 
-                        jt_cmdname(argv[0])); 
+                        "device name for config commands.\n",
+                        jt_cmdname(argv[0]));
                 return -EINVAL;
         }
 
@@ -239,8 +256,8 @@ int jt_obd_cleanup(int argc, char **argv)
         return rc;
 }
 
-static 
-int do_add_uuid(char * func, char *uuid, lnet_nid_t nid) 
+static
+int do_add_uuid(char * func, char *uuid, lnet_nid_t nid)
 {
         int rc;
         struct lustre_cfg_bufs bufs;
@@ -252,7 +269,7 @@ int do_add_uuid(char * func, char *uuid, lnet_nid_t nid)
 
         lcfg = lustre_cfg_new(LCFG_ADD_UUID, &bufs);
         lcfg->lcfg_nid = nid;
-        /* Poison NAL -- pre 1.4.6 will LASSERT on 0 NAL, this way it 
+        /* Poison NAL -- pre 1.4.6 will LASSERT on 0 NAL, this way it
            doesn't work without crashing (bz 10130) */
         lcfg->lcfg_nal = 0x5a;
 
@@ -275,8 +292,8 @@ int do_add_uuid(char * func, char *uuid, lnet_nid_t nid)
 int jt_lcfg_add_uuid(int argc, char **argv)
 {
         lnet_nid_t nid;
-        
-        if (argc != 3) {                
+
+        if (argc != 3) {
                 return CMD_HELP;
         }
 
@@ -308,7 +325,7 @@ int jt_lcfg_del_uuid(int argc, char **argv)
         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
         if (strcmp (argv[1], "_all_"))
                 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
-        
+
         lcfg = lustre_cfg_new(LCFG_DEL_UUID, &bufs);
         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
         lustre_cfg_free(lcfg);
@@ -365,7 +382,7 @@ int jt_lcfg_set_timeout(int argc, char **argv)
         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
         lcfg = lustre_cfg_new(LCFG_SET_TIMEOUT, &bufs);
         lcfg->lcfg_num = atoi(argv[1]);
-        
+
         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
         //rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
 
@@ -395,8 +412,8 @@ int jt_lcfg_add_conn(int argc, char **argv)
 
         if (lcfg_devname == NULL) {
                 fprintf(stderr, "%s: please use 'device name' to set the "
-                        "device name for config commands.\n", 
-                        jt_cmdname(argv[0])); 
+                        "device name for config commands.\n",
+                        jt_cmdname(argv[0]));
                 return -EINVAL;
         }
 
@@ -428,8 +445,8 @@ int jt_lcfg_del_conn(int argc, char **argv)
 
         if (lcfg_devname == NULL) {
                 fprintf(stderr, "%s: please use 'device name' to set the "
-                        "device name for config commands.\n", 
-                        jt_cmdname(argv[0])); 
+                        "device name for config commands.\n",
+                        jt_cmdname(argv[0]));
                 return -EINVAL;
         }
 
@@ -467,7 +484,7 @@ int jt_lcfg_param(int argc, char **argv)
         }
 
         lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
-        
+
         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
         lustre_cfg_free(lcfg);
         if (rc < 0) {
@@ -502,8 +519,247 @@ int jt_lcfg_mgsparam(int argc, char **argv)
                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
                         strerror(rc = errno));
         }
-        
+
         return rc;
 }
 
+/* Display the path in the same format as sysctl
+ * For eg. obdfilter.lustre-OST0000.stats */
+static char *display_name(char *filename)
+{
+        char *tmp;
 
+        filename += strlen("/proc/");
+        if (strncmp(filename, "fs/", strlen("fs/")) == 0)
+                filename += strlen("fs/");
+        else
+                filename += strlen("sys/");
+
+        if (strncmp(filename, "lustre/", strlen("lustre/")) == 0)
+                filename += strlen("lustre/");
+
+        /* replace '/' with '.' to match conf_param and sysctl */
+        tmp = filename;
+        while ((tmp = strchr(tmp, '/')) != NULL)
+                *tmp = '.';
+
+        return filename;
+}
+
+/* Find a character in a length limited string */
+/* BEWARE - kernel definition of strnchr has args in different order! */
+static char *strnchr(const char *p, char c, size_t n)
+{
+       if (!p)
+               return (0);
+
+       while (n-- > 0) {
+               if (*p == c)
+                       return ((char *)p);
+               p++;
+       }
+       return (0);
+}
+
+int jt_lcfg_getparam(int argc, char **argv)
+{
+        int fp;
+        int rc = 0, i, show_path = 0, only_path = 0;
+        char pattern[PATH_MAX];
+        char *path, *tmp, *buf;
+        glob_t glob_info;
+
+        if (argc == 3 && (strcmp(argv[1], "-n") == 0 || strcmp(argv[1], "-N") == 0)) {
+                path = argv[2];
+                if (strcmp(argv[1], "-N") == 0) {
+                        only_path = 1;
+                        show_path = 1;
+                }
+        } else if (argc == 2) {
+                show_path = 1;
+                path = argv[1];
+        } else {
+                return CMD_HELP;
+        }
+
+        /* If the input is in form Eg. obdfilter.*.stats */
+        if (strchr(path, '.')) {
+                tmp = path;
+                while (*tmp != '\0') {
+                        if (*tmp == '.')
+                                *tmp = '/';
+                        tmp ++;
+                }
+        }
+
+        /* If the entire path is specified as input */
+        fp = open(path, O_RDONLY);
+        if (fp < 0)
+                snprintf(pattern, PATH_MAX, "/proc/{fs,sys}/{lnet,lustre}/%s",
+                         path);
+        else {
+                strcpy(pattern, path);
+                close(fp);
+        }
+
+        rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
+        if (rc) {
+                fprintf(stderr, "error : glob %s: %s \n", pattern,strerror(rc));
+                return rc;
+        }
+
+        buf = malloc(CFS_PAGE_SIZE);
+        for (i = 0; i  < glob_info.gl_pathc; i++) {
+                char *valuename = NULL;
+
+                memset(buf, 0, CFS_PAGE_SIZE);
+                if (show_path) {
+                        char *filename;
+                        filename = strdup(glob_info.gl_pathv[i]);
+                        valuename = display_name(filename);
+                        if (valuename && only_path) {
+                                printf("%s\n", valuename);
+                                continue;
+                        }
+                }
+
+                /* Write the contents of file to stdout */
+                fp = open(glob_info.gl_pathv[i], O_RDONLY);
+                if (fp < 0) {
+                        fprintf(stderr, "error: %s: opening('%s') failed: %s\n",
+                                jt_cmdname(argv[0]), glob_info.gl_pathv[i],
+                                strerror(errno));
+                        continue;
+                }
+
+                do {
+                        rc = read(fp, buf, CFS_PAGE_SIZE);
+                        if (rc == 0)
+                                break;
+                        if (rc < 0) {
+                                fprintf(stderr, "error: %s: read('%s') "
+                                        "failed: %s\n", jt_cmdname(argv[0]),
+                                        glob_info.gl_pathv[i], strerror(errno));
+                                break;
+                        }
+                        /* Print the output in the format path=value if the
+                         * value contains no new line character or cab be
+                         * occupied in a line, else print value on new line */
+                        if (valuename && show_path) {
+                                int longbuf = strnchr(buf, rc - 1, '\n') != NULL
+                                              || rc > 60;
+                                printf("%s=%s", valuename, longbuf ? "\n" : buf);
+                                valuename = NULL;
+                                if (!longbuf)
+                                        continue;
+                                fflush(stdout);
+                        }
+                        rc = write(fileno(stdout), buf, rc);
+                        if (rc < 0) {
+                                fprintf(stderr, "error: %s: write to stdout "
+                                        "failed: %s\n", jt_cmdname(argv[0]),
+                                        strerror(errno));
+                                break;
+                        }
+                } while (1);
+                close(fp);
+        }
+
+        globfree(&glob_info);
+        free(buf);
+        return rc;
+}
+
+
+int jt_lcfg_setparam(int argc, char **argv)
+{
+        int rc = 0, i;
+        int fp, show_path = 0;
+        char pattern[PATH_MAX];
+        char *path, *value, *tmp;
+        glob_t glob_info;
+
+        path = argv[1];
+        if (argc == 4 && (strcmp(argv[1], "-n") == 0)) {
+                /* Format: lctl set_param -n param value */
+                path = argv[2];
+                value = argv[3];
+        } else if (argc == 3) {
+                if (strcmp(argv[1], "-n") != 0) {
+                        /* Format: lctl set_param param value */
+                        show_path = 1;
+                        value = argv[2];
+                } else if ((value = strchr(argv[2], '=')) != NULL) {
+                        /* Format: lctl set_param -n param=value */
+                        path = argv[2];
+                        *value = '\0';
+                        value ++;
+                } else {
+                        fprintf(stderr, "error: %s Incorrect arguments."
+                                        "See Usage\n",
+                                jt_cmdname(argv[0]));
+                        return CMD_HELP;
+                }
+        } else if (argc == 2 && ((value = strchr(argv[1], '=')) != NULL)) {
+                /* Format: lctl set_param param=value */
+                show_path = 1;
+                *value = '\0';
+                value++;
+        } else {
+                fprintf(stderr, "error: %s Incorrect arguments. See Usage\n",
+                        jt_cmdname(argv[0]));
+                return CMD_HELP;
+        }
+
+        /* If the input is in form Eg. obdfilter.*.stats */
+        if (strchr(path, '.')) {
+                tmp = path;
+                while (*tmp != '\0') {
+                        if (*tmp == '.')
+                                *tmp = '/';
+                        tmp ++;
+                }
+        }
+
+        fp = open(path, O_RDONLY);
+        if (fp < 0)
+                snprintf(pattern, PATH_MAX, "/proc/{fs,sys}/{lnet,lustre}/%s",
+                         path);
+        else {
+                strcpy(pattern, path);
+                close(fp);
+        }
+
+        rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
+        if (rc) {
+                fprintf(stderr, "error : glob %s: %s \n", pattern,strerror(rc));
+                return rc;
+        }
+        for (i = 0; i  < glob_info.gl_pathc; i++) {
+                if (show_path) {
+                        char *valuename, *filename;
+                        filename = strdup(glob_info.gl_pathv[i]);
+                        valuename = display_name(filename);
+                        printf("%s=%s\n", valuename, value);
+                }
+                /* Write the new value to the file */
+                fp = open(glob_info.gl_pathv[i], O_WRONLY);
+                if (fp > 0) {
+                        rc = write(fp, value, strlen(value));
+                        if (rc < 0)
+                                fprintf(stderr,
+                                        "error writing to file %s\n",
+                                        glob_info.gl_pathv[i]);
+                        else
+                                rc = 0;
+                        close(fp);
+                } else {
+                        fprintf(stderr, "error: %s: %s opening %s\n",
+                                jt_cmdname(argv[0]), strerror(rc = errno),
+                                glob_info.gl_pathv[i]);
+                }
+        }
+
+        globfree(&glob_info);
+        return rc;
+}