Whamcloud - gitweb
osd/mdd: new (weaker) locking for ->do_attr_{g,e}set(), see message to colibri@ for...
[fs/lustre-release.git] / lustre / utils / lustre_cfg.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2002 Cluster File Systems, Inc.
5  *   Author: Peter J. Braam <braam@clusterfs.com>
6  *   Author: Phil Schwan <phil@clusterfs.com>
7  *   Author: Andreas Dilger <adilger@clusterfs.com>
8  *   Author: Robert Read <rread@clusterfs.com>
9  *
10  *   This file is part of Lustre, http://www.lustre.org.
11  *
12  *   Lustre is free software; you can redistribute it and/or
13  *   modify it under the terms of version 2 of the GNU General Public
14  *   License as published by the Free Software Foundation.
15  *
16  *   Lustre is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with Lustre; if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  */
26
27
28 #include <stdlib.h>
29 #include <sys/ioctl.h>
30 #include <stdio.h>
31 #include <stdarg.h>
32
33 #ifndef __KERNEL__
34 #include <liblustre.h>
35 #endif
36 #include <lustre_lib.h>
37 #include <lustre_cfg.h>
38 #include <lustre/lustre_idl.h>
39 #include <lustre_dlm.h>
40 #include <obd.h>          /* for struct lov_stripe_md */
41 #include <obd_lov.h>
42 #include <linux/lustre_build_version.h>
43
44 #include <unistd.h>
45 #include <sys/un.h>
46 #include <time.h>
47 #include <sys/time.h>
48 #include <errno.h>
49 #include <string.h>
50
51
52 #include "obdctl.h"
53 #include <lnet/lnetctl.h>
54 #include "parser.h"
55 #include <stdio.h>
56
57 static char * lcfg_devname;
58
59 void lcfg_set_devname(char *name)
60 {
61         if (lcfg_devname)
62                 free(lcfg_devname);
63         lcfg_devname = strdup(name);
64 }
65
66
67 int jt_lcfg_device(int argc, char **argv)
68 {
69         char *name;
70
71         if (argc == 1) {
72                 printf("current device is %s\n", lcfg_devname? : "not set");
73                 return 0;
74         } else if (argc != 2) {
75                 return CMD_HELP;
76         }
77
78         name = argv[1];
79
80         /* quietly strip the unnecessary '$' */
81         if (*name == '$')
82                 name++;
83
84         lcfg_set_devname(name);
85
86         return 0;
87 }
88
89 /* NOOP */
90 int jt_lcfg_newdev(int argc, char **argv)
91 {
92         return 0;
93 }
94
95 int jt_lcfg_attach(int argc, char **argv)
96 {
97         struct lustre_cfg_bufs bufs;
98         struct lustre_cfg *lcfg;
99         int rc;
100
101         if (argc != 4)
102                 return CMD_HELP;
103
104         lustre_cfg_bufs_reset(&bufs, NULL);
105
106         lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
107         lustre_cfg_bufs_set_string(&bufs, 0, argv[2]);
108         lustre_cfg_bufs_set_string(&bufs, 2, argv[3]);
109
110         lcfg = lustre_cfg_new(LCFG_ATTACH, &bufs);
111         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
112         lustre_cfg_free(lcfg);
113         if (rc < 0) {
114                 fprintf(stderr, "error: %s: LCFG_ATTACH %s\n",
115                         jt_cmdname(argv[0]), strerror(rc = errno));
116         } else if (argc == 3) {
117                 char name[1024];
118
119                 lcfg_set_devname(argv[2]);
120                 if (strlen(argv[2]) > 128) {
121                         printf("Name too long to set environment\n");
122                         return -EINVAL;
123                 }
124                 snprintf(name, 512, "LUSTRE_DEV_%s", argv[2]);
125                 rc = setenv(name, argv[1], 1);
126                 if (rc) {
127                         printf("error setting env variable %s\n", name);
128                 }
129         } else {
130                 lcfg_set_devname(argv[2]);
131         }
132
133         return rc;
134 }
135
136 int jt_lcfg_setup(int argc, char **argv)
137 {
138         struct lustre_cfg_bufs bufs;
139         struct lustre_cfg *lcfg;
140         int i;
141         int rc;
142
143         if (lcfg_devname == NULL) {
144                 fprintf(stderr, "%s: please use 'cfg_device name' to set the "
145                         "device name for config commands.\n", 
146                         jt_cmdname(argv[0])); 
147                 return -EINVAL;
148         }
149
150         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
151
152         if (argc > 6)
153                 return CMD_HELP;
154
155         for (i = 1; i < argc; i++) {
156                 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
157         }
158
159         lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
160         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
161         lustre_cfg_free(lcfg);
162         if (rc < 0)
163                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
164                         strerror(rc = errno));
165
166         return rc;
167 }
168
169 int jt_obd_detach(int argc, char **argv)
170 {
171         struct lustre_cfg_bufs bufs;
172         struct lustre_cfg *lcfg;
173         int rc;
174
175         if (lcfg_devname == NULL) {
176                 fprintf(stderr, "%s: please use 'cfg_device name' to set the "
177                         "device name for config commands.\n", 
178                         jt_cmdname(argv[0])); 
179                 return -EINVAL;
180         }
181
182         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
183
184         if (argc != 1)
185                 return CMD_HELP;
186
187         lcfg = lustre_cfg_new(LCFG_DETACH, &bufs);
188         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
189         lustre_cfg_free(lcfg);
190         if (rc < 0)
191                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
192                         strerror(rc = errno));
193
194         return rc;
195 }
196
197 int jt_obd_cleanup(int argc, char **argv)
198 {
199         struct lustre_cfg_bufs bufs;
200         struct lustre_cfg *lcfg;
201         char force = 'F';
202         char failover = 'A';
203         char flags[3] = { 0 };
204         int flag_cnt = 0, n;
205         int rc;
206
207         if (lcfg_devname == NULL) {
208                 fprintf(stderr, "%s: please use 'cfg_device name' to set the "
209                         "device name for config commands.\n", 
210                         jt_cmdname(argv[0])); 
211                 return -EINVAL;
212         }
213
214         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
215
216         if (argc < 1 || argc > 3)
217                 return CMD_HELP;
218
219         /* we are protected from overflowing our buffer by the argc
220          * check above
221          */
222         for (n = 1; n < argc; n++) {
223                 if (strcmp(argv[n], "force") == 0) {
224                         flags[flag_cnt++] = force;
225                 } else if (strcmp(argv[n], "failover") == 0) {
226                         flags[flag_cnt++] = failover;
227                 } else {
228                         fprintf(stderr, "unknown option: %s", argv[n]);
229                         return CMD_HELP;
230                 }
231         }
232
233         if (flag_cnt) {
234                 lustre_cfg_bufs_set_string(&bufs, 1, flags);
235         }
236
237         lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
238         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
239         lustre_cfg_free(lcfg);
240         if (rc < 0)
241                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
242                         strerror(rc = errno));
243
244         return rc;
245 }
246
247 static 
248 int do_add_uuid(char * func, char *uuid, lnet_nid_t nid) 
249 {
250         int rc;
251         struct lustre_cfg_bufs bufs;
252         struct lustre_cfg *lcfg;
253
254         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
255         if (uuid)
256                 lustre_cfg_bufs_set_string(&bufs, 1, uuid);
257
258         lcfg = lustre_cfg_new(LCFG_ADD_UUID, &bufs);
259         lcfg->lcfg_nid = nid;
260         /* Poison NAL -- pre 1.4.6 will LASSERT on 0 NAL, this way it 
261            doesn't work without crashing (bz 10130) */
262         lcfg->lcfg_nal = 0x5a;
263
264 #if 0
265         fprintf(stderr, "adding\tnid: %d\tuuid: %s\n",
266                lcfg->lcfg_nid, uuid);
267 #endif
268         rc = lcfg_ioctl(func, OBD_DEV_ID, lcfg);
269         lustre_cfg_free(lcfg);
270         if (rc) {
271                 fprintf(stderr, "IOC_PORTAL_ADD_UUID failed: %s\n",
272                         strerror(errno));
273                 return -1;
274         }
275
276         printf ("Added uuid %s: %s\n", uuid, libcfs_nid2str(nid));
277         return 0;
278 }
279
280 int jt_lcfg_add_uuid(int argc, char **argv)
281 {
282         lnet_nid_t nid;
283         
284         if (argc != 3) {                
285                 return CMD_HELP;
286         }
287
288         nid = libcfs_str2nid(argv[2]);
289         if (nid == LNET_NID_ANY) {
290                 fprintf (stderr, "Can't parse NID %s\n", argv[2]);
291                 return (-1);
292         }
293
294         return do_add_uuid(argv[0], argv[1], nid);
295 }
296
297 int obd_add_uuid(char *uuid, lnet_nid_t nid)
298 {
299         return do_add_uuid("obd_add_uuid", uuid, nid);
300 }
301
302 int jt_lcfg_del_uuid(int argc, char **argv)
303 {
304         int rc;
305         struct lustre_cfg_bufs bufs;
306         struct lustre_cfg *lcfg;
307
308         if (argc != 2) {
309                 fprintf(stderr, "usage: %s <uuid>\n", argv[0]);
310                 return 0;
311         }
312
313         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
314         if (strcmp (argv[1], "_all_"))
315                 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
316         
317         lcfg = lustre_cfg_new(LCFG_DEL_UUID, &bufs);
318         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
319         lustre_cfg_free(lcfg);
320         if (rc) {
321                 fprintf(stderr, "IOC_PORTAL_DEL_UUID failed: %s\n",
322                         strerror(errno));
323                 return -1;
324         }
325         return 0;
326 }
327
328 int jt_lcfg_lov_setup(int argc, char **argv)
329 {
330         struct lustre_cfg_bufs bufs;
331         struct lustre_cfg *lcfg;
332         struct lov_desc desc;
333         int rc;
334         char *end;
335
336          /* argv: lov_setup <LOV uuid> <stripe count> <stripe size>
337           *                 <stripe offset> <pattern> [ <max tgt index> ]
338           */
339         if (argc < 6 || argc > 7)
340                 return CMD_HELP;
341
342         if (strlen(argv[1]) > sizeof(desc.ld_uuid) - 1) {
343                 fprintf(stderr,
344                         "error: %s: LOV uuid '%s' longer than "LPSZ" chars\n",
345                         jt_cmdname(argv[0]), argv[1], sizeof(desc.ld_uuid) - 1);
346                 return -EINVAL;
347         }
348
349         memset(&desc, 0, sizeof(desc));
350         obd_str2uuid(&desc.ld_uuid, argv[1]);
351         desc.ld_tgt_count = 0;
352         desc.ld_magic = LOV_DESC_MAGIC;
353         desc.ld_default_stripe_count = strtoul(argv[2], &end, 0);
354         if (*end) {
355                 fprintf(stderr, "error: %s: bad default stripe count '%s'\n",
356                         jt_cmdname(argv[0]), argv[2]);
357                 return CMD_HELP;
358         }
359
360         desc.ld_default_stripe_size = strtoull(argv[3], &end, 0);
361         if (*end) {
362                 fprintf(stderr, "error: %s: bad default stripe size '%s'\n",
363                         jt_cmdname(argv[0]), argv[3]);
364                 return CMD_HELP;
365         }
366         if (desc.ld_default_stripe_size < 4096) {
367                 fprintf(stderr,
368                         "error: %s: default stripe size "LPU64" smaller than "
369                         "minimum %u\n",
370                         jt_cmdname(argv[0]), desc.ld_default_stripe_size,
371                         LOV_MIN_STRIPE_SIZE);
372                 return -EINVAL;
373         } else if ((long)desc.ld_default_stripe_size <
374                    desc.ld_default_stripe_size) {
375                 fprintf(stderr,
376                         "error: %s: default stripe size "LPU64" too large\n",
377                         jt_cmdname(argv[0]), desc.ld_default_stripe_size);
378                 return -EINVAL;
379         }
380         desc.ld_default_stripe_offset = strtoull(argv[4], &end, 0);
381         if (*end) {
382                 fprintf(stderr, "error: %s: bad default stripe offset '%s'\n",
383                         jt_cmdname(argv[0]), argv[4]);
384                 return CMD_HELP;
385         }
386         desc.ld_pattern = strtoul(argv[5], &end, 0);
387         if (*end) {
388                 fprintf(stderr, "error: %s: bad stripe pattern '%s'\n",
389                         jt_cmdname(argv[0]), argv[5]);
390                 return CMD_HELP;
391         }
392         desc.ld_qos_maxage = QOS_DEFAULT_MAXAGE;
393
394         if (argc == 7) {
395                 desc.ld_tgt_count = strtoul(argv[6], &end, 0);
396                 if (*end) {
397                         fprintf(stderr, "error: %s: bad target count '%s'\n",
398                                 jt_cmdname(argv[0]), argv[6]);
399                         return CMD_HELP;
400                 }
401                 if (desc.ld_default_stripe_count > desc.ld_tgt_count) {
402                         fprintf(stderr,
403                                 "error: %s: default stripe count %u > "
404                                 "OST count %u\n", jt_cmdname(argv[0]),
405                                 desc.ld_default_stripe_count,
406                                 desc.ld_tgt_count);
407                         return -EINVAL;
408                 }
409         }
410
411         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
412         lustre_cfg_bufs_set(&bufs, 1, &desc, sizeof(desc));
413
414         lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
415         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
416         lustre_cfg_free(lcfg);
417         if (rc)
418                 fprintf(stderr, "error: %s: ioctl error: %s\n",
419                         jt_cmdname(argv[0]), strerror(rc = errno));
420         return rc;
421 }
422
423 int jt_lcfg_lov_modify_tgts(int argc, char **argv)
424 {
425         struct lustre_cfg_bufs bufs;
426         struct lustre_cfg *lcfg;
427         char *end;
428         int cmd = 0;
429         int index;
430         int gen;
431         int rc;
432         
433         /* argv: lov_modify_tgts <op> <LOV name> <OBD uuid> <index> <gen> */
434         if (argc != 6)
435                 return CMD_HELP;
436         
437         if (!strncmp(argv[1], "add", 4)) {
438                 cmd = LCFG_LOV_ADD_OBD;
439         } else if (!strncmp(argv[1], "del", 4)) {
440                 cmd = LCFG_LOV_DEL_OBD;
441         } else {
442                 fprintf(stderr, "error: %s: bad operation '%s'\n",
443                         jt_cmdname(argv[0]), argv[1]);
444                 return CMD_HELP;
445         }
446         
447         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
448         
449         if (((index = strlen(argv[3]) + 1)) > sizeof(struct obd_uuid)) {
450                 fprintf(stderr,
451                         "error: %s: OBD uuid '%s' longer than "LPSZ" chars\n",
452                         jt_cmdname(argv[0]), argv[3],
453                         sizeof(struct obd_uuid) - 1);
454                 return -EINVAL;
455         }
456         lustre_cfg_bufs_set(&bufs, 1, argv[3], index);
457         
458         index = strtoul(argv[4], &end, 0);
459         if (*end) {
460                 fprintf(stderr, "error: %s: bad OBD index '%s'\n",
461                         jt_cmdname(argv[0]), argv[4]);
462                 return CMD_HELP;
463         }
464         lustre_cfg_bufs_set(&bufs, 2, argv[4], strlen(argv[4]));
465         
466         gen = strtoul(argv[5], &end, 0);
467         if (*end) {
468                 fprintf(stderr, "error: %s: bad OBD generation '%s'\n",
469                         jt_cmdname(argv[0]), argv[5]);
470                 return CMD_HELP;
471         }
472         lustre_cfg_bufs_set(&bufs, 3, argv[5], strlen(argv[5]));
473         
474         lcfg = lustre_cfg_new(cmd, &bufs);
475         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
476         lustre_cfg_free(lcfg);
477         if (rc)
478                 fprintf(stderr, "error: %s: ioctl error: %s\n",
479                         jt_cmdname(argv[0]), strerror(rc = errno));
480         
481         return rc;
482 }                                                     
483    
484
485
486 int jt_lcfg_mount_option(int argc, char **argv)
487 {
488         int rc;
489         struct lustre_cfg_bufs bufs;
490         struct lustre_cfg *lcfg;
491         int i;
492
493         if (argc < 3 || argc > 4)
494                 return CMD_HELP;
495
496         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
497
498         for (i = 1; i < argc; i++)
499                 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
500
501         lcfg = lustre_cfg_new(LCFG_MOUNTOPT, &bufs);
502         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
503         lustre_cfg_free(lcfg);
504         if (rc < 0) {
505                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
506                         strerror(rc = errno));
507         }
508         return rc;
509 }
510
511 int jt_lcfg_del_mount_option(int argc, char **argv)
512 {
513         int rc;
514         struct lustre_cfg_bufs bufs;
515         struct lustre_cfg *lcfg;
516
517         if (argc != 2)
518                 return CMD_HELP;
519
520         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
521
522         /* profile name */
523         lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
524
525         lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
526         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
527         lustre_cfg_free(lcfg);
528         if (rc < 0) {
529                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
530                         strerror(rc = errno));
531         }
532         return rc;
533 }
534
535 int jt_lcfg_set_timeout(int argc, char **argv)
536 {
537         int rc;
538         struct lustre_cfg_bufs bufs;
539         struct lustre_cfg *lcfg;
540
541         fprintf(stderr, "%s has been deprecated. Use conf_param instead.\n"
542                 "e.g. conf_param lustre-MDT0000 obd_timeout=50\n",
543                 jt_cmdname(argv[0]));
544         return CMD_HELP;
545
546
547         if (argc != 2)
548                 return CMD_HELP;
549
550         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
551         lcfg = lustre_cfg_new(LCFG_SET_TIMEOUT, &bufs);
552         lcfg->lcfg_num = atoi(argv[1]);
553         
554         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
555         //rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
556
557         lustre_cfg_free(lcfg);
558         if (rc < 0) {
559                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
560                         strerror(rc = errno));
561         }
562         return rc;
563 }
564
565
566 int jt_lcfg_set_lustre_upcall(int argc, char **argv)
567 {
568         int rc;
569         struct lustre_cfg_bufs bufs;
570         struct lustre_cfg *lcfg;
571
572         if (argc != 2)
573                 return CMD_HELP;
574
575         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
576
577         /* profile name */
578         lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
579
580         lcfg = lustre_cfg_new(LCFG_SET_UPCALL, &bufs);
581         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
582         lustre_cfg_free(lcfg);
583         if (rc < 0) {
584                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
585                         strerror(rc = errno));
586         }
587         return rc;
588 }
589
590 int jt_lcfg_add_conn(int argc, char **argv)
591 {
592         struct lustre_cfg_bufs bufs;
593         struct lustre_cfg *lcfg;
594         int priority;
595         int rc;
596
597         if (argc == 2)
598                 priority = 0;
599         else if (argc == 3)
600                 priority = 1;
601         else
602                 return CMD_HELP;
603
604         if (lcfg_devname == NULL) {
605                 fprintf(stderr, "%s: please use 'cfg_device name' to set the "
606                         "device name for config commands.\n", 
607                         jt_cmdname(argv[0])); 
608                 return -EINVAL;
609         }
610
611         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
612
613         lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
614
615         lcfg = lustre_cfg_new(LCFG_ADD_CONN, &bufs);
616         lcfg->lcfg_num = priority;
617
618         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
619         lustre_cfg_free (lcfg);
620         if (rc < 0) {
621                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
622                         strerror(rc = errno));
623         }
624
625         return rc;
626 }
627
628 int jt_lcfg_del_conn(int argc, char **argv)
629 {
630         struct lustre_cfg_bufs bufs;
631         struct lustre_cfg *lcfg;
632         int rc;
633
634         if (argc != 2)
635                 return CMD_HELP;
636
637         if (lcfg_devname == NULL) {
638                 fprintf(stderr, "%s: please use 'cfg_device name' to set the "
639                         "device name for config commands.\n", 
640                         jt_cmdname(argv[0])); 
641                 return -EINVAL;
642         }
643
644         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
645
646         /* connection uuid */
647         lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
648
649         lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
650
651         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
652         lustre_cfg_free(lcfg);
653         if (rc < 0) {
654                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
655                         strerror(rc = errno));
656         }
657
658         return rc;
659 }
660
661 /* Param set locally, directly on target */
662 int jt_lcfg_param(int argc, char **argv)
663 {
664         int i, rc;
665         struct lustre_cfg_bufs bufs;
666         struct lustre_cfg *lcfg;
667
668         if (argc >= LUSTRE_CFG_MAX_BUFCOUNT)
669                 return CMD_HELP;
670
671         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
672
673         for (i = 1; i < argc; i++) {
674                 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
675         }
676
677         lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
678         
679         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
680         lustre_cfg_free(lcfg);
681         if (rc < 0) {
682                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
683                         strerror(rc = errno));
684         }
685         return rc;
686 }
687
688 /* Param set in config log on MGS */
689 /* conf_param <cfg_device> key1=value1 [key2=value2...] */
690 int jt_lcfg_mgsparam(int argc, char **argv)
691 {
692         int i, rc, index_offset = 0;
693         struct lustre_cfg_bufs bufs;
694         struct lustre_cfg *lcfg;
695
696         if ((argc >= LUSTRE_CFG_MAX_BUFCOUNT) || (argc <= 1))
697                 return CMD_HELP;
698
699         if (!strchr(argv[1], '=')) {
700                 /* Not key=val, assume <cfg_device> */
701                 rc = jt_lcfg_device(2, argv);
702                 if (rc) 
703                         return rc;
704                 index_offset = 1;
705         }
706
707         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
708
709         for (i = 1; i < (argc - index_offset); i++) {
710                 lustre_cfg_bufs_set_string(&bufs, i, argv[i + index_offset]);
711         }
712
713         /* We could put other opcodes here. */
714         lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
715
716         rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
717         lustre_cfg_free(lcfg);
718         if (rc < 0) {
719                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
720                         strerror(rc = errno));
721         }
722         
723         return rc;
724 }
725
726