dm_SUNW_DISK_ARCHIVING.c revision cee0fb94c0d4227de0a00efc162fb2739844b641
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <note.h>
#include <syslog.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <stropts.h>
#include <time.h>
#include <mms_dmd.h>
#include <mms_trace.h>
#include <dmd_impl.h>
#include <dm_impl.h>
#include <dm_drive.h>
#include <dm_msg.h>
#include <dm_proto.h>
#include <dda.h>
#include <mms_strapp.h>
/*
* Specify whether the persistent reserve out command is supported or not.
* 0 - not supported
* 1 - supported
*
* If the persistent reserve out command is supported, then it will be used
* to reserve the drive.
* If the persistent reserve out command is not supported, then the reserve
* command will be used to reserve the drive.
*/
/*
* specify timeouts for this drive. Time is specified in seconds.
*/
(151 *60), /* For really long commands */
(20 *60), /* Normal commands */
(1 *60), /* short commands */
};
/*
* Specify the drive type.
* Drive type must begin with "dt_"
*/
char drv_drive_type[] = "dt_disk";
/*
* Specify the directory in which this device can be found.
*
* The DM will open each device in this directory and look for a device
* whose serial number matches the serial number specified in
* DRIVE.'DriveSerialNum'.
* If this is a null string, then the full pathname of the device is specified
* in DM.'DMTargetPath'.
*/
char drv_dev_dir[] = "";
/*
* drv_density[]
* - Specify density names with their density codes supported by this DM.
* - Densities must be specified in the order of their selection priority.
* The ones at the beginning of the list will be selected before those
* at the end of the list.
* - Density names must start with "den_" to avoid conflict with other names.
*/
mms_sym_t drv_density[] = {
"den_DISK", 0,
};
/*
* drv_shape[]
* - Specify shape names of cartridge types supported by this DM.
* - Shape names must be specified in the order of their selection priority.
* The ones at the beginning of the list will be selected before those
* at the end of the list.
* - Shape name must be a well known and published name.
*/
char *drv_shape[] = {
"DISK",
};
/*
* drv_shape_den[]
* Specify the shape of a cartridge and the density on it that can be
* written over by a readwrite density.
* All shape names and density names must have been specified in
* drv_density[] and drv_shape[].
* Each entry of the array consists of:
* {shapename, density on cart, readwrite density}.
* If the density on cartridge is the same as the readwrite density, then
* the drive can read and write with that density.
* If the density on cartridge is read only, then the readwrite density
* is NULL.
* If the readwrite density is not NULL and it is different from the density
* on cartridge, then the drive is able to write over the existing data
* starting from the beginning of medium.
*/
"DISK", "den_DISK", "den_DISK",
};
/*
* Specify SCSI commands that a client may not issue using USCSI
*/
int drv_disallowed_cmds[] = {
SCMD_PROUT, /* persistent reserve out */
SCMD_RESERVE, /* reserve */
SCMD_RELEASE, /* release */
};
int drv_num_disallowed_cmds =
sizeof (drv_disallowed_cmds) / sizeof (int);
/*
* Specify ioctl's that a client may not issue
*/
int drv_disallowed_ioctls[] = {
};
sizeof (drv_disallowed_ioctls) / sizeof (int);
typedef struct drv_cart_mountpt {
int drv_state;
char *drv_mpoint;
/*
* drv_state flags
*/
#define DRV_MOUNTED 1
#define DRV_MOUNT_THREAD_ACTIVE 2
static char **drv_mounted = NULL;
static int drv_mounted_size = 0;
static int drv_cart_mountpt_size = 0;
static char **drv_mnttab = NULL;
static int drv_mnttab_size = 0;
static int drv_mount_initialized = 0;
static int drv_mount_cnt;
static pthread_cond_t drv_mount_cv;
static pthread_mutex_t drv_mount_mutex;
#define DRV_MOUNTTAB_SIZE 20
/*
* Since there is no library to unload a dda tape drive, it has to be
* initialized by unload any loaded tape when the drive is activate enabled.
*/
void
drv_init_dev(void)
{
DRV_CALL(drv_unload, ());
}
drv_get_avail_capacity(void)
{
return (-1);
}
}
int
{
return (-1);
}
cap->mms_pc_avail =
return (0);
}
/*
* drv_mode_sense - issue mode sense
* - page - page code
* - len - allocation length
*
* - always return block descriptor block
* - always get current value
*/
/*ARGSUSED0*/
int
{
return (-1);
}
/*
* drv_mode_select - issue mode select
* - pf - page format - 0, no page data, or 1, send page data
* - len - allocation length
*/
/*ARGSUSED0*/
int
{
return (-1);
}
int
drv_inquiry(void)
{
return (-1);
}
int
drv_clrerr(void)
{
return (-1);
}
int
drv_tur(void)
{
return (-1);
}
return (-1);
}
return (0);
}
int
drv_load(void)
{
char *path;
int err;
return (-1);
}
/*
* If path does not exist
*/
continue;
}
"cartridge %s does not exist", path));
return (-1);
}
return (-1);
}
return (0);
}
int
{
return (-1);
}
return (0);
}
/*ARGSUSED0*/
int
{
return (-1);
}
int
{
return (-1);
}
return (0);
}
int
drv_release(void)
{
return (0);
}
int
drv_prsv_register(void)
{
return (0);
}
int
drv_prsv_reserve(void)
{
return (0);
}
int
drv_prsv_release(void)
{
return (0);
}
/*ARGSUSED0*/
int
drv_prsv_preempt(char *curkey)
{
return (0);
}
int
drv_prsv_clear(void)
{
return (0);
}
/*ARGSUSED0*/
int
{
return (-1);
}
/*ARGSUSED0*/
int
{
return (-1);
}
int
drv_reserve(void)
{
return (0);
}
int
drv_get_serial_num(char *ser)
{
return (-1);
}
return (0);
}
int
drv_get_write_protect(int *wp)
{
return (0);
}
/*ARGSUSED0*/
int
drv_set_compression(int comp)
{
return (0);
}
/*ARGSUSED0*/
void
drv_pthread_cleanup(void *arg)
{
(void) pthread_mutex_unlock(&drv_mount_mutex);
}
/*
* A thread to do stat
*/
void *
drv_stat_mount_point(void *mntpt)
{
char *path;
(void) pthread_mutex_lock(&drv_mount_mutex);
(void) pthread_mutex_unlock(&drv_mount_mutex);
(void) pthread_mutex_lock(&drv_mount_mutex);
if (drv_mount_cnt == 0) {
(void) pthread_cond_broadcast(&drv_mount_cv);
}
(void) pthread_mutex_unlock(&drv_mount_mutex);
pthread_exit(0);
return (NULL);
}
int
drv_bld_mounted(void)
{
int i;
int j;
int k;
char **newpt;
int newsize;
int size;
if (drv_mounted == NULL) {
size = drv_mounted_size * sizeof (char *);
if (drv_mounted == NULL) {
"out of memory"));
return (-1);
}
drv_mounted[0] = NULL;
}
/*
* Find where to add to drv_mounted
*/
for (k = 0; drv_mounted[k] != NULL; k++)
;
(void) pthread_mutex_lock(&drv_mount_mutex);
/* Not mounted, skip */
continue;
}
/* Check if already in drv_mounted */
for (j = 0; drv_mounted[j] != NULL; j++) {
drv_mounted[j]) == 0) {
break;
}
}
if (drv_mounted[j] == NULL) {
/* mount point not in mounted */
if (k == drv_mounted_size - 1) {
newpt = (char **)
"out of memory"));
(void) pthread_mutex_unlock(
return (-1);
}
drv_mounted = newpt;
}
if (drv_mounted[k] == NULL) {
"out of memory"));
(void) pthread_mutex_unlock(&drv_mount_mutex);
return (-1);
}
k++;
drv_mounted[k] = NULL;
}
}
(void) pthread_mutex_unlock(&drv_mount_mutex);
/*
* If no mount point return -1
*/
if (drv_mounted[0] == NULL) {
dm_msg_destroy(); /* Remove unreleated msgs */
"No mount point accessible by this DM"));
return (-1);
}
return (0);
}
int
drv_add_mounted(void)
{
int i;
int j;
(void) pthread_mutex_lock(&drv_mount_mutex);
/* already mounted or unknown */
continue;
}
for (j = 0; drv_mnttab[j] != NULL; j++) {
drv_mnttab[j]) == 0) {
break;
}
}
}
(void) pthread_mutex_unlock(&drv_mount_mutex);
return (0);
}
int
drv_force_mount(void)
{
int rc = ~0;
int i;
if (drv_mount_initialized == 0) {
drv_mount_cnt = 0;
}
(void) pthread_mutex_lock(&drv_mount_mutex);
drv_mount_cnt = 0;
/* Create a thread to stat a file in cart_mountpt[i] */
(void *)(&drv_cart_mountpt[i])) != 0) {
(void) pthread_mutex_unlock(&drv_mount_mutex);
return (-1);
}
}
/*
* Wait for mounts
*/
for (;;) {
&ts);
if (drv_mount_cnt == 0 ||
break;
}
}
}
}
drv_mount_cnt = 0;
(void) pthread_mutex_unlock(&drv_mount_mutex);
return (0);
}
int
drv_get_mnttab(void)
{
int newsize;
char **newpt;
int i;
int k;
int size;
if (drv_mnttab == NULL) {
size = drv_mnttab_size * sizeof (char *);
if (drv_mnttab == NULL) {
"out of memory"));
return (-1);
}
drv_mnttab[0] = NULL;
}
/*
* Find offset to add new entries
*/
for (k = 0; drv_mnttab[k] != NULL; k++)
;
/*
*/
return (-1);
}
for (i = 0; drv_mnttab[i] != NULL; i++) {
break;
}
}
if (drv_mnttab[i] != NULL) {
/* Already in mnttab */
continue;
}
if (k == drv_mnttab_size - 1) {
"out of memory"));
return (-1);
}
drv_mnttab = newpt;
}
if (drv_mnttab[k] == NULL) {
"out of memory"));
return (-1);
}
drv_mnttab[k]));
k++;
drv_mnttab[k] = NULL;
}
}
return (0);
}
int
drv_get_mount_points(void)
{
char *val;
int newsize;
int size;
int i;
int k;
if (dm_show_mount_point(&root) != 0) {
return (-1);
}
if (drv_cart_mountpt == NULL) {
if (drv_cart_mountpt == NULL) {
"out of memory"));
return (-1);
}
drv_cart_mountpt[0].drv_state = 0;
}
(void) pthread_mutex_lock(&drv_mount_mutex);
;
while (text =
"CartridgeMountPoint");
"no DISK cartridge"));
break;
}
/*
* Discard if already in mp
*/
for (i = 0; i < k; i++) {
/* Already in mp */
break;
}
}
if (i < k) {
/* already in mp */
continue; /* discard */
}
/*
* A new mount point
*/
if (k == drv_cart_mountpt_size - 1) {
newpt = (drv_cart_mountpt_t *)
"out of memory"));
(void) pthread_mutex_unlock(&drv_mount_mutex);
return (-1);
}
}
"out of memory"));
(void) pthread_mutex_unlock(&drv_mount_mutex);
return (-1);
}
drv_cart_mountpt[k].drv_mpoint));
k++;
drv_cart_mountpt[k].drv_state = 0;
}
(void) pthread_mutex_unlock(&drv_mount_mutex);
/*
* Done
*/
return (0);
}
char **
drv_get_mounted(void)
{
int i;
/*
* Show mount points in DISK cartridges
*/
if (drv_get_mount_points() != 0) {
return (NULL);
}
/*
* Stat a file on the mount points to force mount if necessary
*/
if (drv_force_mount() != 0) {
goto out1;
}
/*
*/
if (drv_get_mnttab() != 0) {
goto out1;
}
/*
* Add to the mounted table
*/
if (drv_add_mounted() != 0) {
goto out2;
}
/*
* Add to the mounted table
*/
if (drv_bld_mounted() != 0) {
goto out3;
}
return (drv_mounted);
out3:
for (i = 0; drv_mounted[i] != NULL; i++) {
free(drv_mounted[i]);
}
drv_mounted = NULL;
out2:
for (i = 0; drv_mnttab[i] != NULL; i++) {
free(drv_mnttab[i]);
}
drv_mnttab = NULL;
out1:
(void) pthread_mutex_lock(&drv_mount_mutex);
if (drv_mount_cnt != 0) {
if (drv_cart_mountpt[i].drv_state ==
(void) pthread_cancel(drv_cart_mountpt[i].
drv_tid);
}
}
}
}
(void) pthread_mutex_unlock(&drv_mount_mutex);
return (NULL);
}
void
drv_disallowed(void)
{
}
void
drv_mk_prsv_key(void)
{
}
int
drv_rebind_target(void)
{
/*
* Target is already bound.
*/
return (0);
}
/*ARGSUSED0*/
int
drv_bind_raw_dev(int oflags)
{
return (0);
}
int
drv_get_statistics(void)
{
return (-1);
}
int
{
*den = 0; /* DISK density */
if (comp) {
*comp = 0;
}
return (0);
}
int
/* ARGSUSED */
drv_set_density(int den)
{
return (0);
}