1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 1995-2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * Just in case we're not in a build environment, make sure that 31*0Sstevel@tonic-gate * TEXT_DOMAIN gets set to something. 32*0Sstevel@tonic-gate */ 33*0Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 34*0Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 35*0Sstevel@tonic-gate #endif 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate /* 38*0Sstevel@tonic-gate * libmeta wrappers for event notification 39*0Sstevel@tonic-gate */ 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate #include <meta.h> 42*0Sstevel@tonic-gate #include <sys/lvm/md_notify.h> 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate #if defined(DEBUG) 45*0Sstevel@tonic-gate #include <assert.h> 46*0Sstevel@tonic-gate #endif /* DEBUG */ 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate struct tag2obj_type { 49*0Sstevel@tonic-gate md_tags_t tag; 50*0Sstevel@tonic-gate ev_obj_t obj; 51*0Sstevel@tonic-gate } tag2obj_typetab[] = 52*0Sstevel@tonic-gate { 53*0Sstevel@tonic-gate { TAG_EMPTY, EVO_EMPTY }, 54*0Sstevel@tonic-gate { TAG_METADEVICE, EVO_METADEV }, 55*0Sstevel@tonic-gate { TAG_REPLICA, EVO_REPLICA }, 56*0Sstevel@tonic-gate { TAG_HSP, EVO_HSP }, 57*0Sstevel@tonic-gate { TAG_HS, EVO_HS }, 58*0Sstevel@tonic-gate { TAG_SET, EVO_SET }, 59*0Sstevel@tonic-gate { TAG_DRIVE, EVO_DRIVE }, 60*0Sstevel@tonic-gate { TAG_HOST, EVO_HOST }, 61*0Sstevel@tonic-gate { TAG_MEDIATOR, EVO_MEDIATOR }, 62*0Sstevel@tonic-gate { TAG_UNK, EVO_UNSPECIFIED }, 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate { TAG_LAST, EVO_LAST } 65*0Sstevel@tonic-gate }; 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate struct evdrv2evlib_type { 68*0Sstevel@tonic-gate md_event_type_t drv; 69*0Sstevel@tonic-gate evid_t lib; 70*0Sstevel@tonic-gate } evdrv2evlib_typetab[] = 71*0Sstevel@tonic-gate { 72*0Sstevel@tonic-gate { EQ_EMPTY, EV_EMPTY }, 73*0Sstevel@tonic-gate { EQ_CREATE, EV_CREATE }, 74*0Sstevel@tonic-gate { EQ_DELETE, EV_DELETE }, 75*0Sstevel@tonic-gate { EQ_ADD, EV_ADD }, 76*0Sstevel@tonic-gate { EQ_REMOVE, EV_REMOVE }, 77*0Sstevel@tonic-gate { EQ_REPLACE, EV_REPLACE }, 78*0Sstevel@tonic-gate { EQ_MEDIATOR_ADD, EV_MEDIATOR_ADD }, 79*0Sstevel@tonic-gate { EQ_MEDIATOR_DELETE, EV_MEDIATOR_DELETE }, 80*0Sstevel@tonic-gate { EQ_HOST_ADD, EV_HOST_ADD }, 81*0Sstevel@tonic-gate { EQ_HOST_DELETE, EV_HOST_DELETE }, 82*0Sstevel@tonic-gate { EQ_DRIVE_ADD, EV_DRIVE_ADD }, 83*0Sstevel@tonic-gate { EQ_DRIVE_DELETE, EV_DRIVE_DELETE }, 84*0Sstevel@tonic-gate { EQ_RENAME_SRC, EV_RENAME_SRC }, 85*0Sstevel@tonic-gate { EQ_RENAME_DST, EV_RENAME_DST }, 86*0Sstevel@tonic-gate { EQ_INIT_START, EV_INIT_START }, 87*0Sstevel@tonic-gate { EQ_INIT_FAILED, EV_INIT_FAILED }, 88*0Sstevel@tonic-gate { EQ_INIT_FATAL, EV_INIT_FATAL }, 89*0Sstevel@tonic-gate { EQ_INIT_SUCCESS, EV_INIT_SUCCESS }, 90*0Sstevel@tonic-gate { EQ_IOERR, EV_IOERR }, 91*0Sstevel@tonic-gate { EQ_ERRED, EV_ERRED }, 92*0Sstevel@tonic-gate { EQ_LASTERRED, EV_LASTERRED }, 93*0Sstevel@tonic-gate { EQ_OK, EV_OK }, 94*0Sstevel@tonic-gate { EQ_ENABLE, EV_ENABLE }, 95*0Sstevel@tonic-gate { EQ_RESYNC_START, EV_RESYNC_START }, 96*0Sstevel@tonic-gate { EQ_RESYNC_FAILED, EV_RESYNC_FAILED }, 97*0Sstevel@tonic-gate { EQ_RESYNC_SUCCESS, EV_RESYNC_SUCCESS }, 98*0Sstevel@tonic-gate { EQ_RESYNC_DONE, EV_RESYNC_DONE }, 99*0Sstevel@tonic-gate { EQ_HOTSPARED, EV_HOTSPARED }, 100*0Sstevel@tonic-gate { EQ_HS_FREED, EV_HS_FREED }, 101*0Sstevel@tonic-gate { EQ_TAKEOVER, EV_TAKEOVER }, 102*0Sstevel@tonic-gate { EQ_RELEASE, EV_RELEASE }, 103*0Sstevel@tonic-gate { EQ_OPEN_FAIL, EV_OPEN_FAIL }, 104*0Sstevel@tonic-gate { EQ_OFFLINE, EV_OFFLINE }, 105*0Sstevel@tonic-gate { EQ_ONLINE, EV_ONLINE }, 106*0Sstevel@tonic-gate { EQ_GROW, EV_GROW }, 107*0Sstevel@tonic-gate { EQ_DETACH, EV_DETACH }, 108*0Sstevel@tonic-gate { EQ_DETACHING, EV_DETACHING }, 109*0Sstevel@tonic-gate { EQ_ATTACH, EV_ATTACH }, 110*0Sstevel@tonic-gate { EQ_ATTACHING, EV_ATTACHING }, 111*0Sstevel@tonic-gate { EQ_CHANGE, EV_CHANGE }, 112*0Sstevel@tonic-gate { EQ_EXCHANGE, EV_EXCHANGE }, 113*0Sstevel@tonic-gate { EQ_REGEN_START, EV_REGEN_START }, 114*0Sstevel@tonic-gate { EQ_REGEN_DONE, EV_REGEN_DONE }, 115*0Sstevel@tonic-gate { EQ_REGEN_FAILED, EV_REGEN_FAILED }, 116*0Sstevel@tonic-gate { EQ_USER, EV_USER }, 117*0Sstevel@tonic-gate { EQ_NOTIFY_LOST, EV_NOTIFY_LOST }, 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate { EQ_LAST, EV_LAST } 120*0Sstevel@tonic-gate }; 121*0Sstevel@tonic-gate 122*0Sstevel@tonic-gate static ev_obj_t 123*0Sstevel@tonic-gate dev2tag(md_dev64_t dev, set_t setno, md_error_t *ep) 124*0Sstevel@tonic-gate { 125*0Sstevel@tonic-gate mdname_t *np = NULL; 126*0Sstevel@tonic-gate mdsetname_t *sp = NULL; 127*0Sstevel@tonic-gate ev_obj_t obj = EVO_METADEV; 128*0Sstevel@tonic-gate char *miscname; 129*0Sstevel@tonic-gate 130*0Sstevel@tonic-gate if ((sp = metasetnosetname(setno, ep)) == NULL) { 131*0Sstevel@tonic-gate goto out; 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate if (!(np = metamnumname(&sp, meta_getminor(dev), 0, ep))) { 134*0Sstevel@tonic-gate goto out; 135*0Sstevel@tonic-gate } 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate /* need to invalidate name in case rename or delete/create done */ 138*0Sstevel@tonic-gate meta_invalidate_name(np); 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate if (!(miscname = metagetmiscname(np, ep))) { 141*0Sstevel@tonic-gate goto out; 142*0Sstevel@tonic-gate } 143*0Sstevel@tonic-gate if (strcmp(miscname, MD_STRIPE) == 0) { 144*0Sstevel@tonic-gate obj = EVO_STRIPE; 145*0Sstevel@tonic-gate } else if (strcmp(miscname, MD_MIRROR) == 0) { 146*0Sstevel@tonic-gate obj = EVO_MIRROR; 147*0Sstevel@tonic-gate } else if (strcmp(miscname, MD_RAID) == 0) { 148*0Sstevel@tonic-gate obj = EVO_RAID5; 149*0Sstevel@tonic-gate } else if (strcmp(miscname, MD_TRANS) == 0) { 150*0Sstevel@tonic-gate obj = EVO_TRANS; 151*0Sstevel@tonic-gate } 152*0Sstevel@tonic-gate out: 153*0Sstevel@tonic-gate return (obj); 154*0Sstevel@tonic-gate } 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate static ev_obj_t 157*0Sstevel@tonic-gate tagdrv_2_objlib(md_tags_t tag) 158*0Sstevel@tonic-gate { 159*0Sstevel@tonic-gate int i; 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate for (i = 0; tag2obj_typetab[i].tag != TAG_LAST; i++) { 162*0Sstevel@tonic-gate if (tag2obj_typetab[i].tag == tag) 163*0Sstevel@tonic-gate return (tag2obj_typetab[i].obj); 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate return (EVO_UNSPECIFIED); 166*0Sstevel@tonic-gate } 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate static md_tags_t 169*0Sstevel@tonic-gate objlib_2_tagdrv(ev_obj_t obj) 170*0Sstevel@tonic-gate { 171*0Sstevel@tonic-gate int i; 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate for (i = 0; tag2obj_typetab[i].tag != TAG_LAST; i++) { 174*0Sstevel@tonic-gate if (tag2obj_typetab[i].obj == obj) 175*0Sstevel@tonic-gate return (tag2obj_typetab[i].tag); 176*0Sstevel@tonic-gate } 177*0Sstevel@tonic-gate return (TAG_UNK); 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate static evid_t 182*0Sstevel@tonic-gate evdrv_2_evlib(md_event_type_t drv_ev) 183*0Sstevel@tonic-gate { 184*0Sstevel@tonic-gate int i; 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate for (i = 0; evdrv2evlib_typetab[i].drv != EQ_LAST; i++) { 187*0Sstevel@tonic-gate if (evdrv2evlib_typetab[i].drv == drv_ev) 188*0Sstevel@tonic-gate return (evdrv2evlib_typetab[i].lib); 189*0Sstevel@tonic-gate } 190*0Sstevel@tonic-gate return (EV_UNK); 191*0Sstevel@tonic-gate } 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate static md_event_type_t 194*0Sstevel@tonic-gate evlib_2_evdrv(evid_t lib_ev) 195*0Sstevel@tonic-gate { 196*0Sstevel@tonic-gate int i; 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate for (i = 0; evdrv2evlib_typetab[i].drv != EQ_LAST; i++) { 199*0Sstevel@tonic-gate if (evdrv2evlib_typetab[i].lib == lib_ev) 200*0Sstevel@tonic-gate return (evdrv2evlib_typetab[i].drv); 201*0Sstevel@tonic-gate } 202*0Sstevel@tonic-gate return (EQ_EMPTY); 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate /* 207*0Sstevel@tonic-gate * meta_event 208*0Sstevel@tonic-gate * returns 0 on succcess or < 0 to indicate error. 209*0Sstevel@tonic-gate * abs(return code) = errno 210*0Sstevel@tonic-gate */ 211*0Sstevel@tonic-gate static int 212*0Sstevel@tonic-gate meta_event(md_event_ioctl_t *evctl, md_error_t *ep) 213*0Sstevel@tonic-gate { 214*0Sstevel@tonic-gate int l; 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate if (!evctl || !ep) 217*0Sstevel@tonic-gate return (-EINVAL); 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate l = strlen(evctl->mdn_name); 220*0Sstevel@tonic-gate if ((l == 0 && evctl->mdn_cmd != EQ_PUT) || l >= MD_NOTIFY_NAME_SIZE) { 221*0Sstevel@tonic-gate return (-EINVAL); 222*0Sstevel@tonic-gate } 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate MD_SETDRIVERNAME(evctl, MD_NOTIFY, 0); 225*0Sstevel@tonic-gate mdclrerror(ep); 226*0Sstevel@tonic-gate errno = 0; 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate if (metaioctl(MD_IOCNOTIFY, evctl, ep, evctl->mdn_name) != 0) { 229*0Sstevel@tonic-gate if (errno == 0) { 230*0Sstevel@tonic-gate errno = EINVAL; 231*0Sstevel@tonic-gate } 232*0Sstevel@tonic-gate if (mdisok(ep)) { 233*0Sstevel@tonic-gate (void) mdsyserror(ep, errno, evctl->mdn_name); 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate return (-errno); 236*0Sstevel@tonic-gate } 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate return (0); 239*0Sstevel@tonic-gate } 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate static void 242*0Sstevel@tonic-gate init_evctl(char *qname, 243*0Sstevel@tonic-gate md_tags_t tag, 244*0Sstevel@tonic-gate md_event_type_t ev, 245*0Sstevel@tonic-gate uint_t flags, 246*0Sstevel@tonic-gate set_t set, 247*0Sstevel@tonic-gate md_dev64_t dev, 248*0Sstevel@tonic-gate md_event_cmds_t cmd, 249*0Sstevel@tonic-gate u_longlong_t udata, 250*0Sstevel@tonic-gate md_event_ioctl_t *evctlp) 251*0Sstevel@tonic-gate { 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate assert(evctlp); 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate (void) memset(evctlp, 0, sizeof (md_event_ioctl_t)); 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate evctlp->mdn_magic = MD_EVENT_ID; 258*0Sstevel@tonic-gate evctlp->mdn_rev = MD_NOTIFY_REVISION; 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate if (qname) 261*0Sstevel@tonic-gate (void) strncpy(evctlp->mdn_name, qname, MD_NOTIFY_NAME_SIZE-1); 262*0Sstevel@tonic-gate else 263*0Sstevel@tonic-gate (void) memset(evctlp->mdn_name, 0, MD_NOTIFY_NAME_SIZE); 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate evctlp->mdn_tag = tag; 266*0Sstevel@tonic-gate evctlp->mdn_event = ev; 267*0Sstevel@tonic-gate evctlp->mdn_flags = flags; 268*0Sstevel@tonic-gate evctlp->mdn_set = set; 269*0Sstevel@tonic-gate evctlp->mdn_dev = dev; 270*0Sstevel@tonic-gate evctlp->mdn_cmd = cmd; 271*0Sstevel@tonic-gate evctlp->mdn_user = udata; 272*0Sstevel@tonic-gate } 273*0Sstevel@tonic-gate 274*0Sstevel@tonic-gate /* 275*0Sstevel@tonic-gate * meta_notify_createq 276*0Sstevel@tonic-gate * - creates an eventq 277*0Sstevel@tonic-gate * - returns 0 on success or errno and sets ep 278*0Sstevel@tonic-gate */ 279*0Sstevel@tonic-gate int 280*0Sstevel@tonic-gate meta_notify_createq(char *qname, ulong_t flags, md_error_t *ep) 281*0Sstevel@tonic-gate { 282*0Sstevel@tonic-gate md_event_ioctl_t evctl; 283*0Sstevel@tonic-gate int err = 0; 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate mdclrerror(ep); 286*0Sstevel@tonic-gate if (!qname || strlen(qname) == 0) { 287*0Sstevel@tonic-gate (void) mdsyserror(ep, EINVAL, 288*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, 289*0Sstevel@tonic-gate "null or zero-length queue name")); 290*0Sstevel@tonic-gate return (EINVAL); 291*0Sstevel@tonic-gate } 292*0Sstevel@tonic-gate 293*0Sstevel@tonic-gate init_evctl(qname, 294*0Sstevel@tonic-gate TAG_EMPTY, 295*0Sstevel@tonic-gate EQ_EMPTY, 296*0Sstevel@tonic-gate (flags & EVFLG_PERMANENT) != 0? EQ_Q_PERM: 0, 297*0Sstevel@tonic-gate /* set */ 0, 298*0Sstevel@tonic-gate /* dev */ 0, 299*0Sstevel@tonic-gate EQ_ON, 300*0Sstevel@tonic-gate /* user-defined event data */ 0, 301*0Sstevel@tonic-gate &evctl); 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate err = meta_event(&evctl, ep); 304*0Sstevel@tonic-gate 305*0Sstevel@tonic-gate if (err == -EEXIST && !(flags & EVFLG_EXISTERR)) { 306*0Sstevel@tonic-gate err = 0; 307*0Sstevel@tonic-gate mdclrerror(ep); 308*0Sstevel@tonic-gate } 309*0Sstevel@tonic-gate if (!mdisok(ep) && mdanysyserror(ep)) { 310*0Sstevel@tonic-gate err = (ep)->info.md_error_info_t_u.ds_error.errnum; 311*0Sstevel@tonic-gate } 312*0Sstevel@tonic-gate return (-err); 313*0Sstevel@tonic-gate } 314*0Sstevel@tonic-gate 315*0Sstevel@tonic-gate /* 316*0Sstevel@tonic-gate * meta_notify_deleteq 317*0Sstevel@tonic-gate * - deletes an eventq 318*0Sstevel@tonic-gate * - free's any underlying resources 319*0Sstevel@tonic-gate * - returns 0 on success or errno and sets ep 320*0Sstevel@tonic-gate */ 321*0Sstevel@tonic-gate int 322*0Sstevel@tonic-gate meta_notify_deleteq(char *qname, md_error_t *ep) 323*0Sstevel@tonic-gate { 324*0Sstevel@tonic-gate md_event_ioctl_t evctl; 325*0Sstevel@tonic-gate int err; 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate init_evctl(qname, 328*0Sstevel@tonic-gate TAG_EMPTY, 329*0Sstevel@tonic-gate EQ_EMPTY, 330*0Sstevel@tonic-gate /* flags */ 0, 331*0Sstevel@tonic-gate /* set */ 0, 332*0Sstevel@tonic-gate /* dev */ 0, 333*0Sstevel@tonic-gate EQ_OFF, 334*0Sstevel@tonic-gate /* user-defined event data */ 0, 335*0Sstevel@tonic-gate &evctl); 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate err = meta_event(&evctl, ep); 338*0Sstevel@tonic-gate return (-err); 339*0Sstevel@tonic-gate } 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate /* 342*0Sstevel@tonic-gate * meta_notify_validq 343*0Sstevel@tonic-gate * - verifies that the queue exists 344*0Sstevel@tonic-gate * - returns true or false, ep may be changed as a side-effect 345*0Sstevel@tonic-gate */ 346*0Sstevel@tonic-gate bool_t 347*0Sstevel@tonic-gate meta_notify_validq(char *qname, md_error_t *ep) 348*0Sstevel@tonic-gate { 349*0Sstevel@tonic-gate md_event_ioctl_t evctl; 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate init_evctl(qname, 352*0Sstevel@tonic-gate TAG_EMPTY, 353*0Sstevel@tonic-gate EQ_EMPTY, 354*0Sstevel@tonic-gate /* flags */ 0, 355*0Sstevel@tonic-gate /* set */ 0, 356*0Sstevel@tonic-gate /* dev */ 0, 357*0Sstevel@tonic-gate EQ_ON, 358*0Sstevel@tonic-gate /* user-defined event data */ 0, 359*0Sstevel@tonic-gate &evctl); 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate return (meta_event(&evctl, ep) == -EEXIST); 362*0Sstevel@tonic-gate } 363*0Sstevel@tonic-gate 364*0Sstevel@tonic-gate /* 365*0Sstevel@tonic-gate * meta_notify_listq 366*0Sstevel@tonic-gate * - returns number of (currently) active queus or -errno 367*0Sstevel@tonic-gate * - allocates qnames array and sets user's pointer to it, 368*0Sstevel@tonic-gate * fills in array with vector of qnames 369*0Sstevel@tonic-gate */ 370*0Sstevel@tonic-gate int 371*0Sstevel@tonic-gate meta_notify_listq(char ***qnames, md_error_t *ep) 372*0Sstevel@tonic-gate { 373*0Sstevel@tonic-gate 374*0Sstevel@tonic-gate #ifdef lint 375*0Sstevel@tonic-gate qnames = qnames; 376*0Sstevel@tonic-gate #endif /* lint */ 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate mdclrerror(ep); 379*0Sstevel@tonic-gate (void) mdsyserror(ep, EOPNOTSUPP, "EOPNOTSUPP"); 380*0Sstevel@tonic-gate return (-EOPNOTSUPP); 381*0Sstevel@tonic-gate } 382*0Sstevel@tonic-gate 383*0Sstevel@tonic-gate /* 384*0Sstevel@tonic-gate * meta_notify_flushq 385*0Sstevel@tonic-gate * - calls the underlying notify driver to flush all events 386*0Sstevel@tonic-gate * from the named queue 387*0Sstevel@tonic-gate * - returns 0 on success or errno and sets ep as necessary 388*0Sstevel@tonic-gate */ 389*0Sstevel@tonic-gate int 390*0Sstevel@tonic-gate meta_notify_flushq(char *qname, md_error_t *ep) 391*0Sstevel@tonic-gate { 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate #ifdef lint 394*0Sstevel@tonic-gate qname = qname; 395*0Sstevel@tonic-gate #endif /* lint */ 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate mdclrerror(ep); 398*0Sstevel@tonic-gate (void) mdsyserror(ep, EOPNOTSUPP, "EOPNOTSUPP"); 399*0Sstevel@tonic-gate return (EOPNOTSUPP); 400*0Sstevel@tonic-gate } 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate static void 403*0Sstevel@tonic-gate cook_ev(md_event_ioctl_t *evctlp, md_ev_t *evp, md_error_t *ep) 404*0Sstevel@tonic-gate { 405*0Sstevel@tonic-gate assert(evctlp); 406*0Sstevel@tonic-gate assert(evp); 407*0Sstevel@tonic-gate 408*0Sstevel@tonic-gate evp->obj_type = tagdrv_2_objlib(evctlp->mdn_tag); 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate if (evp->obj_type == EVO_METADEV) { 411*0Sstevel@tonic-gate evp->obj_type = dev2tag(evctlp->mdn_dev, evctlp->mdn_set, ep); 412*0Sstevel@tonic-gate } 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate evp->setno = evctlp->mdn_set; 415*0Sstevel@tonic-gate evp->ev = evdrv_2_evlib(evctlp->mdn_event); 416*0Sstevel@tonic-gate evp->obj = evctlp->mdn_dev; 417*0Sstevel@tonic-gate evp->uev = evctlp->mdn_user; 418*0Sstevel@tonic-gate } 419*0Sstevel@tonic-gate 420*0Sstevel@tonic-gate /* 421*0Sstevel@tonic-gate * meta_notify_getev 422*0Sstevel@tonic-gate * - collects up to 1 event and stores it into md_ev_t 423*0Sstevel@tonic-gate * - returns number of events found (0 or 1) on success or -errno 424*0Sstevel@tonic-gate * - flags governs whether an empty queue is waited upon (EVFLG_WAIT) 425*0Sstevel@tonic-gate */ 426*0Sstevel@tonic-gate int 427*0Sstevel@tonic-gate meta_notify_getev(char *qname, ulong_t flags, md_ev_t *evp, md_error_t *ep) 428*0Sstevel@tonic-gate { 429*0Sstevel@tonic-gate md_event_ioctl_t evctl; 430*0Sstevel@tonic-gate int n_ev; 431*0Sstevel@tonic-gate int err = -EINVAL; 432*0Sstevel@tonic-gate 433*0Sstevel@tonic-gate if (!evp) { 434*0Sstevel@tonic-gate goto out; 435*0Sstevel@tonic-gate } 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate init_evctl(qname, 438*0Sstevel@tonic-gate TAG_EMPTY, 439*0Sstevel@tonic-gate EQ_EMPTY, 440*0Sstevel@tonic-gate /* flags (unused in get) */ 0, 441*0Sstevel@tonic-gate (evp->setno == EV_ALLSETS)? MD_ALLSETS: evp->setno, 442*0Sstevel@tonic-gate (evp->obj == EV_ALLOBJS)? MD_ALLDEVS: evp->obj, 443*0Sstevel@tonic-gate (flags & EVFLG_WAIT) != 0? EQ_GET_WAIT: EQ_GET_NOWAIT, 444*0Sstevel@tonic-gate /* user-defined event data */ 0, 445*0Sstevel@tonic-gate &evctl); 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate err = meta_event(&evctl, ep); 448*0Sstevel@tonic-gate 449*0Sstevel@tonic-gate /* 450*0Sstevel@tonic-gate * trap EAGAIN so that EV_EMPTY events get returned, but 451*0Sstevel@tonic-gate * be sure n_ev = 0 so that users who just watch the count 452*0Sstevel@tonic-gate * will also work 453*0Sstevel@tonic-gate */ 454*0Sstevel@tonic-gate switch (err) { 455*0Sstevel@tonic-gate case -EAGAIN: 456*0Sstevel@tonic-gate err = n_ev = 0; 457*0Sstevel@tonic-gate cook_ev(&evctl, evp, ep); 458*0Sstevel@tonic-gate break; 459*0Sstevel@tonic-gate case 0: 460*0Sstevel@tonic-gate n_ev = 1; 461*0Sstevel@tonic-gate cook_ev(&evctl, evp, ep); 462*0Sstevel@tonic-gate break; 463*0Sstevel@tonic-gate } 464*0Sstevel@tonic-gate out: 465*0Sstevel@tonic-gate return (err == 0? n_ev: err); 466*0Sstevel@tonic-gate } 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate 469*0Sstevel@tonic-gate /* 470*0Sstevel@tonic-gate * meta_notify_getevlist 471*0Sstevel@tonic-gate * - collects all pending events in the named queue and allocates 472*0Sstevel@tonic-gate * an md_evlist_t * to return them 473*0Sstevel@tonic-gate * - returns the number of events found (may be 0 if !WAIT) on success 474*0Sstevel@tonic-gate * or -errno and sets ep as necessary 475*0Sstevel@tonic-gate */ 476*0Sstevel@tonic-gate int 477*0Sstevel@tonic-gate meta_notify_getevlist(char *qname, 478*0Sstevel@tonic-gate ulong_t flags, 479*0Sstevel@tonic-gate md_evlist_t **evpp_arg, 480*0Sstevel@tonic-gate md_error_t *ep) 481*0Sstevel@tonic-gate { 482*0Sstevel@tonic-gate md_ev_t *evp = NULL; 483*0Sstevel@tonic-gate md_evlist_t *evlp = NULL; 484*0Sstevel@tonic-gate md_evlist_t *evlp_head = NULL; 485*0Sstevel@tonic-gate md_evlist_t *new = NULL; 486*0Sstevel@tonic-gate int n_ev = 0; 487*0Sstevel@tonic-gate int err = -EINVAL; 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate mdclrerror(ep); 490*0Sstevel@tonic-gate if (!evpp_arg) { 491*0Sstevel@tonic-gate (void) mdsyserror(ep, EINVAL, dgettext(TEXT_DOMAIN, 492*0Sstevel@tonic-gate "No event list pointer")); 493*0Sstevel@tonic-gate goto out; 494*0Sstevel@tonic-gate } 495*0Sstevel@tonic-gate 496*0Sstevel@tonic-gate if (!qname || strlen(qname) == 0) { 497*0Sstevel@tonic-gate (void) mdsyserror(ep, EINVAL, dgettext(TEXT_DOMAIN, 498*0Sstevel@tonic-gate "Null or zero-length queue name")); 499*0Sstevel@tonic-gate goto out; 500*0Sstevel@tonic-gate } 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate do { 503*0Sstevel@tonic-gate if (!(evp = (md_ev_t *)Malloc(sizeof (md_ev_t)))) { 504*0Sstevel@tonic-gate (void) mdsyserror(ep, ENOMEM, qname); 505*0Sstevel@tonic-gate continue; 506*0Sstevel@tonic-gate } 507*0Sstevel@tonic-gate evp->obj_type = EVO_EMPTY; 508*0Sstevel@tonic-gate evp->setno = EV_ALLSETS; 509*0Sstevel@tonic-gate evp->ev = EV_EMPTY; 510*0Sstevel@tonic-gate evp->obj = EV_ALLOBJS; 511*0Sstevel@tonic-gate evp->uev = 0ULL; 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate err = meta_notify_getev(qname, flags, evp, ep); 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate if (evp->ev != EV_EMPTY) { 516*0Sstevel@tonic-gate new = (md_evlist_t *)Zalloc(sizeof (md_evlist_t)); 517*0Sstevel@tonic-gate if (evlp_head == NULL) { 518*0Sstevel@tonic-gate evlp = evlp_head = new; 519*0Sstevel@tonic-gate } else { 520*0Sstevel@tonic-gate evlp->next = new; 521*0Sstevel@tonic-gate evlp = new; 522*0Sstevel@tonic-gate } 523*0Sstevel@tonic-gate evlp->evp = evp; 524*0Sstevel@tonic-gate n_ev++; 525*0Sstevel@tonic-gate } 526*0Sstevel@tonic-gate 527*0Sstevel@tonic-gate } while (err >= 0 && evp && evp->ev != EV_EMPTY); 528*0Sstevel@tonic-gate out: 529*0Sstevel@tonic-gate if (err == -EAGAIN) { 530*0Sstevel@tonic-gate err = 0; 531*0Sstevel@tonic-gate } 532*0Sstevel@tonic-gate 533*0Sstevel@tonic-gate if (err < 0) { 534*0Sstevel@tonic-gate meta_notify_freeevlist(evlp_head); 535*0Sstevel@tonic-gate evlp_head = NULL; 536*0Sstevel@tonic-gate return (err); 537*0Sstevel@tonic-gate } else if ((err == 0) && (evp->ev == EV_EMPTY)) { 538*0Sstevel@tonic-gate Free(evp); 539*0Sstevel@tonic-gate evp = NULL; 540*0Sstevel@tonic-gate } 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate if (evpp_arg) { 543*0Sstevel@tonic-gate *evpp_arg = evlp_head; 544*0Sstevel@tonic-gate } 545*0Sstevel@tonic-gate 546*0Sstevel@tonic-gate return (n_ev); 547*0Sstevel@tonic-gate } 548*0Sstevel@tonic-gate 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate /* 551*0Sstevel@tonic-gate * the guts of meta_notify_putev() and meta_notify_sendev() 552*0Sstevel@tonic-gate * are within this function. 553*0Sstevel@tonic-gate * 554*0Sstevel@tonic-gate * meta_notify_putev() is intended for general use by user-level code, 555*0Sstevel@tonic-gate * such as the GUI, to send user-defined events. 556*0Sstevel@tonic-gate * 557*0Sstevel@tonic-gate * meta_notify_sendev() is for "user-level driver" code, such as 558*0Sstevel@tonic-gate * set manipulation and the multi-host daemon to generate events. 559*0Sstevel@tonic-gate * 560*0Sstevel@tonic-gate * Note- only convention enforces this usage. 561*0Sstevel@tonic-gate */ 562*0Sstevel@tonic-gate int 563*0Sstevel@tonic-gate meta_notify_doputev(md_ev_t *evp, md_error_t *ep) 564*0Sstevel@tonic-gate { 565*0Sstevel@tonic-gate md_event_ioctl_t evctl; 566*0Sstevel@tonic-gate 567*0Sstevel@tonic-gate if (!evp || !ep) { 568*0Sstevel@tonic-gate return (EINVAL); 569*0Sstevel@tonic-gate } 570*0Sstevel@tonic-gate 571*0Sstevel@tonic-gate /* 572*0Sstevel@tonic-gate * users may only put events of type EQ_USER 573*0Sstevel@tonic-gate */ 574*0Sstevel@tonic-gate init_evctl(/* qname (unused in put) */ NULL, 575*0Sstevel@tonic-gate TAG_EMPTY, 576*0Sstevel@tonic-gate EQ_EMPTY, 577*0Sstevel@tonic-gate /* flags (unused in put) */ 0, 578*0Sstevel@tonic-gate (evp->setno == EV_ALLSETS)? MD_ALLSETS: evp->setno, 579*0Sstevel@tonic-gate (evp->obj == EV_ALLOBJS)? MD_ALLDEVS: evp->obj, 580*0Sstevel@tonic-gate EQ_PUT, 581*0Sstevel@tonic-gate evp->uev, 582*0Sstevel@tonic-gate &evctl); 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate evctl.mdn_tag = objlib_2_tagdrv(evp->obj_type); 585*0Sstevel@tonic-gate evctl.mdn_event = evlib_2_evdrv(evp->ev); 586*0Sstevel@tonic-gate 587*0Sstevel@tonic-gate return (-meta_event(&evctl, ep)); 588*0Sstevel@tonic-gate } 589*0Sstevel@tonic-gate 590*0Sstevel@tonic-gate /* 591*0Sstevel@tonic-gate * meta_notify_putev 592*0Sstevel@tonic-gate * - sends an event down to the notify driver (hence, all queues) 593*0Sstevel@tonic-gate * - returns 0 on success or errno 594*0Sstevel@tonic-gate */ 595*0Sstevel@tonic-gate int 596*0Sstevel@tonic-gate meta_notify_putev(md_ev_t *evp, md_error_t *ep) 597*0Sstevel@tonic-gate { 598*0Sstevel@tonic-gate if (!evp || !ep) { 599*0Sstevel@tonic-gate return (EINVAL); 600*0Sstevel@tonic-gate } 601*0Sstevel@tonic-gate 602*0Sstevel@tonic-gate evp->ev = EV_USER; /* by definition */ 603*0Sstevel@tonic-gate 604*0Sstevel@tonic-gate return (meta_notify_doputev(evp, ep)); 605*0Sstevel@tonic-gate } 606*0Sstevel@tonic-gate 607*0Sstevel@tonic-gate /* 608*0Sstevel@tonic-gate * alternate put event entry point which allows 609*0Sstevel@tonic-gate * more control of event innards (for use by md "user-level drivers") 610*0Sstevel@tonic-gate * 611*0Sstevel@tonic-gate * Since this routine isn't for use by clients, the user event data 612*0Sstevel@tonic-gate * is always forced to be 0. That is only meaningful for events 613*0Sstevel@tonic-gate * of type EQ_USER (and those go through meta_notify_putev()), so 614*0Sstevel@tonic-gate * this is consistent. 615*0Sstevel@tonic-gate */ 616*0Sstevel@tonic-gate int 617*0Sstevel@tonic-gate meta_notify_sendev( 618*0Sstevel@tonic-gate ev_obj_t tag, 619*0Sstevel@tonic-gate set_t set, 620*0Sstevel@tonic-gate md_dev64_t dev, 621*0Sstevel@tonic-gate evid_t ev) 622*0Sstevel@tonic-gate { 623*0Sstevel@tonic-gate md_error_t status = mdnullerror; 624*0Sstevel@tonic-gate md_error_t *ep = &status; 625*0Sstevel@tonic-gate md_ev_t ev_packet; 626*0Sstevel@tonic-gate int rc; 627*0Sstevel@tonic-gate 628*0Sstevel@tonic-gate ev_packet.obj_type = tag; 629*0Sstevel@tonic-gate ev_packet.setno = set; 630*0Sstevel@tonic-gate ev_packet.obj = dev; 631*0Sstevel@tonic-gate ev_packet.ev = ev; 632*0Sstevel@tonic-gate ev_packet.uev = 0ULL; 633*0Sstevel@tonic-gate 634*0Sstevel@tonic-gate rc = meta_notify_doputev(&ev_packet, ep); 635*0Sstevel@tonic-gate 636*0Sstevel@tonic-gate if (0 == rc && !mdisok(ep)) { 637*0Sstevel@tonic-gate rc = EINVAL; 638*0Sstevel@tonic-gate mdclrerror(ep); 639*0Sstevel@tonic-gate } 640*0Sstevel@tonic-gate return (rc); 641*0Sstevel@tonic-gate } 642*0Sstevel@tonic-gate 643*0Sstevel@tonic-gate /* 644*0Sstevel@tonic-gate * meta_notify_putevlist 645*0Sstevel@tonic-gate * - sends all of the events in the event list 646*0Sstevel@tonic-gate * - returns number of events sent (>= 0) on success or -errno 647*0Sstevel@tonic-gate */ 648*0Sstevel@tonic-gate int 649*0Sstevel@tonic-gate meta_notify_putevlist(md_evlist_t *evlp, md_error_t *ep) 650*0Sstevel@tonic-gate { 651*0Sstevel@tonic-gate md_evlist_t *evlpi; 652*0Sstevel@tonic-gate int n_ev = 0; 653*0Sstevel@tonic-gate int err; 654*0Sstevel@tonic-gate 655*0Sstevel@tonic-gate if (!evlp) { 656*0Sstevel@tonic-gate err = 0; 657*0Sstevel@tonic-gate goto out; /* that was easy */ 658*0Sstevel@tonic-gate } 659*0Sstevel@tonic-gate 660*0Sstevel@tonic-gate for (n_ev = 0, evlpi = evlp; evlpi; evlpi = evlpi->next) { 661*0Sstevel@tonic-gate if ((err = meta_notify_putev(evlpi->evp, ep)) < 0) { 662*0Sstevel@tonic-gate goto out; 663*0Sstevel@tonic-gate } 664*0Sstevel@tonic-gate n_ev++; 665*0Sstevel@tonic-gate } 666*0Sstevel@tonic-gate out: 667*0Sstevel@tonic-gate return (err != 0? err: n_ev); 668*0Sstevel@tonic-gate } 669*0Sstevel@tonic-gate 670*0Sstevel@tonic-gate /* 671*0Sstevel@tonic-gate * meta_notify_freevlist 672*0Sstevel@tonic-gate * - frees any memory allocated within the event list 673*0Sstevel@tonic-gate * - returns 0 on success or errno and sets ep as necessary 674*0Sstevel@tonic-gate */ 675*0Sstevel@tonic-gate void 676*0Sstevel@tonic-gate meta_notify_freeevlist(md_evlist_t *evlp) 677*0Sstevel@tonic-gate { 678*0Sstevel@tonic-gate md_evlist_t *i; 679*0Sstevel@tonic-gate md_evlist_t *next; 680*0Sstevel@tonic-gate 681*0Sstevel@tonic-gate for (i = evlp; i; i = i->next) { 682*0Sstevel@tonic-gate if (i && i->evp) { 683*0Sstevel@tonic-gate Free(i->evp); 684*0Sstevel@tonic-gate i->evp = NULL; 685*0Sstevel@tonic-gate } 686*0Sstevel@tonic-gate } 687*0Sstevel@tonic-gate for (i = evlp; i; /* NULL */) { 688*0Sstevel@tonic-gate next = i->next; 689*0Sstevel@tonic-gate Free(i); 690*0Sstevel@tonic-gate i = next; 691*0Sstevel@tonic-gate } 692*0Sstevel@tonic-gate } 693