1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include "metad_local.h"
27 #include <metad.h>
28 #include <sys/lvm/md_mddb.h>
29 #include <sdssc.h>
30 #include <sys/lvm/md_mirror.h>
31 #include <syslog.h>
32
33 #include <sys/sysevent/eventdefs.h>
34 #include <sys/sysevent/svm.h>
35 #include <thread.h>
36
37 #define MDDOORS "/usr/lib/lvm/mddoors"
38
39 /*
40 * rpc.metad daemon
41 *
42 * The rpc.metad deamon supports two versions of the svm rpc calls - version 1
43 * and version 2. The over-the-wire structures sent as part of these rpc calls
44 * are also versioned - version 1 and version 2 exist. It must be noted that
45 * the version 2 structures have sub-versions or revisions as well. The
46 * revisions in the version 2 structures allow for flexiblility in changing
47 * over the wire structures without creating a new version of the svm rpc
48 * calls. No changes may be made to the version 1 routines or structures used
49 * by these routines.
50 *
51 * If, for example, the version 2 mdrpc_devinfo_args over the wire structure
52 * (mdrpc_devinfo_2_args*) is changed then the structure change must be
53 * accompanied by the following:
54 *
55 * Header file changes:
56 * . May need to introduce a new structure revision MD_METAD_ARGS_REV_X, where
57 * X is the revision number.
58 * . Create mdrpc_devinfo_2_args_rX, where X is the new revision of the
59 * structure.
60 * . Add a switch statement in mdrpc_devinfo_2_args.
61 *
62 * rpc.metad changes:
63 * . Check for the structure revision in the appropriate mdrpc_devinfo_svc
64 * routine (mdrpc_devinfo_2_svc).
65 *
66 * libmeta changes:
67 * . In the libmeta code that makes the mdrpc_devinfo rpc call, the arguments
68 * being passed as part of this call (namely mdrpc_devinfo_Y_args) must have
69 * the revision field and associated structure populated correctly.
70 */
71
72 static md_setkey_t *my_svc_sk = NULL;
73
74 /*
75 * Add namespace entry to local mddb for using given sideno, key
76 * and names.
77 */
78 static int
add_sideno_sidenm(mdsidenames_t * sidenms,mdkey_t local_key,side_t sideno,md_set_desc * sd,md_error_t * ep)79 add_sideno_sidenm(
80 mdsidenames_t *sidenms,
81 mdkey_t local_key,
82 side_t sideno,
83 md_set_desc *sd, /* Only used with Version 2 */
84 md_error_t *ep
85 )
86 {
87 mdsidenames_t *sn;
88 mdsetname_t *local_sp;
89 char *nm;
90
91 if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
92 return (-1);
93
94 for (sn = sidenms; sn != NULL; sn = sn->next)
95 if (sn->sideno == sideno)
96 break;
97
98 assert(sn != NULL);
99
100
101 /*
102 * SKEW will be used on the traditional diskset despite of the
103 * rpc version. SKEW is not used on the multinode diskset
104 */
105 if (MD_MNSET_DESC(sd)) {
106 nm = meta_getnmbykey(MD_LOCAL_SET, sideno, local_key, ep);
107 } else {
108 nm = meta_getnmbykey(MD_LOCAL_SET, sideno+SKEW, local_key, ep);
109 }
110
111 if (nm == NULL) {
112 if (! mdisok(ep)) {
113 if (! mdissyserror(ep, ENOENT))
114 return (-1);
115 mdclrerror(ep);
116 }
117
118 /*
119 * Ignore returned key from add_name, only care about errs
120 *
121 * SKEW is used for a regular diskset since sideno could
122 * have a value of 0 in that diskset type. add_name is
123 * writing to the local mddb and a sideno of 0 in the
124 * local mddb is reserved for non-diskset names.
125 * SKEW is added to the sideno in the local mddb so that
126 * the sideno for the diskset will never be 0.
127 *
128 * In a MNdiskset, the sideno will never be 0 (by design).
129 * So, no SKEW is needed when writing to the local mddb.
130 */
131 if (MD_MNSET_DESC(sd)) {
132 if (add_name(local_sp, sideno, local_key,
133 sn->dname, sn->mnum, sn->cname, NULL, NULL,
134 ep) == -1)
135 return (-1);
136 } else {
137 if (add_name(local_sp, sideno+SKEW, local_key,
138 sn->dname, sn->mnum, sn->cname, NULL, NULL,
139 ep) == -1)
140 return (-1);
141 }
142 } else
143 Free(nm);
144
145 return (0);
146 }
147
148 /*
149 * Delete sidename entry from local set using key and sideno.
150 */
151 static int
del_sideno_sidenm(mdkey_t sidekey,side_t sideno,md_error_t * ep)152 del_sideno_sidenm(
153 mdkey_t sidekey,
154 side_t sideno,
155 md_error_t *ep
156 )
157 {
158 mdsetname_t *local_sp;
159
160 if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
161 return (-1);
162
163 if (del_name(local_sp, sideno, sidekey, ep) == -1)
164 mdclrerror(ep); /* ignore errs */
165
166 return (0);
167 }
168
169
170 /*
171 * Add namespace entries to local mddb for drives in drive list in
172 * set descriptor.
173 *
174 * If a MNset and if this host is being added to the set (this host
175 * is in the node_v list), add a namespace entry for the name of
176 * each drive using this host's sideno.
177 *
178 * If not a MNset, add namespace entries for all the new hosts being
179 * added to this set (list in node_v).
180 */
181 static void
add_drv_sidenms(char * hostname,mdsetname_t * sp,md_set_desc * sd,int node_c,char ** node_v,md_error_t * ep)182 add_drv_sidenms(
183 char *hostname,
184 mdsetname_t *sp,
185 md_set_desc *sd,
186 int node_c,
187 char **node_v,
188 md_error_t *ep
189 )
190 {
191 mdsetname_t *my_sp;
192 md_drive_desc *dd, *my_dd, *p, *q;
193 mddrivename_t *dn, *my_dn;
194 int i;
195 side_t sideno = 0, mysideno = 0;
196 ddi_devid_t devid_remote = NULL;
197 ddi_devid_t devid_local = NULL;
198 int devid_same = -1;
199 int using_devid = 0;
200 md_mnnode_desc *nd;
201
202 assert(sd->sd_drvs != NULL);
203 dd = sd->sd_drvs;
204
205 if (dd->dd_dnp == NULL)
206 return;
207
208 if ((my_sp = metasetname(sp->setname, ep)) == NULL)
209 return;
210 metaflushsetname(my_sp);
211
212 /* If a MN diskset */
213 if (MD_MNSET_DESC(sd)) {
214 /* Find sideno associated with RPC client. */
215 nd = sd->sd_nodelist;
216 while (nd) {
217
218 if (strcmp(nd->nd_nodename, hostname) == 0) {
219 sideno = nd->nd_nodeid;
220 }
221
222 /* While looping, find my side num as well */
223 if (strcmp(nd->nd_nodename, mynode()) == 0) {
224 mysideno = nd->nd_nodeid;
225 }
226
227 if ((sideno) && (mysideno)) {
228 break;
229 }
230 nd = nd->nd_next;
231 }
232
233 if (!sideno) {
234 (void) mddserror(ep, MDE_DS_HOSTNOSIDE,
235 sp->setno, hostname, NULL, sp->setname);
236 return;
237 }
238 } else {
239 /*
240 * if not a MN diskset
241 * do action for traditional diskset.
242 * despite of the rpc version
243 */
244 for (sideno = 0; sideno < MD_MAXSIDES; sideno++) {
245 /* Skip empty slots */
246 if (sd->sd_nodes[sideno][0] == '\0')
247 continue;
248
249 if (strcmp(hostname, sd->sd_nodes[sideno]) == 0)
250 break;
251 }
252
253 if (sideno == MD_MAXSIDES) {
254 (void) mddserror(ep, MDE_DS_HOSTNOSIDE, sp->setno,
255 hostname, NULL, sp->setname);
256 return;
257 }
258 }
259 if ((my_dd = metaget_drivedesc_sideno(my_sp, sideno, MD_BASICNAME_OK,
260 ep)) == NULL) {
261 if (! mdisok(ep))
262 return;
263 /* we are supposed to have drives!!!! */
264 assert(0);
265 }
266
267 /*
268 * The system is either all devid or all
269 * non-devid so we look at the first item
270 * in the list to determine if we're using devids or not.
271 * We also check to make sure it's not a multi-node diskset.
272 * If it is, we don't use devid's.
273 *
274 * For did disks, the dd_dnp->devid is a valid pointer which
275 * points to a '' string of devid. We need to check this
276 * before set the using_devid.
277 */
278 if ((dd->dd_dnp->devid != NULL) && (dd->dd_dnp->devid[0] != '\0') &&
279 (!(MD_MNSET_DESC(sd))))
280 using_devid = 1;
281
282 /*
283 * We have to match-up the dd that were passed
284 * across the wire to the dd we have in this daemon.
285 * That way we can pick up the new sidenames that were
286 * passed to us and match them up with the local namespace key.
287 * Only we have the key, this cannot be passed in.
288 */
289 for (p = dd; p != NULL; p = p->dd_next) {
290 dn = p->dd_dnp;
291 devid_remote = NULL;
292
293 if (dn->devid != NULL && (strlen(dn->devid) != 0) &&
294 using_devid) {
295 /*
296 * We have a devid so use it
297 */
298 (void) devid_str_decode(dn->devid, &devid_remote, NULL);
299 }
300
301 /* check to make sure using_devid agrees with reality... */
302 if ((using_devid == 1) && (devid_remote == NULL)) {
303 /* something went really wrong. Can't process */
304 (void) mddserror(ep, MDE_DS_INVALIDDEVID, sp->setno,
305 hostname, dn->cname, sp->setname);
306 return;
307 }
308
309 for (q = my_dd; q != NULL; q = q->dd_next) {
310 my_dn = q->dd_dnp;
311 devid_same = -1;
312
313 if (my_dn->devid != NULL && using_devid) {
314 if (devid_str_decode(my_dn->devid,
315 &devid_local, NULL) == 0) {
316 devid_same = devid_compare(devid_remote,
317 devid_local);
318 devid_free(devid_local);
319 }
320 }
321
322 if (using_devid && devid_same == 0) {
323 break;
324 }
325
326 if (!using_devid &&
327 strcmp(my_dn->cname, dn->cname) == 0)
328 break;
329 }
330
331 if (devid_remote) {
332 devid_free(devid_remote);
333 }
334 assert(q != NULL);
335 assert(my_dn->side_names_key != MD_KEYWILD);
336
337 if (MD_MNSET_DESC(sd)) {
338 /*
339 * Add the side names to the local db
340 * for this node only.
341 */
342 if (add_sideno_sidenm(dn->side_names,
343 my_dn->side_names_key, mysideno, sd, ep))
344 return;
345 /*
346 * Sidenames for this drive were added
347 * to this host during the routine adddrvs.
348 * The sidenames that were added are the
349 * names associated with this drive on
350 * each of the hosts that were previously
351 * in the set.
352 * When the sidename for this drive on
353 * this host is added, the sidename
354 * from the host executing the command
355 * (not this host) is sent to this host.
356 * This host finds the originating host's
357 * sidename and can then determine this
358 * host's sidename.
359 * The sidenames from the other hosts serve
360 * only as temporary sidenames until this
361 * host's sidename can be added.
362 * In order to conserve space in the
363 * local mddb, the code now deletes the
364 * temporary sidenames added during adddrvs.
365 * When finished, only the sidename for this
366 * node should be left.
367 * Ignore any errors during this process since
368 * a failure to delete the extraneous
369 * sidenames shouldn't cause this routine
370 * to fail (in case that sidename didn't exist).
371 */
372 nd = sd->sd_nodelist;
373 while (nd) {
374 if (nd->nd_nodeid != mysideno) {
375 if (del_sideno_sidenm(
376 dn->side_names_key,
377 nd->nd_nodeid, ep) == -1)
378 mdclrerror(ep);
379 }
380 nd = nd->nd_next;
381 }
382 } else {
383 for (i = 0; i < MD_MAXSIDES; i++) {
384 /* Skip empty slots */
385 if (sd->sd_nodes[i][0] == '\0')
386 continue;
387
388 /* Skip nodes not being added */
389 if (! strinlst(sd->sd_nodes[i],
390 node_c, node_v))
391 continue;
392
393 /* Add the per side names to local db */
394 if (add_sideno_sidenm(dn->side_names,
395 my_dn->side_names_key, i, sd, ep))
396 return;
397 }
398 }
399 }
400 }
401
402 /* ARGSUSED */
403 bool_t
mdrpc_flush_internal_common(mdrpc_null_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)404 mdrpc_flush_internal_common(mdrpc_null_args *args, mdrpc_generic_res *res,
405 struct svc_req *rqstp)
406 {
407 md_error_t *ep = &res->status;
408 int err, op_mode = W_OK;
409
410 (void) memset(res, 0, sizeof (*res));
411 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
412 return (FALSE);
413 else if (err != 0)
414 return (TRUE);
415
416 metaflushnames(1);
417
418 err = svc_fini(ep);
419
420 return (TRUE);
421 }
422
423 bool_t
mdrpc_flush_internal_1_svc(mdrpc_null_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)424 mdrpc_flush_internal_1_svc(mdrpc_null_args *args, mdrpc_generic_res *res,
425 struct svc_req *rqstp)
426 {
427 return (mdrpc_flush_internal_common(args, res, rqstp));
428 }
429
430 bool_t
mdrpc_flush_internal_2_svc(mdrpc_null_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)431 mdrpc_flush_internal_2_svc(mdrpc_null_args *args, mdrpc_generic_res *res,
432 struct svc_req *rqstp)
433 {
434 return (mdrpc_flush_internal_common(args, res, rqstp));
435 }
436
437 /*
438 * add 1 or more namespace entries per drive record.
439 * (into the local namespace)
440 */
441 bool_t
mdrpc_add_drv_sidenms_common(mdrpc_drv_sidenm_2_args_r1 * args,mdrpc_generic_res * res,struct svc_req * rqstp)442 mdrpc_add_drv_sidenms_common(
443 mdrpc_drv_sidenm_2_args_r1 *args,
444 mdrpc_generic_res *res,
445 struct svc_req *rqstp /* RPC stuff */
446 )
447 {
448 md_error_t *ep = &res->status;
449 int err;
450 int op_mode = W_OK;
451
452 /* setup, check permissions */
453 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
454 return (FALSE);
455 else if (err != 0)
456 return (TRUE);
457
458 if (check_set_lock(op_mode, args->cl_sk, ep))
459 return (TRUE);
460
461 /* doit */
462 add_drv_sidenms(args->hostname, args->sp, args->sd,
463 args->node_v.node_v_len, args->node_v.node_v_val, ep);
464
465 err = svc_fini(ep);
466
467 return (TRUE);
468 }
469
470 /*
471 * version 1 of the remote procedure. This procedure is called if the
472 * client is running in version 1. We first convert version 1 arguments
473 * into version 2 arguments and then call the common remote procedure.
474 */
475 bool_t
mdrpc_add_drv_sidenms_1_svc(mdrpc_drv_sidenm_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)476 mdrpc_add_drv_sidenms_1_svc(
477 mdrpc_drv_sidenm_args *args,
478 mdrpc_generic_res *res,
479 struct svc_req *rqstp /* RPC stuff */
480 )
481 {
482 bool_t retval;
483 mdrpc_drv_sidenm_2_args_r1 v2_args;
484 int i, j;
485
486 /* allocate memory */
487 v2_args.sd = Zalloc(sizeof (md_set_desc));
488 alloc_newdrvdesc(args->sd->sd_drvs, &v2_args.sd->sd_drvs);
489 (void) memset(res, 0, sizeof (*res));
490
491 /* build args */
492 v2_args.hostname = args->hostname;
493 v2_args.cl_sk = args->cl_sk;
494 v2_args.sp = args->sp;
495 /* set descriptor */
496 v2_args.sd->sd_ctime = args->sd->sd_ctime;
497 v2_args.sd->sd_genid = args->sd->sd_genid;
498 v2_args.sd->sd_setno = args->sd->sd_setno;
499 v2_args.sd->sd_flags = args->sd->sd_flags;
500 for (i = 0; i < MD_MAXSIDES; i++) {
501 v2_args.sd->sd_isown[i] = args->sd->sd_isown[i];
502
503 for (j = 0; j < MD_MAX_NODENAME_PLUS_1; j++)
504 v2_args.sd->sd_nodes[i][j] =
505 args->sd->sd_nodes[i][j];
506 }
507 v2_args.sd->sd_med = args->sd->sd_med;
508 /* convert v1 args to v2 (revision 1) args */
509 meta_conv_drvdesc_old2new(args->sd->sd_drvs, v2_args.sd->sd_drvs);
510 v2_args.node_v.node_v_len = args->node_v.node_v_len;
511 v2_args.node_v.node_v_val = args->node_v.node_v_val;
512
513 retval = mdrpc_add_drv_sidenms_common(&v2_args, res, rqstp);
514
515 free(v2_args.sd);
516 free_newdrvdesc(v2_args.sd->sd_drvs);
517
518 return (retval);
519 }
520
521 bool_t
mdrpc_add_drv_sidenms_2_svc(mdrpc_drv_sidenm_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)522 mdrpc_add_drv_sidenms_2_svc(
523 mdrpc_drv_sidenm_2_args *args,
524 mdrpc_generic_res *res,
525 struct svc_req *rqstp /* RPC stuff */
526 )
527 {
528 (void) memset(res, 0, sizeof (*res));
529 switch (args->rev) {
530 case MD_METAD_ARGS_REV_1:
531 return (mdrpc_add_drv_sidenms_common(
532 &args->mdrpc_drv_sidenm_2_args_u.rev1, res, rqstp));
533 default:
534 return (FALSE);
535 }
536 }
537
538 static int
add_sidenamelist(mddrivename_t * dn,side_t thisside,md_set_record * sr,md_error_t * ep)539 add_sidenamelist(
540 mddrivename_t *dn,
541 side_t thisside,
542 md_set_record *sr, /* used by RPC version 2 */
543 md_error_t *ep
544 )
545 {
546 mdsidenames_t *sn;
547 mdkey_t key;
548 int err;
549 mdsetname_t *local_sp;
550 md_mnset_record *mnsr;
551 md_mnnode_record *nr;
552 uint_t nodeid = 0;
553
554 if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
555 return (-1);
556
557 key = MD_KEYWILD;
558
559 /*
560 * If a multi-node diskset, find nodeid associated with this node.
561 */
562 if (MD_MNSET_REC(sr)) {
563 mnsr = (struct md_mnset_record *)sr;
564 nr = mnsr->sr_nodechain;
565 while (nr) {
566 if (strcmp(nr->nr_nodename, mynode()) == 0) {
567 break;
568 }
569 nr = nr->nr_next;
570 }
571 /*
572 * If node is found, then a new drive is being added to
573 * a MN set of which this node is a member.
574 * If node is not found, then this host is being added to
575 * a MN set that has drives associated with it.
576 */
577 if (nr)
578 nodeid = nr->nr_nodeid;
579 }
580 for (sn = dn->side_names; sn != NULL; sn = sn->next) {
581 if (MD_MNSET_REC(sr)) {
582 /*
583 * In multi-node disksets, only add side information
584 * to the local mddb about this node.
585 * If the sideno for this node is found, then
586 * a new drive is being added to a MN set of
587 * which this node is a member.
588 * If the sideno for this node is not found, then
589 * this host is being added to a MNset that
590 * has drives associated with it. In this case,
591 * need to add the sidename associated with the
592 * rpc client, but since we don't know which node
593 * is the client, then add temp entries for all sides.
594 * Later, the sidename for this node will be set
595 * via add_drv_sidenms and then the temp
596 * sidenames can be removed.
597 */
598 if (nodeid == sn->sideno) {
599 if ((err = add_name(local_sp, sn->sideno, key,
600 sn->dname, sn->mnum, sn->cname,
601 NULL, NULL, ep)) == -1)
602 return (-1);
603 key = (mdkey_t)err;
604 break;
605 }
606 } else {
607 /*
608 * When a sidename is added into the namespace the local
609 * side information for the name is added first of all.
610 * When the first sidename is created this causes the
611 * devid of the disk to be recorded in the namespace, if
612 * the non-local side information is added first then
613 * there is the possibility of getting the wrong devid
614 * because there is no guarantee that the dev_t (mnum in
615 * this instance) is the same across all the nodes in
616 * the set. So the only way to make sure that the
617 * correct dev_t is used is to force the adding in of
618 * the local sidename record first of all. This same
619 * issue affects add_key_name().
620 */
621 if (sn->sideno != thisside)
622 continue;
623 if ((err = add_name(local_sp, sn->sideno+SKEW, key,
624 sn->dname, sn->mnum, sn->cname, NULL,
625 NULL, ep)) == -1)
626 return (-1);
627 key = (mdkey_t)err;
628 break;
629 }
630 }
631
632 /*
633 * Now the other sides for non-MN set
634 */
635 if (!MD_MNSET_REC(sr)) {
636 for (sn = dn->side_names; sn != NULL; sn = sn->next) {
637 if (sn->sideno == thisside)
638 continue;
639 if ((err = add_name(local_sp, sn->sideno+SKEW, key,
640 sn->dname, sn->mnum, sn->cname, NULL, NULL,
641 ep)) == -1)
642 return (-1);
643 key = (mdkey_t)err;
644 }
645 }
646
647 /* Temporarily add all sides. */
648 if ((key == MD_KEYWILD) && (MD_MNSET_REC(sr))) {
649 for (sn = dn->side_names; sn != NULL; sn = sn->next) {
650 sn = dn->side_names;
651 if (sn) {
652 if ((err = add_name(local_sp, sn->sideno, key,
653 sn->dname, sn->mnum, sn->cname,
654 NULL, NULL, ep)) == -1)
655 return (-1);
656 key = (mdkey_t)err;
657 }
658 }
659 }
660
661 dn->side_names_key = key;
662 return (0);
663 }
664
665 /*
666 * imp_adddrvs
667 * This is a version of adddrvs that is specific to the
668 * metaimport command. Due to the unavailability of some disks,
669 * information needs to be obtained about the disk from the devid so
670 * it can eventually be passed down to add_sidenamelist.
671 * Go ahead and set drive state to MD_DR_OK here so that no
672 * later RPC is needed to set OK where UNRLSV_REPLICATED could
673 * be cleared. Set record is still set to MD_SR_ADD which will force
674 * a cleanup of the set in case of panic.
675 */
676 void
imp_adddrvs(char * setname,md_drive_desc * dd,md_timeval32_t timestamp,ulong_t genid,md_error_t * ep)677 imp_adddrvs(
678 char *setname,
679 md_drive_desc *dd,
680 md_timeval32_t timestamp,
681 ulong_t genid,
682 md_error_t *ep
683 )
684 {
685 mddb_userreq_t req;
686 md_drive_record *dr, *tdr;
687 md_set_record *sr;
688 md_drive_desc *p;
689 mddrivename_t *dn;
690 mdname_t *np;
691 md_dev64_t dev;
692 md_error_t xep = mdnullerror;
693 char *minorname = NULL;
694 ddi_devid_t devidp = NULL;
695 mdsidenames_t *sn;
696 mdsetname_t *local_sp;
697
698
699 if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) {
700 return;
701 }
702
703 if ((sr = getsetbyname(setname, ep)) == NULL)
704 return;
705
706 for (p = dd; p != NULL; p = p->dd_next) {
707 uint_t rep_slice;
708 int ret = 0;
709
710 dn = p->dd_dnp;
711
712 /*
713 * We need the minorname and devid string decoded from the
714 * devid to add the sidename for this drive to the
715 * local set.
716 */
717 ret = devid_str_decode(dn->devid, &devidp, &minorname);
718 if (ret != 0) {
719 /* failed to decode the devid */
720 goto out;
721 }
722
723 sn = dn->side_names;
724 if (sn == NULL) {
725 dn->side_names_key = MD_KEYWILD;
726 continue;
727 }
728
729 if ((dn->side_names_key = add_name(local_sp, SKEW, MD_KEYWILD,
730 sn->dname, sn->mnum, sn->cname, minorname, devidp,
731 ep)) == -1) {
732 devid_free(devidp);
733 devid_str_free(minorname);
734 goto out;
735 }
736
737 devid_free(devidp);
738 devid_str_free(minorname);
739
740 /* Create the drive record */
741 (void) memset(&req, 0, sizeof (req));
742 METAD_SETUP_DR(MD_DB_CREATE, 0);
743 req.ur_size = sizeof (*dr);
744 if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
745 (void) mdstealerror(ep, &req.ur_mde);
746 goto out;
747 }
748
749 /* Fill in the drive record values */
750 dr = Zalloc(sizeof (*dr));
751 dr->dr_selfid = req.ur_recid;
752 dr->dr_dbcnt = p->dd_dbcnt;
753 dr->dr_dbsize = p->dd_dbsize;
754 dr->dr_key = dn->side_names_key;
755
756 dr->dr_ctime = timestamp;
757 dr->dr_genid = genid;
758 dr->dr_revision = MD_DRIVE_RECORD_REVISION;
759 dr->dr_flags = MD_DR_OK;
760 if (p->dd_flags & MD_DR_UNRSLV_REPLICATED) {
761 dr->dr_flags |= MD_DR_UNRSLV_REPLICATED;
762 sr->sr_flags |= MD_SR_UNRSLV_REPLICATED;
763 }
764
765 /* Link the drive records and fill in in-core data */
766 dr_cache_add(sr, dr);
767
768 dev = NODEV64;
769 if ((meta_replicaslice(dn, &rep_slice, &xep) == 0) &&
770 ((np = metaslicename(dn, rep_slice, &xep)) != NULL))
771 dev = np->dev;
772 else
773 mdclrerror(&xep);
774
775 SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_REMOVE, SVM_TAG_DRIVE,
776 MD_LOCAL_SET, dev);
777 SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_DRIVE,
778 sr->sr_setno, dev);
779 }
780
781 /* Commit all the records atomically */
782 commitset(sr, TRUE, ep);
783 free_sr(sr);
784 return;
785
786 out:
787 /* If failures, remove drive records. */
788 dr = tdr = sr->sr_drivechain;
789 while (dr != NULL) {
790 tdr = dr->dr_next;
791 if (del_name(local_sp, 0, dr->dr_key, &xep))
792 mdclrerror(&xep);
793 sr_del_drv(sr, dr->dr_selfid);
794 dr = tdr;
795 }
796 }
797
798 static void
adddrvs(char * setname,md_drive_desc * dd,md_timeval32_t timestamp,ulong_t genid,md_error_t * ep)799 adddrvs(
800 char *setname,
801 md_drive_desc *dd,
802 md_timeval32_t timestamp,
803 ulong_t genid,
804 md_error_t *ep
805 )
806 {
807 mddb_userreq_t req;
808 md_drive_record *dr;
809 md_set_record *sr;
810 md_drive_desc *p;
811 mddrivename_t *dn;
812 mdname_t *np;
813 md_dev64_t dev;
814 md_error_t xep = mdnullerror;
815 int i;
816
817 if ((sr = getsetbyname(setname, ep)) == NULL)
818 return;
819
820 if (MD_MNSET_REC(sr))
821 i = 0;
822 else {
823 /* get thisside */
824 for (i = 0; i < MD_MAXSIDES; i++) {
825 if (sr->sr_nodes[i][0] == '\0')
826 continue;
827 if (strcmp(mynode(), sr->sr_nodes[i]) == 0)
828 break;
829 }
830
831 if (i == MD_MAXSIDES) {
832 /* so find the first free slot! */
833 for (i = 0; i < MD_MAXSIDES; i++) {
834 if (sr->sr_nodes[i][0] == '\0')
835 break;
836 }
837 }
838 }
839
840 for (p = dd; p != NULL; p = p->dd_next) {
841 uint_t rep_slice;
842
843 dn = p->dd_dnp;
844
845 /* Add the per side names to the local db */
846 if (add_sidenamelist(dn, (side_t)i, sr, ep)) {
847 free_sr(sr);
848 return;
849 }
850
851 /* Create the drive record */
852 (void) memset(&req, 0, sizeof (req));
853 METAD_SETUP_DR(MD_DB_CREATE, 0);
854 req.ur_size = sizeof (*dr);
855 if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
856 (void) mdstealerror(ep, &req.ur_mde);
857 free_sr(sr);
858 return;
859 }
860
861 /* Fill in the drive record values */
862 dr = Zalloc(sizeof (*dr));
863 dr->dr_selfid = req.ur_recid;
864 dr->dr_dbcnt = p->dd_dbcnt;
865 dr->dr_dbsize = p->dd_dbsize;
866 dr->dr_key = dn->side_names_key;
867
868 dr->dr_ctime = timestamp;
869 dr->dr_genid = genid;
870 dr->dr_revision = MD_DRIVE_RECORD_REVISION;
871 dr->dr_flags = MD_DR_ADD;
872
873 /* Link the drive records and fill in in-core data */
874 dr_cache_add(sr, dr);
875
876 dev = NODEV64;
877 if ((meta_replicaslice(dn, &rep_slice, &xep) == 0) &&
878 ((np = metaslicename(dn, rep_slice, &xep)) != NULL))
879 dev = np->dev;
880 else
881 mdclrerror(&xep);
882
883 SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_REMOVE, SVM_TAG_DRIVE,
884 MD_LOCAL_SET, dev);
885 SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_DRIVE,
886 sr->sr_setno, dev);
887 }
888
889 /* Commit all the records atomically */
890 commitset(sr, TRUE, ep);
891 free_sr(sr);
892 }
893
894 /*
895 * add 1 or more drive records to a set.
896 */
897 bool_t
mdrpc_adddrvs_common(mdrpc_drives_2_args_r1 * args,mdrpc_generic_res * res,struct svc_req * rqstp)898 mdrpc_adddrvs_common(
899 mdrpc_drives_2_args_r1 *args,
900 mdrpc_generic_res *res,
901 struct svc_req *rqstp /* RPC stuff */
902 )
903 {
904 md_error_t *ep = &res->status;
905 int err;
906 int op_mode = W_OK;
907
908 /* setup, check permissions */
909 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
910 return (FALSE);
911 else if (err != 0)
912 return (TRUE);
913
914 if (check_set_lock(op_mode, args->cl_sk, ep))
915 return (TRUE);
916
917 /* doit */
918 adddrvs(args->sp->setname, args->drivedescs, args->timestamp,
919 args->genid, ep);
920
921 err = svc_fini(ep);
922
923 return (TRUE);
924 }
925
926 /*
927 * version 1 of the remote procedure. This procedure is called if the
928 * client is running in version 1. We first convert version 1 arguments
929 * into version 2 arguments and then call the common remote procedure.
930 */
931 bool_t
mdrpc_adddrvs_1_svc(mdrpc_drives_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)932 mdrpc_adddrvs_1_svc(
933 mdrpc_drives_args *args,
934 mdrpc_generic_res *res,
935 struct svc_req *rqstp /* RPC stuff */
936 )
937 {
938 bool_t retval;
939 mdrpc_drives_2_args_r1 v2_args;
940
941 /* allocate memory */
942 alloc_newdrvdesc(args->drivedescs, &v2_args.drivedescs);
943 (void) memset(res, 0, sizeof (*res));
944
945 /* build args */
946 v2_args.cl_sk = args->cl_sk;
947 v2_args.sp = args->sp;
948 /* convert v1 args to v2 (revision 1) args */
949 meta_conv_drvdesc_old2new(args->drivedescs, v2_args.drivedescs);
950 v2_args.timestamp = args->timestamp;
951 v2_args.genid = args->genid;
952
953 retval = mdrpc_adddrvs_common(&v2_args, res, rqstp);
954
955 free_newdrvdesc(v2_args.drivedescs);
956
957 return (retval);
958 }
959
960 bool_t
mdrpc_adddrvs_2_svc(mdrpc_drives_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)961 mdrpc_adddrvs_2_svc(
962 mdrpc_drives_2_args *args,
963 mdrpc_generic_res *res,
964 struct svc_req *rqstp /* RPC stuff */
965 )
966 {
967 (void) memset(res, 0, sizeof (*res));
968 switch (args->rev) {
969 case MD_METAD_ARGS_REV_1:
970 return (mdrpc_adddrvs_common(
971 &args->mdrpc_drives_2_args_u.rev1, res, rqstp));
972 default:
973 return (FALSE);
974 }
975 }
976
977 /*
978 * add 1 or more drive records to a set when importing.
979 */
980 bool_t
mdrpc_imp_adddrvs_2_svc(mdrpc_drives_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)981 mdrpc_imp_adddrvs_2_svc(
982 mdrpc_drives_2_args *args,
983 mdrpc_generic_res *res,
984 struct svc_req *rqstp /* RPC stuff */
985 )
986 {
987 mdrpc_drives_2_args_r1 *v2_args;
988 md_error_t *ep = &res->status;
989 int err;
990 int op_mode = W_OK;
991
992 (void) memset(res, 0, sizeof (*res));
993 switch (args->rev) {
994 case MD_METAD_ARGS_REV_1:
995 v2_args = &args->mdrpc_drives_2_args_u.rev1;
996 if (v2_args == NULL) {
997 return (FALSE);
998 }
999 break;
1000 default:
1001 return (FALSE);
1002 }
1003
1004 /* setup, check permissions */
1005 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
1006 return (FALSE);
1007 else if (err != 0)
1008 return (TRUE);
1009
1010 if (check_set_lock(op_mode, v2_args->cl_sk, ep))
1011 return (TRUE);
1012
1013 /* doit */
1014 imp_adddrvs(v2_args->sp->setname, v2_args->drivedescs,
1015 v2_args->timestamp, v2_args->genid, ep);
1016
1017 err = svc_fini(ep);
1018
1019 return (TRUE);
1020 }
1021
1022 static void
addhosts(char * setname,int node_c,char ** node_v,int version,md_error_t * ep)1023 addhosts(
1024 char *setname,
1025 int node_c,
1026 char **node_v,
1027 int version, /* RPC version of calling routine */
1028 md_error_t *ep
1029 )
1030 {
1031 mddb_userreq_t req;
1032 md_set_record *sr;
1033 int i, j;
1034 md_mnset_record *mnsr;
1035 md_mnnode_record *nr;
1036 mddb_set_node_params_t snp;
1037 int nodecnt;
1038 mndiskset_membershiplist_t *nl, *nl2;
1039
1040 if ((sr = getsetbyname(setname, ep)) == NULL)
1041 return;
1042
1043 /* Do MN operation if rpc version supports it and if a MN set */
1044 if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
1045 mnsr = (md_mnset_record *)sr;
1046 /*
1047 * Verify nodes are in membership list on THIS node.
1048 * Initiating node has verified that nodes are in membership
1049 * list on the initiating node.
1050 * Get membershiplist from API routine. If there's
1051 * an error, fail to add hosts and pass back error.
1052 */
1053 if (meta_read_nodelist(&nodecnt, &nl, ep) == -1) {
1054 free_sr(sr);
1055 return;
1056 }
1057 /* Verify that all nodes are in member list */
1058 for (i = 0; i < node_c; i++) {
1059 /*
1060 * If node in list isn't a member of the membership,
1061 * just return error.
1062 */
1063 if (meta_is_member(node_v[i], NULL, nl) == 0) {
1064 meta_free_nodelist(nl);
1065 (void) mddserror(ep, MDE_DS_NOTINMEMBERLIST,
1066 sr->sr_setno, node_v[i], NULL, setname);
1067 free_sr(sr);
1068 return;
1069 }
1070 }
1071 }
1072
1073 for (i = 0; i < node_c; i++) {
1074 /* Do MN operation if rpc version supports it and if a MN set */
1075 if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
1076 mnsr = (md_mnset_record *)sr;
1077 /* Create the node record */
1078 (void) memset(&req, 0, sizeof (req));
1079 METAD_SETUP_NR(MD_DB_CREATE, 0);
1080 req.ur_size = sizeof (*nr);
1081 if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL)
1082 != 0) {
1083 (void) mdstealerror(ep, &req.ur_mde);
1084 meta_free_nodelist(nl);
1085 free_sr(sr);
1086 return;
1087 }
1088
1089 nr = Zalloc(sizeof (*nr));
1090 nr->nr_revision = MD_MNNODE_RECORD_REVISION;
1091 nr->nr_selfid = req.ur_recid;
1092 nr->nr_ctime = sr->sr_ctime;
1093 nr->nr_genid = sr->sr_genid;
1094 nr->nr_flags = MD_MN_NODE_ADD;
1095 nl2 = nl;
1096 while (nl2) {
1097 if (strcmp(nl2->msl_node_name, node_v[i])
1098 == 0) {
1099 nr->nr_nodeid = nl2->msl_node_id;
1100 break;
1101 }
1102 nl2 = nl2->next;
1103 }
1104
1105 (void) strcpy(nr->nr_nodename, node_v[i]);
1106
1107 /*
1108 * When a node is added to a MN diskset, set the
1109 * nodeid of this node in the md_set structure
1110 * in the kernel.
1111 */
1112 if (strcmp(nr->nr_nodename, mynode()) == 0) {
1113 (void) memset(&snp, 0, sizeof (snp));
1114 snp.sn_nodeid = nr->nr_nodeid;
1115 snp.sn_setno = mnsr->sr_setno;
1116 if (metaioctl(MD_MN_SET_NODEID, &snp,
1117 &snp.sn_mde, NULL) != 0) {
1118 (void) mdstealerror(ep, &snp.sn_mde);
1119 meta_free_nodelist(nl);
1120 free_sr(sr);
1121 return;
1122 }
1123 }
1124
1125 /* Link the node records and fill in in-core data */
1126 mnnr_cache_add(mnsr, nr);
1127
1128 SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_HOST,
1129 mnsr->sr_setno, nr->nr_nodeid);
1130 } else {
1131 for (j = 0; j < MD_MAXSIDES; j++) {
1132 if (sr->sr_nodes[j][0] != '\0')
1133 continue;
1134 (void) strcpy(sr->sr_nodes[j], node_v[i]);
1135 SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD,
1136 SVM_TAG_HOST, sr->sr_setno, j);
1137 break;
1138 }
1139 }
1140 }
1141 /* Do MN operation if rpc version supports it and if a MN set */
1142 if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
1143 meta_free_nodelist(nl);
1144 }
1145
1146 (void) memset(&req, '\0', sizeof (req));
1147
1148 METAD_SETUP_SR(MD_DB_SETDATA, sr->sr_selfid)
1149
1150 /* Do MN operation if rpc version supports it and if a MN set */
1151 if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
1152 req.ur_size = sizeof (*mnsr);
1153 } else {
1154 req.ur_size = sizeof (*sr);
1155 }
1156 req.ur_data = (uintptr_t)sr;
1157 if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
1158 (void) mdstealerror(ep, &req.ur_mde);
1159 free_sr(sr);
1160 return;
1161 }
1162
1163 commitset(sr, TRUE, ep);
1164
1165 free_sr(sr);
1166 }
1167
1168 /*
1169 * add 1 or more hosts to a set.
1170 */
1171 bool_t
mdrpc_addhosts_common(mdrpc_host_args * args,mdrpc_generic_res * res,struct svc_req * rqstp,int version)1172 mdrpc_addhosts_common(
1173 mdrpc_host_args *args,
1174 mdrpc_generic_res *res,
1175 struct svc_req *rqstp, /* RPC stuff */
1176 int version /* RPC version */
1177 )
1178 {
1179 md_error_t *ep = &res->status;
1180 int err;
1181 int op_mode = W_OK;
1182
1183 /* setup, check permissions */
1184 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
1185 return (FALSE);
1186 else if (err != 0)
1187 return (TRUE);
1188
1189 if (check_set_lock(op_mode, args->cl_sk, ep))
1190 return (TRUE);
1191
1192 /* doit */
1193 addhosts(args->sp->setname, args->hosts.hosts_len,
1194 args->hosts.hosts_val, version, ep);
1195
1196 err = svc_fini(ep);
1197
1198 return (TRUE);
1199 }
1200
1201 bool_t
mdrpc_addhosts_1_svc(mdrpc_host_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)1202 mdrpc_addhosts_1_svc(
1203 mdrpc_host_args *args,
1204 mdrpc_generic_res *res,
1205 struct svc_req *rqstp /* RPC stuff */
1206 )
1207 {
1208 /* Pass RPC version (METAD_VERSION) to common routine */
1209 (void) memset(res, 0, sizeof (*res));
1210 return (mdrpc_addhosts_common(args, res, rqstp, METAD_VERSION));
1211 }
1212
1213 bool_t
mdrpc_addhosts_2_svc(mdrpc_host_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)1214 mdrpc_addhosts_2_svc(
1215 mdrpc_host_2_args *args,
1216 mdrpc_generic_res *res,
1217 struct svc_req *rqstp /* RPC stuff */
1218 )
1219 {
1220 (void) memset(res, 0, sizeof (*res));
1221 switch (args->rev) {
1222 case MD_METAD_ARGS_REV_1:
1223 /* Pass RPC version (METAD_VERSION_DEVID) to common routine */
1224 return (mdrpc_addhosts_common(
1225 &args->mdrpc_host_2_args_u.rev1, res,
1226 rqstp, METAD_VERSION_DEVID));
1227 default:
1228 return (FALSE);
1229 }
1230 }
1231
1232 static void
createset(mdsetname_t * sp,md_node_nm_arr_t nodes,md_timeval32_t timestamp,ulong_t genid,md_error_t * ep)1233 createset(
1234 mdsetname_t *sp,
1235 md_node_nm_arr_t nodes,
1236 md_timeval32_t timestamp,
1237 ulong_t genid,
1238 md_error_t *ep
1239 )
1240 {
1241 mddb_userreq_t req;
1242 md_set_record *sr;
1243 int i;
1244
1245 (void) memset(&req, 0, sizeof (req));
1246 METAD_SETUP_SR(MD_DB_CREATE, 0);
1247 req.ur_size = sizeof (*sr);
1248 if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
1249 (void) mdstealerror(ep, &req.ur_mde);
1250 return;
1251 }
1252
1253 sr = Zalloc(sizeof (*sr));
1254
1255 sr->sr_selfid = req.ur_recid;
1256 sr->sr_setno = sp->setno;
1257 (void) strcpy(sr->sr_setname, sp->setname);
1258
1259 SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_CREATE, SVM_TAG_SET, sp->setno,
1260 NODEV64);
1261
1262 (void) meta_smf_enable(META_SMF_DISKSET, NULL);
1263
1264 for (i = 0; i < MD_MAXSIDES; i++) {
1265 (void) strcpy(sr->sr_nodes[i], nodes[i]);
1266 /* Skip empty slots */
1267 if (sr->sr_nodes[i][0] == '\0')
1268 continue;
1269 SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_HOST, sp->setno,
1270 i);
1271 }
1272
1273 sr->sr_ctime = timestamp;
1274 sr->sr_genid = genid;
1275 sr->sr_revision = MD_SET_RECORD_REVISION;
1276 sr->sr_flags |= MD_SR_ADD;
1277
1278 sr->sr_mhiargs = defmhiargs;
1279
1280 sr_cache_add(sr);
1281
1282 commitset(sr, TRUE, ep);
1283 }
1284
1285 static void
mncreateset(mdsetname_t * sp,md_mnnode_desc * nodelist,md_timeval32_t timestamp,ulong_t genid,md_node_nm_t master_nodenm,int master_nodeid,md_error_t * ep)1286 mncreateset(
1287 mdsetname_t *sp,
1288 md_mnnode_desc *nodelist,
1289 md_timeval32_t timestamp,
1290 ulong_t genid,
1291 md_node_nm_t master_nodenm,
1292 int master_nodeid,
1293 md_error_t *ep
1294 )
1295 {
1296 mddb_userreq_t req;
1297 md_mnset_record *mnsr;
1298 md_mnnode_record *nr;
1299 md_mnnode_desc *nd;
1300 mddb_set_node_params_t snp;
1301 int nodecnt;
1302 mndiskset_membershiplist_t *nl;
1303
1304 /*
1305 * Validate that nodes in set being created are in the
1306 * membership list on THIS node.
1307 * Initiating node has verified that nodes are in membership
1308 * list on the initiating node.
1309 * Get membershiplist from API routine. If there's
1310 * an error, fail to add set and pass back error.
1311 */
1312 if (meta_read_nodelist(&nodecnt, &nl, ep) == -1) {
1313 return;
1314 }
1315 /* Verify that all nodes are in member list */
1316 nd = nodelist;
1317 while (nd) {
1318 /*
1319 * If node in list isn't a member of the membership,
1320 * just return error.
1321 */
1322 if (meta_is_member(nd->nd_nodename, 0, nl) == 0) {
1323 meta_free_nodelist(nl);
1324 (void) mddserror(ep, MDE_DS_NOTINMEMBERLIST,
1325 sp->setno, nd->nd_nodename, NULL, sp->setname);
1326 return;
1327 }
1328 nd = nd->nd_next;
1329 }
1330 meta_free_nodelist(nl);
1331
1332 (void) memset(&req, 0, sizeof (req));
1333 METAD_SETUP_SR(MD_DB_CREATE, 0);
1334 req.ur_size = sizeof (*mnsr);
1335 if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
1336 (void) mdstealerror(ep, &req.ur_mde);
1337 return;
1338 }
1339
1340 mnsr = Zalloc(sizeof (*mnsr));
1341 mnsr->sr_selfid = req.ur_recid;
1342 mnsr->sr_setno = sp->setno;
1343 (void) strlcpy(mnsr->sr_setname, sp->setname, MD_MAX_SETNAME);
1344
1345 SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_CREATE, SVM_TAG_SET, sp->setno,
1346 NODEV64);
1347
1348 (void) meta_smf_enable(META_SMF_DISKSET | META_SMF_MN_DISKSET, NULL);
1349
1350 nd = nodelist;
1351 while (nd) {
1352 /* Create the node record */
1353 (void) memset(&req, 0, sizeof (req));
1354 METAD_SETUP_NR(MD_DB_CREATE, 0);
1355 req.ur_size = sizeof (*nr);
1356 if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
1357 /* Frees mnsr and any alloc'd node records */
1358 free_sr((struct md_set_record *)mnsr);
1359 (void) mdstealerror(ep, &req.ur_mde);
1360 return;
1361 }
1362
1363 nr = Zalloc(sizeof (*nr));
1364 nr->nr_revision = MD_MNNODE_RECORD_REVISION;
1365 nr->nr_selfid = req.ur_recid;
1366 nr->nr_ctime = timestamp;
1367 nr->nr_genid = genid;
1368 nr->nr_nodeid = nd->nd_nodeid;
1369 nr->nr_flags = nd->nd_flags;
1370 (void) strlcpy(nr->nr_nodename, nd->nd_nodename,
1371 MD_MAX_NODENAME);
1372
1373 /* Link the node records and fill in in-core data */
1374 mnnr_cache_add(mnsr, nr);
1375
1376 SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_HOST, sp->setno,
1377 nr->nr_nodeid);
1378
1379 nd = nd->nd_next;
1380 }
1381
1382 /*
1383 * For backward compatibility, fill in mynode name
1384 * as the only name in the sr_nodes array. This
1385 * allows the pre-MNdiskset code to see that there
1386 * is a node in this diskset. This will keep the
1387 * pre-MNdiskset code from removing this set.
1388 */
1389 (void) strlcpy(mnsr->sr_nodes_bw_compat[0], mynode(), MD_MAX_NODENAME);
1390
1391 mnsr->sr_ctime = timestamp;
1392 mnsr->sr_genid = genid;
1393 mnsr->sr_revision = MD_SET_RECORD_REVISION;
1394 mnsr->sr_flags |= MD_SR_ADD;
1395
1396 mnsr->sr_flags |= MD_SR_MN;
1397 (void) strcpy(mnsr->sr_master_nodenm, master_nodenm);
1398 mnsr->sr_master_nodeid = master_nodeid;
1399
1400 mnsr->sr_mhiargs = defmhiargs;
1401
1402 sr_cache_add((struct md_set_record *)mnsr);
1403
1404 commitset((struct md_set_record *)mnsr, TRUE, ep);
1405
1406 /*
1407 * When a set is created for the first time, the nodelist
1408 * will contain this node.
1409 * When a node is just being added to a set, the nodelist
1410 * will not contain this node. This node is added to the
1411 * set structure with a later call to addhosts.
1412 *
1413 * So, if the nodelist contains an entry for this node
1414 * then set the nodeid of this node in the md_set kernel
1415 * data structure.
1416 */
1417 nd = nodelist;
1418 while (nd) {
1419 if (strcmp(nd->nd_nodename, mynode()) == 0) {
1420 break;
1421 }
1422 nd = nd->nd_next;
1423 }
1424 if (nd) {
1425 (void) memset(&snp, 0, sizeof (snp));
1426 snp.sn_nodeid = nd->nd_nodeid;
1427 snp.sn_setno = sp->setno;
1428 if (metaioctl(MD_MN_SET_NODEID, &snp, &snp.sn_mde, NULL) != 0) {
1429 (void) mdstealerror(ep, &snp.sn_mde);
1430 return;
1431 }
1432 }
1433 }
1434
1435 /*
1436 * create a set on a host
1437 */
1438 bool_t
mdrpc_createset_common(mdrpc_createset_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)1439 mdrpc_createset_common(
1440 mdrpc_createset_args *args,
1441 mdrpc_generic_res *res,
1442 struct svc_req *rqstp /* RPC stuff */
1443 )
1444 {
1445 md_error_t *ep = &res->status;
1446 char stringbuf1[MAXPATHLEN];
1447 char stringbuf2[MAXPATHLEN];
1448 int err;
1449 int op_mode = W_OK;
1450
1451 /* setup, check permissions */
1452 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
1453 return (FALSE);
1454 else if (err != 0)
1455 return (TRUE);
1456
1457 if (check_set_lock(op_mode, args->cl_sk, ep))
1458 return (TRUE);
1459
1460 /* create the arguments for the symlink() and unlink() calls */
1461 (void) snprintf(stringbuf2, sizeof (stringbuf2), "/dev/md/%s",
1462 args->sp->setname);
1463 (void) snprintf(stringbuf1, sizeof (stringbuf1), "shared/%d",
1464 args->sp->setno);
1465
1466 /*
1467 * Since we already verified that the setname was OK, make sure to
1468 * cleanup before proceeding.
1469 */
1470 if (unlink(stringbuf2) == -1) {
1471 if (errno != ENOENT) {
1472 (void) mdsyserror(ep, errno, stringbuf2);
1473 return (TRUE);
1474 }
1475 }
1476
1477 /* create the set */
1478 createset(args->sp, args->nodes, args->timestamp, args->genid, ep);
1479
1480 if (! mdisok(ep))
1481 return (TRUE);
1482
1483 /* create the symlink */
1484 if (symlink(stringbuf1, stringbuf2) == -1)
1485 (void) mdsyserror(ep, errno, stringbuf2);
1486
1487 err = svc_fini(ep);
1488
1489 return (TRUE);
1490 }
1491
1492 bool_t
mdrpc_createset_1_svc(mdrpc_createset_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)1493 mdrpc_createset_1_svc(
1494 mdrpc_createset_args *args,
1495 mdrpc_generic_res *res,
1496 struct svc_req *rqstp /* RPC stuff */
1497 )
1498 {
1499 (void) memset(res, 0, sizeof (*res));
1500 return (mdrpc_createset_common(args, res, rqstp));
1501 }
1502
1503 bool_t
mdrpc_createset_2_svc(mdrpc_createset_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)1504 mdrpc_createset_2_svc(
1505 mdrpc_createset_2_args *args,
1506 mdrpc_generic_res *res,
1507 struct svc_req *rqstp /* RPC stuff */
1508 )
1509 {
1510 (void) memset(res, 0, sizeof (*res));
1511 switch (args->rev) {
1512 case MD_METAD_ARGS_REV_1:
1513 return (mdrpc_createset_common(
1514 &args->mdrpc_createset_2_args_u.rev1, res, rqstp));
1515 default:
1516 return (FALSE);
1517 }
1518 }
1519
1520 bool_t
mdrpc_mncreateset_common(mdrpc_mncreateset_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)1521 mdrpc_mncreateset_common(
1522 mdrpc_mncreateset_args *args,
1523 mdrpc_generic_res *res,
1524 struct svc_req *rqstp /* RPC stuff */
1525 )
1526 {
1527 md_error_t *ep = &res->status;
1528 char stringbuf1[MAXPATHLEN];
1529 char stringbuf2[MAXPATHLEN];
1530 int err;
1531 int op_mode = W_OK;
1532
1533 /* setup, check permissions */
1534 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
1535 return (FALSE);
1536 else if (err != 0)
1537 return (TRUE);
1538
1539 if (check_set_lock(op_mode, args->cl_sk, ep))
1540 return (TRUE);
1541
1542 /* create the arguments for the symlink() and unlink() calls */
1543 (void) snprintf(stringbuf2, sizeof (stringbuf2), "/dev/md/%s",
1544 args->sp->setname);
1545 (void) snprintf(stringbuf1, sizeof (stringbuf1), "shared/%d",
1546 args->sp->setno);
1547
1548 /*
1549 * Since we already verified that the setname was OK, make sure to
1550 * cleanup before proceeding.
1551 */
1552 if (unlink(stringbuf2) == -1) {
1553 if (errno != ENOENT) {
1554 (void) mdsyserror(ep, errno, stringbuf2);
1555 return (TRUE);
1556 }
1557 }
1558
1559 /* create the set */
1560 mncreateset(args->sp, args->nodelist, args->timestamp, args->genid,
1561 args->master_nodenm, args->master_nodeid, ep);
1562
1563 if (! mdisok(ep)) {
1564 return (TRUE);
1565 }
1566
1567 /* create the symlink */
1568 if (symlink(stringbuf1, stringbuf2) == -1)
1569 (void) mdsyserror(ep, errno, stringbuf2);
1570
1571 err = svc_fini(ep);
1572
1573 return (TRUE);
1574 }
1575
1576 bool_t
mdrpc_mncreateset_2_svc(mdrpc_mncreateset_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)1577 mdrpc_mncreateset_2_svc(
1578 mdrpc_mncreateset_2_args *args,
1579 mdrpc_generic_res *res,
1580 struct svc_req *rqstp /* RPC stuff */
1581 )
1582 {
1583 (void) memset(res, 0, sizeof (*res));
1584 switch (args->rev) {
1585 case MD_METAD_ARGS_REV_1:
1586 return (mdrpc_mncreateset_common(
1587 &args->mdrpc_mncreateset_2_args_u.rev1, res, rqstp));
1588 default:
1589 return (FALSE);
1590 }
1591 }
1592
1593 static void
del_drv_sidenms(mdsetname_t * sp,int version,md_error_t * ep)1594 del_drv_sidenms(
1595 mdsetname_t *sp,
1596 int version, /* RPC version of calling routine */
1597 md_error_t *ep
1598 )
1599 {
1600 md_set_record *sr;
1601 md_drive_desc *dd, *p;
1602 mddrivename_t *dn;
1603 mdsetname_t *local_sp;
1604 int i;
1605 int rb_mode = 0;
1606
1607 if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
1608 return;
1609
1610 if ((sr = getsetbyname(sp->setname, ep)) == NULL)
1611 return;
1612
1613 /* Do MN operation if rpc version supports it and if a MN set */
1614 if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
1615 /*
1616 * In the multi-node diskset, there are no diskset
1617 * entries in the local set for other nodes, so there's
1618 * nothing to do.
1619 */
1620 free_sr(sr);
1621 return;
1622 }
1623
1624 if ((dd = metaget_drivedesc(sp, (MD_BASICNAME_OK | PRINT_FAST),
1625 ep)) == NULL) {
1626 if (! mdisdserror(ep, MDE_DS_HOSTNOSIDE)) {
1627 metaflushsetname(sp);
1628 if (! mdisok(ep)) {
1629 free_sr(sr);
1630 return;
1631 }
1632 /* we are supposed to have drives!!!! */
1633 assert(0);
1634 }
1635 rb_mode = 1;
1636 mdclrerror(ep);
1637 for (i = 0; i < MD_MAXSIDES; i++) {
1638 /* Skip empty sides of the diskset */
1639 if (sr->sr_nodes[i][0] == '\0')
1640 continue;
1641 dd = metaget_drivedesc_sideno(sp, i,
1642 (MD_BASICNAME_OK | PRINT_FAST), ep);
1643 /* Got dd, get out of loop */
1644 if (dd != NULL)
1645 break;
1646
1647 /* some error occurred, get out of loop */
1648 if (! mdisok(ep))
1649 break;
1650 }
1651 /*
1652 * At this point, we have one of three possibilities:
1653 * 1) dd != NULL (we have found drives using an alternate
1654 * side.)
1655 * 2) dd == NULL (no drives) && mdisok(ep) : assert(0)
1656 * 3) dd == NULL (no drives) && ! mdisok(ep) : return
1657 * error information to caller.
1658 */
1659 if (dd == NULL) {
1660 metaflushsetname(sp);
1661 if (! mdisok(ep)) {
1662 free_sr(sr);
1663 return;
1664 }
1665 /* we are supposed to have drives!!!! */
1666 assert(0);
1667 }
1668 }
1669
1670 /*
1671 * Let's run through each drive descriptor, and delete the
1672 * sidename for all sides that are not in the sr_nodes array.
1673 * We will ignore errors, cause the empty side may not
1674 * have had any names to begin with.
1675 */
1676 for (p = dd; p != NULL; p = p->dd_next) {
1677 dn = p->dd_dnp;
1678
1679 for (i = 0; i < MD_MAXSIDES; i++) {
1680 /* Skip existing sides of the diskset */
1681 if (!rb_mode && sr->sr_nodes[i][0] != '\0')
1682 continue;
1683 /* An empty side, delete the sidename */
1684 if (del_name(local_sp, i+SKEW,
1685 dn->side_names_key, ep)) {
1686 if (!mdissyserror(ep, ENOENT)) {
1687 free_sr(sr);
1688 return;
1689 }
1690 mdclrerror(ep);
1691 }
1692 }
1693 }
1694 free_sr(sr);
1695 metaflushsetname(sp);
1696 }
1697
1698 /*
1699 * delete 1 or more sidenames per drive desc, from the local namespace
1700 */
1701 bool_t
mdrpc_del_drv_sidenms_common(mdrpc_sp_args * args,mdrpc_generic_res * res,struct svc_req * rqstp,int version)1702 mdrpc_del_drv_sidenms_common(
1703 mdrpc_sp_args *args,
1704 mdrpc_generic_res *res,
1705 struct svc_req *rqstp, /* RPC stuff */
1706 int version /* RPC version */
1707 )
1708 {
1709 md_error_t *ep = &res->status;
1710 int err;
1711 int op_mode = W_OK;
1712
1713 /* setup, check permissions */
1714 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
1715 return (FALSE);
1716 else if (err != 0)
1717 return (TRUE);
1718
1719 if (check_set_lock(op_mode, args->cl_sk, ep))
1720 return (TRUE);
1721
1722 /* doit */
1723 del_drv_sidenms(args->sp, version, ep);
1724
1725 err = svc_fini(ep);
1726
1727 return (TRUE);
1728 }
1729
1730 bool_t
mdrpc_del_drv_sidenms_1_svc(mdrpc_sp_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)1731 mdrpc_del_drv_sidenms_1_svc(
1732 mdrpc_sp_args *args,
1733 mdrpc_generic_res *res,
1734 struct svc_req *rqstp /* RPC stuff */
1735 )
1736 {
1737 (void) memset(res, 0, sizeof (*res));
1738 /* Pass RPC version (METAD_VERSION) to common routine */
1739 return (mdrpc_del_drv_sidenms_common(args, res, rqstp, METAD_VERSION));
1740 }
1741
1742 bool_t
mdrpc_del_drv_sidenms_2_svc(mdrpc_sp_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)1743 mdrpc_del_drv_sidenms_2_svc(
1744 mdrpc_sp_2_args *args,
1745 mdrpc_generic_res *res,
1746 struct svc_req *rqstp /* RPC stuff */
1747 )
1748 {
1749 (void) memset(res, 0, sizeof (*res));
1750 switch (args->rev) {
1751 case MD_METAD_ARGS_REV_1:
1752 /* Pass RPC version (METAD_VERSION_DEVID) to common routine */
1753 return (mdrpc_del_drv_sidenms_common(
1754 &args->mdrpc_sp_2_args_u.rev1, res,
1755 rqstp, METAD_VERSION_DEVID));
1756 default:
1757 return (FALSE);
1758 }
1759 }
1760
1761 static int
del_sidenamelist(md_set_record * sr,mddrivename_t * dn,md_error_t * ep)1762 del_sidenamelist(
1763 md_set_record *sr,
1764 mddrivename_t *dn,
1765 md_error_t *ep
1766 )
1767 {
1768 mdsidenames_t *sn;
1769 mdsetname_t *local_sp;
1770 md_mnset_record *mnsr;
1771 md_mnnode_record *nr;
1772
1773 if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
1774 return (-1);
1775
1776 for (sn = dn->side_names; sn != NULL; sn = sn->next)
1777 if (MD_MNSET_REC(sr)) {
1778 mnsr = (struct md_mnset_record *)sr;
1779 /*
1780 * Only delete side name entries for this node
1781 * on a multi-node diskset.
1782 */
1783 nr = mnsr->sr_nodechain;
1784 while (nr) {
1785 if (nr->nr_nodeid == sn->sideno) {
1786 if (del_name(local_sp, sn->sideno,
1787 dn->side_names_key, ep) == -1)
1788 mdclrerror(ep); /* ignore err */
1789 break;
1790 }
1791 nr = nr->nr_next;
1792 }
1793 } else {
1794 if (del_name(local_sp, sn->sideno+SKEW,
1795 dn->side_names_key, ep) == -1)
1796 mdclrerror(ep); /* ignore errors */
1797 }
1798
1799 dn->side_names_key = MD_KEYBAD;
1800 return (0);
1801 }
1802
1803 static void
deldrvs(char * setname,md_drive_desc * dd,md_error_t * ep)1804 deldrvs(
1805 char *setname,
1806 md_drive_desc *dd,
1807 md_error_t *ep
1808 )
1809 {
1810 mdsetname_t *sp;
1811 md_set_record *sr;
1812 md_drive_record *dr;
1813 mddb_userreq_t req;
1814 md_drive_desc *p;
1815 mddrivename_t *dn, *dn1;
1816 side_t sideno;
1817 int i;
1818 int rb_mode = 0;
1819 mdname_t *np;
1820 md_dev64_t dev;
1821 md_error_t xep = mdnullerror;
1822 ddi_devid_t devid_remote = NULL;
1823 ddi_devid_t devid_local = NULL;
1824 int devid_same = -1;
1825 int using_devid = 0;
1826 md_mnnode_record *nr;
1827 md_mnset_record *mnsr;
1828
1829 if ((sp = metasetname(setname, ep)) == NULL)
1830 return;
1831
1832 metaflushsetname(sp);
1833
1834 if ((sideno = getmyside(sp, ep)) == MD_SIDEWILD) {
1835 if (! mdisdserror(ep, MDE_DS_HOSTNOSIDE))
1836 return;
1837 mdclrerror(ep);
1838 /*
1839 * The set record is incomplete, so we need to make note
1840 * here so that we can do some special handling later.
1841 */
1842 rb_mode = 1;
1843 }
1844
1845 if ((sr = getsetbyname(setname, ep)) == NULL)
1846 return;
1847
1848 if (dd->dd_dnp == NULL)
1849 return;
1850
1851 /*
1852 * The system is either all devid or all
1853 * non-devid so we determine this by looking
1854 * at the first item in the list.
1855 *
1856 * For did disks, the dd_dnp->devid is a valid pointer which
1857 * points to a '' string of devid. We need to check this
1858 * before set the using_devid.
1859 */
1860 if ((dd->dd_dnp->devid != NULL) && (dd->dd_dnp->devid[0] != '\0') &&
1861 (!(MD_MNSET_REC(sr))))
1862 using_devid = 1;
1863
1864 for (p = dd; p != NULL; p = p->dd_next) {
1865 dn = p->dd_dnp;
1866 devid_remote = NULL;
1867
1868 if (dn->devid != NULL && (strlen(dn->devid) != 0) &&
1869 using_devid) {
1870 /*
1871 * We have a devid so use it
1872 */
1873 (void) devid_str_decode(dn->devid, &devid_remote, NULL);
1874 }
1875
1876 /* check to make sure using_devid agrees with reality... */
1877 if ((using_devid == 1) && (devid_remote == NULL)) {
1878 /* something went really wrong. Can't process */
1879 (void) mddserror(ep, MDE_DS_INVALIDDEVID, sp->setno,
1880 mynode(), dn->cname, sp->setname);
1881 return;
1882 }
1883
1884 for (dr = sr->sr_drivechain; dr; dr = dr->dr_next) {
1885 devid_same = -1;
1886
1887 if (! rb_mode) {
1888 dn1 = metadrivename_withdrkey(sp, sideno,
1889 dr->dr_key, MD_BASICNAME_OK, ep);
1890 if (dn1 == NULL) {
1891 free_sr(sr);
1892 if (devid_remote)
1893 devid_free(devid_remote);
1894 return;
1895 }
1896 } else {
1897 /*
1898 * Handle special case here where sidenames
1899 * from other hosts for this drive may be
1900 * in the local mddb, but there is no
1901 * sidename entry for this host for this drive.
1902 * This could have happened if the node
1903 * panic'd between the 2 operations when
1904 * adding this node to the set.
1905 * So, delete all sidename entries for this
1906 * drive.
1907 */
1908 if (MD_MNSET_REC(sr)) {
1909 mnsr = (struct md_mnset_record *)sr;
1910 nr = mnsr->sr_nodechain;
1911 while (nr) {
1912 /* We delete all dr sides */
1913 dn1 = metadrivename_withdrkey(
1914 sp, nr->nr_nodeid,
1915 dr->dr_key,
1916 MD_BASICNAME_OK, ep);
1917
1918 /* if we do, get out of loop */
1919 if (dn1 != NULL)
1920 break;
1921
1922 /* save error for later */
1923 (void) mdstealerror(&xep, ep);
1924
1925 mdclrerror(ep);
1926
1927 nr = nr->nr_next;
1928 }
1929 } else {
1930 /*
1931 * Handle special case here
1932 * for traditional diskset
1933 */
1934 for (i = 0; i < MD_MAXSIDES; i++) {
1935 /* We delete all dr sides */
1936 dn1 = metadrivename_withdrkey(
1937 sp, i, dr->dr_key,
1938 MD_BASICNAME_OK, ep);
1939
1940 /* if we do, get out of loop */
1941 if (dn1 != NULL)
1942 break;
1943
1944 /* save error for later */
1945 (void) mdstealerror(&xep, ep);
1946
1947 mdclrerror(ep);
1948 }
1949 }
1950
1951 if (dn1 == NULL) {
1952 (void) mdstealerror(ep, &xep);
1953 free_sr(sr);
1954 if (devid_remote)
1955 devid_free(devid_remote);
1956 return;
1957 }
1958
1959 if (!using_devid)
1960 mdclrerror(ep);
1961 }
1962
1963 if (dn1->devid != NULL && using_devid) {
1964 if (devid_str_decode(dn1->devid, &devid_local,
1965 NULL) == 0) {
1966 devid_same = devid_compare(devid_remote,
1967 devid_local);
1968 devid_free(devid_local);
1969 }
1970 }
1971
1972 /*
1973 * Has the required disk been found - either the devids
1974 * match if devid are being used or the actual name of
1975 * the disk matches.
1976 */
1977 if ((using_devid && devid_same == 0) ||
1978 (!using_devid &&
1979 strcmp(dn->cname, dn1->cname) == 0)) {
1980 uint_t rep_slice;
1981
1982 dev = NODEV64;
1983 np = NULL;
1984 if (meta_replicaslice(dn1,
1985 &rep_slice, &xep) == 0) {
1986 np = metaslicename(dn1,
1987 rep_slice, &xep);
1988 }
1989
1990 if (np != NULL)
1991 dev = np->dev;
1992 else
1993 mdclrerror(&xep);
1994 break;
1995 }
1996 }
1997
1998 if (dr) {
1999 (void) memset(&req, 0, sizeof (req));
2000 METAD_SETUP_DR(MD_DB_DELETE, dr->dr_selfid)
2001 if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL)
2002 != 0) {
2003 (void) mdstealerror(ep, &req.ur_mde);
2004 if (devid_remote)
2005 devid_free(devid_remote);
2006 free_sr(sr);
2007 return;
2008 }
2009
2010 dr_cache_del(sr, dr->dr_selfid);
2011
2012 if (del_sidenamelist(sr, dn1, ep) == -1) {
2013 goto out;
2014 }
2015
2016 SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_REMOVE, SVM_TAG_DRIVE,
2017 sr->sr_setno, dev);
2018 SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_DRIVE,
2019 MD_LOCAL_SET, dev);
2020
2021 continue;
2022 }
2023
2024 if (devid_remote)
2025 devid_free(devid_remote);
2026 }
2027
2028 out:
2029 commitset(sr, TRUE, ep);
2030
2031 free_sr(sr);
2032 }
2033
2034 /*
2035 * delete 1 or more drive records from a host.
2036 */
2037 bool_t
mdrpc_deldrvs_common(mdrpc_drives_2_args_r1 * args,mdrpc_generic_res * res,struct svc_req * rqstp)2038 mdrpc_deldrvs_common(
2039 mdrpc_drives_2_args_r1 *args,
2040 mdrpc_generic_res *res,
2041 struct svc_req *rqstp /* RPC stuff */
2042 )
2043 {
2044 md_error_t *ep = &res->status;
2045 int err;
2046 int op_mode = W_OK;
2047
2048 /* setup, check permissions */
2049 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2050 return (FALSE);
2051 else if (err != 0)
2052 return (TRUE);
2053
2054 if (check_set_lock(op_mode, args->cl_sk, ep))
2055 return (TRUE);
2056
2057 /* doit */
2058 deldrvs(args->sp->setname, args->drivedescs, ep);
2059
2060 err = svc_fini(ep);
2061
2062 return (TRUE);
2063 }
2064
2065 /*
2066 * version 1 of the remote procedure. This procedure is called if the
2067 * client is running in version 1. We first convert version 1 arguments
2068 * into version 2 arguments and then call the common remote procedure.
2069 */
2070 bool_t
mdrpc_deldrvs_1_svc(mdrpc_drives_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)2071 mdrpc_deldrvs_1_svc(
2072 mdrpc_drives_args *args,
2073 mdrpc_generic_res *res,
2074 struct svc_req *rqstp /* RPC stuff */
2075 )
2076 {
2077 bool_t retval;
2078 mdrpc_drives_2_args_r1 v2_args;
2079
2080 /* allocate memory */
2081 alloc_newdrvdesc(args->drivedescs, &v2_args.drivedescs);
2082 (void) memset(res, 0, sizeof (*res));
2083
2084 /* build args */
2085 v2_args.cl_sk = args->cl_sk;
2086 v2_args.sp = args->sp;
2087 /* convert v1 args to v2 (revision 1) args */
2088 meta_conv_drvdesc_old2new(args->drivedescs, v2_args.drivedescs);
2089 v2_args.timestamp = args->timestamp;
2090 v2_args.genid = args->genid;
2091
2092 retval = mdrpc_deldrvs_common(&v2_args, res, rqstp);
2093
2094 free_newdrvdesc(v2_args.drivedescs);
2095
2096 return (retval);
2097 }
2098
2099 bool_t
mdrpc_deldrvs_2_svc(mdrpc_drives_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)2100 mdrpc_deldrvs_2_svc(
2101 mdrpc_drives_2_args *args,
2102 mdrpc_generic_res *res,
2103 struct svc_req *rqstp /* RPC stuff */
2104 )
2105 {
2106 (void) memset(res, 0, sizeof (*res));
2107 switch (args->rev) {
2108 case MD_METAD_ARGS_REV_1:
2109 return (mdrpc_deldrvs_common(
2110 &args->mdrpc_drives_2_args_u.rev1, res, rqstp));
2111 default:
2112 return (FALSE);
2113 }
2114 }
2115
2116 static void
delhosts(char * setname,int node_c,char ** node_v,int version,md_error_t * ep)2117 delhosts(
2118 char *setname,
2119 int node_c,
2120 char **node_v,
2121 int version, /* RPC version of calling routine */
2122 md_error_t *ep
2123 )
2124 {
2125 mddb_userreq_t req;
2126 md_set_record *sr;
2127 int i, j;
2128 md_mnset_record *mnsr;
2129 md_mnnode_record *nr;
2130
2131 if ((sr = getsetbyname(setname, ep)) == NULL)
2132 return;
2133
2134 for (i = 0; i < node_c; i++) {
2135 /* Do MN operation if rpc version supports it and if a MN set */
2136 if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
2137 mnsr = (struct md_mnset_record *)sr;
2138 nr = mnsr->sr_nodechain;
2139 while (nr) {
2140 if (strcmp(nr->nr_nodename, node_v[i]) == 0) {
2141 SE_NOTIFY(EC_SVM_CONFIG,
2142 ESC_SVM_REMOVE, SVM_TAG_HOST,
2143 sr->sr_setno, nr->nr_nodeid);
2144 (void) memset(&req, '\0', sizeof (req));
2145 METAD_SETUP_NR(MD_DB_DELETE,
2146 nr->nr_selfid);
2147 if (metaioctl(MD_DB_USERREQ, &req,
2148 &req.ur_mde, NULL) != 0) {
2149 (void) mdstealerror(ep,
2150 &req.ur_mde);
2151 free_sr(sr);
2152 return;
2153 }
2154 mnnr_cache_del(mnsr, nr->nr_selfid);
2155 break;
2156 }
2157 nr = nr->nr_next;
2158 }
2159 } else {
2160 for (j = 0; j < MD_MAXSIDES; j++) {
2161 if (sr->sr_nodes[j][0] == '\0')
2162 continue;
2163 if (strcmp(sr->sr_nodes[j], node_v[i]) != 0)
2164 continue;
2165 (void) memset(sr->sr_nodes[j], '\0',
2166 sizeof (sr->sr_nodes[j]));
2167 SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_REMOVE,
2168 SVM_TAG_HOST, sr->sr_setno, j);
2169 break;
2170 }
2171 }
2172 }
2173
2174 (void) memset(&req, '\0', sizeof (req));
2175 METAD_SETUP_SR(MD_DB_SETDATA, sr->sr_selfid)
2176 /* Do MN operation if rpc version supports it and if a MN set */
2177 if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
2178 req.ur_size = sizeof (*mnsr);
2179 } else {
2180 req.ur_size = sizeof (*sr);
2181 }
2182 req.ur_data = (uintptr_t)sr;
2183 if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
2184 (void) mdstealerror(ep, &req.ur_mde);
2185 free_sr(sr);
2186 return;
2187 }
2188
2189 commitset(sr, TRUE, ep);
2190 free_sr(sr);
2191 }
2192
2193 /*
2194 * delete 1 or more a hosts from a set.
2195 */
2196 bool_t
mdrpc_delhosts_common(mdrpc_host_args * args,mdrpc_generic_res * res,struct svc_req * rqstp,int version)2197 mdrpc_delhosts_common(
2198 mdrpc_host_args *args,
2199 mdrpc_generic_res *res,
2200 struct svc_req *rqstp, /* RPC stuff */
2201 int version /* RPC version */
2202 )
2203 {
2204 md_error_t *ep = &res->status;
2205 int err;
2206 int op_mode = W_OK;
2207
2208 /* setup, check permissions */
2209 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2210 return (FALSE);
2211 else if (err != 0)
2212 return (TRUE);
2213
2214 if (check_set_lock(op_mode, args->cl_sk, ep))
2215 return (TRUE);
2216
2217 /* doit */
2218 delhosts(args->sp->setname, args->hosts.hosts_len,
2219 args->hosts.hosts_val, version, ep);
2220
2221 err = svc_fini(ep);
2222
2223 return (TRUE);
2224 }
2225
2226 bool_t
mdrpc_delhosts_1_svc(mdrpc_host_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)2227 mdrpc_delhosts_1_svc(
2228 mdrpc_host_args *args,
2229 mdrpc_generic_res *res,
2230 struct svc_req *rqstp /* RPC stuff */
2231 )
2232 {
2233 (void) memset(res, 0, sizeof (*res));
2234 /* Pass RPC version (METAD_VERSION) to common routine */
2235 return (mdrpc_delhosts_common(args, res, rqstp, METAD_VERSION));
2236 }
2237
2238 bool_t
mdrpc_delhosts_2_svc(mdrpc_host_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)2239 mdrpc_delhosts_2_svc(
2240 mdrpc_host_2_args *args,
2241 mdrpc_generic_res *res,
2242 struct svc_req *rqstp /* RPC stuff */
2243 )
2244 {
2245 (void) memset(res, 0, sizeof (*res));
2246 switch (args->rev) {
2247 case MD_METAD_ARGS_REV_1:
2248 /* Pass RPC version (METAD_VERSION_DEVID) to common routine */
2249 return (mdrpc_delhosts_common(
2250 &args->mdrpc_host_2_args_u.rev1, res,
2251 rqstp, METAD_VERSION_DEVID));
2252 default:
2253 return (FALSE);
2254 }
2255 }
2256
2257 /*
2258 * delete a set.
2259 */
2260 bool_t
mdrpc_delset_common(mdrpc_sp_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)2261 mdrpc_delset_common(
2262 mdrpc_sp_args *args,
2263 mdrpc_generic_res *res,
2264 struct svc_req *rqstp /* RPC stuff */
2265 )
2266 {
2267 md_error_t *ep = &res->status;
2268 int err;
2269 int op_mode = W_OK;
2270
2271 /* setup, check permissions */
2272 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2273 return (FALSE);
2274 else if (err != 0)
2275 return (TRUE);
2276
2277 if (check_set_lock(op_mode, args->cl_sk, ep))
2278 return (TRUE);
2279
2280 /* doit */
2281 s_delset(args->sp->setname, ep);
2282
2283 err = svc_fini(ep);
2284
2285 return (TRUE);
2286 }
2287
2288 bool_t
mdrpc_delset_1_svc(mdrpc_sp_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)2289 mdrpc_delset_1_svc(
2290 mdrpc_sp_args *args,
2291 mdrpc_generic_res *res,
2292 struct svc_req *rqstp /* RPC stuff */
2293 )
2294 {
2295 (void) memset(res, 0, sizeof (*res));
2296 return (mdrpc_delset_common(args, res, rqstp));
2297 }
2298
2299 bool_t
mdrpc_delset_2_svc(mdrpc_sp_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)2300 mdrpc_delset_2_svc(
2301 mdrpc_sp_2_args *args,
2302 mdrpc_generic_res *res,
2303 struct svc_req *rqstp /* RPC stuff */
2304 )
2305 {
2306 (void) memset(res, 0, sizeof (*res));
2307 switch (args->rev) {
2308 case MD_METAD_ARGS_REV_1:
2309 return (mdrpc_delset_common(
2310 &args->mdrpc_sp_2_args_u.rev1, res, rqstp));
2311 default:
2312 return (FALSE);
2313 }
2314 }
2315
2316 /*
2317 * return device info
2318 */
2319 static void
devinfo(mdsetname_t * sp,mddrivename_t * dp,mdrpc_devinfo_2_res * res,md_error_t * ep)2320 devinfo(
2321 mdsetname_t *sp,
2322 mddrivename_t *dp,
2323 mdrpc_devinfo_2_res *res,
2324 md_error_t *ep
2325 )
2326 {
2327 mdname_t *np, *real_np;
2328
2329 if ((np = metaslicename(dp, MD_SLICE0, ep)) == NULL)
2330 return;
2331
2332 if ((real_np = metaname(&sp, np->bname, LOGICAL_DEVICE, ep)) == NULL)
2333 return;
2334
2335 res->dev = real_np->dev;
2336 (void) getdevstamp(dp, (long *)&res->vtime, ep);
2337 res->enc_devid = meta_get_devid(np->rname);
2338 }
2339
2340 bool_t
mdrpc_devinfo_common(mdrpc_devinfo_2_args_r1 * args,mdrpc_devinfo_2_res * res,struct svc_req * rqstp)2341 mdrpc_devinfo_common(
2342 mdrpc_devinfo_2_args_r1 *args,
2343 mdrpc_devinfo_2_res *res,
2344 struct svc_req *rqstp /* RPC stuff */
2345 )
2346 {
2347 int slice;
2348 mdname_t *np;
2349 mddrivename_t *dnp = args->drivenamep;
2350 md_error_t *ep = &res->status;
2351 int err;
2352 int op_mode = R_OK;
2353
2354 /* setup, check permissions */
2355 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2356 return (FALSE);
2357 else if (err != 0)
2358 return (TRUE);
2359
2360 if (check_set_lock(op_mode, NULL, ep))
2361 return (TRUE);
2362
2363 /*
2364 * fix all the drivenamep's in the mdname_t's to
2365 * point to the right place.
2366 */
2367 for (slice = 0; (slice < dnp->parts.parts_len); ++slice) {
2368 if ((np = metaslicename(dnp, slice, ep)) == NULL)
2369 return (TRUE);
2370 np->drivenamep = dnp;
2371 }
2372
2373 /* doit */
2374 devinfo(args->sp, dnp, res, ep);
2375
2376 err = svc_fini(ep);
2377
2378 return (TRUE);
2379 }
2380
2381 /*
2382 * version 1 of the remote procedure. This procedure is called if the
2383 * client is running in version 1. We first convert version 1 arguments
2384 * into version 2 arguments and then call the common remote procedure.
2385 */
2386 bool_t
mdrpc_devinfo_1_svc(mdrpc_devinfo_args * args,mdrpc_devinfo_res * res,struct svc_req * rqstp)2387 mdrpc_devinfo_1_svc(
2388 mdrpc_devinfo_args *args,
2389 mdrpc_devinfo_res *res,
2390 struct svc_req *rqstp /* RPC stuff */
2391 )
2392 {
2393 bool_t retval;
2394 mdrpc_devinfo_2_args_r1 v2_args;
2395 mdrpc_devinfo_2_res v2_res;
2396
2397 /* allocate memory */
2398 v2_args.drivenamep = Zalloc(sizeof (mddrivename_t));
2399 v2_args.drivenamep->parts.parts_val =
2400 Zalloc(sizeof (mdname_t) * args->drivenamep->parts.parts_len);
2401 (void) memset(res, 0, sizeof (*res));
2402
2403 /* convert v1 args to v2 (revision 1) args */
2404 meta_conv_drvname_old2new(args->drivenamep, v2_args.drivenamep);
2405 retval = mdrpc_devinfo_common(&v2_args, &v2_res, rqstp);
2406
2407 /*
2408 * Fill in the result appropriately.
2409 * Since dev_t's for version 2 are 64-bit,
2410 * we need to convert them to 32-bit for version 1.
2411 */
2412 res->dev = meta_cmpldev(v2_res.dev);
2413 res->vtime = v2_res.vtime;
2414 res->status = v2_res.status;
2415
2416 free(v2_args.drivenamep);
2417 free(v2_args.drivenamep->parts.parts_val);
2418
2419 return (retval);
2420 }
2421
2422 bool_t
mdrpc_devinfo_2_svc(mdrpc_devinfo_2_args * args,mdrpc_devinfo_2_res * res,struct svc_req * rqstp)2423 mdrpc_devinfo_2_svc(
2424 mdrpc_devinfo_2_args *args,
2425 mdrpc_devinfo_2_res *res,
2426 struct svc_req *rqstp /* RPC stuff */
2427 )
2428 {
2429 (void) memset(res, 0, sizeof (*res));
2430 switch (args->rev) {
2431 case MD_METAD_ARGS_REV_1:
2432 return (mdrpc_devinfo_common(
2433 &args->mdrpc_devinfo_2_args_u.rev1, res, rqstp));
2434 default:
2435 return (FALSE);
2436 }
2437 }
2438
2439 /*
2440 * return device id
2441 */
2442 static void
mdrpc_get_devid(mdsetname_t * sp,mddrivename_t * dp,mdrpc_devid_res * res,md_error_t * ep)2443 mdrpc_get_devid(
2444 mdsetname_t *sp,
2445 mddrivename_t *dp,
2446 mdrpc_devid_res *res,
2447 md_error_t *ep
2448 )
2449 {
2450 mdname_t *np;
2451
2452 if ((np = metaslicename(dp, MD_SLICE0, ep)) == NULL)
2453 return;
2454
2455 if (metaname(&sp, np->bname, LOGICAL_DEVICE, ep) == NULL)
2456 return;
2457
2458 res->enc_devid = meta_get_devid(np->rname);
2459 }
2460
2461 bool_t
mdrpc_devid_2_svc(mdrpc_devid_2_args * args,mdrpc_devid_res * res,struct svc_req * rqstp)2462 mdrpc_devid_2_svc(
2463 mdrpc_devid_2_args *args,
2464 mdrpc_devid_res *res,
2465 struct svc_req *rqstp /* RPC stuff */
2466 )
2467 {
2468 int slice;
2469 mdname_t *np;
2470 mddrivename_t *dnp;
2471 md_error_t *ep = &res->status;
2472 int err;
2473 int op_mode = R_OK;
2474
2475 (void) memset(res, 0, sizeof (*res));
2476 switch (args->rev) {
2477 case MD_METAD_ARGS_REV_1:
2478 dnp = (&(args->mdrpc_devid_2_args_u.rev1))->drivenamep;
2479 break;
2480 default:
2481 return (FALSE);
2482 }
2483
2484 /* setup, check permissions */
2485 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2486 return (FALSE);
2487 else if (err != 0)
2488 return (TRUE);
2489
2490 if (check_set_lock(op_mode, NULL, ep))
2491 return (TRUE);
2492
2493 /*
2494 * fix all the drivenamep's in the mdname_t's to
2495 * point to the right place.
2496 */
2497 for (slice = 0; (slice < dnp->parts.parts_len); ++slice) {
2498 if ((np = metaslicename(dnp, slice, ep)) == NULL)
2499 return (TRUE);
2500 np->drivenamep = dnp;
2501 }
2502
2503 /* doit */
2504 mdrpc_get_devid((&(args->mdrpc_devid_2_args_u.rev1))->sp, dnp, res, ep);
2505
2506 err = svc_fini(ep);
2507
2508 return (TRUE);
2509 }
2510
2511 /*
2512 * This routine should not be called for a multi-node diskset.
2513 *
2514 * The devid support is disabled for MN diskset so this routine
2515 * will not be called if the set is MN diskset. The check has
2516 * been done early in meta_getnextside_devinfo. However this
2517 * routine will be called when the devid support for MN set is
2518 * enabled and check is removed.
2519 */
2520 bool_t
mdrpc_devinfo_by_devid_2_svc(mdrpc_devidstr_args * args,mdrpc_devinfo_2_res * res,struct svc_req * rqstp)2521 mdrpc_devinfo_by_devid_2_svc(
2522 mdrpc_devidstr_args *args,
2523 mdrpc_devinfo_2_res *res,
2524 struct svc_req *rqstp /* RPC stuff */
2525 )
2526 {
2527
2528 char *devidstr = args->enc_devid;
2529 md_error_t *ep = &res->status;
2530 ddi_devid_t devid;
2531 char *minor_name = NULL;
2532 int ret = 0;
2533 int err;
2534 devid_nmlist_t *disklist = NULL;
2535 int op_mode = R_OK;
2536 mdname_t *np;
2537 mdsetname_t *sp = args->sp;
2538
2539 /* setup, check permissions */
2540 (void) memset(res, 0, sizeof (*res));
2541 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2542 return (FALSE);
2543 else if (err != 0)
2544 return (TRUE);
2545
2546 if (check_set_lock(op_mode, NULL, ep))
2547 return (TRUE);
2548
2549 if (devid_str_decode(devidstr, &devid, &minor_name) != 0)
2550 return (TRUE);
2551
2552 /*
2553 * if we do not have a minor name then look for a character device.
2554 * This is because the caller (checkdrive_onnode) expects a character
2555 * device to be returned. The other client of this interface is
2556 * meta_getnextside_devinfo and this supplies a minor name.
2557 */
2558 if (minor_name == NULL) {
2559 ret = meta_deviceid_to_nmlist("/dev", devid,
2560 DEVID_MINOR_NAME_ALL_CHR, &disklist);
2561 } else {
2562 ret = meta_deviceid_to_nmlist("/dev", devid, minor_name,
2563 &disklist);
2564 devid_str_free(minor_name);
2565 }
2566
2567 devid_free(devid);
2568 if (ret != 0) {
2569 res->dev = NODEV64;
2570 devid_free_nmlist(disklist);
2571 return (TRUE);
2572 }
2573
2574 np = metaname(&sp, disklist[0].devname, LOGICAL_DEVICE, ep);
2575 if (np != NULL) {
2576 mdcinfo_t *cinfo;
2577 if ((cinfo = metagetcinfo(np, ep)) != NULL) {
2578 res->drivername = Strdup(cinfo->dname);
2579 }
2580 }
2581
2582 res->dev = meta_expldev(disklist[0].dev);
2583 res->devname = strdup(disklist[0].devname);
2584
2585 devid_free_nmlist(disklist);
2586
2587 err = svc_fini(ep);
2588
2589 return (TRUE);
2590 }
2591
2592 /*
2593 * This routine should not be called for a multi-node diskset.
2594 *
2595 * The devid support is disabled for MN diskset so this routine
2596 * will not be called if the set is MN diskset. The check has
2597 * been done early in meta_getnextside_devinfo. However this
2598 * routine will be called when the devid support for MN set is
2599 * enabled and check is removed.
2600 *
2601 * This function will return the device info attempting to use
2602 * both the passed in devid and device name. This is to deal
2603 * with systems that use multi-path disks but not running mpxio.
2604 * In this situation meta_deviceid_to_nmlist will return multiple
2605 * devices. The orig_devname is used to disambiguate.
2606 *
2607 */
2608 bool_t
mdrpc_devinfo_by_devid_name_2_svc(mdrpc_devid_name_2_args * args,mdrpc_devinfo_2_res * res,struct svc_req * rqstp)2609 mdrpc_devinfo_by_devid_name_2_svc(
2610 mdrpc_devid_name_2_args *args,
2611 mdrpc_devinfo_2_res *res,
2612 struct svc_req *rqstp /* RPC stuff */
2613 )
2614 {
2615
2616 char *devidstr;
2617 char *orig_devname;
2618 md_error_t *ep = &res->status;
2619 ddi_devid_t devid;
2620 char *minor_name = NULL;
2621 int ret = 0;
2622 int err;
2623 int i;
2624 devid_nmlist_t *disklist = NULL;
2625 int op_mode = R_OK;
2626 mdname_t *np;
2627 mdsetname_t *sp;
2628
2629 (void) memset(res, 0, sizeof (*res));
2630 switch (args->rev) {
2631 case MD_METAD_ARGS_REV_1:
2632 sp = (&(args->mdrpc_devid_name_2_args_u.rev1))->sp;
2633 devidstr = (&(args->mdrpc_devid_name_2_args_u.rev1))->enc_devid;
2634 orig_devname =
2635 (&(args->mdrpc_devid_name_2_args_u.rev1))->orig_devname;
2636 break;
2637 default:
2638 return (FALSE);
2639 }
2640
2641 /* setup, check permissions */
2642 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2643 return (FALSE);
2644 else if (err != 0)
2645 return (TRUE);
2646
2647 if (check_set_lock(op_mode, NULL, ep))
2648 return (TRUE);
2649
2650 if (devid_str_decode(devidstr, &devid, &minor_name) != 0)
2651 return (TRUE);
2652
2653 /*
2654 * if we do not have a minor name then look for a character device.
2655 * This is because the caller (checkdrive_onnode) expects a character
2656 * device to be returned. The other client of this interface is
2657 * meta_getnextside_devinfo and this supplies a minor name.
2658 */
2659 if (minor_name == NULL) {
2660 ret = meta_deviceid_to_nmlist("/dev", devid,
2661 DEVID_MINOR_NAME_ALL_CHR, &disklist);
2662 } else {
2663 ret = meta_deviceid_to_nmlist("/dev", devid, minor_name,
2664 &disklist);
2665 devid_str_free(minor_name);
2666 }
2667
2668 devid_free(devid);
2669 if (ret != 0) {
2670 res->dev = NODEV64;
2671 devid_free_nmlist(disklist);
2672 return (TRUE);
2673 }
2674
2675 /* attempt to match to the device name on the originating node */
2676 for (i = 0; disklist[i].dev != NODEV; i++) {
2677 if (strncmp(orig_devname, disklist[i].devname,
2678 strlen(disklist[i].devname)) == 0)
2679 break;
2680 }
2681
2682 /* if it's not found then use the first disk in the list */
2683 if (disklist[i].dev == NODEV)
2684 i = 0;
2685
2686 np = metaname(&sp, disklist[i].devname, LOGICAL_DEVICE, ep);
2687 if (np != NULL) {
2688 mdcinfo_t *cinfo;
2689 if ((cinfo = metagetcinfo(np, ep)) != NULL) {
2690 res->drivername = Strdup(cinfo->dname);
2691 }
2692 }
2693
2694 res->dev = meta_expldev(disklist[i].dev);
2695 res->devname = strdup(disklist[i].devname);
2696
2697 devid_free_nmlist(disklist);
2698
2699 err = svc_fini(ep);
2700
2701 return (TRUE);
2702 }
2703
2704 static void
drvused(mdsetname_t * sp,mddrivename_t * dnp,md_error_t * ep)2705 drvused(mdsetname_t *sp, mddrivename_t *dnp, md_error_t *ep)
2706 {
2707 if (meta_check_drivemounted(sp, dnp, ep))
2708 return;
2709
2710 if (meta_check_driveswapped(sp, dnp, ep))
2711 return;
2712
2713 if (meta_check_drive_inuse(metasetname(MD_LOCAL_NAME, ep), dnp,
2714 TRUE, ep))
2715 return;
2716
2717 (void) meta_check_driveinset(sp, dnp, ep);
2718 }
2719
2720 /*
2721 * determine if a device is in use.
2722 */
2723 bool_t
mdrpc_drvused_common(mdrpc_drvused_2_args_r1 * args,mdrpc_generic_res * res,struct svc_req * rqstp)2724 mdrpc_drvused_common(
2725 mdrpc_drvused_2_args_r1 *args,
2726 mdrpc_generic_res *res,
2727 struct svc_req *rqstp /* RPC stuff */
2728 )
2729 {
2730 md_error_t *ep = &res->status;
2731 int slice;
2732 mdname_t *np;
2733 mddrivename_t *dnp = args->drivenamep;
2734 int err;
2735 int op_mode = R_OK;
2736
2737 /* setup, check permissions */
2738 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2739 return (FALSE);
2740 else if (err != 0)
2741 return (TRUE);
2742
2743 if (check_set_lock(op_mode, NULL, ep))
2744 return (TRUE);
2745
2746 if (dnp == NULL) {
2747 /* no drive pointer specified */
2748 return (TRUE);
2749 }
2750 /*
2751 * fix all the drivenamep's in the mdname_t's to
2752 * point to the right place.
2753 */
2754 for (slice = 0; (slice < dnp->parts.parts_len); ++slice) {
2755 if ((np = metaslicename(dnp, slice, ep)) == NULL)
2756 return (TRUE);
2757 np->drivenamep = dnp;
2758 }
2759
2760 /* doit */
2761 drvused(args->sp, dnp, ep);
2762
2763 err = svc_fini(ep);
2764
2765 return (TRUE);
2766 }
2767
2768 /*
2769 * version 1 of the remote procedure. This procedure is called if the
2770 * client is running in version 1. We first convert version 1 arguments
2771 * into version 2 arguments and then call the common remote procedure.
2772 */
2773 bool_t
mdrpc_drvused_1_svc(mdrpc_drvused_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)2774 mdrpc_drvused_1_svc(
2775 mdrpc_drvused_args *args,
2776 mdrpc_generic_res *res,
2777 struct svc_req *rqstp /* RPC stuff */
2778 )
2779 {
2780 bool_t retval;
2781 mdrpc_drvused_2_args_r1 v2_args;
2782
2783 /* allocate memory */
2784 v2_args.drivenamep = Zalloc(sizeof (mddrivename_t));
2785 v2_args.drivenamep->parts.parts_val =
2786 Zalloc(sizeof (mdname_t) * args->drivenamep->parts.parts_len);
2787 (void) memset(res, 0, sizeof (*res));
2788
2789 /* build args */
2790 v2_args.sp = args->sp;
2791 v2_args.cl_sk = args->cl_sk;
2792
2793 /* convert v1 args to v2 (revision 1) args */
2794 meta_conv_drvname_old2new(args->drivenamep, v2_args.drivenamep);
2795 retval = mdrpc_drvused_common(&v2_args, res, rqstp);
2796
2797 free(v2_args.drivenamep);
2798 free(v2_args.drivenamep->parts.parts_val);
2799
2800 return (retval);
2801 }
2802
2803 bool_t
mdrpc_drvused_2_svc(mdrpc_drvused_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)2804 mdrpc_drvused_2_svc(
2805 mdrpc_drvused_2_args *args,
2806 mdrpc_generic_res *res,
2807 struct svc_req *rqstp /* RPC stuff */
2808 )
2809 {
2810 (void) memset(res, 0, sizeof (*res));
2811 switch (args->rev) {
2812 case MD_METAD_ARGS_REV_1:
2813 return (mdrpc_drvused_common(
2814 &args->mdrpc_drvused_2_args_u.rev1, res, rqstp));
2815 default:
2816 return (FALSE);
2817 }
2818 }
2819
2820 /*
2821 * return a set records selected by name or number.
2822 */
2823 bool_t
mdrpc_getset_common(mdrpc_getset_args * args,mdrpc_getset_res * res,struct svc_req * rqstp)2824 mdrpc_getset_common(
2825 mdrpc_getset_args *args,
2826 mdrpc_getset_res *res,
2827 struct svc_req *rqstp /* RPC stuff */
2828 )
2829 {
2830 md_error_t *ep = &res->status;
2831 int err;
2832 int op_mode = R_OK;
2833
2834 /* setup, check permissions */
2835 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2836 return (FALSE);
2837 else if (err != 0)
2838 return (TRUE);
2839
2840 /* Don't have a setno, so we don't check the lock */
2841 if (check_set_lock(op_mode, NULL, ep))
2842 return (TRUE);
2843
2844 /* doit */
2845 if (args->setname && *args->setname)
2846 res->sr = setdup(getsetbyname(args->setname, ep));
2847 else if (args->setno > 0)
2848 res->sr = setdup(getsetbynum(args->setno, ep));
2849 else
2850 res->sr = NULL;
2851
2852 err = svc_fini(ep);
2853
2854 return (TRUE);
2855 }
2856
2857 bool_t
mdrpc_getset_1_svc(mdrpc_getset_args * args,mdrpc_getset_res * res,struct svc_req * rqstp)2858 mdrpc_getset_1_svc(
2859 mdrpc_getset_args *args,
2860 mdrpc_getset_res *res,
2861 struct svc_req *rqstp /* RPC stuff */
2862 )
2863 {
2864 (void) memset(res, 0, sizeof (*res));
2865 return (mdrpc_getset_common(args, res, rqstp));
2866 }
2867
2868 bool_t
mdrpc_getset_2_svc(mdrpc_getset_2_args * args,mdrpc_getset_res * res,struct svc_req * rqstp)2869 mdrpc_getset_2_svc(
2870 mdrpc_getset_2_args *args,
2871 mdrpc_getset_res *res,
2872 struct svc_req *rqstp /* RPC stuff */
2873 )
2874 {
2875 (void) memset(res, 0, sizeof (*res));
2876 switch (args->rev) {
2877 case MD_METAD_ARGS_REV_1:
2878 return (mdrpc_getset_common(
2879 &args->mdrpc_getset_2_args_u.rev1, res, rqstp));
2880 default:
2881 return (FALSE);
2882 }
2883 }
2884
2885 /*
2886 * return a MN set record selected by name or number.
2887 */
2888 bool_t
mdrpc_mngetset_common(mdrpc_getset_args * args,mdrpc_mngetset_res * res,struct svc_req * rqstp)2889 mdrpc_mngetset_common(
2890 mdrpc_getset_args *args,
2891 mdrpc_mngetset_res *res,
2892 struct svc_req *rqstp /* RPC stuff */
2893 )
2894 {
2895 md_error_t *ep = &res->status;
2896 int err;
2897 int op_mode = R_OK;
2898 md_set_record *sr = NULL;
2899 md_mnset_record *mnsr = NULL;
2900
2901 /* setup, check permissions */
2902 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2903 return (FALSE);
2904 else if (err != 0)
2905 return (TRUE);
2906
2907 /* Don't have a setno, so we don't check the lock */
2908 if (check_set_lock(op_mode, NULL, ep))
2909 return (TRUE);
2910
2911 /* doit */
2912 res->mnsr = NULL;
2913 if (args->setname && *args->setname)
2914 sr = getsetbyname(args->setname, ep);
2915 else if (args->setno > 0)
2916 sr = getsetbynum(args->setno, ep);
2917
2918 if ((sr) && (MD_MNSET_REC(sr))) {
2919 mnsr = (struct md_mnset_record *)sr;
2920 res->mnsr = mnsetdup(mnsr);
2921 }
2922
2923 err = svc_fini(ep);
2924
2925 return (TRUE);
2926 }
2927
2928 bool_t
mdrpc_mngetset_2_svc(mdrpc_getset_2_args * args,mdrpc_mngetset_res * res,struct svc_req * rqstp)2929 mdrpc_mngetset_2_svc(
2930 mdrpc_getset_2_args *args,
2931 mdrpc_mngetset_res *res,
2932 struct svc_req *rqstp /* RPC stuff */
2933 )
2934 {
2935 (void) memset(res, 0, sizeof (*res));
2936 switch (args->rev) {
2937 case MD_METAD_ARGS_REV_1:
2938 return (mdrpc_mngetset_common(
2939 &args->mdrpc_getset_2_args_u.rev1, res, rqstp));
2940 default:
2941 return (FALSE);
2942 }
2943 }
2944
2945 static void
upd_setmaster(mdsetname_t * sp,md_node_nm_t master_nodenm,int master_nodeid,md_error_t * ep)2946 upd_setmaster(
2947 mdsetname_t *sp,
2948 md_node_nm_t master_nodenm,
2949 int master_nodeid,
2950 md_error_t *ep
2951 )
2952 {
2953 mdsetname_t *local_sp;
2954 md_set_record *sr;
2955 md_mnset_record *mnsr;
2956 mddb_setmaster_config_t sm;
2957
2958 if ((local_sp = metasetname(sp->setname, ep)) == NULL)
2959 return;
2960
2961 metaflushsetname(local_sp);
2962
2963 if ((sr = getsetbyname(sp->setname, ep)) == NULL)
2964 return;
2965
2966 if (MD_MNSET_REC(sr)) {
2967 mnsr = (struct md_mnset_record *)sr;
2968 (void) strlcpy(mnsr->sr_master_nodenm, master_nodenm,
2969 MD_MAX_NODENAME);
2970 mnsr->sr_master_nodeid = master_nodeid;
2971 if (master_nodeid != 0) {
2972 (void) memset(&sm, 0, sizeof (sm));
2973 sm.c_setno = sp->setno;
2974 /* Use magic to help protect ioctl against attack. */
2975 sm.c_magic = MDDB_SETMASTER_MAGIC;
2976 if (strcmp(master_nodenm, mynode()) == 0) {
2977 sm.c_current_host_master = 1;
2978 } else {
2979 sm.c_current_host_master = 0;
2980 }
2981 (void) metaioctl(MD_SETMASTER, &sm, &sm.c_mde, NULL);
2982 mdclrerror(&sm.c_mde);
2983 }
2984 }
2985
2986 out:
2987 commitset(sr, FALSE, ep);
2988 free_sr(sr);
2989 }
2990
2991 /*
2992 * set the master and nodeid in node record
2993 */
2994 bool_t
mdrpc_mnsetmaster_common(mdrpc_mnsetmaster_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)2995 mdrpc_mnsetmaster_common(
2996 mdrpc_mnsetmaster_args *args,
2997 mdrpc_generic_res *res,
2998 struct svc_req *rqstp /* RPC stuff */
2999 )
3000 {
3001 md_error_t *ep = &res->status;
3002 int err;
3003 int op_mode = W_OK;
3004
3005 /* setup, check permissions */
3006 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3007 return (FALSE);
3008 else if (err != 0)
3009 return (TRUE);
3010
3011 if (check_set_lock(op_mode, args->cl_sk, ep))
3012 return (TRUE);
3013
3014 /* doit */
3015 upd_setmaster(args->sp, args->master_nodenm, args->master_nodeid, ep);
3016
3017 err = svc_fini(ep);
3018
3019 return (TRUE);
3020 }
3021
3022 bool_t
mdrpc_mnsetmaster_2_svc(mdrpc_mnsetmaster_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)3023 mdrpc_mnsetmaster_2_svc(
3024 mdrpc_mnsetmaster_2_args *args,
3025 mdrpc_generic_res *res,
3026 struct svc_req *rqstp /* RPC stuff */
3027 )
3028 {
3029 (void) memset(res, 0, sizeof (*res));
3030 switch (args->rev) {
3031 case MD_METAD_ARGS_REV_1:
3032 return (mdrpc_mnsetmaster_common(
3033 &args->mdrpc_mnsetmaster_2_args_u.rev1, res, rqstp));
3034 default:
3035 return (FALSE);
3036 }
3037 }
3038
3039 /*
3040 * Join this node to the diskset.
3041 * Pass stale_flag information to snarf_set so that snarf code
3042 * can choose a STALE or non-STALE state when starting the set.
3043 * If master is STALE, any joining node will join a stale set regardless
3044 * of the number of accessible mddbs. Also, if master is at 50%
3045 * accessible replicas and is in the TOOFEW state, don't mark newly
3046 * joining node as STALE; mark it TOOFEW instead.
3047 */
3048 static void
joinset(mdsetname_t * sp,int flags,md_error_t * ep)3049 joinset(
3050 mdsetname_t *sp,
3051 int flags,
3052 md_error_t *ep
3053 )
3054 {
3055 mdsetname_t *local_sp;
3056 md_drive_desc *mydd;
3057 bool_t stale_bool;
3058 mddb_block_parm_t mbp;
3059 md_error_t xep = mdnullerror;
3060
3061 if ((local_sp = metasetname(sp->setname, ep)) == NULL)
3062 return;
3063
3064 /*
3065 * Start mddoors daemon here.
3066 * mddoors itself takes care there will be
3067 * only one instance running, so starting it twice won't hurt
3068 */
3069 (void) pclose(popen(MDDOORS, "w"));
3070
3071 /*
3072 * Get latest copy of data. If a drive was just added causing
3073 * nodes to get joined - this drive won't be in the local
3074 * name caches drive list yet.
3075 */
3076 metaflushsetname(local_sp);
3077
3078 mydd = metaget_drivedesc(local_sp, (MD_BASICNAME_OK | PRINT_FAST), ep);
3079 if (mydd) {
3080 /*
3081 * Causes mddbs to be loaded into the kernel.
3082 * Set the force flag so that replica locations can be loaded
3083 * into the kernel even if a mediator node was unavailable.
3084 * This allows a node to join an MO diskset when there are
3085 * sufficient replicas available, but a mediator node
3086 * in unavailable.
3087 */
3088 if (setup_db_bydd(local_sp, mydd, TRUE, ep) == -1) {
3089 /* If ep isn't set for some reason, set it */
3090 if (mdisok(ep)) {
3091 (void) mdmddberror(ep, MDE_DB_NOTNOW,
3092 (minor_t)NODEV64, sp->setno, 0, NULL);
3093 }
3094 return;
3095 }
3096
3097 if (flags & MNSET_IS_STALE)
3098 stale_bool = TRUE;
3099 else
3100 stale_bool = FALSE;
3101
3102 /*
3103 * Snarf the set. No failure has occurred if STALE or
3104 * ACCOK error was set. Otherwise, fail the call setting
3105 * a generic error if no error was already set.
3106 *
3107 * STALE means that set has < 50% mddbs.
3108 * ACCOK means that the mediator provided an extra vote.
3109 */
3110 if (snarf_set(local_sp, stale_bool, ep) != 0) {
3111 if (!(mdismddberror(ep, MDE_DB_STALE)) &&
3112 !(mdismddberror(ep, MDE_DB_ACCOK))) {
3113 return;
3114 } else if (mdisok(ep)) {
3115 /* If snarf failed, but no error set - set it */
3116 (void) mdmddberror(ep, MDE_DB_NOTNOW,
3117 (minor_t)NODEV64, sp->setno, 0, NULL);
3118 return;
3119 }
3120 }
3121
3122 /*
3123 * If node is joining during reconfig cycle, then
3124 * set mddb_parse to be in blocked state so that
3125 * mddb reparse messages are not generated until
3126 * the commd has been resumed later in the reconfig
3127 * cycle.
3128 */
3129 if (flags & MNSET_IN_RECONFIG) {
3130 (void) memset(&mbp, 0, sizeof (mbp));
3131 if (s_ownset(sp->setno, &xep) == MD_SETOWNER_YES) {
3132 (void) memset(&mbp, 0, sizeof (mbp));
3133 mbp.c_setno = local_sp->setno;
3134 mbp.c_blk_flags = MDDB_BLOCK_PARSE;
3135 if (metaioctl(MD_MN_MDDB_BLOCK, &mbp,
3136 &mbp.c_mde, NULL)) {
3137 (void) mdstealerror(&xep, &mbp.c_mde);
3138 mde_perror(ep, gettext(
3139 "Could not block set %s"),
3140 sp->setname);
3141 return;
3142 }
3143 }
3144 /*
3145 * If s_ownset fails and snarf_set succeeded,
3146 * then can steal the ownset failure information
3147 * and store it into ep. If snarf_set failed,
3148 * don't overwrite critical ep information even
3149 * if s_ownset failed.
3150 */
3151 if (!mdisok(&xep)) {
3152 /*
3153 * If snarf_set succeeded or snarf_set failed
3154 * with MDE_DB_ACCOK (which is set if the
3155 * mediator provided the extra vote) then
3156 * steal the xep failure information and put
3157 * into ep.
3158 */
3159 if (mdisok(ep) ||
3160 mdismddberror(ep, MDE_DB_ACCOK)) {
3161 (void) mdstealerror(ep, &xep);
3162 }
3163 }
3164 }
3165 }
3166 }
3167
3168 /*
3169 * Have this node join the set.
3170 * This is called when a node has been
3171 * added to a MN diskset that has drives.
3172 * Also, called when a node is an alive
3173 * member of a MN diskset and the first
3174 * drive has been added.
3175 */
3176 bool_t
mdrpc_joinset_common(mdrpc_sp_flags_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)3177 mdrpc_joinset_common(
3178 mdrpc_sp_flags_args *args,
3179 mdrpc_generic_res *res,
3180 struct svc_req *rqstp /* RPC stuff */
3181 )
3182 {
3183 md_error_t *ep = &res->status;
3184 int err;
3185 int op_mode = W_OK;
3186
3187 /* setup, check permissions */
3188 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3189 return (FALSE);
3190 else if (err != 0)
3191 return (TRUE);
3192
3193 /*
3194 * During reconfig, joinset can happen without
3195 * locking first. Turn off reconfig flag before calling
3196 * joinset.
3197 */
3198 if (!(args->flags & MNSET_IN_RECONFIG)) {
3199 if (check_set_lock(op_mode, args->cl_sk, ep))
3200 return (TRUE);
3201 }
3202
3203 /* doit */
3204 joinset(args->sp, args->flags, ep);
3205
3206 err = svc_fini(ep);
3207
3208 return (TRUE);
3209 }
3210
3211 bool_t
mdrpc_joinset_2_svc(mdrpc_sp_flags_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)3212 mdrpc_joinset_2_svc(
3213 mdrpc_sp_flags_2_args *args,
3214 mdrpc_generic_res *res,
3215 struct svc_req *rqstp /* RPC stuff */
3216 )
3217 {
3218 (void) memset(res, 0, sizeof (*res));
3219 switch (args->rev) {
3220 case MD_METAD_ARGS_REV_1:
3221 return (mdrpc_joinset_common(
3222 &args->mdrpc_sp_flags_2_args_u.rev1, res, rqstp));
3223 default:
3224 return (FALSE);
3225 }
3226 }
3227
3228 static void
withdrawset(mdsetname_t * sp,md_error_t * ep)3229 withdrawset(
3230 mdsetname_t *sp,
3231 md_error_t *ep
3232 )
3233 {
3234 mdsetname_t *my_sp;
3235
3236 if ((my_sp = metasetname(sp->setname, ep)) == NULL)
3237 return;
3238
3239 (void) halt_set(my_sp, ep);
3240 }
3241
3242 /*
3243 * Have this node withdraw from set.
3244 * In response to a failure that occurred
3245 * on the client after a joinset.
3246 */
3247 bool_t
mdrpc_withdrawset_common(mdrpc_sp_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)3248 mdrpc_withdrawset_common(
3249 mdrpc_sp_args *args,
3250 mdrpc_generic_res *res,
3251 struct svc_req *rqstp /* RPC stuff */
3252 )
3253 {
3254 md_error_t *ep = &res->status;
3255 int err;
3256 int op_mode = W_OK;
3257
3258 /* setup, check permissions */
3259 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3260 return (FALSE);
3261 else if (err != 0)
3262 return (TRUE);
3263
3264 if (check_set_lock(op_mode, args->cl_sk, ep))
3265 return (TRUE);
3266
3267 /* doit */
3268 withdrawset(args->sp, ep);
3269
3270 err = svc_fini(ep);
3271
3272 return (TRUE);
3273 }
3274
3275 bool_t
mdrpc_withdrawset_2_svc(mdrpc_sp_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)3276 mdrpc_withdrawset_2_svc(
3277 mdrpc_sp_2_args *args,
3278 mdrpc_generic_res *res,
3279 struct svc_req *rqstp /* RPC stuff */
3280 )
3281 {
3282 (void) memset(res, 0, sizeof (*res));
3283 switch (args->rev) {
3284 case MD_METAD_ARGS_REV_1:
3285 return (mdrpc_withdrawset_common(
3286 &args->mdrpc_sp_2_args_u.rev1, res, rqstp));
3287 default:
3288 return (FALSE);
3289 }
3290 }
3291
3292 static mhd_mhiargs_t *
gtimeout(mdsetname_t * sp,md_error_t * ep)3293 gtimeout(mdsetname_t *sp, md_error_t *ep)
3294 {
3295 md_set_record *sr;
3296 mhd_mhiargs_t *mhiargs;
3297
3298 if ((sr = getsetbyname(sp->setname, ep)) == NULL)
3299 return (NULL);
3300
3301 mhiargs = Zalloc(sizeof (*mhiargs));
3302 *mhiargs = sr->sr_mhiargs;
3303
3304 free_sr(sr);
3305 return (mhiargs);
3306 }
3307
3308 /*
3309 * Get the MH timeout values for this set.
3310 */
3311 bool_t
mdrpc_gtimeout_common(mdrpc_sp_args * args,mdrpc_gtimeout_res * res,struct svc_req * rqstp)3312 mdrpc_gtimeout_common(
3313 mdrpc_sp_args *args,
3314 mdrpc_gtimeout_res *res,
3315 struct svc_req *rqstp /* RPC stuff */
3316 )
3317 {
3318 md_error_t *ep = &res->status;
3319 int err;
3320 int op_mode = R_OK;
3321
3322 /* setup, check permissions */
3323 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3324 return (FALSE);
3325 else if (err != 0)
3326 return (TRUE);
3327
3328 if (check_set_lock(op_mode, NULL, ep))
3329 return (TRUE);
3330
3331 /* doit */
3332 res->mhiargsp = gtimeout(args->sp, ep);
3333
3334 err = svc_fini(ep);
3335
3336 return (TRUE);
3337 }
3338
3339 bool_t
mdrpc_gtimeout_1_svc(mdrpc_sp_args * args,mdrpc_gtimeout_res * res,struct svc_req * rqstp)3340 mdrpc_gtimeout_1_svc(
3341 mdrpc_sp_args *args,
3342 mdrpc_gtimeout_res *res,
3343 struct svc_req *rqstp /* RPC stuff */
3344 )
3345 {
3346 (void) memset(res, 0, sizeof (*res));
3347 return (mdrpc_gtimeout_common(args, res, rqstp));
3348 }
3349
3350 bool_t
mdrpc_gtimeout_2_svc(mdrpc_sp_2_args * args,mdrpc_gtimeout_res * res,struct svc_req * rqstp)3351 mdrpc_gtimeout_2_svc(
3352 mdrpc_sp_2_args *args,
3353 mdrpc_gtimeout_res *res,
3354 struct svc_req *rqstp /* RPC stuff */
3355 )
3356 {
3357 (void) memset(res, 0, sizeof (*res));
3358 switch (args->rev) {
3359 case MD_METAD_ARGS_REV_1:
3360 return (mdrpc_gtimeout_common(
3361 &args->mdrpc_sp_2_args_u.rev1, res, rqstp));
3362 default:
3363 return (FALSE);
3364 }
3365 }
3366
3367 /*
3368 * return the official host name for the callee
3369 */
3370 /*ARGSUSED*/
3371 bool_t
mdrpc_hostname_common(mdrpc_null_args * args,mdrpc_hostname_res * res,struct svc_req * rqstp)3372 mdrpc_hostname_common(
3373 mdrpc_null_args *args,
3374 mdrpc_hostname_res *res,
3375 struct svc_req *rqstp /* RPC stuff */
3376 )
3377 {
3378 md_error_t *ep = &res->status;
3379 int err;
3380 int op_mode = R_OK;
3381
3382 /* setup, check permissions */
3383 (void) memset(res, 0, sizeof (*res));
3384 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3385 return (FALSE);
3386 else if (err != 0)
3387 return (TRUE);
3388
3389 if (check_set_lock(op_mode, NULL, ep))
3390 return (TRUE);
3391
3392 /* doit */
3393 res->hostname = Strdup(mynode());
3394
3395 err = svc_fini(ep);
3396
3397 return (TRUE);
3398 }
3399
3400 bool_t
mdrpc_hostname_1_svc(mdrpc_null_args * args,mdrpc_hostname_res * res,struct svc_req * rqstp)3401 mdrpc_hostname_1_svc(
3402 mdrpc_null_args *args,
3403 mdrpc_hostname_res *res,
3404 struct svc_req *rqstp /* RPC stuff */
3405 )
3406 {
3407 return (mdrpc_hostname_common(args, res, rqstp));
3408 }
3409
3410 bool_t
mdrpc_hostname_2_svc(mdrpc_null_args * args,mdrpc_hostname_res * res,struct svc_req * rqstp)3411 mdrpc_hostname_2_svc(
3412 mdrpc_null_args *args,
3413 mdrpc_hostname_res *res,
3414 struct svc_req *rqstp /* RPC stuff */
3415 )
3416 {
3417 return (mdrpc_hostname_common(args, res, rqstp));
3418 }
3419
3420 /*
3421 * return a response
3422 */
3423 /*ARGSUSED*/
3424 bool_t
mdrpc_nullproc_common(void * args,md_error_t * ep,struct svc_req * rqstp)3425 mdrpc_nullproc_common(
3426 void *args,
3427 md_error_t *ep,
3428 struct svc_req *rqstp /* RPC stuff */
3429 )
3430 {
3431 *ep = mdnullerror;
3432 /* do nothing */
3433 return (TRUE);
3434 }
3435
3436 bool_t
mdrpc_nullproc_1_svc(void * args,md_error_t * ep,struct svc_req * rqstp)3437 mdrpc_nullproc_1_svc(
3438 void *args,
3439 md_error_t *ep,
3440 struct svc_req *rqstp /* RPC stuff */
3441 )
3442 {
3443 return (mdrpc_nullproc_common(args, ep, rqstp));
3444 }
3445
3446 bool_t
mdrpc_nullproc_2_svc(void * args,md_error_t * ep,struct svc_req * rqstp)3447 mdrpc_nullproc_2_svc(
3448 void *args,
3449 md_error_t *ep,
3450 struct svc_req *rqstp /* RPC stuff */
3451 )
3452 {
3453 return (mdrpc_nullproc_common(args, ep, rqstp));
3454 }
3455
3456 /*
3457 * determine if the caller owns the set.
3458 */
3459 bool_t
mdrpc_ownset_common(mdrpc_sp_args * args,mdrpc_bool_res * res,struct svc_req * rqstp)3460 mdrpc_ownset_common(
3461 mdrpc_sp_args *args,
3462 mdrpc_bool_res *res,
3463 struct svc_req *rqstp /* RPC stuff */
3464 )
3465 {
3466 md_error_t *ep = &res->status;
3467 int err;
3468 int op_mode = R_OK;
3469
3470 /* setup, check permissions */
3471 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3472 return (FALSE);
3473 else if (err != 0)
3474 return (TRUE);
3475
3476 if (check_set_lock(op_mode, NULL, ep))
3477 return (TRUE);
3478
3479 /* doit */
3480 if (s_ownset(args->sp->setno, ep))
3481 res->value = TRUE;
3482 else
3483 res->value = FALSE;
3484
3485 err = svc_fini(ep);
3486
3487 return (TRUE);
3488 }
3489
3490 bool_t
mdrpc_ownset_1_svc(mdrpc_sp_args * args,mdrpc_bool_res * res,struct svc_req * rqstp)3491 mdrpc_ownset_1_svc(
3492 mdrpc_sp_args *args,
3493 mdrpc_bool_res *res,
3494 struct svc_req *rqstp /* RPC stuff */
3495 )
3496 {
3497 (void) memset(res, 0, sizeof (*res));
3498 return (mdrpc_ownset_common(args, res, rqstp));
3499 }
3500
3501 bool_t
mdrpc_ownset_2_svc(mdrpc_sp_2_args * args,mdrpc_bool_res * res,struct svc_req * rqstp)3502 mdrpc_ownset_2_svc(
3503 mdrpc_sp_2_args *args,
3504 mdrpc_bool_res *res,
3505 struct svc_req *rqstp /* RPC stuff */
3506 )
3507 {
3508 (void) memset(res, 0, sizeof (*res));
3509 switch (args->rev) {
3510 case MD_METAD_ARGS_REV_1:
3511 return (mdrpc_ownset_common(
3512 &args->mdrpc_sp_2_args_u.rev1, res, rqstp));
3513 default:
3514 return (FALSE);
3515 }
3516 }
3517
3518 static int
setnameok(char * setname,md_error_t * ep)3519 setnameok(char *setname, md_error_t *ep)
3520 {
3521 int rval = 0;
3522 struct stat statb;
3523 md_set_record *sr = NULL;
3524 char *setlink = NULL;
3525
3526 setlink = Strdup("/dev/md/");
3527 setlink = Realloc(setlink, strlen(setlink) + strlen(setname) + 1);
3528 (void) strcat(setlink, setname);
3529
3530 if (lstat(setlink, &statb) == -1) {
3531 /*
3532 * If lstat() fails with ENOENT, setname is OK, if it
3533 * fails for other than that, we fail the RPC
3534 */
3535 if (errno == ENOENT) {
3536 rval = 1;
3537 goto out;
3538 }
3539
3540 (void) mdsyserror(ep, errno, setlink);
3541 goto out;
3542 }
3543
3544 /*
3545 * If the lstat() succeeded, then we see what type of object
3546 * we are dealing with, if it is a symlink, we do some further
3547 * checking, if it is not a symlink, then we return an
3548 * indication that the set name is NOT acceptable.
3549 */
3550 if (! S_ISLNK(statb.st_mode))
3551 goto out;
3552
3553 /*
3554 * We look up the setname to see if there is a set
3555 * with that name, if there is, then we return
3556 * an indication that the set name is NOT acceptable.
3557 */
3558 if ((sr = getsetbyname(setname, ep)) != NULL)
3559 goto out;
3560
3561 if (! mdiserror(ep, MDE_NO_SET))
3562 goto out;
3563
3564 mdclrerror(ep);
3565
3566 rval = 1;
3567 out:
3568 if (sr != NULL)
3569 free_sr(sr);
3570 Free(setlink);
3571 return (rval);
3572 }
3573
3574 /*
3575 * Make sure the name of the set is OK.
3576 */
3577 bool_t
mdrpc_setnameok_common(mdrpc_sp_args * args,mdrpc_bool_res * res,struct svc_req * rqstp)3578 mdrpc_setnameok_common(
3579 mdrpc_sp_args *args, /* device name */
3580 mdrpc_bool_res *res,
3581 struct svc_req *rqstp /* RPC stuff */
3582 )
3583 {
3584 md_error_t *ep = &res->status;
3585 int err;
3586 int op_mode = R_OK;
3587
3588 /* setup, check permissions */
3589 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3590 return (FALSE);
3591 else if (err != 0)
3592 return (TRUE);
3593
3594 if (check_set_lock(op_mode, NULL, ep))
3595 return (TRUE);
3596
3597 /* doit */
3598 res->value = setnameok(args->sp->setname, ep);
3599
3600 err = svc_fini(ep);
3601
3602 return (TRUE);
3603 }
3604
3605 bool_t
mdrpc_setnameok_1_svc(mdrpc_sp_args * args,mdrpc_bool_res * res,struct svc_req * rqstp)3606 mdrpc_setnameok_1_svc(
3607 mdrpc_sp_args *args, /* device name */
3608 mdrpc_bool_res *res,
3609 struct svc_req *rqstp /* RPC stuff */
3610 )
3611 {
3612 (void) memset(res, 0, sizeof (*res));
3613 return (mdrpc_setnameok_common(args, res, rqstp));
3614 }
3615
3616 bool_t
mdrpc_setnameok_2_svc(mdrpc_sp_2_args * args,mdrpc_bool_res * res,struct svc_req * rqstp)3617 mdrpc_setnameok_2_svc(
3618 mdrpc_sp_2_args *args, /* device name */
3619 mdrpc_bool_res *res,
3620 struct svc_req *rqstp /* RPC stuff */
3621 )
3622 {
3623 (void) memset(res, 0, sizeof (*res));
3624 switch (args->rev) {
3625 case MD_METAD_ARGS_REV_1:
3626 return (mdrpc_setnameok_common(
3627 &args->mdrpc_sp_2_args_u.rev1, res, rqstp));
3628 default:
3629 return (FALSE);
3630 }
3631 }
3632
3633 /*
3634 * determine if the setnumber we want to share is in use.
3635 */
3636 bool_t
mdrpc_setnumbusy_common(mdrpc_setno_args * args,mdrpc_bool_res * res,struct svc_req * rqstp)3637 mdrpc_setnumbusy_common(
3638 mdrpc_setno_args *args,
3639 mdrpc_bool_res *res,
3640 struct svc_req *rqstp /* RPC stuff */
3641 )
3642 {
3643 md_error_t *ep = &res->status;
3644 md_set_record *sr = NULL;
3645 int err;
3646 int op_mode = R_OK;
3647
3648 /* setup, check permissions */
3649 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3650 return (FALSE);
3651 else if (err != 0)
3652 return (TRUE);
3653
3654 if (check_set_lock(op_mode, NULL, ep))
3655 return (TRUE);
3656
3657 /* doit */
3658 if ((sr = getsetbynum(args->setno, ep)) != NULL) {
3659 res->value = TRUE;
3660 free_sr(sr);
3661 return (TRUE);
3662 }
3663 res->value = FALSE;
3664 if (mdiserror(ep, MDE_NO_SET))
3665 mdclrerror(ep);
3666
3667 err = svc_fini(ep);
3668
3669 return (TRUE);
3670 }
3671
3672 bool_t
mdrpc_setnumbusy_1_svc(mdrpc_setno_args * args,mdrpc_bool_res * res,struct svc_req * rqstp)3673 mdrpc_setnumbusy_1_svc(
3674 mdrpc_setno_args *args,
3675 mdrpc_bool_res *res,
3676 struct svc_req *rqstp /* RPC stuff */
3677 )
3678 {
3679 (void) memset(res, 0, sizeof (*res));
3680 return (mdrpc_setnumbusy_common(args, res, rqstp));
3681 }
3682
3683 bool_t
mdrpc_setnumbusy_2_svc(mdrpc_setno_2_args * args,mdrpc_bool_res * res,struct svc_req * rqstp)3684 mdrpc_setnumbusy_2_svc(
3685 mdrpc_setno_2_args *args,
3686 mdrpc_bool_res *res,
3687 struct svc_req *rqstp /* RPC stuff */
3688 )
3689 {
3690 (void) memset(res, 0, sizeof (*res));
3691 switch (args->rev) {
3692 case MD_METAD_ARGS_REV_1:
3693 return (mdrpc_setnumbusy_common(
3694 &args->mdrpc_setno_2_args_u.rev1, res, rqstp));
3695 default:
3696 return (FALSE);
3697 }
3698 }
3699
3700 static void
stimeout(mdsetname_t * sp,mhd_mhiargs_t * mhiargsp,int version,md_error_t * ep)3701 stimeout(
3702 mdsetname_t *sp,
3703 mhd_mhiargs_t *mhiargsp,
3704 int version, /* RPC version of calling routine */
3705 md_error_t *ep
3706 )
3707 {
3708 mddb_userreq_t req;
3709 md_set_record *sr;
3710
3711 if ((sr = getsetbyname(sp->setname, ep)) == NULL)
3712 return;
3713
3714 sr->sr_mhiargs = *mhiargsp;
3715
3716 (void) memset(&req, '\0', sizeof (req));
3717
3718 METAD_SETUP_SR(MD_DB_SETDATA, sr->sr_selfid)
3719 /* Do MN operation if rpc version supports it and if a MN set */
3720 if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
3721 req.ur_size = sizeof (struct md_mnset_record);
3722 } else {
3723 req.ur_size = sizeof (*sr);
3724 }
3725 req.ur_data = (uintptr_t)sr;
3726
3727 /*
3728 * Cluster nodename support
3729 * Convert nodename -> nodeid
3730 * Don't do this for MN disksets since we've already stored
3731 * both the nodeid and name.
3732 */
3733 if ((version == METAD_VERSION) ||
3734 ((version == METAD_VERSION_DEVID) && (!(MD_MNSET_REC(sr)))))
3735 sdssc_cm_sr_nm2nid(sr);
3736
3737 if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
3738 (void) mdstealerror(ep, &req.ur_mde);
3739 return;
3740 }
3741
3742 (void) memset(&req, '\0', sizeof (req));
3743 METAD_SETUP_SR(MD_DB_COMMIT_ONE, sr->sr_selfid)
3744 if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0)
3745 (void) mdstealerror(ep, &req.ur_mde);
3746
3747 /*
3748 * Cluster nodename support
3749 * Convert nodeid -> nodename
3750 * Don't do this for MN disksets since we've already stored
3751 * both the nodeid and name.
3752 */
3753 if ((version == METAD_VERSION) ||
3754 ((version == METAD_VERSION_DEVID) && (!(MD_MNSET_REC(sr)))))
3755 sdssc_cm_sr_nid2nm(sr);
3756
3757 free_sr(sr);
3758 }
3759
3760 /*
3761 * Set MH ioctl timeout values.
3762 */
3763 bool_t
mdrpc_stimeout_common(mdrpc_stimeout_args * args,mdrpc_generic_res * res,struct svc_req * rqstp,int version)3764 mdrpc_stimeout_common(
3765 mdrpc_stimeout_args *args,
3766 mdrpc_generic_res *res,
3767 struct svc_req *rqstp, /* RPC stuff */
3768 int version /* RPC version */
3769 )
3770 {
3771 md_error_t *ep = &res->status;
3772 int err;
3773 int op_mode = W_OK;
3774
3775 /* setup, check permissions */
3776 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3777 return (FALSE);
3778 else if (err != 0)
3779 return (TRUE);
3780
3781 if (check_set_lock(op_mode, NULL, ep))
3782 return (TRUE);
3783
3784 /* doit */
3785 stimeout(args->sp, args->mhiargsp, version, ep);
3786
3787 err = svc_fini(ep);
3788
3789 return (TRUE);
3790 }
3791
3792 bool_t
mdrpc_stimeout_1_svc(mdrpc_stimeout_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)3793 mdrpc_stimeout_1_svc(
3794 mdrpc_stimeout_args *args,
3795 mdrpc_generic_res *res,
3796 struct svc_req *rqstp /* RPC stuff */
3797 )
3798 {
3799 (void) memset(res, 0, sizeof (*res));
3800 /* Pass RPC version (METAD_VERSION) to common routine */
3801 return (mdrpc_stimeout_common(args, res, rqstp, METAD_VERSION));
3802 }
3803
3804 bool_t
mdrpc_stimeout_2_svc(mdrpc_stimeout_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)3805 mdrpc_stimeout_2_svc(
3806 mdrpc_stimeout_2_args *args,
3807 mdrpc_generic_res *res,
3808 struct svc_req *rqstp /* RPC stuff */
3809 )
3810 {
3811 (void) memset(res, 0, sizeof (*res));
3812 switch (args->rev) {
3813 case MD_METAD_ARGS_REV_1:
3814 /* Pass RPC version (METAD_VERSION_DEVID) to common routine */
3815 return (mdrpc_stimeout_common(
3816 &args->mdrpc_stimeout_2_args_u.rev1, res,
3817 rqstp, METAD_VERSION_DEVID));
3818 default:
3819 return (FALSE);
3820 }
3821 }
3822
3823 static void
upd_dr_dbinfo(mdsetname_t * sp,md_drive_desc * dd,md_error_t * ep)3824 upd_dr_dbinfo(
3825 mdsetname_t *sp,
3826 md_drive_desc *dd,
3827 md_error_t *ep
3828 )
3829 {
3830 mdsetname_t *local_sp;
3831 md_set_record *sr;
3832 md_drive_record *dr;
3833 md_drive_desc *p;
3834 mddrivename_t *dn, *dn1;
3835 ddi_devid_t devid_remote = NULL;
3836 ddi_devid_t devid_local = NULL;
3837 int devid_same = -1;
3838 side_t sideno;
3839 int using_devid = 0;
3840
3841 if ((local_sp = metasetname(sp->setname, ep)) == NULL)
3842 return;
3843
3844 metaflushsetname(local_sp);
3845
3846 if ((sideno = getmyside(local_sp, ep)) == MD_SIDEWILD)
3847 return;
3848
3849 if ((sr = getsetbyname(sp->setname, ep)) == NULL)
3850 return;
3851
3852 if (dd->dd_dnp == NULL)
3853 return;
3854
3855 /*
3856 * The system is either all devid or all
3857 * non-devid so we determine this by looking
3858 * at the first item in the list.
3859 *
3860 * For did disks, the dd_dnp->devid is a valid pointer which
3861 * points to a '' string of devid. We need to check this
3862 * before set the using_devid.
3863 */
3864 if ((dd->dd_dnp->devid != NULL) && (dd->dd_dnp->devid[0] != '\0') &&
3865 (!(MD_MNSET_REC(sr))))
3866 using_devid = 1;
3867
3868 for (p = dd; p != NULL; p = p->dd_next) {
3869 dn = p->dd_dnp;
3870 devid_remote = NULL;
3871
3872 if (dn->devid != NULL && (strlen(dn->devid) != 0) &&
3873 using_devid) {
3874 /*
3875 * We have a devid so use it.
3876 */
3877 (void) devid_str_decode(dn->devid, &devid_remote, NULL);
3878 }
3879
3880 /* check to make sure using_devid agrees with reality... */
3881 if ((using_devid == 1) && (devid_remote == NULL)) {
3882 /* something went really wrong. Can't process */
3883 (void) mddserror(ep, MDE_DS_INVALIDDEVID, sp->setno,
3884 mynode(), dn->cname, sp->setname);
3885 return;
3886 }
3887
3888 for (dr = sr->sr_drivechain; dr; dr = dr->dr_next) {
3889 devid_same = -1;
3890
3891 dn1 = metadrivename_withdrkey(local_sp, sideno,
3892 dr->dr_key, MD_BASICNAME_OK, ep);
3893
3894 if (dn1 == NULL) {
3895 if (devid_remote)
3896 devid_free(devid_remote);
3897 goto out;
3898 }
3899
3900 if (dn1->devid != NULL && using_devid) {
3901 if (devid_str_decode(dn1->devid, &devid_local,
3902 NULL) == 0) {
3903 devid_same = devid_compare(devid_remote,
3904 devid_local);
3905 devid_free(devid_local);
3906 }
3907 }
3908
3909 if (using_devid && devid_same == 0)
3910 break;
3911
3912 if (!using_devid &&
3913 strcmp(dn->cname, dn1->cname) == 0)
3914 break;
3915 }
3916
3917 if (dr) {
3918 /* Adjust the fields in the copy */
3919 dr->dr_dbcnt = p->dd_dbcnt;
3920 dr->dr_dbsize = p->dd_dbsize;
3921 }
3922 if (devid_remote)
3923 devid_free(devid_remote);
3924 }
3925
3926
3927 out:
3928 commitset(sr, FALSE, ep);
3929 free_sr(sr);
3930 }
3931
3932 /*
3933 * update the database count and size field of drive records.
3934 */
3935 bool_t
mdrpc_upd_dr_dbinfo_common(mdrpc_drives_2_args_r1 * args,mdrpc_generic_res * res,struct svc_req * rqstp)3936 mdrpc_upd_dr_dbinfo_common(
3937 mdrpc_drives_2_args_r1 *args,
3938 mdrpc_generic_res *res,
3939 struct svc_req *rqstp /* RPC stuff */
3940 )
3941 {
3942 md_error_t *ep = &res->status;
3943 int err;
3944 int op_mode = W_OK;
3945
3946 /* setup, check permissions */
3947 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3948 return (FALSE);
3949 else if (err != 0)
3950 return (TRUE);
3951
3952 if (check_set_lock(op_mode, args->cl_sk, ep))
3953 return (TRUE);
3954
3955 /* doit */
3956 upd_dr_dbinfo(args->sp, args->drivedescs, ep);
3957
3958 err = svc_fini(ep);
3959
3960 return (TRUE);
3961 }
3962
3963 /*
3964 * version 1 of the remote procedure. This procedure is called if the
3965 * client is running in version 1. We first convert version 1 arguments
3966 * into version 2 arguments and then call the common remote procedure.
3967 */
3968 bool_t
mdrpc_upd_dr_dbinfo_1_svc(mdrpc_drives_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)3969 mdrpc_upd_dr_dbinfo_1_svc(
3970 mdrpc_drives_args *args,
3971 mdrpc_generic_res *res,
3972 struct svc_req *rqstp /* RPC stuff */
3973 )
3974 {
3975 bool_t retval;
3976 mdrpc_drives_2_args_r1 v2_args;
3977
3978 /* allocate memory */
3979 alloc_newdrvdesc(args->drivedescs, &v2_args.drivedescs);
3980 (void) memset(res, 0, sizeof (*res));
3981
3982 /* build args */
3983 v2_args.cl_sk = args->cl_sk;
3984 v2_args.sp = args->sp;
3985 /* convert v1 args to v2 (revision 1) args */
3986 meta_conv_drvdesc_old2new(args->drivedescs, v2_args.drivedescs);
3987 v2_args.timestamp = args->timestamp;
3988 v2_args.genid = args->genid;
3989
3990 retval = mdrpc_upd_dr_dbinfo_common(&v2_args, res, rqstp);
3991
3992 free_newdrvdesc(v2_args.drivedescs);
3993
3994 return (retval);
3995 }
3996
3997 bool_t
mdrpc_upd_dr_dbinfo_2_svc(mdrpc_drives_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)3998 mdrpc_upd_dr_dbinfo_2_svc(
3999 mdrpc_drives_2_args *args,
4000 mdrpc_generic_res *res,
4001 struct svc_req *rqstp /* RPC stuff */
4002 )
4003 {
4004 (void) memset(res, 0, sizeof (*res));
4005 switch (args->rev) {
4006 case MD_METAD_ARGS_REV_1:
4007 return (mdrpc_upd_dr_dbinfo_common(
4008 &args->mdrpc_drives_2_args_u.rev1, res, rqstp));
4009 default:
4010 return (FALSE);
4011 }
4012 }
4013
4014 static void
upd_dr_flags(mdsetname_t * sp,md_drive_desc * dd,uint_t new_flags,md_error_t * ep)4015 upd_dr_flags(
4016 mdsetname_t *sp,
4017 md_drive_desc *dd,
4018 uint_t new_flags,
4019 md_error_t *ep
4020 )
4021 {
4022 mdsetname_t *local_sp;
4023 md_set_record *sr;
4024 md_drive_record *dr;
4025 md_drive_desc *p;
4026 mddrivename_t *dn, *dn1;
4027 ddi_devid_t devid_remote = NULL;
4028 ddi_devid_t devid_local = NULL;
4029 int devid_same = -1;
4030 side_t sideno;
4031 int using_devid = 0;
4032
4033 if ((local_sp = metasetname(sp->setname, ep)) == NULL)
4034 return;
4035
4036 metaflushsetname(local_sp);
4037
4038 if ((sideno = getmyside(local_sp, ep)) == MD_SIDEWILD)
4039 return;
4040
4041 if ((sr = getsetbyname(sp->setname, ep)) == NULL)
4042 return;
4043
4044 if (dd->dd_dnp == NULL)
4045 return;
4046
4047 /*
4048 * The system is either all devid or all
4049 * non-devid so we determine this by looking
4050 * at the first item in the list.
4051 *
4052 * For did disks, the dd_dnp->devid is a valid pointer which
4053 * points to a '' string of devid. We need to check this
4054 * before set the using_devid.
4055 */
4056 if ((dd->dd_dnp->devid != NULL) && (dd->dd_dnp->devid[0] != '\0') &&
4057 (!(MD_MNSET_REC(sr))))
4058 using_devid = 1;
4059
4060 for (p = dd; p != NULL; p = p->dd_next) {
4061 dn = p->dd_dnp;
4062 devid_remote = NULL;
4063
4064 if (dn->devid != NULL && (strlen(dn->devid) != 0) &&
4065 using_devid) {
4066 /*
4067 * We have a devid so use it.
4068 */
4069 (void) devid_str_decode(dn->devid, &devid_remote, NULL);
4070 }
4071
4072 /* check to make sure using_devid agrees with reality... */
4073 if ((using_devid == 1) && (devid_remote == NULL)) {
4074 /* something went really wrong. Can't process */
4075 (void) mddserror(ep, MDE_DS_INVALIDDEVID, sp->setno,
4076 mynode(), dn->cname, sp->setname);
4077 return;
4078 }
4079
4080 for (dr = sr->sr_drivechain; dr; dr = dr->dr_next) {
4081 devid_same = -1;
4082
4083 dn1 = metadrivename_withdrkey(local_sp, sideno,
4084 dr->dr_key, MD_BASICNAME_OK, ep);
4085
4086 if (dn1 == NULL) {
4087 if (devid_remote)
4088 devid_free(devid_remote);
4089 goto out;
4090 }
4091
4092 if (dn1->devid != NULL && using_devid) {
4093 if (devid_str_decode(dn1->devid,
4094 &devid_local, NULL) == 0) {
4095 devid_same = devid_compare(devid_remote,
4096 devid_local);
4097 devid_free(devid_local);
4098 }
4099 }
4100
4101 if (using_devid && devid_same == 0)
4102 break;
4103
4104 if (!using_devid &&
4105 strcmp(dn->cname, dn1->cname) == 0)
4106 break;
4107 }
4108
4109 if (dr)
4110 dr->dr_flags = new_flags;
4111 if (devid_remote)
4112 devid_free(devid_remote);
4113 }
4114 out:
4115 commitset(sr, TRUE, ep);
4116 free_sr(sr);
4117 }
4118
4119 /*
4120 * update the database count and size field of drive records.
4121 */
4122 bool_t
mdrpc_upd_dr_flags_common(mdrpc_upd_dr_flags_2_args_r1 * args,mdrpc_generic_res * res,struct svc_req * rqstp)4123 mdrpc_upd_dr_flags_common(
4124 mdrpc_upd_dr_flags_2_args_r1 *args,
4125 mdrpc_generic_res *res,
4126 struct svc_req *rqstp /* RPC stuff */
4127 )
4128 {
4129 md_error_t *ep = &res->status;
4130 int err;
4131 int op_mode = W_OK;
4132
4133 /* setup, check permissions */
4134 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4135 return (FALSE);
4136 else if (err != 0)
4137 return (TRUE);
4138
4139 if (check_set_lock(op_mode, args->cl_sk, ep))
4140 return (TRUE);
4141
4142 /* doit */
4143 upd_dr_flags(args->sp, args->drivedescs, args->new_flags, ep);
4144
4145 err = svc_fini(ep);
4146
4147 return (TRUE);
4148 }
4149
4150 /*
4151 * version 1 of the remote procedure. This procedure is called if the
4152 * client is running in version 1. We first convert version 1 arguments
4153 * into version 2 arguments and then call the common remote procedure.
4154 */
4155 bool_t
mdrpc_upd_dr_flags_1_svc(mdrpc_upd_dr_flags_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)4156 mdrpc_upd_dr_flags_1_svc(
4157 mdrpc_upd_dr_flags_args *args,
4158 mdrpc_generic_res *res,
4159 struct svc_req *rqstp /* RPC stuff */
4160 )
4161 {
4162 bool_t retval;
4163 mdrpc_upd_dr_flags_2_args_r1 v2_args;
4164
4165 /* allocate memory */
4166 alloc_newdrvdesc(args->drivedescs, &v2_args.drivedescs);
4167 (void) memset(res, 0, sizeof (*res));
4168
4169 /* build args */
4170 v2_args.cl_sk = args->cl_sk;
4171 v2_args.sp = args->sp;
4172 /* convert v1 args to v2 (revision 1) args */
4173 meta_conv_drvdesc_old2new(args->drivedescs, v2_args.drivedescs);
4174 v2_args.new_flags = args->new_flags;
4175
4176 retval = mdrpc_upd_dr_flags_common(&v2_args, res, rqstp);
4177
4178 free_newdrvdesc(v2_args.drivedescs);
4179
4180 return (retval);
4181 }
4182
4183 bool_t
mdrpc_upd_dr_flags_2_svc(mdrpc_upd_dr_flags_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)4184 mdrpc_upd_dr_flags_2_svc(
4185 mdrpc_upd_dr_flags_2_args *args,
4186 mdrpc_generic_res *res,
4187 struct svc_req *rqstp /* RPC stuff */
4188 )
4189 {
4190 (void) memset(res, 0, sizeof (*res));
4191 switch (args->rev) {
4192 case MD_METAD_ARGS_REV_1:
4193 return (mdrpc_upd_dr_flags_common(
4194 &args->mdrpc_upd_dr_flags_2_args_u.rev1, res, rqstp));
4195 default:
4196 return (FALSE);
4197 }
4198 }
4199
4200 static void
upd_sr_flags(mdsetname_t * sp,uint_t new_flags,md_error_t * ep)4201 upd_sr_flags(
4202 mdsetname_t *sp,
4203 uint_t new_flags,
4204 md_error_t *ep
4205 )
4206 {
4207 md_set_record *sr;
4208
4209 if ((sr = getsetbyname(sp->setname, ep)) == NULL)
4210 return;
4211
4212 sr->sr_flags = new_flags;
4213 commitset(sr, TRUE, ep);
4214 free_sr(sr);
4215 }
4216
4217 /*
4218 * update the set record flags
4219 */
4220 bool_t
mdrpc_upd_sr_flags_common(mdrpc_upd_sr_flags_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)4221 mdrpc_upd_sr_flags_common(
4222 mdrpc_upd_sr_flags_args *args,
4223 mdrpc_generic_res *res,
4224 struct svc_req *rqstp /* RPC stuff */
4225 )
4226 {
4227 md_error_t *ep = &res->status;
4228 int err;
4229 int op_mode = W_OK;
4230
4231 /* setup, check permissions */
4232 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4233 return (FALSE);
4234 else if (err != 0)
4235 return (TRUE);
4236
4237 if (check_set_lock(op_mode, args->cl_sk, ep))
4238 return (TRUE);
4239
4240 /* doit */
4241 upd_sr_flags(args->sp, args->new_flags, ep);
4242
4243 err = svc_fini(ep);
4244
4245 return (TRUE);
4246 }
4247
4248 bool_t
mdrpc_upd_sr_flags_1_svc(mdrpc_upd_sr_flags_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)4249 mdrpc_upd_sr_flags_1_svc(
4250 mdrpc_upd_sr_flags_args *args,
4251 mdrpc_generic_res *res,
4252 struct svc_req *rqstp /* RPC stuff */
4253 )
4254 {
4255 (void) memset(res, 0, sizeof (*res));
4256 return (mdrpc_upd_sr_flags_common(args, res, rqstp));
4257 }
4258
4259 bool_t
mdrpc_upd_sr_flags_2_svc(mdrpc_upd_sr_flags_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)4260 mdrpc_upd_sr_flags_2_svc(
4261 mdrpc_upd_sr_flags_2_args *args,
4262 mdrpc_generic_res *res,
4263 struct svc_req *rqstp /* RPC stuff */
4264 )
4265 {
4266 (void) memset(res, 0, sizeof (*res));
4267 switch (args->rev) {
4268 case MD_METAD_ARGS_REV_1:
4269 return (mdrpc_upd_sr_flags_common(
4270 &args->mdrpc_upd_sr_flags_2_args_u.rev1, res, rqstp));
4271 default:
4272 return (FALSE);
4273 }
4274 }
4275
4276 /*
4277 * upd_nr_flags updates the node records stored in this node's local mddb
4278 * given a node desciptor list and an action. upd_nr_flags then commits
4279 * the node records to the local mddb.
4280 *
4281 * nd - A linked list of node descriptors that describes the node records
4282 * in this diskset on which the action applies.
4283 * flag_action: action to be taken on node records that match the nd list.
4284 * flag_action can be:
4285 * MD_NR_JOIN: set OWN flag in node records
4286 * MD_NR_WITHDRAW: reset OWN flag in node records
4287 * MD_NR_OK: reset ADD flags and set OK flag in node records
4288 * MD_NR_SET: set node record flags based on flags stored in nd
4289 *
4290 * Typically, the JOIN, WITHDRAW and OK flag_actions are used when setting
4291 * all nodes in a diskset to JOIN (add first disk to set), WITHDRAW
4292 * (remove last disk from set) or OK (after addition of host to set).
4293 *
4294 * The SET flag_action is typically used when nodelist contains all nodes
4295 * in the diskset, but specific nodes have had flag changes. An example of
4296 * this would be the join/withdraw of a specific node to/from the set.
4297 *
4298 * Ignore the MD_MN_NODE_RB_JOIN flag if set in node record flag. This
4299 * flag is used by the client to recover in case of failure and should not
4300 * be set in the node record flags.
4301 */
4302 static void
upd_nr_flags(mdsetname_t * sp,md_mnnode_desc * nd,uint_t flag_action,md_error_t * ep)4303 upd_nr_flags(
4304 mdsetname_t *sp,
4305 md_mnnode_desc *nd,
4306 uint_t flag_action,
4307 md_error_t *ep
4308 )
4309 {
4310 mdsetname_t *local_sp;
4311 md_set_record *sr;
4312 md_mnset_record *mnsr;
4313 md_mnnode_desc *ndp;
4314 md_mnnode_record *nrp;
4315
4316 if ((local_sp = metasetname(sp->setname, ep)) == NULL)
4317 return;
4318
4319 metaflushsetname(local_sp);
4320
4321 if ((sr = getsetbyname(sp->setname, ep)) == NULL)
4322 return;
4323
4324 if (!(MD_MNSET_REC(sr))) {
4325 return;
4326 }
4327 mnsr = (struct md_mnset_record *)sr;
4328
4329 switch (flag_action) {
4330 case MD_NR_JOIN:
4331 case MD_NR_WITHDRAW:
4332 case MD_NR_SET:
4333 case MD_NR_OK:
4334 case MD_NR_DEL:
4335 break;
4336 default:
4337 return;
4338 }
4339
4340 for (ndp = nd; ndp != NULL; ndp = ndp->nd_next) {
4341 /* Find matching node record for given node descriptor */
4342 for (nrp = mnsr->sr_nodechain; nrp != NULL;
4343 nrp = nrp->nr_next) {
4344 if (ndp->nd_nodeid == nrp->nr_nodeid) {
4345 switch (flag_action) {
4346 case MD_NR_JOIN:
4347 nrp->nr_flags |= MD_MN_NODE_OWN;
4348 break;
4349 case MD_NR_WITHDRAW:
4350 nrp->nr_flags &= ~MD_MN_NODE_OWN;
4351 break;
4352 case MD_NR_OK:
4353 nrp->nr_flags &=
4354 ~(MD_MN_NODE_ADD | MD_MN_NODE_DEL);
4355 nrp->nr_flags |= MD_MN_NODE_OK;
4356 break;
4357 case MD_NR_DEL:
4358 nrp->nr_flags &=
4359 ~(MD_MN_NODE_OK | MD_MN_NODE_ADD);
4360 nrp->nr_flags |= MD_MN_NODE_DEL;
4361 break;
4362 case MD_NR_SET:
4363 /* Do not set RB_JOIN flag */
4364 nrp->nr_flags =
4365 ndp->nd_flags & ~MD_MN_NODE_RB_JOIN;
4366 break;
4367 }
4368 break;
4369 }
4370 }
4371 }
4372 out:
4373 /* Don't increment set genid for node record flag update */
4374 commitset(sr, FALSE, ep);
4375 free_sr(sr);
4376 }
4377
4378 /*
4379 * init/fini wrapper around upd_nr_flags
4380 */
4381 bool_t
mdrpc_upd_nr_flags_common(mdrpc_upd_nr_flags_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)4382 mdrpc_upd_nr_flags_common(
4383 mdrpc_upd_nr_flags_args *args,
4384 mdrpc_generic_res *res,
4385 struct svc_req *rqstp /* RPC stuff */
4386 )
4387 {
4388 md_error_t *ep = &res->status;
4389 int err;
4390 int op_mode = W_OK;
4391
4392 /* setup, check permissions */
4393 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4394 return (FALSE);
4395 else if (err != 0)
4396 return (TRUE);
4397
4398 /*
4399 * During reconfig, node record flags can be updated without
4400 * locking first.
4401 */
4402 if (!(args->flags & MNSET_IN_RECONFIG)) {
4403 if (check_set_lock(op_mode, args->cl_sk, ep))
4404 return (TRUE);
4405 }
4406
4407 /* doit */
4408 upd_nr_flags(args->sp, args->nodedescs, args->flag_action, ep);
4409
4410 err = svc_fini(ep);
4411
4412 return (TRUE);
4413 }
4414
4415 /*
4416 * update the node records using given flag action.
4417 */
4418 bool_t
mdrpc_upd_nr_flags_2_svc(mdrpc_upd_nr_flags_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)4419 mdrpc_upd_nr_flags_2_svc(
4420 mdrpc_upd_nr_flags_2_args *args,
4421 mdrpc_generic_res *res,
4422 struct svc_req *rqstp /* RPC stuff */
4423 )
4424 {
4425 (void) memset(res, 0, sizeof (*res));
4426 switch (args->rev) {
4427 case MD_METAD_ARGS_REV_1:
4428 return (mdrpc_upd_nr_flags_common(
4429 &args->mdrpc_upd_nr_flags_2_args_u.rev1, res, rqstp));
4430 default:
4431 return (FALSE);
4432 }
4433 }
4434
4435 void
free_sk(md_setkey_t * skp)4436 free_sk(md_setkey_t *skp)
4437 {
4438 Free(skp->sk_setname);
4439 Free(skp->sk_host);
4440 Free(skp);
4441 }
4442
4443 void
del_sk(set_t setno)4444 del_sk(set_t setno)
4445 {
4446 md_setkey_t *skp;
4447 md_setkey_t *tskp;
4448
4449 for (skp = tskp = my_svc_sk; skp; tskp = skp, skp = skp->sk_next) {
4450 if (setno == skp->sk_setno) {
4451 if (skp == my_svc_sk)
4452 my_svc_sk = skp->sk_next;
4453 else
4454 tskp->sk_next = skp->sk_next;
4455
4456 Free(skp->sk_setname);
4457 Free(skp->sk_host);
4458 Free(skp);
4459 break;
4460 }
4461 }
4462 }
4463
4464 md_setkey_t *
dupsk(md_setkey_t * skp)4465 dupsk(md_setkey_t *skp)
4466 {
4467 md_setkey_t *tskp;
4468
4469 tskp = Zalloc(sizeof (md_setkey_t));
4470
4471 *tskp = *skp;
4472 tskp->sk_host = Strdup(skp->sk_host);
4473 tskp->sk_setname = Strdup(skp->sk_setname);
4474
4475 return (tskp);
4476 }
4477
4478 md_setkey_t *
svc_get_setkey(set_t setno)4479 svc_get_setkey(set_t setno)
4480 {
4481 md_setkey_t *skp;
4482
4483 for (skp = my_svc_sk; skp != NULL; skp = skp->sk_next)
4484 if (setno == skp->sk_setno)
4485 return (dupsk(skp));
4486 return (NULL);
4487 }
4488
4489 void
svc_set_setkey(md_setkey_t * svc_sk)4490 svc_set_setkey(md_setkey_t *svc_sk)
4491 {
4492 md_setkey_t *skp;
4493
4494 if (my_svc_sk == NULL) {
4495 my_svc_sk = dupsk(svc_sk);
4496 return;
4497 }
4498
4499 for (skp = my_svc_sk; skp->sk_next != NULL; skp = skp->sk_next)
4500 assert(svc_sk->sk_setno != skp->sk_setno);
4501
4502 skp->sk_next = dupsk(svc_sk);
4503 }
4504
4505 /*
4506 * Unlock the set
4507 *
4508 * To unlock the set, the user must have the correct key, once this is verified
4509 * the set is unlocked and the cached information for the set is flushed.
4510 */
4511 bool_t
mdrpc_unlock_set_common(mdrpc_null_args * args,mdrpc_setlock_res * res,struct svc_req * rqstp)4512 mdrpc_unlock_set_common(
4513 mdrpc_null_args *args,
4514 mdrpc_setlock_res *res,
4515 struct svc_req *rqstp /* RPC stuff */
4516 )
4517 {
4518 md_error_t *ep = &res->status;
4519 int err;
4520 int op_mode = W_OK;
4521 md_setkey_t *svc_skp;
4522 md_set_desc *sd;
4523 mdsetname_t *sp;
4524 int multi_node = 0;
4525 md_error_t xep = mdnullerror;
4526
4527 /* setup, check permissions */
4528 (void) memset(res, 0, sizeof (*res));
4529 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4530 return (FALSE);
4531 else if (err != 0)
4532 return (TRUE);
4533
4534 /*
4535 * Is diskset a MN diskset?
4536 * Don't set error from this check since unlock set can be
4537 * called after a set has been deleted.
4538 */
4539 if (((sp = metasetnosetname(args->cl_sk->sk_setno, &xep)) != NULL) &&
4540 ((sd = metaget_setdesc(sp, &xep)) != NULL)) {
4541 if ((MD_MNSET_DESC(sd))) {
4542 multi_node = 1;
4543 }
4544 }
4545
4546 /* Get the set key, if any */
4547 svc_skp = svc_get_setkey(args->cl_sk->sk_setno);
4548
4549 /* The set is locked */
4550 if (svc_skp != NULL) {
4551
4552 /* Make sure the opener has the right key. */
4553 if (args->cl_sk->sk_key.tv_sec != svc_skp->sk_key.tv_sec ||
4554 args->cl_sk->sk_key.tv_usec != svc_skp->sk_key.tv_usec) {
4555 (void) mddserror(ep, MDE_DS_ULKSBADKEY,
4556 svc_skp->sk_setno, mynode(), svc_skp->sk_host,
4557 svc_skp->sk_setname);
4558 free_sk(svc_skp);
4559 return (TRUE);
4560 }
4561
4562 /* Unlock the set */
4563 del_sk(args->cl_sk->sk_setno);
4564
4565 /* Cleanup */
4566 free_sk(svc_skp);
4567
4568 goto out;
4569 }
4570
4571
4572 /*
4573 * It is possible on a MN diskset to attempt to unlock a set that
4574 * is unlocked. This could occur when the metaset or metadb command
4575 * is failing due to another metaset or metadb command running.
4576 * So, print no warning for MN disksets.
4577 */
4578 if (multi_node == 0) {
4579 md_eprintf("Warning: set unlocked when unlock_set called!\n");
4580 }
4581
4582 out:
4583 res->cl_sk = svc_get_setkey(args->cl_sk->sk_setno);
4584
4585 /* Flush the set cache */
4586 sr_cache_flush_setno(args->cl_sk->sk_setno);
4587
4588 return (TRUE);
4589 }
4590
4591 bool_t
mdrpc_unlock_set_1_svc(mdrpc_null_args * args,mdrpc_setlock_res * res,struct svc_req * rqstp)4592 mdrpc_unlock_set_1_svc(
4593 mdrpc_null_args *args,
4594 mdrpc_setlock_res *res,
4595 struct svc_req *rqstp /* RPC stuff */
4596 )
4597 {
4598 return (mdrpc_unlock_set_common(args, res, rqstp));
4599 }
4600
4601 bool_t
mdrpc_unlock_set_2_svc(mdrpc_null_args * args,mdrpc_setlock_res * res,struct svc_req * rqstp)4602 mdrpc_unlock_set_2_svc(
4603 mdrpc_null_args *args,
4604 mdrpc_setlock_res *res,
4605 struct svc_req *rqstp /* RPC stuff */
4606 )
4607 {
4608 return (mdrpc_unlock_set_common(args, res, rqstp));
4609 }
4610
4611 /*
4612 * Lock the set
4613 *
4614 * If the user does not hand us a key, then we generate a new key and lock the
4615 * set using this new key that was generated, if the user hands us a key then
4616 * we use the key to lock the set.
4617 */
4618 bool_t
mdrpc_lock_set_common(mdrpc_null_args * args,mdrpc_setlock_res * res,struct svc_req * rqstp)4619 mdrpc_lock_set_common(
4620 mdrpc_null_args *args,
4621 mdrpc_setlock_res *res,
4622 struct svc_req *rqstp /* RPC stuff */
4623 )
4624 {
4625 md_error_t *ep = &res->status;
4626 int err;
4627 md_error_t xep = mdnullerror;
4628 int op_mode = W_OK;
4629 md_setkey_t *svc_skp;
4630 md_setkey_t new_sk;
4631 md_set_desc *sd = NULL;
4632 mdsetname_t *sp = NULL;
4633
4634 /* setup, check permissions */
4635 (void) memset(res, 0, sizeof (*res));
4636 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4637 return (FALSE);
4638 else if (err != 0)
4639 return (TRUE);
4640
4641 svc_skp = svc_get_setkey(args->cl_sk->sk_setno);
4642
4643 /* The set is locked */
4644 if (svc_skp != NULL) {
4645
4646 /*
4647 * This lock request could be for a new diskset, as
4648 * such metasetnosetname() may not return anything
4649 * useful. Only call it if there is already a key.
4650 */
4651 if ((sp = metasetnosetname(args->cl_sk->sk_setno, ep))
4652 != NULL) {
4653 sd = metaget_setdesc(sp, ep);
4654 }
4655
4656 /*
4657 * meta_lock() provides local locking for non-MN
4658 * disksets. The local lock is held before we call
4659 * this RPC function. We should not receive a lock
4660 * request from the host which owns the lock. If we
4661 * do, release the lock.
4662 */
4663 if (!((sd != NULL) && (MD_MNSET_DESC(sd))) &&
4664 (strcmp(svc_skp->sk_host, args->cl_sk->sk_host) == 0)) {
4665 md_eprintf(
4666 "Warning: set locked when lock_set called!\n");
4667
4668 md_eprintf("Held lock info:\n");
4669
4670 md_eprintf("\tLock:\n");
4671 md_eprintf("\t\tSetname: %s\n", svc_skp->sk_setname);
4672 md_eprintf("\t\tSetno: %d\n", svc_skp->sk_setno);
4673 md_eprintf("\t\tHost: %s\n", svc_skp->sk_host);
4674 md_eprintf("\t\tKey: %d/%d %s\n",
4675 svc_skp->sk_key.tv_sec, svc_skp->sk_key.tv_usec,
4676 ctime((const time_t *)&svc_skp->sk_key.tv_sec));
4677
4678 /* Unlock set */
4679 del_sk(svc_skp->sk_setno);
4680 free_sk(svc_skp);
4681 svc_skp = NULL;
4682
4683 md_eprintf("Released lock held by requesting host\n");
4684 }
4685 }
4686
4687 /* The set is unlocked */
4688 if (svc_skp == NULL) {
4689 /* If we have been given a key, use it. */
4690 if (args->cl_sk->sk_key.tv_sec || args->cl_sk->sk_key.tv_usec) {
4691 svc_set_setkey(args->cl_sk);
4692 res->cl_sk = svc_get_setkey(args->cl_sk->sk_setno);
4693 goto out;
4694 }
4695
4696 /* We need to lock it, with a new key */
4697 new_sk = *args->cl_sk;
4698 if (meta_gettimeofday(&new_sk.sk_key) == -1) {
4699 (void) mdsyserror(ep, errno, "meta_gettimeofday()");
4700 mde_perror(&xep, "");
4701 md_exit(NULL, 1);
4702 }
4703 svc_set_setkey(&new_sk);
4704
4705 res->cl_sk = svc_get_setkey(args->cl_sk->sk_setno);
4706 goto out;
4707 }
4708
4709 /*
4710 * If a MN diskset, the lock_set routine is used as a locking
4711 * mechanism to keep multiple metaset and/or metadb commads
4712 * from interfering with each other. If two metaset/metadb
4713 * commands are issued at the same time - one will complete
4714 * and the other command will fail with MDE_DS_NOTNOW_CMD.
4715 */
4716 if ((sd != NULL) && MD_MNSET_DESC(sd)) {
4717 (void) mddserror(ep, MDE_DS_NOTNOW_CMD,
4718 svc_skp->sk_setno, mynode(),
4719 svc_skp->sk_host, svc_skp->sk_setname);
4720 goto out;
4721 }
4722
4723 md_eprintf("Warning: set locked when lock_set called!\n");
4724
4725 md_eprintf("Lock info:\n");
4726
4727 md_eprintf("\tLock(svc):\n");
4728 md_eprintf("\t\tSetname: %s\n", svc_skp->sk_setname);
4729 md_eprintf("\t\tSetno: %d\n", svc_skp->sk_setno);
4730 md_eprintf("\t\tHost: %s\n", svc_skp->sk_host);
4731 md_eprintf("\t\tKey: %d/%d %s",
4732 svc_skp->sk_key.tv_sec, svc_skp->sk_key.tv_usec,
4733 ctime((const time_t *)&svc_skp->sk_key.tv_sec));
4734
4735 md_eprintf("\tLock(cl):\n");
4736 md_eprintf("\t\tSetname: %s\n", args->cl_sk->sk_setname);
4737 md_eprintf("\t\tSetno: %d\n", args->cl_sk->sk_setno);
4738 md_eprintf("\t\tHost: %s\n", args->cl_sk->sk_host);
4739 md_eprintf("\t\tKey: %d/%d %s",
4740 args->cl_sk->sk_key.tv_sec, args->cl_sk->sk_key.tv_usec,
4741 ctime((const time_t *)&args->cl_sk->sk_key.tv_sec));
4742
4743 /* The set is locked, do we have the key? */
4744 if (args->cl_sk->sk_key.tv_sec == svc_skp->sk_key.tv_sec &&
4745 args->cl_sk->sk_key.tv_usec == svc_skp->sk_key.tv_usec) {
4746 res->cl_sk = svc_get_setkey(args->cl_sk->sk_setno);
4747 goto out;
4748 }
4749
4750 /*
4751 * The set is locked and we do not have the key, so we set up an error.
4752 */
4753 (void) mddserror(ep, MDE_DS_LKSBADKEY, svc_skp->sk_setno, mynode(),
4754 svc_skp->sk_host, args->cl_sk->sk_setname);
4755
4756 out:
4757 if (svc_skp != NULL)
4758 free_sk(svc_skp);
4759
4760 /* Flush the set cache */
4761 sr_cache_flush_setno(args->cl_sk->sk_setno);
4762
4763 return (TRUE);
4764 }
4765
4766 bool_t
mdrpc_lock_set_1_svc(mdrpc_null_args * args,mdrpc_setlock_res * res,struct svc_req * rqstp)4767 mdrpc_lock_set_1_svc(
4768 mdrpc_null_args *args,
4769 mdrpc_setlock_res *res,
4770 struct svc_req *rqstp /* RPC stuff */
4771 )
4772 {
4773 return (mdrpc_lock_set_common(args, res, rqstp));
4774 }
4775
4776 bool_t
mdrpc_lock_set_2_svc(mdrpc_null_args * args,mdrpc_setlock_res * res,struct svc_req * rqstp)4777 mdrpc_lock_set_2_svc(
4778 mdrpc_null_args *args,
4779 mdrpc_setlock_res *res,
4780 struct svc_req *rqstp /* RPC stuff */
4781 )
4782 {
4783 return (mdrpc_lock_set_common(args, res, rqstp));
4784 }
4785
4786 static void
updmeds(char * setname,md_h_arr_t * medp,int version,md_error_t * ep)4787 updmeds(
4788 char *setname,
4789 md_h_arr_t *medp,
4790 int version, /* RPC version of calling routine */
4791 md_error_t *ep
4792 )
4793 {
4794 mddb_userreq_t req;
4795 md_set_record *sr;
4796 mddb_med_parm_t mp;
4797
4798 if ((sr = getsetbyname(setname, ep)) == NULL)
4799 return;
4800
4801 sr->sr_med = *medp; /* structure assignment */
4802
4803 (void) memset(&req, '\0', sizeof (req));
4804
4805 METAD_SETUP_SR(MD_DB_SETDATA, sr->sr_selfid)
4806 /* Do MN operation if rpc version supports it and if a MN set */
4807 if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
4808 req.ur_size = sizeof (struct md_mnset_record);
4809 } else {
4810 req.ur_size = sizeof (*sr);
4811 }
4812 req.ur_data = (uintptr_t)sr;
4813 if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
4814 (void) mdstealerror(ep, &req.ur_mde);
4815 free_sr(sr);
4816 return;
4817 }
4818
4819 commitset(sr, TRUE, ep);
4820
4821 /*
4822 * If a MN disket, send the mediator list to the kernel.
4823 */
4824 if (MD_MNSET_REC(sr)) {
4825 (void) memset(&mp, '\0', sizeof (mddb_med_parm_t));
4826 mp.med_setno = sr->sr_setno;
4827 if (meta_h2hi(medp, &mp.med, ep)) {
4828 free_sr(sr);
4829 return;
4830 }
4831
4832 /* Resolve the IP addresses for the host list */
4833 if (meta_med_hnm2ip(&mp.med, ep)) {
4834 free_sr(sr);
4835 return;
4836 }
4837
4838 /* If node not yet joined to set, failure is ok. */
4839 if (metaioctl(MD_MED_SET_LST, &mp, &mp.med_mde, NULL) != 0) {
4840 if (!mdismddberror(&mp.med_mde, MDE_DB_NOTOWNER)) {
4841 (void) mdstealerror(ep, &mp.med_mde);
4842 }
4843 }
4844 }
4845 free_sr(sr);
4846 }
4847
4848 /*
4849 * Update the mediator data in the set record
4850 */
4851 bool_t
mdrpc_updmeds_common(mdrpc_updmeds_args * args,mdrpc_generic_res * res,struct svc_req * rqstp,int version)4852 mdrpc_updmeds_common(
4853 mdrpc_updmeds_args *args,
4854 mdrpc_generic_res *res,
4855 struct svc_req *rqstp, /* RPC stuff */
4856 int version /* RPC version */
4857 )
4858 {
4859 md_error_t *ep = &res->status;
4860 int err;
4861 int op_mode = W_OK;
4862
4863 /* setup, check permissions */
4864 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4865 return (FALSE);
4866 else if (err != 0)
4867 return (TRUE);
4868
4869 if (check_set_lock(op_mode, args->cl_sk, ep))
4870 return (TRUE);
4871
4872 /* doit */
4873 updmeds(args->sp->setname, &args->meds, version, ep);
4874
4875 err = svc_fini(ep);
4876
4877 return (TRUE);
4878 }
4879
4880 bool_t
mdrpc_updmeds_1_svc(mdrpc_updmeds_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)4881 mdrpc_updmeds_1_svc(
4882 mdrpc_updmeds_args *args,
4883 mdrpc_generic_res *res,
4884 struct svc_req *rqstp /* RPC stuff */
4885 )
4886 {
4887 (void) memset(res, 0, sizeof (*res));
4888 /* Pass RPC version (METAD_VERSION) to common routine */
4889 return (mdrpc_updmeds_common(args, res, rqstp, METAD_VERSION));
4890 }
4891
4892 bool_t
mdrpc_updmeds_2_svc(mdrpc_updmeds_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)4893 mdrpc_updmeds_2_svc(
4894 mdrpc_updmeds_2_args *args,
4895 mdrpc_generic_res *res,
4896 struct svc_req *rqstp /* RPC stuff */
4897 )
4898 {
4899 (void) memset(res, 0, sizeof (*res));
4900 switch (args->rev) {
4901 case MD_METAD_ARGS_REV_1:
4902 /* Pass RPC version (METAD_VERSION_DEVID) to common routine */
4903 return (mdrpc_updmeds_common(
4904 &args->mdrpc_updmeds_2_args_u.rev1, res,
4905 rqstp, METAD_VERSION_DEVID));
4906 default:
4907 return (FALSE);
4908 }
4909 }
4910
4911 /*
4912 * Call routines to suspend, reinit and resume mdcommd.
4913 * Called during metaset and metadb command.
4914 * NOT called during reconfig cycle.
4915 */
4916 bool_t
mdrpc_mdcommdctl_2_svc(mdrpc_mdcommdctl_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)4917 mdrpc_mdcommdctl_2_svc(
4918 mdrpc_mdcommdctl_2_args *args,
4919 mdrpc_generic_res *res,
4920 struct svc_req *rqstp /* RPC stuff */
4921 )
4922 {
4923 mdrpc_mdcommdctl_args *args_cc;
4924 md_error_t *ep = &res->status;
4925 int err;
4926 int op_mode = R_OK;
4927 int suspend_ret;
4928
4929 (void) memset(res, 0, sizeof (*res));
4930 switch (args->rev) {
4931 case MD_METAD_ARGS_REV_1:
4932 /* setup, check permissions */
4933 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4934 return (FALSE);
4935 else if (err != 0)
4936 return (TRUE);
4937
4938 args_cc = &(args->mdrpc_mdcommdctl_2_args_u.rev1);
4939 switch (args_cc->flag_action) {
4940 case COMMDCTL_SUSPEND:
4941 suspend_ret = mdmn_suspend(args_cc->setno,
4942 args_cc->class, 0);
4943 if (suspend_ret != 0) {
4944 (void) mddserror(ep, suspend_ret,
4945 args_cc->setno, mynode(),
4946 NULL, mynode());
4947 }
4948 break;
4949 case COMMDCTL_RESUME:
4950 if (mdmn_resume(args_cc->setno,
4951 args_cc->class, args_cc->flags, 0)) {
4952 (void) mddserror(ep,
4953 MDE_DS_COMMDCTL_RESUME_FAIL,
4954 args_cc->setno, mynode(),
4955 NULL, mynode());
4956 }
4957 break;
4958 case COMMDCTL_REINIT:
4959 if (mdmn_reinit_set(args_cc->setno, 0)) {
4960 (void) mddserror(ep,
4961 MDE_DS_COMMDCTL_REINIT_FAIL,
4962 args_cc->setno, mynode(),
4963 NULL, mynode());
4964 }
4965 break;
4966 }
4967 err = svc_fini(ep);
4968 return (TRUE);
4969
4970 default:
4971 return (FALSE);
4972 }
4973 }
4974
4975 /*
4976 * Return TRUE if set is stale.
4977 */
4978 bool_t
mdrpc_mn_is_stale_2_svc(mdrpc_setno_2_args * args,mdrpc_bool_res * res,struct svc_req * rqstp)4979 mdrpc_mn_is_stale_2_svc(
4980 mdrpc_setno_2_args *args,
4981 mdrpc_bool_res *res,
4982 struct svc_req *rqstp /* RPC stuff */
4983 )
4984 {
4985 md_error_t *ep = &res->status;
4986 mddb_config_t c;
4987 int err;
4988 int op_mode = R_OK;
4989
4990 (void) memset(res, 0, sizeof (*res));
4991 (void) memset(&c, 0, sizeof (c));
4992 switch (args->rev) {
4993 case MD_METAD_ARGS_REV_1:
4994 c.c_id = 0;
4995 c.c_setno = args->mdrpc_setno_2_args_u.rev1.setno;
4996
4997 /* setup, check permissions */
4998 (void) memset(res, 0, sizeof (*res));
4999 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
5000 return (FALSE);
5001 else if (err != 0)
5002 return (TRUE);
5003
5004 if (metaioctl(MD_DB_GETDEV, &c, &c.c_mde, NULL) != 0) {
5005 (void) mdstealerror(ep, &c.c_mde);
5006 return (TRUE);
5007 }
5008
5009 if (c.c_flags & MDDB_C_STALE) {
5010 res->value = TRUE;
5011 } else {
5012 res->value = FALSE;
5013 }
5014
5015 err = svc_fini(ep);
5016 return (TRUE);
5017
5018 default:
5019 return (FALSE);
5020 }
5021 }
5022
5023 /*
5024 * Clear out all clnt_locks held by all MN disksets.
5025 * This is only used during a reconfig cycle.
5026 */
5027 /* ARGSUSED */
5028 int
mdrpc_clr_mnsetlock_2_svc(mdrpc_null_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)5029 mdrpc_clr_mnsetlock_2_svc(
5030 mdrpc_null_args *args,
5031 mdrpc_generic_res *res,
5032 struct svc_req *rqstp /* RPC stuff */
5033 )
5034 {
5035 set_t max_sets, setno;
5036 md_error_t *ep = &res->status;
5037 int err;
5038 int op_mode = W_OK;
5039 mdsetname_t *sp;
5040
5041 /* setup, check permissions */
5042 (void) memset(res, 0, sizeof (*res));
5043
5044 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
5045 return (FALSE);
5046 else if (err != 0)
5047 return (TRUE);
5048
5049 /*
5050 * Walk through all possible disksets.
5051 * For each MN set, delete all keys associated with that set.
5052 */
5053 if ((max_sets = get_max_sets(ep)) == 0) {
5054 return (TRUE);
5055 }
5056
5057 /* start walking through all possible disksets */
5058 for (setno = 1; setno < max_sets; setno++) {
5059 if ((sp = metasetnosetname(setno, ep)) == NULL) {
5060 if (mdiserror(ep, MDE_NO_SET)) {
5061 /* No set for this setno - continue */
5062 mdclrerror(ep);
5063 continue;
5064 } else {
5065 mde_perror(ep, gettext(
5066 "Unable to get set %s information"),
5067 sp->setname);
5068 mdclrerror(ep);
5069 continue;
5070 }
5071 }
5072
5073 /* only check multi-node disksets */
5074 if (!meta_is_mn_set(sp, ep)) {
5075 mdclrerror(ep);
5076 continue;
5077 }
5078
5079 /* Delete keys associated with rpc.metad clnt_lock */
5080 del_sk(setno);
5081 }
5082
5083 *ep = mdnullerror;
5084
5085 err = svc_fini(ep);
5086
5087 return (TRUE);
5088 }
5089
5090 /*
5091 * Get drive desc on this host for given setno.
5092 * This is only used during a reconfig cycle.
5093 * Returns a drive desc structure for the given mdsetname
5094 * from this host.
5095 *
5096 * Returned drive desc structure is partially filled in with
5097 * the drive name but is not filled in with any other strings
5098 * in the drivename structure.
5099 */
5100 bool_t
mdrpc_getdrivedesc_2_svc(mdrpc_sp_2_args * args,mdrpc_getdrivedesc_res * res,struct svc_req * rqstp)5101 mdrpc_getdrivedesc_2_svc(
5102 mdrpc_sp_2_args *args,
5103 mdrpc_getdrivedesc_res *res,
5104 struct svc_req *rqstp /* RPC stuff */
5105 )
5106 {
5107 md_drive_desc *dd;
5108 md_error_t *ep = &res->status;
5109 int err;
5110 int op_mode = R_OK;
5111 mdsetname_t *my_sp;
5112 mdrpc_sp_args *args_r1;
5113
5114 (void) memset(res, 0, sizeof (*res));
5115 switch (args->rev) {
5116 case MD_METAD_ARGS_REV_1:
5117 /* setup, check permissions */
5118 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
5119 return (FALSE);
5120 else if (err != 0)
5121 return (TRUE);
5122
5123 /* doit */
5124 args_r1 = &args->mdrpc_sp_2_args_u.rev1;
5125 if ((my_sp = metasetname(args_r1->sp->setname, ep)) == NULL)
5126 return (TRUE);
5127
5128 dd = metaget_drivedesc(my_sp,
5129 (MD_BASICNAME_OK | PRINT_FAST), ep);
5130
5131 res->dd = dd_list_dup(dd);
5132
5133 err = svc_fini(ep);
5134
5135 return (TRUE);
5136 default:
5137 return (FALSE);
5138 }
5139 }
5140
5141 /*
5142 * Update drive records given list from master during reconfig.
5143 * Make this node's list match the master's list which may include
5144 * deleting a drive record that is known by this node and not known
5145 * by the master node.
5146 *
5147 * Sync up the set/node/drive record genids to match the genid
5148 * passed in the dd structure (all genids in this structure
5149 * are the same).
5150 */
5151 bool_t
mdrpc_upd_dr_reconfig_common(mdrpc_upd_dr_flags_2_args_r1 * args,mdrpc_generic_res * res,struct svc_req * rqstp)5152 mdrpc_upd_dr_reconfig_common(
5153 mdrpc_upd_dr_flags_2_args_r1 *args,
5154 mdrpc_generic_res *res,
5155 struct svc_req *rqstp /* RPC stuff */
5156 )
5157 {
5158 md_error_t *ep = &res->status;
5159 int err;
5160 mdsetname_t *local_sp;
5161 md_set_record *sr;
5162 md_mnset_record *mnsr;
5163 md_drive_record *dr, *dr_placeholder = NULL;
5164 md_drive_desc *dd;
5165 mddrivename_t *dn, *dn1;
5166 side_t sideno;
5167 md_mnnode_record *nrp;
5168 int op_mode = W_OK;
5169 int change = 0;
5170
5171 /* setup, check permissions */
5172 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
5173 return (FALSE);
5174 else if (err != 0)
5175 return (TRUE);
5176
5177 if ((local_sp = metasetname(args->sp->setname, ep)) == NULL)
5178 return (TRUE);
5179
5180 metaflushsetname(local_sp);
5181
5182 if ((sideno = getmyside(local_sp, ep)) == MD_SIDEWILD)
5183 return (TRUE);
5184
5185 if ((sr = getsetbyname(args->sp->setname, ep)) == NULL)
5186 return (TRUE);
5187
5188 if (!(MD_MNSET_REC(sr))) {
5189 free_sr(sr);
5190 return (TRUE);
5191 }
5192
5193 mnsr = (md_mnset_record *)sr;
5194 /* Setup genid on set and node records */
5195 if (args->drivedescs) {
5196 if (mnsr->sr_genid != args->drivedescs->dd_genid) {
5197 change = 1;
5198 mnsr->sr_genid = args->drivedescs->dd_genid;
5199 }
5200 nrp = mnsr->sr_nodechain;
5201 while (nrp) {
5202 if (nrp->nr_genid != args->drivedescs->dd_genid) {
5203 change = 1;
5204 nrp->nr_genid = args->drivedescs->dd_genid;
5205 }
5206 nrp = nrp->nr_next;
5207 }
5208 }
5209 for (dr = mnsr->sr_drivechain; dr; dr = dr->dr_next) {
5210 dn1 = metadrivename_withdrkey(local_sp, sideno,
5211 dr->dr_key, (MD_BASICNAME_OK | PRINT_FAST), ep);
5212 if (dn1 == NULL)
5213 goto out;
5214 for (dd = args->drivedescs; dd != NULL; dd = dd->dd_next) {
5215 dn = dd->dd_dnp;
5216 /* Found this node's drive rec to match dd */
5217 if (strcmp(dn->cname, dn1->cname) == 0)
5218 break;
5219 }
5220
5221 /*
5222 * If drive found in master's list, make slave match master.
5223 * If drive not found in master's list, remove drive.
5224 */
5225 if (dd) {
5226 if ((dr->dr_flags != dd->dd_flags) ||
5227 (dr->dr_genid != dd->dd_genid)) {
5228 change = 1;
5229 dr->dr_flags = dd->dd_flags;
5230 dr->dr_genid = dd->dd_genid;
5231 }
5232 } else {
5233 /*
5234 * Delete entry from linked list. Need to use
5235 * dr_placeholder so that dr->dr_next points to
5236 * the next drive record in the list.
5237 */
5238 if (dr_placeholder == NULL) {
5239 dr_placeholder =
5240 Zalloc(sizeof (md_drive_record));
5241 }
5242 dr_placeholder->dr_next = dr->dr_next;
5243 dr_placeholder->dr_key = dr->dr_key;
5244 sr_del_drv(sr, dr->dr_selfid);
5245 (void) del_sideno_sidenm(dr_placeholder->dr_key,
5246 sideno, ep);
5247 change = 1;
5248 dr = dr_placeholder;
5249 }
5250 }
5251 out:
5252 /* If incore records are correct, don't need to write to disk */
5253 if (change) {
5254 /* Don't increment the genid in commitset */
5255 commitset(sr, FALSE, ep);
5256 }
5257 free_sr(sr);
5258
5259 err = svc_fini(ep);
5260
5261 if (dr_placeholder != NULL)
5262 Free(dr_placeholder);
5263
5264 return (TRUE);
5265 }
5266
5267 /*
5268 * Version 2 routine to update this node's drive records based on
5269 * list passed in from master node.
5270 */
5271 bool_t
mdrpc_upd_dr_reconfig_2_svc(mdrpc_upd_dr_flags_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)5272 mdrpc_upd_dr_reconfig_2_svc(
5273 mdrpc_upd_dr_flags_2_args *args,
5274 mdrpc_generic_res *res,
5275 struct svc_req *rqstp /* RPC stuff */
5276 )
5277 {
5278 (void) memset(res, 0, sizeof (*res));
5279 switch (args->rev) {
5280 case MD_METAD_ARGS_REV_1:
5281 return (mdrpc_upd_dr_reconfig_common(
5282 &args->mdrpc_upd_dr_flags_2_args_u.rev1, res, rqstp));
5283 default:
5284 return (FALSE);
5285 }
5286 }
5287
5288 /*
5289 * reset mirror owner for mirrors owned by deleted
5290 * or withdrawn host(s). Hosts being deleted or
5291 * withdrawn are designated by nodeid since host is
5292 * already deleted or withdrawn from set and may not
5293 * be able to translate between a nodename and a nodeid.
5294 * If an error occurs, ep will be set to that error information.
5295 */
5296 static void
reset_mirror_owner(char * setname,int node_c,int * node_id,md_error_t * ep)5297 reset_mirror_owner(
5298 char *setname,
5299 int node_c,
5300 int *node_id, /* Array of node ids */
5301 md_error_t *ep
5302 )
5303 {
5304 mdsetname_t *local_sp;
5305 int i;
5306 mdnamelist_t *devnlp = NULL;
5307 mdnamelist_t *p;
5308 mdname_t *devnp = NULL;
5309 md_set_mmown_params_t ownpar_p;
5310 md_set_mmown_params_t *ownpar = &ownpar_p;
5311 char *miscname;
5312
5313 if ((local_sp = metasetname(setname, ep)) == NULL)
5314 return;
5315
5316 /* get a list of all the mirrors for current set */
5317 if (meta_get_mirror_names(local_sp, &devnlp, 0, ep) < 0)
5318 return;
5319
5320 /* for each mirror */
5321 for (p = devnlp; (p != NULL); p = p->next) {
5322 devnp = p->namep;
5323
5324 /*
5325 * we can only do these for mirrors so make sure we
5326 * really have a mirror device and not a softpartition
5327 * imitating one. meta_get_mirror_names seems to think
5328 * softparts on top of a mirror are mirrors!
5329 */
5330 if ((miscname = metagetmiscname(devnp, ep)) == NULL)
5331 goto out;
5332 if (strcmp(miscname, MD_MIRROR) != 0)
5333 continue;
5334
5335 (void) memset(ownpar, 0, sizeof (*ownpar));
5336 ownpar->d.mnum = meta_getminor(devnp->dev);
5337 MD_SETDRIVERNAME(ownpar, MD_MIRROR, local_sp->setno);
5338
5339 /* get the current owner id */
5340 if (metaioctl(MD_MN_GET_MM_OWNER, ownpar, ep,
5341 "MD_MN_GET_MM_OWNER") != 0) {
5342 mde_perror(ep, gettext(
5343 "Unable to get mirror owner for %s/%s"),
5344 local_sp->setname,
5345 get_mdname(local_sp, ownpar->d.mnum));
5346 goto out;
5347 }
5348
5349 if (ownpar->d.owner == MD_MN_MIRROR_UNOWNED) {
5350 mdclrerror(ep);
5351 continue;
5352 }
5353 /*
5354 * reset owner only if the current owner is
5355 * in the list of nodes being deleted.
5356 */
5357 for (i = 0; i < node_c; i++) {
5358 if (ownpar->d.owner == node_id[i]) {
5359 if (meta_mn_change_owner(&ownpar,
5360 local_sp->setno, ownpar->d.mnum,
5361 MD_MN_MIRROR_UNOWNED,
5362 MD_MN_MM_ALLOW_CHANGE) == -1) {
5363 mde_perror(ep, gettext(
5364 "Unable to reset mirror owner for"
5365 " %s/%s"), local_sp->setname,
5366 get_mdname(local_sp,
5367 ownpar->d.mnum));
5368 goto out;
5369 }
5370 break;
5371 }
5372 }
5373 }
5374
5375 out:
5376 /* cleanup */
5377 metafreenamelist(devnlp);
5378 }
5379
5380 /*
5381 * Wrapper routine for reset_mirror_owner.
5382 * Called when hosts are deleted or withdrawn
5383 * in order to reset any mirror owners that are needed.
5384 */
5385 bool_t
mdrpc_reset_mirror_owner_common(mdrpc_nodeid_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)5386 mdrpc_reset_mirror_owner_common(
5387 mdrpc_nodeid_args *args,
5388 mdrpc_generic_res *res,
5389 struct svc_req *rqstp /* RPC stuff */
5390 )
5391 {
5392 md_error_t *ep = &res->status;
5393 int err;
5394 int op_mode = W_OK;
5395
5396 /* setup, check permissions */
5397 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
5398 return (FALSE);
5399 else if (err != 0)
5400 return (TRUE);
5401
5402 if (check_set_lock(op_mode, args->cl_sk, ep))
5403 return (TRUE);
5404
5405 /* doit */
5406 reset_mirror_owner(args->sp->setname, args->nodeid.nodeid_len,
5407 args->nodeid.nodeid_val, ep);
5408
5409 err = svc_fini(ep);
5410
5411 return (TRUE);
5412 }
5413
5414 /*
5415 * RPC service routine to reset the mirror owner for mirrors owned
5416 * by the given hosts. Typically, the list of given hosts is a list
5417 * of nodes being deleted or withdrawn from a diskset.
5418 * The given hosts are designated by nodeid since host may
5419 * already be deleted or withdrawn from set and may not
5420 * be able to translate between a nodename and a nodeid.
5421 */
5422 bool_t
mdrpc_reset_mirror_owner_2_svc(mdrpc_nodeid_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)5423 mdrpc_reset_mirror_owner_2_svc(
5424 mdrpc_nodeid_2_args *args,
5425 mdrpc_generic_res *res,
5426 struct svc_req *rqstp /* RPC stuff */
5427 )
5428 {
5429 (void) memset(res, 0, sizeof (*res));
5430 switch (args->rev) {
5431 case MD_METAD_ARGS_REV_1:
5432 return (mdrpc_reset_mirror_owner_common(
5433 &args->mdrpc_nodeid_2_args_u.rev1, res,
5434 rqstp));
5435 default:
5436 return (FALSE);
5437 }
5438 }
5439
5440 /*
5441 * Call routines to suspend and resume I/O for the given diskset(s).
5442 * Called during reconfig cycle.
5443 * Diskset of 0 represents all MN disksets.
5444 */
5445 bool_t
mdrpc_mn_susp_res_io_2_svc(mdrpc_mn_susp_res_io_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)5446 mdrpc_mn_susp_res_io_2_svc(
5447 mdrpc_mn_susp_res_io_2_args *args,
5448 mdrpc_generic_res *res,
5449 struct svc_req *rqstp /* RPC stuff */
5450 )
5451 {
5452 mdrpc_mn_susp_res_io_args *args_sr;
5453 md_error_t *ep = &res->status;
5454 int err;
5455 int op_mode = R_OK;
5456
5457 (void) memset(res, 0, sizeof (*res));
5458 switch (args->rev) {
5459 case MD_METAD_ARGS_REV_1:
5460 /* setup, check permissions */
5461 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
5462 return (FALSE);
5463 else if (err != 0)
5464 return (TRUE);
5465
5466 args_sr = &(args->mdrpc_mn_susp_res_io_2_args_u.rev1);
5467 switch (args_sr->susp_res_cmd) {
5468 case MN_SUSP_IO:
5469 (void) (metaioctl(MD_MN_SUSPEND_SET,
5470 &args_sr->susp_res_setno, ep, NULL));
5471 break;
5472 case MN_RES_IO:
5473 (void) (metaioctl(MD_MN_RESUME_SET,
5474 &args_sr->susp_res_setno, ep, NULL));
5475 break;
5476 }
5477 err = svc_fini(ep);
5478 return (TRUE);
5479
5480 default:
5481 return (FALSE);
5482 }
5483 }
5484
5485 /*
5486 * Resnarf a set after it has been imported
5487 */
5488 bool_t
mdrpc_resnarf_set_2_svc(mdrpc_setno_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)5489 mdrpc_resnarf_set_2_svc(
5490 mdrpc_setno_2_args *args,
5491 mdrpc_generic_res *res,
5492 struct svc_req *rqstp /* RPC stuff */
5493 )
5494 {
5495 mdrpc_setno_args *setno_args;
5496 md_error_t *ep = &res->status;
5497 int err;
5498 int op_mode = R_OK;
5499
5500 (void) memset(res, 0, sizeof (*res));
5501 switch (args->rev) {
5502 case MD_METAD_ARGS_REV_1:
5503 setno_args = &args->mdrpc_setno_2_args_u.rev1;
5504 break;
5505 default:
5506 return (FALSE);
5507 }
5508
5509 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
5510 return (FALSE);
5511 else if (err != 0)
5512 return (TRUE);
5513
5514 /* do it */
5515 if (resnarf_set(setno_args->setno, ep) < 0)
5516 return (FALSE);
5517
5518 err = svc_fini(ep);
5519 return (TRUE);
5520 }
5521
5522 /*
5523 * Creates a resync thread.
5524 * Always returns true.
5525 */
5526 bool_t
mdrpc_mn_mirror_resync_all_2_svc(mdrpc_setno_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)5527 mdrpc_mn_mirror_resync_all_2_svc(
5528 mdrpc_setno_2_args *args,
5529 mdrpc_generic_res *res,
5530 struct svc_req *rqstp /* RPC stuff */
5531 )
5532 {
5533 md_error_t *ep = &res->status;
5534 mdrpc_setno_args *setno_args;
5535 int err;
5536 int op_mode = R_OK;
5537
5538 (void) memset(res, 0, sizeof (*res));
5539 switch (args->rev) {
5540 case MD_METAD_ARGS_REV_1:
5541 /* setup, check permissions */
5542 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
5543 return (FALSE);
5544 else if (err != 0)
5545 return (TRUE);
5546 setno_args = &args->mdrpc_setno_2_args_u.rev1;
5547
5548 /*
5549 * Need to invoke a metasync on a node newly added to a set.
5550 */
5551 (void) meta_mn_mirror_resync_all(&(setno_args->setno));
5552
5553 err = svc_fini(ep);
5554 return (TRUE);
5555
5556 default:
5557 return (FALSE);
5558 }
5559 }
5560
5561 /*
5562 * Updates ABR state for all softpartitions. Calls meta_mn_sp_update_abr(),
5563 * which forks a daemon process to perform this action.
5564 * Always returns true.
5565 */
5566 bool_t
mdrpc_mn_sp_update_abr_2_svc(mdrpc_setno_2_args * args,mdrpc_generic_res * res,struct svc_req * rqstp)5567 mdrpc_mn_sp_update_abr_2_svc(
5568 mdrpc_setno_2_args *args,
5569 mdrpc_generic_res *res,
5570 struct svc_req *rqstp /* RPC stuff */
5571 )
5572 {
5573 md_error_t *ep = &res->status;
5574 mdrpc_setno_args *setno_args;
5575 int err;
5576 int op_mode = R_OK;
5577
5578 (void) memset(res, 0, sizeof (*res));
5579 switch (args->rev) {
5580 case MD_METAD_ARGS_REV_1:
5581 /* setup, check permissions */
5582 if ((err = svc_init(rqstp, op_mode, ep)) < 0)
5583 return (FALSE);
5584 else if (err != 0)
5585 return (TRUE);
5586 setno_args = &args->mdrpc_setno_2_args_u.rev1;
5587
5588 (void) meta_mn_sp_update_abr(&(setno_args->setno));
5589
5590 err = svc_fini(ep);
5591 return (TRUE);
5592
5593 default:
5594 return (FALSE);
5595 }
5596 }
5597