예제 #1
0
/*ARGSUSED*/
void
ndmpd_scsi_close_v2(ndmp_connection_t *connection, void *body)
{
	ndmp_scsi_close_reply reply;
	ndmpd_session_t *session = ndmp_get_client_data(connection);

	if (session->ns_scsi.sd_is_open == -1) {
		syslog(LOG_ERR, "SCSI device is not open.");
		reply.error = NDMP_DEV_NOT_OPEN_ERR;
		ndmp_send_reply(connection, (void *) &reply,
		    "sending scsi_close reply");
		return;
	}
	(void) ndmp_open_list_del(session->ns_scsi.sd_adapter_name,
	    session->ns_scsi.sd_sid,
	    session->ns_scsi.sd_lun);
	(void) close(session->ns_scsi.sd_devid);

	session->ns_scsi.sd_is_open = -1;
	session->ns_scsi.sd_devid = -1;
	session->ns_scsi.sd_sid = 0;
	session->ns_scsi.sd_lun = 0;
	session->ns_scsi.sd_valid_target_set = FALSE;
	(void) memset(session->ns_scsi.sd_adapter_name, 0,
	    sizeof (session->ns_scsi.sd_adapter_name));

	reply.error = NDMP_NO_ERR;
	ndmp_send_reply(connection, (void *) &reply,
	    "sending scsi_close reply");
}
예제 #2
0
/*
 * connection_handler
 *
 * NDMP connection handler.
 * Waits for, reads, and processes NDMP requests on a connection.
 *
 * Parameters:
 *   connection (input) - connection handle.
 *
 * Return:
 *   void
 */
void
connection_handler(ndmp_connection_t *connection)
{
	static int conn_id = 1;
	ndmpd_session_t session;
	ndmp_notify_connected_request req;
	int connection_fd;

	(void) memset(&session, 0, sizeof (session));
	session.ns_connection = connection;
	session.ns_eof = FALSE;
	/*
	 * The 'protocol_version' must be 1 at first, since the client talks
	 * to the server in version 1 then they can move to a higher
	 * protocol version.
	 */
	session.ns_protocol_version = ndmp_ver;

	session.ns_scsi.sd_is_open = -1;
	session.ns_scsi.sd_devid = -1;

	session.ns_scsi.sd_sid = 0;
	session.ns_scsi.sd_lun = 0;
	session.ns_scsi.sd_valid_target_set = 0;
	(void) memset(session.ns_scsi.sd_adapter_name, 0,
	    sizeof (session.ns_scsi.sd_adapter_name));

	session.ns_tape.td_fd = -1;
	session.ns_tape.td_sid = 0;
	session.ns_tape.td_lun = 0;
	(void) memset(session.ns_tape.td_adapter_name, 0,
	    sizeof (session.ns_tape.td_adapter_name));
	session.ns_tape.td_pos = 0;
	session.ns_tape.td_record_count = 0;
	session.ns_file_handler_list = 0;

	(void) ndmpd_data_init(&session);
	ndmpd_file_history_init(&session);
	if (ndmpd_mover_init(&session) < 0)
		return;

	if (ndmp_lbr_init(&session) < 0)
		return;

	/*
	 * Setup defaults here. The init functions can not set defaults
	 * since the init functions are called by the stop request handlers
	 * and client set variables need to persist across data operations.
	 */
	session.ns_mover.md_record_size = MAX_RECORD_SIZE;

	ndmp_set_client_data(connection, (void *)&session);

	req.reason = NDMP_CONNECTED;
	req.protocol_version = ndmp_ver;
	req.text_reason = "";

	if (ndmp_send_request_lock(connection, NDMP_NOTIFY_CONNECTION_STATUS,
	    NDMP_NO_ERR, (void *)&req, 0) < 0) {
		NDMP_LOG(LOG_DEBUG, "Connection terminated");
		return;
	}
	connection_fd = ndmp_get_fd(connection);

	NDMP_LOG(LOG_DEBUG, "connection_fd: %d", connection_fd);

	/*
	 * Add the handler function for the connection to the DMA.
	 */
	if (ndmpd_add_file_handler(&session, (void *)&session, connection_fd,
	    NDMPD_SELECT_MODE_READ, HC_CLIENT, connection_file_handler) != 0) {
		NDMP_LOG(LOG_DEBUG, "Could not register session handler.");
		return;
	}

	/*
	 * Register the connection in the list of active connections.
	 */
	if (ndmp_connect_list_add(connection, &conn_id) != 0) {
		NDMP_LOG(LOG_ERR,
		    "Could not register the session to the server.");
		(void) ndmpd_remove_file_handler(&session, connection_fd);
		return;
	}

	session.hardlink_q = hardlink_q_init();

	while (session.ns_eof == FALSE)
		(void) ndmpd_select(&session, TRUE, HC_ALL);

	hardlink_q_cleanup(session.hardlink_q);

	NDMP_LOG(LOG_DEBUG, "Connection terminated");

	(void) ndmpd_remove_file_handler(&session, connection_fd);

	if (session.ns_scsi.sd_is_open != -1) {
		NDMP_LOG(LOG_DEBUG, "scsi.is_open: %d",
		    session.ns_scsi.sd_is_open);
		(void) ndmp_open_list_del(session.ns_scsi.sd_adapter_name,
		    session.ns_scsi.sd_sid, session.ns_scsi.sd_lun);
	}
	if (session.ns_tape.td_fd != -1) {
		NDMP_LOG(LOG_DEBUG, "tape.fd: %d", session.ns_tape.td_fd);
		(void) close(session.ns_tape.td_fd);
		(void) ndmp_open_list_del(session.ns_tape.td_adapter_name,
		    session.ns_tape.td_sid, session.ns_tape.td_lun);
	}
	ndmpd_mover_shut_down(&session);
	ndmp_lbr_cleanup(&session);
	ndmpd_data_cleanup(&session);
	ndmpd_file_history_cleanup(&session, FALSE);
	ndmpd_mover_cleanup(&session);

	(void) ndmp_connect_list_del(connection);
}
예제 #3
0
/*ARGSUSED*/
static void
common_set_target(ndmp_connection_t *connection, char *device,
    ushort_t controller, ushort_t sid, ushort_t lun)
{
	ndmp_scsi_set_target_reply reply;
	ndmpd_session_t *session = ndmp_get_client_data(connection);
	int type;

	reply.error = NDMP_NO_ERR;

	if (session->ns_scsi.sd_is_open == -1) {
		reply.error = NDMP_DEV_NOT_OPEN_ERR;
	} else if (!scsi_dev_exists(session->ns_scsi.sd_adapter_name, sid,
	    lun)) {
		syslog(LOG_ERR, "No such SCSI device: target %d lun %d.",
		    sid, lun);
		reply.error = NDMP_NO_DEVICE_ERR;
	} else {
		type = scsi_get_devtype(session->ns_scsi.sd_adapter_name, sid,
		    lun);
		if (type != DTYPE_SEQUENTIAL && type != DTYPE_CHANGER) {
			syslog(LOG_ERR,
			    "Not a tape or robot device: target %d lun %d.",
			    sid, lun);
			reply.error = NDMP_ILLEGAL_ARGS_ERR;
		}
	}

	if (reply.error != NDMP_NO_ERR) {
		ndmp_send_reply(connection, (void *) &reply,
		    "sending scsi_set_target reply");
		return;
	}

	/*
	 * The open_list must be updated if the SID or LUN are going to be
	 * changed.  Close uses the same SID & LUN for removing the entry
	 * from the open_list.
	 */
	if (sid != session->ns_scsi.sd_sid || lun != session->ns_scsi.sd_lun) {
		switch (ndmp_open_list_add(connection,
		    session->ns_scsi.sd_adapter_name, sid, lun, 0)) {
		case 0:
			(void) ndmp_open_list_del(session->
			    ns_scsi.sd_adapter_name, session->ns_scsi.sd_sid,
			    session->ns_scsi.sd_lun);
			break;
		case EBUSY:
			reply.error = NDMP_DEVICE_BUSY_ERR;
			break;
		case ENOMEM:
			reply.error = NDMP_NO_MEM_ERR;
			break;
		default:
			reply.error = NDMP_IO_ERR;
		}
	}

	if (reply.error == NDMP_NO_ERR) {
		syslog(LOG_DEBUG, "Updated sid %d lun %d", sid, lun);
		session->ns_scsi.sd_sid = sid;
		session->ns_scsi.sd_lun = lun;
		session->ns_scsi.sd_valid_target_set = TRUE;
	}

	ndmp_send_reply(connection, (void *) &reply,
	    "sending scsi_set_target reply");
}