Home | History | Annotate | Download | only in common
      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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     22  * Use is subject to license terms.
     23  */
     24 
     25 
     26 #include <limits.h>
     27 #include <sys/types.h>
     28 #include <sys/mkdev.h>
     29 #include <sys/file.h>
     30 #include <pthread.h>
     31 #include <synch.h>
     32 #include <ctype.h>
     33 #include <signal.h>
     34 #include <pwd.h>
     35 #include <auth_attr.h>
     36 #include <secdb.h>
     37 #include <ucred.h>
     38 #include <fcntl.h>
     39 #include <stdio.h>
     40 #include <stdlib.h>
     41 #include <unistd.h>
     42 #include <dlfcn.h>
     43 #include <link.h>
     44 #include <sys/types.h>
     45 #include <sys/stat.h>
     46 #include <strings.h>
     47 #include <dirent.h>
     48 #include <errno.h>
     49 #include <sys/scsi/impl/uscsi.h>
     50 #include <sys/scsi/generic/sense.h>
     51 #include <sys/scsi/generic/status.h>
     52 #include <dmd_impl.h>
     53 #include <dm_impl.h>
     54 #include <dm_drive.h>
     55 #include <mms_sym.h>
     56 #include <dm_msg.h>
     57 #include <mms_trace.h>
     58 #include <mms_dmd.h>
     59 #include <dm_proto.h>
     60 #include <mms_strapp.h>
     61 
     62 
     63 
     64 static	char *_SrcFile = __FILE__;
     65 
     66 
     67 /*
     68  * Minor device number of the ST driver.
     69  *
     70  * Change device to bn device - turn BSD and norewind bits
     71  *
     72  * The minor device byte structure is (from mtio(7I)):
     73  *
     74  * 15-7     6          5          4         3          2       1   0
     75  * ___________________________________________________________________
     76  * Unit #  BSD	Reserved   Density   Density   No rewind    Unit #
     77  *         behavior		Select    Select    on Close    Bits 0-1
     78  *
     79  */
     80 
     81 minor_t
     82 dm_get_targ(minor_t minor)
     83 {
     84 	minor &= ~0x18;			/* turn off density select */
     85 	minor |= 0x44;			/* BSD, norewind */
     86 
     87 	return (minor);
     88 }
     89 
     90 minor_t
     91 dm_hdl_minor(void)
     92 {
     93 	minor_t		minor = 0;
     94 
     95 	minor = (((wka->dm_counter % 255) + 1) << 8) | wka->dm_drm_minor;
     96 	return (minor);
     97 }
     98 
     99 int
    100 dm_get_target_base(void)
    101 {
    102 	if (drv->drv_serial_num[0] == '\0') {
    103 		/*
    104 		 * Serial number unknown. Have to use specified path
    105 		 */
    106 		return (dm_get_target_pathname());
    107 	} else {
    108 		/*
    109 		 * Have serial number, look in /dev/rmt (tape devices)
    110 		 * for device matching serial number.
    111 		 */
    112 		return (dm_get_target_by_serial_num());
    113 	}
    114 }
    115 
    116 int
    117 dm_get_target_pathname(void)
    118 {
    119 	char		*show_cmd;
    120 	char		*task;
    121 	mms_par_node_t	*root;
    122 	dm_command_t	*cmd;
    123 	char		*val;
    124 
    125 	TRACE((MMS_DEVP, "Getting target base"));
    126 	task = dm_bld_task("show-target-base");
    127 	show_cmd = mms_strapp(NULL,
    128 	    "show task['%s'] reportmode[namevalue] "
    129 	    "match[streq(DM.'DMName' '%s')] "
    130 	    "report[ DM.'DMTargetPath']" ";", task, DMNAME);
    131 	cmd = dm_send_cmd(show_cmd, dm_cmd_response, task);
    132 	free(show_cmd);
    133 	free(task);
    134 	if (cmd == NULL || cmd->cmd_rc != 0) {
    135 		DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    136 		    "unable to get DM.'DMTargetPath'"));
    137 		if (cmd) {
    138 			dm_destroy_cmd(cmd);
    139 		}
    140 		return (-1);
    141 	}
    142 	root = cmd->cmd_root;
    143 	/*
    144 	 * Save tape path
    145 	 */
    146 	val = dm_get_attr_value(root, "DM", "DMTargetPath");
    147 	if (val == NULL) {
    148 		DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    149 		    "No TargetPath"));
    150 		dm_destroy_cmd(cmd);
    151 		return (-1);
    152 	}
    153 	if (dm_verify_target_dev(val) != 0) {
    154 		DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    155 		    "invalid device pathname %s", val));
    156 		dm_destroy_cmd(cmd);
    157 		return (-1);
    158 	}
    159 	wka->dm_target_base = strdup(val);
    160 	TRACE((MMS_OPER, "dm_get_target_base: Target base is %s",
    161 	    wka->dm_target_base));
    162 	dm_destroy_cmd(cmd);
    163 	return (0);
    164 }
    165 
    166 int
    167 dm_get_target_by_serial_num(void)
    168 {
    169 	char	**dirtab;
    170 	int	i;
    171 	int	rc = -1;
    172 
    173 	/*
    174 	 * Search in the default dir
    175 	 */
    176 	if (dm_probe_dir(drv->drv_dev_dir) == 0) {
    177 		/* Found it */
    178 		return (0);
    179 	}
    180 
    181 	/*
    182 	 * Build a dir table from *.so
    183 	 */
    184 	dirtab = dm_bld_dir_tab();
    185 	if (dirtab == NULL) {
    186 		return (-1);
    187 	}
    188 
    189 	/*
    190 	 * Search each entry in dir table
    191 	 */
    192 	rc = -1;				/* assume not found */
    193 	for (i = 0; dirtab[i] != NULL; i++) {
    194 		if (dm_probe_dir(dirtab[i]) == 0) {
    195 			/* Found it */
    196 			rc = 0;
    197 			break;
    198 		}
    199 	}
    200 
    201 	/*
    202 	 * Can't find a device that matches the serial number
    203 	 */
    204 	for (i = 0; dirtab[i] != NULL; i++) {
    205 		free(dirtab[i]);
    206 	}
    207 	free(dirtab);
    208 
    209 	return (rc);
    210 }
    211 
    212 int
    213 dm_probe_dir(char *dirname)
    214 {
    215 	DIR	*dir;
    216 	struct	dirent	*dirent;
    217 	int	len;
    218 	char	sernum[MMS_SER_NUM_LEN + 1];
    219 	int	fd;
    220 	int	rc = -1;
    221 	struct	ent	{
    222 		ino_t	ino;
    223 		char	*name;
    224 	};
    225 	struct	ent	ptab[64];
    226 	int	nument = 0;
    227 	int	probe = 1;
    228 	drm_probe_dev_t	dev;
    229 	int	i;
    230 	int	err;
    231 	int	zero = 0;
    232 
    233 
    234 	if ((dir = opendir(dirname)) == NULL) {
    235 		DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    236 		    "unable to open directory %s: %s",
    237 		    dirname, strerror(errno)));
    238 		return (-1);
    239 	}
    240 
    241 	while ((dirent = readdir(dir)) != NULL) {
    242 		/*
    243 		 * Read the serial number of this device
    244 		 */
    245 		len = strlen(dirent->d_name);
    246 		if (strcmp(dirname, DRV_TAPE_DIR) == 0) {
    247 			if (len < 2) {
    248 				/* Device name must be >= 2 chars */
    249 				continue;
    250 			}
    251 			/* If tape device, look at only norewind devices */
    252 			if (dirent->d_name[len - 1] != 'n' ||
    253 			    !isdigit(dirent->d_name[len - 2])) {
    254 				continue;
    255 			}
    256 		}
    257 		ptab[nument].name = mms_strapp(NULL,
    258 		    "%s/%s", dirname, dirent->d_name);
    259 		ptab[nument].ino = dirent->d_ino;
    260 		nument++;
    261 	}
    262 	closedir(dir);
    263 
    264 	while (probe) {
    265 		/*
    266 		 * Continue to probe until all devices are probed.
    267 		 */
    268 		probe = 0;
    269 		for (i = 0; i < nument; i++) {
    270 			/*
    271 			 * Set the ino in dmd. If EBUSY, then skip for now
    272 			 */
    273 			if (ptab[i].name == NULL) {
    274 				/* Already checked */
    275 				continue;
    276 			}
    277 
    278 			/*
    279 			 * Tell DMD probing this device
    280 			 */
    281 			dev.drm_dev = 0;
    282 			ioctl(drv->drv_fd, DRM_PROBE_DEV, &dev);
    283 			dev.drm_dev = ptab[i].ino;
    284 			if (ioctl(drv->drv_fd, DRM_PROBE_DEV, &dev) < 0) {
    285 				err = errno;
    286 				if (err == EBUSY) {
    287 					TRACE((MMS_DEBUG, "Busy: %s",
    288 					    ptab[i].name));
    289 					continue;
    290 				}
    291 				DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    292 				    "unable to probe device: %s",
    293 				    strerror(err)));
    294 				errno = err;
    295 				rc = -1;
    296 				goto done;
    297 			}
    298 
    299 			/*
    300 			 * Check serial number of this device
    301 			 */
    302 			probe = 1;
    303 			do {
    304 				TRACE((MMS_DEBUG, "Looking at: %s",
    305 				    ptab[i].name));
    306 				fd = open(ptab[i].name, O_NDELAY | O_RDWR);
    307 				if (fd < 0) {
    308 					/*
    309 					 * If can't open this device,
    310 					 * then skip it
    311 					 */
    312 					TRACE((MMS_DEBUG, "probe open error: "
    313 					    "%s: %s",
    314 					    ptab[i].name, strerror(errno)));
    315 					break;
    316 				}
    317 
    318 				/* Read the serial number */
    319 				drv->drv_fd = fd;
    320 						/* drv_*() uses drv->drv_fd */
    321 				if (DRV_CALL(drv_get_serial_num,
    322 				    (sernum)) != 0) {
    323 					TRACE((MMS_DEBUG, "probe get "
    324 					    "serial num  error: %s: %s",
    325 					    ptab[i].name, strerror(errno)));
    326 					close(fd);
    327 					drv->drv_fd = wka->dm_drm_fd;
    328 					/* restoredrv->drv_fd */
    329 					break;
    330 				}
    331 				close(fd);
    332 				drv->drv_fd = wka->dm_drm_fd;
    333 				/* restoredrv->drv_fd */
    334 
    335 				TRACE((MMS_DEBUG, "path %s, serial num %s",
    336 				    ptab[i].name, sernum));
    337 
    338 				/*
    339 				 * Compare serial numbers
    340 				 */
    341 				if (strcmp(sernum, drv->drv_serial_num) == 0) {
    342 					/* Found device matching serial num */
    343 					wka->dm_target_base =
    344 					    strdup(ptab[i].name);
    345 					/* Drop the "n" from pathname */
    346 					wka->dm_target_base[
    347 					    strlen(wka->dm_target_base) - 1] =
    348 					    '\0';
    349 					TRACE((MMS_OPER, "dm_probe_dir: "
    350 					    "Target base is %s",
    351 					    wka->dm_target_base));
    352 					rc = 0;
    353 					probe = 0;	/* probe done */
    354 				}
    355 			} while (zero);
    356 
    357 			free(ptab[i].name);
    358 			ptab[i].name = NULL;
    359 			/*
    360 			 * Unlock this dev
    361 			 */
    362 			dev.drm_dev = 0;
    363 			ioctl(drv->drv_fd, DRM_PROBE_DEV, &dev);
    364 
    365 			if (probe == 0) {
    366 				break;
    367 			}
    368 		}
    369 		if (nument == i) {
    370 			DM_MSG_PREPEND(("dm_probe_dir: "
    371 			    "cannot find a matching drive "
    372 			    "with serial num %s in %s: ",
    373 			    drv->drv_serial_num, dirname));
    374 		}
    375 	}
    376 
    377 done:
    378 	for (i = 0; i < nument; i++) {
    379 		if (ptab[i].name != NULL) {
    380 			free(ptab[i].name);
    381 		}
    382 	}
    383 
    384 	return (rc);
    385 }
    386 
    387 char **
    388 dm_bld_dir_tab(void)
    389 {
    390 	char		**dirtab;
    391 	char		**newtab;
    392 	int		taboff = 0;
    393 	int		size = DRV_DIR_TAB_SIZE;
    394 	char		*libpath;
    395 	char		*libname;
    396 	int		len;
    397 	void		*dlhdl;
    398 	char		*devdir;
    399 	DIR		*dir;
    400 	dirent_t	*dirent;
    401 	int		i;
    402 
    403 	dirtab = (char **)malloc(size * sizeof (char *));
    404 	if (dirtab == NULL) {
    405 		DM_MSG_ADD((MMS_EXIST, MMS_DM_E_INTERNAL,
    406 		    "out of memory"));
    407 		return (NULL);
    408 	}
    409 	memset(dirtab, 0, size);
    410 
    411 	dir = opendir(DM_DEV_LIB_DIR);
    412 	if (dir == NULL) {
    413 		DM_MSG_ADD((MMS_EXIST, MMS_DM_E_INTERNAL,
    414 		    "unable to open %s", DM_DEV_LIB_DIR));
    415 		free(dirtab);
    416 		return (NULL);
    417 	}
    418 
    419 	while (dirent = readdir(dir)) {
    420 		libname = dirent->d_name;
    421 		len = strlen(libname);
    422 		if (strncmp(libname, "lib", 3) ||
    423 		    strncmp(libname + len - 3, ".so", 3)) {
    424 			/* Not lib*.so */
    425 			continue;
    426 		}
    427 
    428 		TRACE((MMS_DEBUG, "looking at lib %s", libname));
    429 		libpath = mms_strapp(NULL,
    430 		    "%s/%s", DM_DEV_LIB_DIR, libname);
    431 		dlhdl = dlopen(libpath, RTLD_LAZY);
    432 		if (dlhdl == NULL) {
    433 			DM_MSG_ADD((MMS_EXIST, MMS_DM_E_INTERNAL,
    434 			    "unable to open %s", libpath));
    435 			free(libpath);
    436 			continue;
    437 		}
    438 		free(libpath);
    439 
    440 		devdir = dlsym(dlhdl, "drv_dev_dir");
    441 		if (devdir != NULL) {
    442 			if (devdir[0] == '\0') {
    443 				/* dev dir not specified */
    444 				dlclose(dlhdl);
    445 				continue;
    446 			}
    447 
    448 			if (strcmp(devdir, DRV_TAPE_DIR) == 0) {
    449 				/* Already probed DRV_TAPE_DIR */
    450 				dlclose(dlhdl);
    451 				continue;
    452 			}
    453 
    454 			/*
    455 			 * Add to dirtab if not in it already
    456 			 */
    457 			for (i = 0; i < taboff && dirtab[i] != NULL; i++) {
    458 				if (strcmp(devdir, dirtab[i]) == 0) {
    459 					/* dir name already in dirtab */
    460 					dlclose(dlhdl);
    461 					continue;
    462 				}
    463 			}
    464 			/* Not in table yet */
    465 			TRACE((MMS_DEBUG, "adding to dirtab: %s", devdir));
    466 			dirtab[taboff] = strdup(devdir);
    467 			taboff++;
    468 			if (taboff == size) {
    469 				size += DRV_DIR_TAB_SIZE;
    470 				newtab = (char **)
    471 				    realloc(dirtab, size * sizeof (char *));
    472 				if (newtab == NULL) {
    473 					DM_MSG_ADD((MMS_EXIST,
    474 					    MMS_DM_E_INTERNAL,
    475 					    "out of memory"));
    476 					return (NULL);
    477 				}
    478 				dirtab = newtab;
    479 			}
    480 
    481 		}
    482 	}
    483 
    484 	/*
    485 	 * Done
    486 	 */
    487 	return (dirtab);
    488 }
    489 
    490 /*
    491  * Verify target device name
    492  */
    493 int
    494 dm_verify_target_dev(char *devname)
    495 {
    496 	int		i;
    497 
    498 	if (devname[0] == '\0') {
    499 		return (-1);
    500 	}
    501 
    502 	if (strncmp(devname, DRV_TAPE_DIR "/", 9) != 0) {
    503 		/* If not a tape dev, ignore */
    504 		return (0);
    505 	}
    506 
    507 	if (!isdigit(devname[9])) {
    508 		return (-1);
    509 	}
    510 
    511 	/*
    512 	 * strip device attribute from devname
    513 	 */
    514 
    515 	for (i = 9; devname[i] != '\0'; i++) {
    516 		if (!isdigit(devname[i])) {
    517 			devname[i] = '\0';
    518 			return (0);
    519 		}
    520 	}
    521 	return (0);
    522 }
    523 
    524 int
    525 dm_stat_targ_base(void)
    526 {
    527 	struct		stat buf;
    528 	int		fd;
    529 
    530 	if (wka->dm_target_base == NULL || wka->dm_target_base[0] == '\0') {
    531 		DM_MSG_ADD((MMS_EXIST, MMS_DM_E_INTERNAL,
    532 		    "target base device not available"));
    533 		return (-1);
    534 	}
    535 
    536 	if ((fd = open(wka->dm_target_base, O_RDWR | O_NDELAY)) < 0 ||
    537 	    fstat(fd, &buf)) {
    538 		DM_MSG_ADD((MMS_EXIST, MMS_DM_E_INTERNAL,
    539 		    "stat '%s' error: %s",
    540 		    wka->dm_target_base, strerror(errno)));
    541 		if (fd >= 0) {
    542 			close(fd);
    543 		}
    544 		return (-1);
    545 	}
    546 
    547 	wka->dm_targ_base_major = major(buf.st_rdev);
    548 	wka->dm_targ_base_minor = minor(buf.st_rdev);
    549 	TRACE((MMS_DEVP, "dm_stat_targ_base: %s - (%d:%d)",
    550 	    wka->dm_target_base, wka->dm_targ_base_major,
    551 	    wka->dm_targ_base_minor));
    552 	close(fd);
    553 	return (0);
    554 }
    555 
    556 int
    557 dm_reserve_target(void)
    558 {
    559 	int		rc = 0;
    560 
    561 	if (drv->drv_flags & DRV_USE_PRSV) {
    562 		for (;;) {
    563 			rc = dm_reserve_target_prsv();
    564 			if (rc == 0) {	/* drive reserved */
    565 				break;
    566 			} else if (rc > 0) {
    567 				/* error other than reservation conflict */
    568 				DM_MSG_ADD_HEAD((MMS_INTERNAL,
    569 				    MMS_DM_E_INTERNAL,
    570 				    "unable to reserve drive: "
    571 				    "I/O error"));
    572 				return (-1);
    573 			}
    574 			/*
    575 			 * If already have MMS reservation, just preempt it.
    576 			 * Otherwise see if we have to ask.
    577 			 */
    578 			rc = DM_REP_YES;	/* assume preempt */
    579 			if (!dm_have_mms_rsv()) {	/* no mms rsv */
    580 				if (wka->dm_flags & DM_ASK_PREEMPT_RSV) {
    581 					rc = dm_ask_preempt();
    582 				}
    583 				if (rc == DM_REP_ERROR) {
    584 					/* Ask got an error, assume "no" */
    585 					rc = DM_REP_NO;
    586 				}
    587 				if (rc == DM_REP_NO) {
    588 					DM_MSG_ADD_HEAD((MMS_INTERNAL,
    589 					    MMS_DM_E_INTERNAL,
    590 					    "drive reservation "
    591 					    "denied by operator"));
    592 					return (-1);
    593 				} else if (rc == DM_REP_RETRY) {
    594 					sleep(1);
    595 					continue;
    596 				}
    597 			}
    598 			if (rc == DM_REP_YES) {
    599 				TRACE((MMS_DEBUG, "Preempting reservation"));
    600 				if (dm_preempt_rsv()) {
    601 					return (-1);
    602 				}
    603 				rc = 0;
    604 				break;
    605 			}
    606 
    607 
    608 		}
    609 	} else {
    610 		rc = dm_reserve_target_rsv();
    611 	}
    612 
    613 	TRACE((MMS_DEBUG, "Drive reserved successfully"));
    614 
    615 	return (rc);
    616 }
    617 
    618 
    619 int
    620 dm_reserve_target_prsv(void)
    621 {
    622 	int		status = 0;
    623 	uint64_t	key;
    624 
    625 	TRACE((MMS_DEVP, "dm_reserve_target_prsv: Using PRSV"));
    626 
    627 	/*
    628 	 * Register key
    629 	 */
    630 
    631 	if (DRV_CALL(drv_prsv_register, ())) {
    632 		status = serr->se_dsreg;
    633 		char_to_uint64((uchar_t *)DRV_PRSV_KEY, 8, &key);
    634 		TRACE((MMS_DEVP, "Can't register PRSV "
    635 		    "reservation key: %16.16llx: %s",
    636 		    key, mms_scsi_status(status)));
    637 		if (status == STATUS_RESERVATION_CONFLICT) {
    638 			DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    639 			    "unable to register key, "
    640 			    "reservation conflict"));
    641 			return (-1);
    642 		} else {
    643 			/* other error */
    644 			DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    645 			    "registration error: %s", strerror(errno)));
    646 			return (EIO);
    647 		}
    648 	}
    649 
    650 	/*
    651 	 * Do an exclusive persistent reservation
    652 	 */
    653 	if (DRV_CALL(drv_prsv_reserve, ()) != 0) {
    654 		status = serr->se_dsreg;
    655 		TRACE((MMS_ERR, "Unable to reserve drive"));
    656 		if (status == STATUS_RESERVATION_CONFLICT) {
    657 			DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    658 			    "unable to reserve drive: "
    659 			    "reservation conflict"));
    660 			return (-1);
    661 		} else {
    662 			/* other error */
    663 			DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    664 			    "reservation error: %s", strerror(errno)));
    665 			return (EIO);
    666 		}
    667 	}
    668 
    669 	/*
    670 	 * Now, get rid of all the attentions
    671 	 */
    672 	TRACE((MMS_DEVP, "dm_reserve_target_prsv: Clear attentions"));
    673 	while (DRV_CALL(drv_tur, ()) != 0 &&
    674 	    serr->se_senkey == KEY_UNIT_ATTENTION) {
    675 		;
    676 	}
    677 
    678 	TRACE((MMS_DEVP, "dm_reserve_target_prsv: Drive %s reserved",
    679 	    DRVNAME));
    680 
    681 	return (0);
    682 }
    683 
    684 int
    685 dm_reserve_target_rsv(void)
    686 {
    687 	int		rc = 0;
    688 
    689 	/*
    690 	 * Since the target is opened (via ldi_open()) with O_NDELAY,
    691 	 * the st drive will not do reserve/release on open/close.
    692 	 * until an I/O is done. A TUR will be done after binding
    693 	 * the target. This causes the st driver to reserve the drive.
    694 	 */
    695 	while (DRV_CALL(drv_tur, ()) != 0 && errno == EACCES) {
    696 		TRACE((MMS_INFO, "TUR error: %s", strerror(errno)));
    697 		/*
    698 		 * Drive is reserved, find out if it is assigned to
    699 		 * another DM
    700 		 */
    701 		if (dm_drv_assigned() != 0) {
    702 			/*
    703 			 * No, not assigned. This means that the drive
    704 			 * is being used by a non MMS client.
    705 			 */
    706 			if ((wka->dm_flags & DM_PREEMPT_RSV) == 0) {
    707 				/* Do not preempt */
    708 				return (-1);
    709 			}
    710 
    711 			rc = DM_REP_YES;	/* assume freserve */
    712 			if (wka->dm_flags & DM_ASK_PREEMPT_RSV) {
    713 				rc = dm_ask_freserve();
    714 			}
    715 			if (rc == DM_REP_ERROR) {
    716 				/* Ask got an error, assume "no" */
    717 				rc = DM_REP_NO;
    718 			}
    719 			if (rc == DM_REP_YES) {
    720 				TRACE((MMS_DEBUG, "Doing forcereserve"));
    721 				if (ioctl(wka->dm_drm_fd, MTIOCFORCERESERVE)) {
    722 					return (-1);
    723 				}
    724 			} else if (rc == DM_REP_NO) {
    725 				return (-1);
    726 			} else if (rc == DM_REP_RETRY) {
    727 				continue;
    728 			}
    729 		} else {
    730 			/*
    731 			 * If drive is assigned to another DM, then
    732 			 * silently wait for it to be unassigned.
    733 			 */
    734 			TRACE((MMS_ERR, "Drive %s is reserved by "
    735 			    "another DM. "
    736 			    "Will keep trying reserve until "
    737 			    "successful", wka->dm_target_base));
    738 		}
    739 	}
    740 
    741 	/*
    742 	 * Release the reservation made by the ST driver and tell it
    743 	 * not to do reserve/release at open/close.
    744 	 * Then do my own reservations
    745 	 */
    746 	ioctl(drv->drv_fd, MTIOCRESERVE);
    747 	DRV_CALL(drv_release, ());
    748 	if (DRV_CALL(drv_reserve, ()) != 0) {
    749 		ioctl(drv->drv_fd, MTIOCRELEASE);
    750 		return (-1);
    751 	}
    752 	drv->drv_flags |= DRV_RESERVED;
    753 	return (0);
    754 }
    755 
    756 int
    757 dm_release_target(void)
    758 {
    759 	if ((drv->drv_flags & DRV_USE_PRSV) == 0) {
    760 		/* Using reserve/release */
    761 		DRV_CALL(drv_release, ());
    762 		return (0);
    763 	}
    764 
    765 	/*
    766 	 * Using persistent reserve out
    767 	 */
    768 	DRV_CALL(drv_prsv_register, ());
    769 	DRV_CALL(drv_prsv_release, ());
    770 	return (0);
    771 }
    772 
    773 int
    774 dm_force_release(void)
    775 {
    776 	if (ioctl(wka->dm_drm_fd, MTIOCFORCERESERVE)) {
    777 		DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    778 		    "Can't do FORCERESERVE: %s", strerror(errno)));
    779 		return (-1);
    780 	}
    781 	TRACE((MMS_DEBUG, "FORCERESERVE successful"));
    782 
    783 	if (DRV_CALL(drv_release, ()) != 0) {
    784 		DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    785 		    "release error: %s", strerror(errno)));
    786 		return (-1);
    787 	}
    788 	TRACE((MMS_DEBUG, "RELEASE successful"));
    789 
    790 	return (0);
    791 }
    792 
    793 int
    794 dm_preempt_rsv(void)
    795 {
    796 	char		buf[24];
    797 	uint32_t	num;
    798 
    799 	if (DRV_CALL(drv_prsv_register, ()) != 0 ||
    800 	    DRV_CALL(drv_prsv_read_rsv, (buf, sizeof (buf))) != 0) {
    801 		if (serr->se_dsreg == STATUS_RESERVATION_CONFLICT) {
    802 			/* Try force reserve and release */
    803 			if (dm_force_release() != 0) {
    804 				/* Can't force release */
    805 				return (-1);
    806 			}
    807 			if (DRV_CALL(drv_prsv_register, ()) != 0 ||
    808 			    DRV_CALL(drv_prsv_reserve, ())) {
    809 				DM_MSG_ADD_HEAD((MMS_INTERNAL,
    810 				    MMS_DM_E_INTERNAL,
    811 				    "persistent reservation " "error"));
    812 				return (-1);
    813 			}
    814 			return (0);
    815 		} else {
    816 			/* Other error */
    817 			DM_MSG_ADD_HEAD((MMS_INTERNAL,
    818 			    MMS_DM_E_INTERNAL,
    819 			    "reservation error", strerror(errno)));
    820 			return (-1);
    821 		}
    822 	}
    823 
    824 	char_to_uint32((uchar_t *)buf + 4, 4, &num);
    825 	if (num == 0) {			/* no reservation */
    826 		if (DRV_CALL(drv_prsv_register, ()) != 0 ||
    827 		    DRV_CALL(drv_prsv_reserve, ()) != 0) {
    828 			DM_MSG_ADD_HEAD((MMS_INTERNAL,
    829 			    MMS_DM_E_INTERNAL,
    830 			    "persistent reservation " "error"));
    831 			return (-1);
    832 		}
    833 	} else {
    834 		/* Preempt the current reservation */
    835 		if (DRV_CALL(drv_prsv_preempt, (buf + 8)) != 0) {
    836 			DM_MSG_ADD_HEAD((MMS_INTERNAL,
    837 			    MMS_DM_E_INTERNAL,
    838 			    "persistent reservation preempt" "error"));
    839 			return (-1);
    840 		}
    841 	}
    842 
    843 	return (0);
    844 }
    845 
    846 int
    847 dm_have_mms_rsv(void)
    848 {
    849 	char		buf[24];
    850 	uint32_t	num;
    851 
    852 	if (DRV_CALL(drv_prsv_register, ()) != 0 ||
    853 	    DRV_CALL(drv_prsv_read_rsv, (buf, sizeof (buf))) != 0) {
    854 		DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    855 		    "unable to read reservation"));
    856 		/* Can't read reservation */
    857 		return (0);
    858 	}
    859 
    860 	char_to_uint32((uchar_t *)buf + 4, 4, &num);
    861 	if (num == 0) {			/* no reservation */
    862 		return (0);
    863 	}
    864 
    865 	if (memcmp(buf + 8, DRV_PRSV_KEY_PFX, 4) != 0) {
    866 		return (0);
    867 	}
    868 
    869 	/*
    870 	 * Have MMS reservation
    871 	 */
    872 	return (1);
    873 }
    874 
    875 int
    876 dm_rebind_target(void)
    877 {
    878 	drm_target_t	targ;
    879 
    880 	wka->dm_targ_base_minor = dm_get_targ(wka->dm_targ_base_minor);
    881 	memset(&targ, 0, sizeof (targ));
    882 	targ.drm_targ_oflags |= FREAD | FWRITE | FNDELAY;
    883 	targ.drm_targ_major = wka->dm_targ_base_major;
    884 	targ.drm_targ_minor = wka->dm_targ_base_minor;
    885 	if (ioctl(wka->dm_drm_fd, DRM_REBIND_DEV, &targ)) {
    886 		DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    887 		    "Rebind base device error: %s",
    888 		    strerror(errno)));
    889 		return (-1);
    890 	}
    891 	TRACE((MMS_DEBUG, "Target rebound to (%d:%d)",
    892 	    wka->dm_targ_base_major, wka->dm_targ_base_minor));
    893 	return (0);
    894 }
    895 
    896 int
    897 dm_open_dm_device(void)
    898 {
    899 	int	fd;
    900 
    901 	/*
    902 	 * close the device if it has been opened to unbind it
    903 	 * from the target (most likely, the ST) driver.
    904 	 */
    905 	if (wka->dm_drm_fd != -1) {
    906 		close(wka->dm_drm_fd);
    907 		wka->dm_drm_fd = -1;
    908 	}
    909 	/*
    910 	 * Open the drive manager device
    911 	 */
    912 	fd = open(wka->dm_drm_path, O_RDWR | O_NDELAY);
    913 	if (fd < 0) {
    914 		DM_MSG_ADD((MMS_EXIST, MMS_DM_E_INTERNAL,
    915 		    "open '%s' error: %s",
    916 		    wka->dm_drm_path, strerror(errno)));
    917 		wka->dm_drm_fd = -1;
    918 		return (-1);
    919 	}
    920 	wka->dm_drm_fd = fd;
    921 	drv->drv_fd = fd;
    922 
    923 	return (0);
    924 }
    925 
    926 int
    927 dm_bind_target(void)
    928 {
    929 	struct		stat statbuf;
    930 
    931 	/*
    932 	 * Get the major and minor of the DRM device
    933 	 */
    934 	fstat(wka->dm_drm_fd, &statbuf);
    935 	wka->dm_drm_major = major(statbuf.st_rdev);
    936 	wka->dm_drm_minor = minor(statbuf.st_rdev);
    937 
    938 	/*
    939 	 * Bind the drive manager to the target device.
    940 	 * Since the target is opened (via ldi_open()) with O_NDELAY,
    941 	 * the st drive will not do reserve/release on open/close.
    942 	 * until an I/O is done. A TUR will be done after binding
    943 	 * the target. This causes the st driver to reserve the drive.
    944 	 */
    945 	if (dm_bind_target_base() != 0) {
    946 		return (-1);
    947 	}
    948 
    949 	return (0);
    950 }
    951 
    952 /*
    953  * Bind manager drive to target
    954  */
    955 int
    956 dm_bind_target_base(void)
    957 {
    958 	drm_target_t	targ;
    959 	int		err;
    960 	uint32_t	buf;
    961 	char		pid[20];
    962 
    963 	targ.drm_targ_major = wka->dm_targ_base_major;
    964 	targ.drm_targ_minor = wka->dm_targ_base_minor;
    965 
    966 	targ.drm_targ_oflags = FWRITE | FNDELAY;
    967 
    968 	pthread_mutex_lock(&wka->dm_tdv_close_mutex);
    969 	while (ioctl(wka->dm_drm_fd, DRM_BIND_DEV, &targ)) {
    970 		err = errno;
    971 		if (err == EMFILE) {
    972 			/* drive is still opened. wait for close */
    973 			ioctl(wka->dm_drm_fd, DRM_TDV_PID, &buf);
    974 			snprintf(pid, sizeof (pid), "%d", buf);
    975 			TRACE((MMS_DEBUG,
    976 			    "Waiting for App to close target device, pid %s",
    977 			    pid));
    978 			DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    979 			    "waiting for close"));
    980 			DM_MSG_SEND((DM_ADM_ERR, DM_6521_MSG,
    981 			    "drive", drv->drv_drvname, "pid", pid,
    982 			    DM_MSG_REASON));
    983 			pthread_cond_wait(&wka->dm_tdv_close_cv,
    984 			    &wka->dm_tdv_close_mutex);
    985 			TRACE((MMS_DEBUG, "Waken up by tdv close"));
    986 		} else {
    987 			DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    988 			    "unable to bind target device: %s", strerror(err)));
    989 			pthread_mutex_unlock(&wka->dm_tdv_close_mutex);
    990 			return (-1);
    991 		}
    992 	}
    993 	pthread_mutex_unlock(&wka->dm_tdv_close_mutex);
    994 	TRACE((MMS_OPER, "Device %s (%lld, %lld) bound to %s",
    995 	    wka->dm_target_base, targ.drm_targ_major, targ.drm_targ_minor,
    996 	    wka->dm_drm_path));
    997 
    998 	return (0);
    999 }
   1000 
   1001 int
   1002 dm_bind_raw_dev(int oflag)
   1003 {
   1004 	int		err;
   1005 	char		*path;
   1006 	char		*den = "";
   1007 	char		*bsd = "";
   1008 	char		*rew = "";
   1009 	struct		stat statbuf;
   1010 	drm_target_t	targ;
   1011 
   1012 	if (mnt->mnt_flags & MNT_LOW) {
   1013 		den = "l";
   1014 	} else if (mnt->mnt_flags & MNT_MEDIUM) {
   1015 		den = "m";
   1016 	} else if (mnt->mnt_flags & MNT_HIGH) {
   1017 		den = "h";
   1018 	} else if (mnt->mnt_flags & (MNT_ULTRA | MNT_COMPRESSION)) {
   1019 		den = "c";
   1020 	}
   1021 	if (mnt->mnt_flags & (MNT_MMS | MNT_MMS_TM | MNT_BSD)) {
   1022 		/* MMS mode always use "b" */
   1023 		bsd = "b";
   1024 	}
   1025 	if (mnt->mnt_flags & (MNT_MMS | MNT_NOREWIND)) {
   1026 		/* MMS mode always use "n" */
   1027 		rew = "n";
   1028 	}
   1029 
   1030 	path = mms_strapp(NULL,
   1031 	    "%s%s%s%s", wka->dm_target_base, den, bsd, rew);
   1032 	TRACE((MMS_DEBUG, "Device path chosen = %s", path));
   1033 
   1034 	if (stat(path, &statbuf) != 0) {
   1035 		err = errno;
   1036 		TRACE((MMS_ERR, "Can't stat %s: %s", path, strerror(err)));
   1037 		return (err);
   1038 	}
   1039 	free(path);
   1040 	targ.drm_targ_oflags = oflag;
   1041 	targ.drm_targ_major = major(statbuf.st_rdev);
   1042 	targ.drm_targ_minor = minor(statbuf.st_rdev);
   1043 	if (ioctl(wka->dm_drm_fd, DRM_REBIND_DEV, &targ)) {
   1044 		err = errno;
   1045 		TRACE((MMS_ERR, "Rebind raw device error: %s",
   1046 		    strerror(err)));
   1047 		return (err);
   1048 	}
   1049 
   1050 	dm_clear_dev();
   1051 
   1052 	return (0);
   1053 }
   1054 
   1055 void
   1056 dm_init_sense_buf(void)
   1057 {
   1058 	struct	scsi_extended_sense	*es;
   1059 
   1060 	if (DRV_CALL(drv_req_sense, (sizeof (struct scsi_extended_sense)))) {
   1061 		/* Can't read sense data */
   1062 		drv->drv_mtee_stat_len = sizeof (struct scsi_extended_sense);
   1063 		TRACE((MMS_DEBUG, "drv_req_sense error: Sense buf size set "
   1064 		    "to %d", sizeof (struct scsi_extended_sense)));
   1065 		return;
   1066 	}
   1067 	es = (struct scsi_extended_sense *)drv->drv_iobuf;
   1068 	drv->drv_num_sen_bytes =
   1069 	    es->es_add_len + ((char *)&es->es_add_len - (char *)es) + 1;
   1070 	drv->drv_mtee_stat_len =
   1071 	    sizeof (struct scsi_arq_status) -
   1072 	    sizeof (struct scsi_extended_sense) + drv->drv_num_sen_bytes;
   1073 	if (drv->drv_mtee_stat_len < sizeof (struct scsi_arq_status)) {
   1074 		drv->drv_mtee_stat_len = sizeof (struct scsi_arq_status);
   1075 	}
   1076 	if (drv->drv_mtee_stat_len > DRV_SENSE_LEN) {
   1077 		drv->drv_mtee_stat_len = DRV_SENSE_LEN;
   1078 	}
   1079 	TRACE((MMS_DEBUG, "add sense length = %d, num of sen bytes = %d",
   1080 	    es->es_add_len, drv->drv_num_sen_bytes));
   1081 	TRACE((MMS_DEBUG, "Sense buf size set = %d", drv->drv_mtee_stat_len));
   1082 }
   1083 
   1084 char *
   1085 dm_get_user(pid_t pid)
   1086 {
   1087 	/*
   1088 	 * Given the pid, return the user login name
   1089 	 */
   1090 	struct	passwd	pwd;
   1091 	struct	passwd	*pwent;
   1092 	ucred_t		*ucred;
   1093 	uid_t		uid;
   1094 
   1095 	ucred = ucred_get(pid);
   1096 	uid = ucred_getruid(ucred);
   1097 
   1098 	setpwent();
   1099 	pwent = getpwuid_r(uid, &pwd, wka->dm_pwbuf, wka->dm_pwbuf_size);
   1100 	if (pwent == NULL) {
   1101 		endpwent();
   1102 		ucred_free(ucred);
   1103 		return (NULL);
   1104 	}
   1105 	TRACE((MMS_DEBUG, "pid %ld, uid %ld, user %s",
   1106 	    (long)pid, (long)uid, pwent->pw_name));
   1107 	endpwent();
   1108 	ucred_free(ucred);
   1109 	return (strdup(pwent->pw_name));
   1110 }
   1111 
   1112 int
   1113 dm_chk_dev_auth(char *user)
   1114 {
   1115 	/*
   1116 	 * Check to see if the user is authorized to use MMS
   1117 	 */
   1118 	setauthattr();
   1119 	if (!chkauthattr(MMS_AUTHNAME, user)) {
   1120 		endauthattr();
   1121 		return (-1);
   1122 	}
   1123 	endauthattr();
   1124 	return (0);
   1125 }
   1126