X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Futils%2Flustre_cfg.c;h=1c9ed42c09d9b38816369b501d1b80b119454603;hp=dfd2ddb8892ce6721669a76e6d4cf19a676b0b34;hb=b50f73018c25d039bf9952728c35985be9a4c1d4;hpb=0ae1c575448dbb0700bc45a88f964645c37a774c diff --git a/lustre/utils/lustre_cfg.c b/lustre/utils/lustre_cfg.c index dfd2ddb..1c9ed42 100644 --- a/lustre/utils/lustre_cfg.c +++ b/lustre/utils/lustre_cfg.c @@ -1,44 +1,64 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: +/* + * GPL HEADER START * - * Copyright (C) 2002 Cluster File Systems, Inc. - * Author: Peter J. Braam - * Author: Phil Schwan - * Author: Andreas Dilger - * Author: Robert Read + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * This file is part of Lustre, http://www.lustre.org. + * 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 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 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). * - * 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. + * 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 * - * 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. + * 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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Use is subject to license terms. + * + * Copyright (c) 2011, 2012, Intel Corporation. + */ +/* + * 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 + * Author: Phil Schwan + * Author: Andreas Dilger + * Author: Robert Read */ - #include #include +#include #include #include +#include +#include #ifndef __KERNEL__ #include #endif -#include -#include -#include -#include -#include /* for struct lov_stripe_md */ -#include +#include +#include +#include +#include +#include /* for struct lov_stripe_md */ +#include +#include #include #include @@ -49,46 +69,53 @@ #include "obdctl.h" -#include -#include "parser.h" +#include +#include #include -static char *lcfg_devname; +static char * lcfg_devname; -void lcfg_set_devname(char *name) +int lcfg_set_devname(char *name) { - if (lcfg_devname) - free(lcfg_devname); - lcfg_devname = strdup(name); -} + char *ptr; + int digit = 1; + + if (name) { + if (lcfg_devname) + free(lcfg_devname); + /* quietly strip the unnecessary '$' */ + if (*name == '$' || *name == '%') + name++; + + ptr = name; + while (*ptr != '\0') { + if (!isdigit(*ptr)) { + digit = 0; + break; + } + ptr++; + } + if (digit) { + /* We can't translate from dev # to name */ + lcfg_devname = NULL; + } else { + lcfg_devname = strdup(name); + } + } else { + lcfg_devname = NULL; + } + return 0; +} -int jt_lcfg_device(int argc, char **argv) +char * lcfg_get_devname(void) { - char *name; - - if (argc == 1) { - printf("current device is %s\n", lcfg_devname? : "not set"); - return 0; - } else if (argc != 2) { - return CMD_HELP; - } - - name = argv[1]; - - /* quietly strip the unnecessary '$' */ - if (*name == '$') - name++; - - lcfg_set_devname(name); - - return 0; + return lcfg_devname; } -/* NOOP */ -int jt_lcfg_newdev(int argc, char **argv) +int jt_lcfg_device(int argc, char **argv) { - return 0; + return jt_obd_device(argc, argv); } int jt_lcfg_attach(int argc, char **argv) @@ -97,45 +124,24 @@ int jt_lcfg_attach(int argc, char **argv) struct lustre_cfg *lcfg; int rc; - lustre_cfg_bufs_reset(&bufs, lcfg_devname); - - if (argc != 2 && argc != 3 && argc != 4) + if (argc != 4) return CMD_HELP; + lustre_cfg_bufs_reset(&bufs, NULL); + lustre_cfg_bufs_set_string(&bufs, 1, argv[1]); - if (argc >= 3) { - lustre_cfg_bufs_set_string(&bufs, 0, argv[2]); - } else { - fprintf(stderr, "error: %s: LCFG_ATTACH requires a name\n", - jt_cmdname(argv[0])); - return -EINVAL; - } + lustre_cfg_bufs_set_string(&bufs, 0, argv[2]); + lustre_cfg_bufs_set_string(&bufs, 2, argv[3]); - if (argc == 4) { - lustre_cfg_bufs_set_string(&bufs, 2, argv[3]); - } lcfg = lustre_cfg_new(LCFG_ATTACH, &bufs); rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg); lustre_cfg_free(lcfg); if (rc < 0) { fprintf(stderr, "error: %s: LCFG_ATTACH %s\n", jt_cmdname(argv[0]), strerror(rc = errno)); - } else if (argc == 3) { - char name[1024]; - - lcfg_set_devname(argv[2]); - if (strlen(argv[2]) > 128) { - printf("Name too long to set environment\n"); - return -EINVAL; - } - snprintf(name, 512, "LUSTRE_DEV_%s", argv[2]); - rc = setenv(name, argv[1], 1); - if (rc) { - printf("error setting env variable %s\n", name); - } } else { - lcfg_set_devname(argv[2]); - } + lcfg_set_devname(argv[2]); + } return rc; } @@ -144,18 +150,19 @@ int jt_lcfg_setup(int argc, char **argv) { struct lustre_cfg_bufs bufs; struct lustre_cfg *lcfg; - int rc, i; + int i; + int rc; if (lcfg_devname == NULL) { - fprintf(stderr, "%s: please use 'cfg_device name' to set the " + fprintf(stderr, "%s: please use 'device name' to set the " "device name for config commands.\n", jt_cmdname(argv[0])); - return -EINVAL; + return -EINVAL; } lustre_cfg_bufs_reset(&bufs, lcfg_devname); - - if (argc > 7) + + if (argc > 6) return CMD_HELP; for (i = 1; i < argc; i++) { @@ -179,11 +186,12 @@ int jt_obd_detach(int argc, char **argv) int rc; if (lcfg_devname == NULL) { - fprintf(stderr, "%s: please use 'cfg_device name' to set the " + fprintf(stderr, "%s: please use 'device name' to set the " "device name for config commands.\n", jt_cmdname(argv[0])); - return -EINVAL; + return -EINVAL; } + lustre_cfg_bufs_reset(&bufs, lcfg_devname); if (argc != 1) @@ -192,10 +200,10 @@ int jt_obd_detach(int argc, char **argv) lcfg = lustre_cfg_new(LCFG_DETACH, &bufs); rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg); lustre_cfg_free(lcfg); - if (rc < 0) fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), strerror(rc = errno)); + return rc; } @@ -205,14 +213,12 @@ int jt_obd_cleanup(int argc, char **argv) struct lustre_cfg *lcfg; char force = 'F'; char failover = 'A'; - char flags[3]; + char flags[3] = { 0 }; int flag_cnt = 0, n; int rc; - - if (lcfg_devname == NULL) { - fprintf(stderr, "%s: please use 'cfg_device name' to set the " + fprintf(stderr, "%s: please use 'device name' to set the " "device name for config commands.\n", jt_cmdname(argv[0])); return -EINVAL; @@ -252,9 +258,8 @@ int jt_obd_cleanup(int argc, char **argv) } static -int do_add_uuid(char * func, char *uuid, ptl_nid_t nid, int nal) +int do_add_uuid(char * func, char *uuid, lnet_nid_t nid) { - char tmp[64]; int rc; struct lustre_cfg_bufs bufs; struct lustre_cfg *lcfg; @@ -265,8 +270,14 @@ int do_add_uuid(char * func, char *uuid, ptl_nid_t nid, int nal) lcfg = lustre_cfg_new(LCFG_ADD_UUID, &bufs); lcfg->lcfg_nid = nid; - lcfg->lcfg_nal = nal; + /* 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; +#if 0 + fprintf(stderr, "adding\tnid: %d\tuuid: %s\n", + lcfg->lcfg_nid, uuid); +#endif rc = lcfg_ioctl(func, OBD_DEV_ID, lcfg); lustre_cfg_free(lcfg); if (rc) { @@ -275,38 +286,30 @@ int do_add_uuid(char * func, char *uuid, ptl_nid_t nid, int nal) return -1; } - printf ("Added uuid %s: %s\n", uuid, ptl_nid2str (tmp, nid)); + printf ("Added uuid %s: %s\n", uuid, libcfs_nid2str(nid)); return 0; - } int jt_lcfg_add_uuid(int argc, char **argv) { - ptl_nid_t nid = 0; - int nal; + lnet_nid_t nid; - if (argc != 4) { + if (argc != 3) { return CMD_HELP; } - if (ptl_parse_nid (&nid, argv[2]) != 0) { + nid = libcfs_str2nid(argv[2]); + if (nid == LNET_NID_ANY) { fprintf (stderr, "Can't parse NID %s\n", argv[2]); - return (-1); + return (-1); } - nal = ptl_name2nal(argv[3]); - - if (nal <= 0) { - fprintf (stderr, "Can't parse NAL %s\n", argv[3]); - return -1; - } - - return do_add_uuid(argv[0], argv[1], nid, nal); + return do_add_uuid(argv[0], argv[1], nid); } -int obd_add_uuid(char *uuid, ptl_nid_t nid, int nal) +int obd_add_uuid(char *uuid, lnet_nid_t nid) { - return do_add_uuid("obd_add_uuid", uuid, nid, nal); + return do_add_uuid("obd_add_uuid", uuid, nid); } int jt_lcfg_del_uuid(int argc, char **argv) @@ -335,275 +338,148 @@ int jt_lcfg_del_uuid(int argc, char **argv) return 0; } -int jt_lcfg_lov_setup(int argc, char **argv) +int jt_lcfg_del_mount_option(int argc, char **argv) { - struct lustre_cfg_bufs bufs; - struct lustre_cfg *lcfg; - struct lov_desc desc; int rc; - char *end; - - /* argv: lov_setup - * [ ] - */ - if (argc <= 6) - return CMD_HELP; - - if (strlen(argv[1]) > sizeof(desc.ld_uuid) - 1) { - fprintf(stderr, - "error: %s: LOV uuid '%s' longer than "LPSZ" chars\n", - jt_cmdname(argv[0]), argv[1], sizeof(desc.ld_uuid) - 1); - return -EINVAL; - } - - memset(&desc, 0, sizeof(desc)); - obd_str2uuid(&desc.ld_uuid, argv[1]); - desc.ld_default_stripe_count = strtoul(argv[2], &end, 0); - if (*end) { - fprintf(stderr, "error: %s: bad default stripe count '%s'\n", - jt_cmdname(argv[0]), argv[2]); - return CMD_HELP; - } - - desc.ld_default_stripe_size = strtoull(argv[3], &end, 0); - if (*end) { - fprintf(stderr, "error: %s: bad default stripe size '%s'\n", - jt_cmdname(argv[0]), argv[3]); - return CMD_HELP; - } - if (desc.ld_default_stripe_size < 4096) { - fprintf(stderr, - "error: %s: default stripe size "LPU64" too small\n", - jt_cmdname(argv[0]), desc.ld_default_stripe_size); - return -EINVAL; - } else if ((long)desc.ld_default_stripe_size < - desc.ld_default_stripe_size) { - fprintf(stderr, - "error: %s: default stripe size "LPU64" too large\n", - jt_cmdname(argv[0]), desc.ld_default_stripe_size); - return -EINVAL; - } - desc.ld_default_stripe_offset = strtoull(argv[4], &end, 0); - if (*end) { - fprintf(stderr, "error: %s: bad default stripe offset '%s'\n", - jt_cmdname(argv[0]), argv[4]); - return CMD_HELP; - } - desc.ld_pattern = strtoul(argv[5], &end, 0); - if (*end) { - fprintf(stderr, "error: %s: bad stripe pattern '%s'\n", - jt_cmdname(argv[0]), argv[5]); - return CMD_HELP; - } - - if (argc > 7) { - desc.ld_tgt_count = argc - 6; - if (desc.ld_default_stripe_count > desc.ld_tgt_count) { - fprintf(stderr, - "error: %s: default stripe count %u > " - "OST count %u\n", jt_cmdname(argv[0]), - desc.ld_default_stripe_count, - desc.ld_tgt_count); - return -EINVAL; - } - } - - lustre_cfg_bufs_reset(&bufs, lcfg_devname); - lustre_cfg_bufs_set(&bufs, 1, &desc, sizeof(desc)); - - lcfg = lustre_cfg_new(LCFG_SETUP, &bufs); - rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg); - lustre_cfg_free(lcfg); - if (rc) - fprintf(stderr, "error: %s: ioctl error: %s\n", - jt_cmdname(argv[0]), strerror(rc = errno)); - return rc; -} - -int jt_lcfg_lmv_setup(int argc, char **argv) -{ struct lustre_cfg_bufs bufs; struct lustre_cfg *lcfg; - struct lmv_desc desc; - struct obd_uuid *uuidarray, *ptr; - int rc, i; - lustre_cfg_bufs_reset(&bufs, lcfg_devname); - if (argc <= 2) + if (argc != 2) return CMD_HELP; - if (strlen(argv[1]) > sizeof(desc.ld_uuid) - 1) { - fprintf(stderr, - "error: %s: LMV uuid '%s' longer than "LPSZ" chars\n", - jt_cmdname(argv[0]), argv[1], sizeof(desc.ld_uuid) - 1); - return -EINVAL; - } - - memset(&desc, 0, sizeof(desc)); - obd_str2uuid(&desc.ld_uuid, argv[1]); - desc.ld_tgt_count = argc - 2; - printf("LMV: %d uuids:\n", desc.ld_tgt_count); + lustre_cfg_bufs_reset(&bufs, lcfg_devname); - /* NOTE: it is possible to overwrite the default striping parameters, - * but EXTREME care must be taken when saving the OST UUID list. - * It must be EXACTLY the same, or have only additions at the - * end of the list, or only overwrite individual OST entries - * that are restored from backups of the previous OST. - */ - uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray)); - if (!uuidarray) { - fprintf(stderr, "error: %s: no memory for %d UUIDs\n", - jt_cmdname(argv[0]), desc.ld_tgt_count); - rc = -ENOMEM; - goto out; - } - for (i = 2, ptr = uuidarray; i < argc; i++, ptr++) { - if (strlen(argv[i]) >= sizeof(*ptr)) { - fprintf(stderr, "error: %s: arg %d (%s) too long\n", - jt_cmdname(argv[0]), i, argv[i]); - rc = -EINVAL; - goto out; - } - printf(" %s\n", argv[i]); - strcpy((char *)ptr, argv[i]); - } + /* profile name */ + lustre_cfg_bufs_set_string(&bufs, 1, argv[1]); - lustre_cfg_bufs_set(&bufs, 1, &desc, sizeof(desc)); - lustre_cfg_bufs_set(&bufs, 2, (char*)uuidarray, - desc.ld_tgt_count * sizeof(*uuidarray)); - lcfg = lustre_cfg_new(LCFG_SETUP, &bufs); + lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs); rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg); lustre_cfg_free(lcfg); - - if (rc) - fprintf(stderr, "error: %s: ioctl error: %s\n", - jt_cmdname(argv[0]), strerror(rc = errno)); -out: - free(uuidarray); + if (rc < 0) { + fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), + strerror(rc = errno)); + } return rc; } -int jt_lcfg_lov_modify_tgts(int argc, char **argv) + +int jt_lcfg_set_timeout(int argc, char **argv) { + int rc; struct lustre_cfg_bufs bufs; struct lustre_cfg *lcfg; - char *end; - int cmd = 0; - int index; - int gen; - int rc; - /* argv: lov_modify_tgts */ - if (argc != 6) - return CMD_HELP; + fprintf(stderr, "%s has been deprecated. Use conf_param instead.\n" + "e.g. conf_param lustre-MDT0000 obd_timeout=50\n", + jt_cmdname(argv[0])); + return CMD_HELP; - if (!strncmp(argv[1], "add", 4)) { - cmd = LCFG_LOV_ADD_OBD; - } else if (!strncmp(argv[1], "del", 4)) { - cmd = LCFG_LOV_DEL_OBD; - } else { - fprintf(stderr, "error: %s: bad operation '%s'\n", - jt_cmdname(argv[0]), argv[1]); - return CMD_HELP; - } - - lustre_cfg_bufs_reset(&bufs, argv[2]); - - if (((index = strlen(argv[3]) + 1)) > sizeof(struct obd_uuid)) { - fprintf(stderr, - "error: %s: OBD uuid '%s' longer than "LPSZ" chars\n", - jt_cmdname(argv[0]), argv[3], - sizeof(struct obd_uuid) - 1); - return -EINVAL; - } - lustre_cfg_bufs_set(&bufs, 1, argv[3], index); - - index = strtoul(argv[4], &end, 0); - if (*end) { - fprintf(stderr, "error: %s: bad OBD index '%s'\n", - jt_cmdname(argv[0]), argv[4]); + if (argc != 2) return CMD_HELP; - } - lustre_cfg_bufs_set(&bufs, 2, argv[4], strlen(argv[4])); - gen = strtoul(argv[5], &end, 0); - if (*end) { - fprintf(stderr, "error: %s: bad OBD generation '%s'\n", - jt_cmdname(argv[0]), argv[5]); - return CMD_HELP; - } - lustre_cfg_bufs_set(&bufs, 3, argv[5], strlen(argv[5])); + lustre_cfg_bufs_reset(&bufs, lcfg_devname); + lcfg = lustre_cfg_new(LCFG_SET_TIMEOUT, &bufs); + lcfg->lcfg_num = atoi(argv[1]); - lcfg = lustre_cfg_new(cmd, &bufs); rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg); + //rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg); + lustre_cfg_free(lcfg); - if (rc) - fprintf(stderr, "error: %s: ioctl error: %s\n", - jt_cmdname(argv[0]), strerror(rc = errno)); + if (rc < 0) { + fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), + strerror(rc = errno)); + } return rc; } -int jt_lcfg_mount_option(int argc, char **argv) +int jt_lcfg_add_conn(int argc, char **argv) { - int rc; struct lustre_cfg_bufs bufs; struct lustre_cfg *lcfg; - int i; + int priority; + int rc; - if (argc < 3 || argc > 5) + if (argc == 2) + priority = 0; + else if (argc == 3) + priority = 1; + else return CMD_HELP; + if (lcfg_devname == NULL) { + fprintf(stderr, "%s: please use 'device name' to set the " + "device name for config commands.\n", + jt_cmdname(argv[0])); + return -EINVAL; + } + lustre_cfg_bufs_reset(&bufs, lcfg_devname); - for (i = 1; i < argc; i++) - lustre_cfg_bufs_set_string(&bufs, i, argv[i]); + lustre_cfg_bufs_set_string(&bufs, 1, argv[1]); + + lcfg = lustre_cfg_new(LCFG_ADD_CONN, &bufs); + lcfg->lcfg_num = priority; - lcfg = lustre_cfg_new(LCFG_MOUNTOPT, &bufs); rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg); - lustre_cfg_free(lcfg); + lustre_cfg_free (lcfg); if (rc < 0) { fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), strerror(rc = errno)); } + return rc; } -int jt_lcfg_del_mount_option(int argc, char **argv) +int jt_lcfg_del_conn(int argc, char **argv) { - int rc; struct lustre_cfg_bufs bufs; struct lustre_cfg *lcfg; + int rc; if (argc != 2) return CMD_HELP; + if (lcfg_devname == NULL) { + fprintf(stderr, "%s: please use 'device name' to set the " + "device name for config commands.\n", + jt_cmdname(argv[0])); + return -EINVAL; + } + lustre_cfg_bufs_reset(&bufs, lcfg_devname); - /* profile name */ + /* connection uuid */ lustre_cfg_bufs_set_string(&bufs, 1, argv[1]); lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs); + rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg); lustre_cfg_free(lcfg); if (rc < 0) { fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), strerror(rc = errno)); } + return rc; } -int jt_lcfg_set_timeout(int argc, char **argv) +/* Param set locally, directly on target */ +int jt_lcfg_param(int argc, char **argv) { - int rc; + int i, rc; struct lustre_cfg_bufs bufs; struct lustre_cfg *lcfg; - if (argc != 2) + if (argc >= LUSTRE_CFG_MAX_BUFCOUNT) return CMD_HELP; - lustre_cfg_bufs_reset(&bufs, lcfg_devname); - lcfg = lustre_cfg_new(LCFG_SET_TIMEOUT, &bufs); - lcfg->lcfg_num = atoi(argv[1]); + lustre_cfg_bufs_reset(&bufs, NULL); + + for (i = 1; i < argc; i++) { + lustre_cfg_bufs_set_string(&bufs, i, argv[i]); + } + + lcfg = lustre_cfg_new(LCFG_PARAM, &bufs); rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg); lustre_cfg_free(lcfg); @@ -614,148 +490,616 @@ int jt_lcfg_set_timeout(int argc, char **argv) return rc; } +struct param_opts { + unsigned int po_only_path:1; + unsigned int po_show_path:1; + unsigned int po_show_type:1; + unsigned int po_recursive:1; + unsigned int po_params2:1; + unsigned int po_delete:1; +}; + +/* Param set to single log file, used by all clients and servers. + * This should be loaded after the individual config logs. + * Called from set param with -P option. + */ +static int jt_lcfg_mgsparam2(int argc, char **argv, struct param_opts *popt) +{ + int rc, i; + int first_param; + struct lustre_cfg_bufs bufs; + struct lustre_cfg *lcfg; + char *buf = NULL; + int len; + + first_param = optind; + if (first_param < 0 || first_param >= argc) + return CMD_HELP; + + for (i = first_param, rc = 0; i < argc; i++) { + lustre_cfg_bufs_reset(&bufs, NULL); + /* This same command would be executed on all nodes, many + * of which should fail (silently) because they don't have + * that proc file existing locally. There would be no + * preprocessing on the MGS to try to figure out which + * parameter files to add this to, there would be nodes + * processing on the cluster nodes to try to figure out + * if they are the intended targets. They will blindly + * try to set the parameter, and ENOTFOUND means it wasn't + * for them. + * Target name "general" means call on all targets. It is + * left here in case some filtering will be added in + * future. + */ + lustre_cfg_bufs_set_string(&bufs, 0, "general"); + + len = strlen(argv[i]); + + /* put an '=' on the end in case it doesn't have one */ + if (popt->po_delete && argv[i][len - 1] != '=') { + buf = malloc(len + 1); + sprintf(buf, "%s=", argv[i]); + } else { + buf = argv[i]; + } + lustre_cfg_bufs_set_string(&bufs, 1, buf); + + lcfg = lustre_cfg_new(LCFG_SET_PARAM, &bufs); + if (IS_ERR(lcfg)) { + fprintf(stderr, "error: allocating lcfg for %s: %s\n", + jt_cmdname(argv[0]), strerror(PTR_ERR(lcfg))); + if (rc == 0) + rc = PTR_ERR(lcfg); + } else { + int rc2 = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg); + if (rc2 != 0) { + fprintf(stderr, "error: executing %s: %s\n", + jt_cmdname(argv[0]), strerror(rc2)); + if (rc == 0) + rc = rc2; + } + lustre_cfg_free(lcfg); + } + if (buf != argv[i]) + free(buf); + } -int jt_lcfg_set_lustre_upcall(int argc, char **argv) + return rc; +} + +/* Param set in config log on MGS */ +/* conf_param key=value */ +/* Note we can actually send mgc conf_params from clients, but currently + * that's only done for default file striping (see ll_send_mgc_param), + * and not here. */ +/* After removal of a parameter (-d) Lustre will use the default + * AT NEXT REBOOT, not immediately. */ +int jt_lcfg_mgsparam(int argc, char **argv) { int rc; + int del = 0; struct lustre_cfg_bufs bufs; struct lustre_cfg *lcfg; + char *buf = NULL; - if (argc != 2) +#if LUSTRE_VERSION >= OBD_OCD_VERSION(2,7,53,0) + fprintf(stderr, "warning: 'lctl conf_param' is deprecated, " + "use 'lctl set_param -P' instead\n"); +#endif + + /* mgs_setparam processes only lctl buf #1 */ + if ((argc > 3) || (argc <= 1)) return CMD_HELP; - lustre_cfg_bufs_reset(&bufs, lcfg_devname); + while ((rc = getopt(argc, argv, "d")) != -1) { + switch (rc) { + case 'd': + del = 1; + break; + default: + return CMD_HELP; + } + } - /* profile name */ - lustre_cfg_bufs_set_string(&bufs, 1, argv[1]); + lustre_cfg_bufs_reset(&bufs, NULL); + if (del) { + char *ptr; + + /* for delete, make it "=\0" */ + buf = malloc(strlen(argv[optind]) + 2); + /* put an '=' on the end in case it doesn't have one */ + sprintf(buf, "%s=", argv[optind]); + /* then truncate after the first '=' */ + ptr = strchr(buf, '='); + *(++ptr) = '\0'; + lustre_cfg_bufs_set_string(&bufs, 1, buf); + } else { + lustre_cfg_bufs_set_string(&bufs, 1, argv[optind]); + } - lcfg = lustre_cfg_new(LCFG_SET_UPCALL, &bufs); - rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg); + /* We could put other opcodes here. */ + lcfg = lustre_cfg_new(LCFG_PARAM, &bufs); + + rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg); lustre_cfg_free(lcfg); + if (buf) + free(buf); if (rc < 0) { fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), strerror(rc = errno)); } + return rc; } -int jt_lcfg_add_conn(int argc, char **argv) +/* Display the path in the same format as sysctl + * For eg. obdfilter.lustre-OST0000.stats */ +static char *display_name(char *filename, unsigned int po_show_type) { - struct lustre_cfg_bufs bufs; - struct lustre_cfg *lcfg; - int priority; - int rc; + char *tmp; + struct stat st; - if (argc == 2) - priority = 0; - else if (argc == 3) - priority = 1; - else - return CMD_HELP; + if (po_show_type) { + if (lstat(filename, &st) < 0) + return NULL; + } - if (lcfg_devname == NULL) { - fprintf(stderr, "%s: please use 'cfg_device name' to set the " - "device name for config commands.\n", - jt_cmdname(argv[0])); - return -EINVAL; + 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/"); + else if (strncmp(filename, "lnet/", strlen("lnet/")) == 0) + filename += strlen("lnet/"); + + /* replace '/' with '.' to match conf_param and sysctl */ + tmp = filename; + while ((tmp = strchr(tmp, '/')) != NULL) + *tmp = '.'; + + /* append the indicator to entries */ + if (po_show_type) { + if (S_ISDIR(st.st_mode)) + strcat(filename, "/"); + else if (S_ISLNK(st.st_mode)) + strcat(filename, "@"); + else if (st.st_mode & S_IWUSR) + strcat(filename, "="); } - lustre_cfg_bufs_reset(&bufs, lcfg_devname); + return filename; +} - lustre_cfg_bufs_set_string(&bufs, 1, argv[1]); +/* 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); +} - lcfg = lustre_cfg_new(LCFG_ADD_CONN, &bufs); - lcfg->lcfg_num = priority; +static char *globerrstr(int glob_rc) +{ + switch(glob_rc) { + case GLOB_NOSPACE: + return "Out of memory"; + case GLOB_ABORTED: + return "Read error"; + case GLOB_NOMATCH: + return "Found no match"; + } + return "Unknown error"; +} - rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg); - lustre_cfg_free (lcfg); - if (rc < 0) { - fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), - strerror(rc = errno)); +static void clean_path(char *path) +{ + char *tmp; + + /* If the input is in form Eg. obdfilter.*.stats */ + if (strchr(path, '.')) { + tmp = path; + while (*tmp != '\0') { + if ((*tmp == '.') && + (tmp != path) && (*(tmp - 1) != '\\')) + *tmp = '/'; + tmp ++; + } + } + /* get rid of '\', glob doesn't like it */ + if ((tmp = strrchr(path, '\\')) != NULL) { + char *tail = path + strlen(path); + while (tmp != path) { + if (*tmp == '\\') { + memmove(tmp, tmp + 1, tail - tmp); + --tail; + } + --tmp; + } } - return rc; } -int jt_lcfg_del_conn(int argc, char **argv) +/* Supporting file paths creates perilous behavoir: LU-888. + * Path support is deprecated. + * If a path is supplied it must begin with /proc. */ +static void lprocfs_param_pattern(const char *cmd, const char *path, char *buf, + size_t buf_size) +{ + /* test path to see if it begins with '/proc/' */ + if (strncmp(path, "/proc/", strlen("/proc/")) == 0) { + static int warned; + if (!warned) { + fprintf(stderr, "%s: specifying parameters via " + "full paths is deprecated.\n", cmd); +#if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 6, 50, 0) +#warning "remove deprecated full path tunable access" +#endif + warned = 1; + } + snprintf(buf, buf_size, "%s", path); + } else { + snprintf(buf, buf_size, "/proc/{fs,sys}/{lnet,lustre}/%s", + path); + } +} + +static int listparam_cmdline(int argc, char **argv, struct param_opts *popt) +{ + int ch; + + popt->po_show_path = 1; + popt->po_only_path = 1; + popt->po_show_type = 0; + popt->po_recursive = 0; + + while ((ch = getopt(argc, argv, "FR")) != -1) { + switch (ch) { + case 'F': + popt->po_show_type = 1; + break; + case 'R': + popt->po_recursive = 1; + break; + default: + return -1; + } + } + + return optind; +} + +static int listparam_display(struct param_opts *popt, char *pattern) { - struct lustre_cfg_bufs bufs; - struct lustre_cfg *lcfg; int rc; + int i; + glob_t glob_info; + char filename[PATH_MAX + 1]; /* extra 1 byte for file type */ - if (argc != 2) + rc = glob(pattern, GLOB_BRACE | (popt->po_recursive ? GLOB_MARK : 0), + NULL, &glob_info); + if (rc) { + fprintf(stderr, "error: list_param: %s: %s\n", + pattern, globerrstr(rc)); + return -ESRCH; + } + + for (i = 0; i < glob_info.gl_pathc; i++) { + char *valuename = NULL; + int last; + + /* Trailing '/' will indicate recursion into directory */ + last = strlen(glob_info.gl_pathv[i]) - 1; + + /* Remove trailing '/' or it will be converted to '.' */ + if (last > 0 && glob_info.gl_pathv[i][last] == '/') + glob_info.gl_pathv[i][last] = '\0'; + else + last = 0; + strcpy(filename, glob_info.gl_pathv[i]); + valuename = display_name(filename, popt->po_show_type); + if (valuename) + printf("%s\n", valuename); + if (last) { + strcpy(filename, glob_info.gl_pathv[i]); + strcat(filename, "/*"); + listparam_display(popt, filename); + } + } + + globfree(&glob_info); + return rc; +} + +int jt_lcfg_listparam(int argc, char **argv) +{ + int rc = 0, i; + struct param_opts popt; + char pattern[PATH_MAX]; + char *path; + + rc = listparam_cmdline(argc, argv, &popt); + if (rc == argc && popt.po_recursive) { + rc--; /* we know at least "-R" is a parameter */ + argv[rc] = "*"; + } else if (rc < 0 || rc >= argc) { return CMD_HELP; + } - if (lcfg_devname == NULL) { - fprintf(stderr, "%s: please use 'cfg_device name' to set the " - "device name for config commands.\n", - jt_cmdname(argv[0])); - return -EINVAL; + for (i = rc; i < argc; i++) { + path = argv[i]; + + clean_path(path); + + lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern)); + + rc = listparam_display(&popt, pattern); + if (rc < 0) + return rc; } - lustre_cfg_bufs_reset(&bufs, lcfg_devname); + return 0; +} - /* connection uuid */ - lustre_cfg_bufs_set_string(&bufs, 1, argv[1]); +static int getparam_cmdline(int argc, char **argv, struct param_opts *popt) +{ + int ch; + + popt->po_show_path = 1; + popt->po_only_path = 0; + popt->po_show_type = 0; + popt->po_recursive = 0; + + while ((ch = getopt(argc, argv, "nNF")) != -1) { + switch (ch) { + case 'N': + popt->po_only_path = 1; + break; + case 'n': + popt->po_show_path = 0; + case 'F': + popt->po_show_type = 1; + break; + default: + return -1; + } + } - lcfg = lustre_cfg_new(LCFG_DEL_CONN, &bufs); + return optind; +} - rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg); - lustre_cfg_free(lcfg); - if (rc < 0) { - fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), - strerror(rc = errno)); +static int getparam_display(struct param_opts *popt, char *pattern) +{ + int rc; + int fd; + int i; + char *buf; + glob_t glob_info; + char filename[PATH_MAX + 1]; /* extra 1 byte for file type */ + + rc = glob(pattern, GLOB_BRACE, NULL, &glob_info); + if (rc) { + fprintf(stderr, "error: get_param: %s: %s\n", + pattern, globerrstr(rc)); + return -ESRCH; } + buf = malloc(PAGE_CACHE_SIZE); + for (i = 0; i < glob_info.gl_pathc; i++) { + char *valuename = NULL; + + memset(buf, 0, PAGE_CACHE_SIZE); + /* As listparam_display is used to show param name (with type), + * here "if (only_path)" is ignored.*/ + if (popt->po_show_path) { + strcpy(filename, glob_info.gl_pathv[i]); + valuename = display_name(filename, 0); + } + + /* Write the contents of file to stdout */ + fd = open(glob_info.gl_pathv[i], O_RDONLY); + if (fd < 0) { + fprintf(stderr, + "error: get_param: opening('%s') failed: %s\n", + glob_info.gl_pathv[i], strerror(errno)); + continue; + } + + do { + rc = read(fd, buf, PAGE_CACHE_SIZE); + if (rc == 0) + break; + if (rc < 0) { + fprintf(stderr, "error: get_param: " + "read('%s') failed: %s\n", + 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 && popt->po_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: get_param: " + "write to stdout failed: %s\n", + strerror(errno)); + break; + } + } while (1); + close(fd); + } + + globfree(&glob_info); + free(buf); return rc; } -int jt_lcfg_set_security(int argc, char **argv) +int jt_lcfg_getparam(int argc, char **argv) { - struct lustre_cfg_bufs bufs; - struct lustre_cfg *lcfg; - int rc; + int rc = 0, i; + struct param_opts popt; + char pattern[PATH_MAX]; + char *path; - if (argc != 3) + rc = getparam_cmdline(argc, argv, &popt); + if (rc < 0 || rc >= argc) return CMD_HELP; - if (lcfg_devname == NULL) { - fprintf(stderr, "%s: please use 'cfg_device name' to set the " - "device name for config commands.\n", - jt_cmdname(argv[0])); - return -EINVAL; - } + for (i = rc, rc = 0; i < argc; i++) { + int rc2; - lustre_cfg_bufs_reset(&bufs, lcfg_devname); + path = argv[i]; - /* currently only used to set on mds */ - if (strcmp(argv[1], "mds_sec") && - strcmp(argv[1], "oss_sec") && - strcmp(argv[1], "deny_sec")) { - fprintf(stderr, "%s: invalid security key %s\n", - jt_cmdname(argv[0]), argv[1]); - return -EINVAL; - } - if (strcmp(argv[2], "null") && - strcmp(argv[2], "krb5i") && - strcmp(argv[2], "krb5p")) { - fprintf(stderr, "%s: invalid security value %s\n", - jt_cmdname(argv[0]), argv[2]); - return -EINVAL; + clean_path(path); + + lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern)); + + if (popt.po_only_path) + rc2 = listparam_display(&popt, pattern); + else + rc2 = getparam_display(&popt, pattern); + if (rc2 < 0 && rc == 0) + rc = rc2; + } + + return rc; +} + +static int setparam_cmdline(int argc, char **argv, struct param_opts *popt) +{ + int ch; + + popt->po_show_path = 1; + popt->po_only_path = 0; + popt->po_show_type = 0; + popt->po_recursive = 0; + popt->po_params2 = 0; + popt->po_delete = 0; + + while ((ch = getopt(argc, argv, "nPd")) != -1) { + switch (ch) { + case 'n': + popt->po_show_path = 0; + break; + case 'P': + popt->po_params2 = 1; + break; + case 'd': + popt->po_delete = 1; + break; + default: + return -1; + } } + return optind; +} - /* connection uuid */ - lustre_cfg_bufs_set_string(&bufs, 1, argv[1]); - lustre_cfg_bufs_set_string(&bufs, 2, argv[2]); - lcfg = lustre_cfg_new(LCFG_SET_SECURITY, &bufs); +static int setparam_display(struct param_opts *popt, char *pattern, char *value) +{ + int rc; + int fd; + int i; + glob_t glob_info; + char filename[PATH_MAX + 1]; /* extra 1 byte for file type */ - rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg); - lustre_cfg_free(lcfg); - if (rc < 0) { - fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), - strerror(rc = errno)); + rc = glob(pattern, GLOB_BRACE, NULL, &glob_info); + if (rc) { + fprintf(stderr, "error: set_param: %s: %s\n", + pattern, globerrstr(rc)); + return -ESRCH; } + for (i = 0; i < glob_info.gl_pathc; i++) { + char *valuename = NULL; + + if (popt->po_show_path) { + strcpy(filename, glob_info.gl_pathv[i]); + valuename = display_name(filename, 0); + if (valuename) + printf("%s=%s\n", valuename, value); + } + /* Write the new value to the file */ + fd = open(glob_info.gl_pathv[i], O_WRONLY); + if (fd >= 0) { + rc = write(fd, value, strlen(value)); + if (rc < 0) + fprintf(stderr, "error: set_param: setting " + "%s=%s: %s\n", glob_info.gl_pathv[i], + value, strerror(errno)); + else + rc = 0; + close(fd); + } else { + fprintf(stderr, "error: set_param: %s opening %s\n", + strerror(rc = errno), glob_info.gl_pathv[i]); + } + } - return rc; + globfree(&glob_info); + return rc; } +int jt_lcfg_setparam(int argc, char **argv) +{ + int rc = 0, i; + struct param_opts popt; + char pattern[PATH_MAX]; + char *path = NULL, *value = NULL; + + rc = setparam_cmdline(argc, argv, &popt); + if (rc < 0 || rc >= argc) + return CMD_HELP; + + if (popt.po_params2) + /* We can't delete parameters that were + * set with old conf_param interface */ + return jt_lcfg_mgsparam2(argc, argv, &popt); + + for (i = rc, rc = 0; i < argc; i++) { + int rc2; + + if ((value = strchr(argv[i], '=')) != NULL) { + /* format: set_param a=b */ + *value = '\0'; + value ++; + path = argv[i]; + } else { + /* format: set_param a b */ + if (path == NULL) { + path = argv[i]; + continue; + } else { + value = argv[i]; + } + } + + clean_path(path); + + lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern)); + + rc2 = setparam_display(&popt, pattern, value); + path = NULL; + value = NULL; + if (rc2 < 0 && rc == 0) + rc = rc2; + } + + return rc; +}