|
Packit Service |
392537 |
/*
|
|
Packit Service |
392537 |
* Copyright (c) 1998,1999,2000
|
|
Packit Service |
392537 |
* Traakan, Inc., Los Altos, CA
|
|
Packit Service |
392537 |
* All rights reserved.
|
|
Packit Service |
392537 |
*
|
|
Packit Service |
392537 |
* Redistribution and use in source and binary forms, with or without
|
|
Packit Service |
392537 |
* modification, are permitted provided that the following conditions
|
|
Packit Service |
392537 |
* are met:
|
|
Packit Service |
392537 |
* 1. Redistributions of source code must retain the above copyright
|
|
Packit Service |
392537 |
* notice unmodified, this list of conditions, and the following
|
|
Packit Service |
392537 |
* disclaimer.
|
|
Packit Service |
392537 |
* 2. Redistributions in binary form must reproduce the above copyright
|
|
Packit Service |
392537 |
* notice, this list of conditions and the following disclaimer in the
|
|
Packit Service |
392537 |
* documentation and/or other materials provided with the distribution.
|
|
Packit Service |
392537 |
*
|
|
Packit Service |
392537 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
Packit Service |
392537 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit Service |
392537 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit Service |
392537 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
Packit Service |
392537 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
Packit Service |
392537 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
Packit Service |
392537 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
Packit Service |
392537 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
Packit Service |
392537 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
Packit Service |
392537 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
Packit Service |
392537 |
* SUCH DAMAGE.
|
|
Packit Service |
392537 |
*/
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
/*
|
|
Packit Service |
392537 |
* Project: NDMJOB
|
|
Packit Service |
392537 |
* Ident: $Id: $
|
|
Packit Service |
392537 |
*
|
|
Packit Service |
392537 |
* Description:
|
|
Packit Service |
392537 |
*
|
|
Packit Service |
392537 |
*/
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
#include "ndmagents.h"
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
#ifndef NDMOS_OPTION_NO_TAPE_AGENT
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
/*
|
|
Packit Service |
392537 |
* Initialization and Cleanup
|
|
Packit Service |
392537 |
****************************************************************
|
|
Packit Service |
392537 |
*/
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
/* Initialize -- Set data structure to know value, ignore current value */
|
|
Packit Service |
392537 |
int
|
|
Packit Service |
392537 |
ndmta_initialize (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
int rc;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
NDMOS_MACRO_ZEROFILL(ta);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ndmta_commission (sess);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
rc = ndmos_tape_initialize (sess);
|
|
Packit Service |
392537 |
if (rc) return rc;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
return 0;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
/* Commission -- Get agent ready. Entire session has been initialize()d */
|
|
Packit Service |
392537 |
int
|
|
Packit Service |
392537 |
ndmta_commission (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
ndmta_init_mover_state (sess);
|
|
Packit Service |
392537 |
return 0;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
/* Decommission -- Discard agent */
|
|
Packit Service |
392537 |
int
|
|
Packit Service |
392537 |
ndmta_decommission (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
ndmis_tape_close (sess);
|
|
Packit Service |
392537 |
ndmta_commission (sess);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
return 0;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
/* helper for mover state */
|
|
Packit Service |
392537 |
int
|
|
Packit Service |
392537 |
ndmta_init_mover_state (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
NDMOS_MACRO_ZEROFILL (&ta->mover_state);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->mover_state.state = NDMP9_MOVER_STATE_IDLE;
|
|
Packit Service |
392537 |
ta->mover_state.window_offset = 0;
|
|
Packit Service |
392537 |
ta->mover_state.record_num = 0; /* this should probably be -1, but spec says 0 */
|
|
Packit Service |
392537 |
ta->mover_state.record_size = 20*512; /* traditional tar default */
|
|
Packit Service |
392537 |
ta->mover_state.window_length = NDMP_LENGTH_INFINITY;
|
|
Packit Service |
392537 |
ta->mover_window_end = NDMP_LENGTH_INFINITY;
|
|
Packit Service |
392537 |
ta->mover_want_pos = 0;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->tb_blockno = -1;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
return 0;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
/*
|
|
Packit Service |
392537 |
* Semantic actions -- called from ndma_dispatch()
|
|
Packit Service |
392537 |
****************************************************************
|
|
Packit Service |
392537 |
*/
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
void
|
|
Packit Service |
392537 |
ndmta_mover_sync_state (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
ndmos_tape_sync_state (sess);
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ndmp9_error
|
|
Packit Service |
392537 |
ndmta_mover_listen (struct ndm_session *sess, ndmp9_mover_mode mover_mode)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->mover_state.mode = mover_mode;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->mover_state.state = NDMP9_MOVER_STATE_LISTEN;
|
|
Packit Service |
392537 |
ta->mover_state.halt_reason = NDMP9_MOVER_HALT_NA;
|
|
Packit Service |
392537 |
ta->mover_state.pause_reason = NDMP9_MOVER_PAUSE_NA;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
return NDMP9_NO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ndmp9_error
|
|
Packit Service |
392537 |
ndmta_mover_connect (struct ndm_session *sess, ndmp9_mover_mode mover_mode)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->mover_state.mode = mover_mode;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ndmta_mover_start_active (sess);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
return NDMP9_NO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
void
|
|
Packit Service |
392537 |
ndmta_mover_halt (struct ndm_session *sess, ndmp9_mover_halt_reason reason)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->mover_state.state = NDMP9_MOVER_STATE_HALTED;
|
|
Packit Service |
392537 |
ta->mover_state.halt_reason = reason;
|
|
Packit Service |
392537 |
ta->mover_state.pause_reason = NDMP9_MOVER_PAUSE_NA;
|
|
Packit Service |
392537 |
ta->pending_change_after_drain = 0;
|
|
Packit Service |
392537 |
ta->mover_notify_pending = 1;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ndmis_tape_close (sess);
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
void
|
|
Packit Service |
392537 |
ndmta_mover_pause (struct ndm_session *sess, ndmp9_mover_pause_reason reason)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->mover_state.state = NDMP9_MOVER_STATE_PAUSED;
|
|
Packit Service |
392537 |
ta->mover_state.halt_reason = NDMP9_MOVER_HALT_NA;
|
|
Packit Service |
392537 |
ta->mover_state.pause_reason = reason;
|
|
Packit Service |
392537 |
ta->pending_change_after_drain = 0;
|
|
Packit Service |
392537 |
ta->mover_notify_pending = 1;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
void
|
|
Packit Service |
392537 |
ndmta_mover_pending (struct ndm_session *sess,
|
|
Packit Service |
392537 |
ndmp9_mover_state pending_state,
|
|
Packit Service |
392537 |
ndmp9_mover_halt_reason halt_reason,
|
|
Packit Service |
392537 |
ndmp9_mover_pause_reason pause_reason)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (ta->pending_change_after_drain) {
|
|
Packit Service |
392537 |
/* internal botch */
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->pending_mover_state = pending_state;
|
|
Packit Service |
392537 |
ta->pending_mover_halt_reason = halt_reason;
|
|
Packit Service |
392537 |
ta->pending_mover_pause_reason = pause_reason;
|
|
Packit Service |
392537 |
ta->pending_change_after_drain = 1;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
void
|
|
Packit Service |
392537 |
ndmta_mover_apply_pending (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (!ta->pending_change_after_drain) {
|
|
Packit Service |
392537 |
/* internal botch */
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->mover_state.state = ta->pending_mover_state;
|
|
Packit Service |
392537 |
ta->mover_state.halt_reason = ta->pending_mover_halt_reason;
|
|
Packit Service |
392537 |
ta->mover_state.pause_reason = ta->pending_mover_pause_reason;
|
|
Packit Service |
392537 |
ta->pending_change_after_drain = 0;
|
|
Packit Service |
392537 |
ta->mover_notify_pending = 1;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
void
|
|
Packit Service |
392537 |
ndmta_mover_halt_pending (struct ndm_session *sess,
|
|
Packit Service |
392537 |
ndmp9_mover_halt_reason halt_reason)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
ndmta_mover_pending (sess, NDMP9_MOVER_STATE_HALTED,
|
|
Packit Service |
392537 |
halt_reason, NDMP9_MOVER_PAUSE_NA);
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
void
|
|
Packit Service |
392537 |
ndmta_mover_pause_pending (struct ndm_session *sess,
|
|
Packit Service |
392537 |
ndmp9_mover_pause_reason pause_reason)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
ndmta_mover_pending (sess, NDMP9_MOVER_STATE_PAUSED,
|
|
Packit Service |
392537 |
NDMP9_MOVER_HALT_NA, pause_reason);
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
void
|
|
Packit Service |
392537 |
ndmta_mover_active (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->mover_state.state = NDMP9_MOVER_STATE_ACTIVE;
|
|
Packit Service |
392537 |
ta->mover_state.halt_reason = NDMP9_MOVER_HALT_NA;
|
|
Packit Service |
392537 |
ta->mover_state.pause_reason = NDMP9_MOVER_PAUSE_NA;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->tb_blockno = -1; /* always mistrust after activating */
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
void
|
|
Packit Service |
392537 |
ndmta_mover_start_active (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ndmalogf (sess, 0, 6, "mover going active");
|
|
Packit Service |
392537 |
ndma_send_logmsg(sess, NDMP9_LOG_DEBUG, sess->plumb.control,
|
|
Packit Service |
392537 |
"mover going active");
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
switch (ta->mover_state.mode) {
|
|
Packit Service |
392537 |
case NDMP9_MOVER_MODE_READ:
|
|
Packit Service |
392537 |
ndmis_tape_start (sess, NDMCHAN_MODE_READ);
|
|
Packit Service |
392537 |
ndmta_mover_active (sess);
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case NDMP9_MOVER_MODE_WRITE:
|
|
Packit Service |
392537 |
ndmis_tape_start (sess, NDMCHAN_MODE_WRITE);
|
|
Packit Service |
392537 |
ndmta_mover_active (sess);
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
default:
|
|
Packit Service |
392537 |
ndmalogf (sess, 0, 0, "BOTCH mover listen, unknown mode");
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
void
|
|
Packit Service |
392537 |
ndmta_mover_stop (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
ndmta_init_mover_state (sess);
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
void
|
|
Packit Service |
392537 |
ndmta_mover_abort (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
ndmta_mover_halt (sess, NDMP9_MOVER_HALT_ABORTED);
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
void
|
|
Packit Service |
392537 |
ndmta_mover_continue (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
ndmta_mover_active (sess);
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
void
|
|
Packit Service |
392537 |
ndmta_mover_close (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (ta->mover_state.state != NDMP9_MOVER_STATE_HALTED)
|
|
Packit Service |
392537 |
ndmta_mover_halt (sess, NDMP9_MOVER_HALT_CONNECT_CLOSED);
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
void
|
|
Packit Service |
392537 |
ndmta_mover_read (struct ndm_session *sess,
|
|
Packit Service |
392537 |
unsigned long long offset, unsigned long long length)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->mover_state.seek_position = offset;
|
|
Packit Service |
392537 |
ta->mover_state.bytes_left_to_read = length;
|
|
Packit Service |
392537 |
ta->mover_want_pos = offset;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
/*
|
|
Packit Service |
392537 |
* Quantum -- get a bit of work done
|
|
Packit Service |
392537 |
****************************************************************
|
|
Packit Service |
392537 |
*/
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
int
|
|
Packit Service |
392537 |
ndmta_quantum (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
int rc = 0; /* did nothing */
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
switch (ta->mover_state.state) {
|
|
Packit Service |
392537 |
default:
|
|
Packit Service |
392537 |
ndmalogf (sess, 0, 0, "BOTCH mover state");
|
|
Packit Service |
392537 |
return -1;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case NDMP9_MOVER_STATE_IDLE:
|
|
Packit Service |
392537 |
case NDMP9_MOVER_STATE_PAUSED:
|
|
Packit Service |
392537 |
case NDMP9_MOVER_STATE_HALTED:
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case NDMP9_MOVER_STATE_LISTEN:
|
|
Packit Service |
392537 |
switch (sess->plumb.image_stream.tape_ep.connect_status) {
|
|
Packit Service |
392537 |
case NDMIS_CONN_LISTEN: /* no connection yet */
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case NDMIS_CONN_ACCEPTED: /* we're in business */
|
|
Packit Service |
392537 |
ndmta_mover_start_active (sess);
|
|
Packit Service |
392537 |
rc = 1; /* did something */
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case NDMIS_CONN_BOTCHED: /* accept() went south */
|
|
Packit Service |
392537 |
default: /* ain't suppose to happen */
|
|
Packit Service |
392537 |
ndmta_mover_halt(sess,NDMP9_MOVER_HALT_CONNECT_ERROR);
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case NDMP9_MOVER_STATE_ACTIVE:
|
|
Packit Service |
392537 |
switch (ta->mover_state.mode) {
|
|
Packit Service |
392537 |
case NDMP9_MOVER_MODE_READ:
|
|
Packit Service |
392537 |
rc = ndmta_read_quantum (sess);
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case NDMP9_MOVER_MODE_WRITE:
|
|
Packit Service |
392537 |
rc = ndmta_write_quantum (sess);
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
default:
|
|
Packit Service |
392537 |
ndmalogf (sess, 0, 0,
|
|
Packit Service |
392537 |
"BOTCH mover active, unknown mode");
|
|
Packit Service |
392537 |
return -1;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ndmta_mover_send_notice (sess);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
return rc;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
int
|
|
Packit Service |
392537 |
ndmta_read_quantum (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
struct ndmchan * ch = &sess->plumb.image_stream.chan;
|
|
Packit Service |
392537 |
unsigned long count = ta->mover_state.record_size;
|
|
Packit Service |
392537 |
int did_something = 0;
|
|
Packit Service |
392537 |
unsigned n_ready;
|
|
Packit Service |
392537 |
char * data;
|
|
Packit Service |
392537 |
unsigned long done_count;
|
|
Packit Service |
392537 |
ndmp9_error error;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
again:
|
|
Packit Service |
392537 |
n_ready = ndmchan_n_ready (ch);
|
|
Packit Service |
392537 |
if (ch->eof) {
|
|
Packit Service |
392537 |
if (n_ready == 0) {
|
|
Packit Service |
392537 |
/* done */
|
|
Packit Service |
392537 |
if (ch->saved_errno)
|
|
Packit Service |
392537 |
ndmta_mover_halt (sess,
|
|
Packit Service |
392537 |
NDMP9_MOVER_HALT_CONNECT_ERROR);
|
|
Packit Service |
392537 |
else
|
|
Packit Service |
392537 |
ndmta_mover_halt (sess,
|
|
Packit Service |
392537 |
NDMP9_MOVER_HALT_CONNECT_CLOSED);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
did_something++;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
return did_something;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (n_ready < count) {
|
|
Packit Service |
392537 |
int n_pad = count - n_ready;
|
|
Packit Service |
392537 |
int n_avail;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
while (n_pad > 0) {
|
|
Packit Service |
392537 |
n_avail = ndmchan_n_avail (ch);
|
|
Packit Service |
392537 |
if (n_avail == 0) {
|
|
Packit Service |
392537 |
/* Uh-oh */
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
data = &ch->data[ch->end_ix];
|
|
Packit Service |
392537 |
if (n_avail > n_pad)
|
|
Packit Service |
392537 |
n_avail = n_pad;
|
|
Packit Service |
392537 |
bzero (data, n_avail);
|
|
Packit Service |
392537 |
ch->end_ix += n_avail;
|
|
Packit Service |
392537 |
n_pad -= n_avail;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
n_ready = ndmchan_n_ready (ch);
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (n_ready < count) {
|
|
Packit Service |
392537 |
return did_something; /* blocked */
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (ta->mover_want_pos >= ta->mover_window_end) {
|
|
Packit Service |
392537 |
ndmta_mover_pause (sess, NDMP9_MOVER_PAUSE_SEEK);
|
|
Packit Service |
392537 |
did_something++;
|
|
Packit Service |
392537 |
return did_something;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
data = &ch->data[ch->beg_ix];
|
|
Packit Service |
392537 |
done_count = 0;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
error = ndmos_tape_write (sess, data, count, &done_count);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
switch (error) {
|
|
Packit Service |
392537 |
case NDMP9_NO_ERR:
|
|
Packit Service |
392537 |
if (done_count != count) {
|
|
Packit Service |
392537 |
/* This ain't suppose to happen */
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
ta->mover_state.bytes_moved += count;
|
|
Packit Service |
392537 |
/* note this is calculated before mover_want_pos is incremented, since
|
|
Packit Service |
392537 |
* record_num is the *last* block processed */
|
|
Packit Service |
392537 |
/* ta->mover_state.record_num = ta->mover_want_pos / ta->mover_state.record_size; */
|
|
Packit Service |
392537 |
/* It was a bug, set record_num after mover_want_pos */
|
|
Packit Service |
392537 |
ta->mover_want_pos += count;
|
|
Packit Service |
392537 |
ta->mover_state.record_num = ta->mover_want_pos / ta->mover_state.record_size;
|
|
Packit Service |
392537 |
ch->beg_ix += count;
|
|
Packit Service |
392537 |
did_something++;
|
|
Packit Service |
392537 |
goto again; /* write as much to tape as possible */
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case NDMP9_EOM_ERR:
|
|
Packit Service |
392537 |
ndmta_mover_pause (sess, NDMP9_MOVER_PAUSE_EOM);
|
|
Packit Service |
392537 |
did_something++;
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
default:
|
|
Packit Service |
392537 |
ndmta_mover_halt (sess, NDMP9_MOVER_HALT_MEDIA_ERROR);
|
|
Packit Service |
392537 |
did_something++;
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
return did_something;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
int
|
|
Packit Service |
392537 |
ndmta_write_quantum (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
struct ndmchan * ch = &sess->plumb.image_stream.chan;
|
|
Packit Service |
392537 |
unsigned long count = ta->mover_state.record_size;
|
|
Packit Service |
392537 |
int did_something = 0;
|
|
Packit Service |
392537 |
unsigned long long max_read;
|
|
Packit Service |
392537 |
unsigned long long want_window_off;
|
|
Packit Service |
392537 |
unsigned long block_size;
|
|
Packit Service |
392537 |
unsigned long want_blockno;
|
|
Packit Service |
392537 |
unsigned long cur_blockno;
|
|
Packit Service |
392537 |
unsigned n_avail, n_read, record_off;
|
|
Packit Service |
392537 |
char * data;
|
|
Packit Service |
392537 |
unsigned long done_count = 0;
|
|
Packit Service |
392537 |
ndmp9_error error;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
again:
|
|
Packit Service |
392537 |
n_read = n_avail = ndmchan_n_avail_record (ch, count);
|
|
Packit Service |
392537 |
if (n_avail < count) {
|
|
Packit Service |
392537 |
/* allow to drain */
|
|
Packit Service |
392537 |
return did_something;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (ta->pending_change_after_drain) {
|
|
Packit Service |
392537 |
if (ndmchan_n_ready (ch) > 0) {
|
|
Packit Service |
392537 |
/* allow to drain */
|
|
Packit Service |
392537 |
} else {
|
|
Packit Service |
392537 |
ndmta_mover_apply_pending (sess);
|
|
Packit Service |
392537 |
did_something++;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
return did_something;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (n_read > ta->mover_state.bytes_left_to_read)
|
|
Packit Service |
392537 |
n_read = ta->mover_state.bytes_left_to_read;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (n_read < count) {
|
|
Packit Service |
392537 |
/* Active, but paused awaiting MOVER_READ request */
|
|
Packit Service |
392537 |
return did_something; /* mover blocked */
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (ta->mover_want_pos < ta->mover_state.window_offset
|
|
Packit Service |
392537 |
|| ta->mover_want_pos >= ta->mover_window_end) {
|
|
Packit Service |
392537 |
ndmta_mover_pause_pending (sess, NDMP9_MOVER_PAUSE_SEEK);
|
|
Packit Service |
392537 |
goto again;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
max_read = ta->mover_window_end - ta->mover_want_pos;
|
|
Packit Service |
392537 |
if (n_read > max_read)
|
|
Packit Service |
392537 |
n_read = max_read;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
want_window_off = ta->mover_want_pos - ta->mover_state.window_offset;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
/* make an estimate of the block size - the tape agent's block size, or
|
|
Packit Service |
392537 |
* if it's in variable block size mode, the mover's record size: "When
|
|
Packit Service |
392537 |
* in variable block mode, as indicated by a tape block_size value of
|
|
Packit Service |
392537 |
* zero, the mover record size defines the actual block size used by
|
|
Packit Service |
392537 |
* the tape subsystem." (NDMPv4 RFC, Section 3.6.2.1) */
|
|
Packit Service |
392537 |
block_size = ta->tape_state.block_size.value;
|
|
Packit Service |
392537 |
if (!block_size)
|
|
Packit Service |
392537 |
block_size = ta->mover_state.record_size;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
want_blockno = ta->mover_window_first_blockno + want_window_off / block_size;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (ta->tb_blockno != want_blockno) {
|
|
Packit Service |
392537 |
unsigned long xsr_count, xsr_resid;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ndmos_tape_sync_state(sess);
|
|
Packit Service |
392537 |
cur_blockno = ta->tape_state.blockno.value;
|
|
Packit Service |
392537 |
if (cur_blockno < want_blockno) {
|
|
Packit Service |
392537 |
xsr_count = want_blockno - cur_blockno;
|
|
Packit Service |
392537 |
error = ndmos_tape_mtio (sess, NDMP9_MTIO_FSR,
|
|
Packit Service |
392537 |
xsr_count, &xsr_resid);
|
|
Packit Service |
392537 |
if (error == NDMP9_EOF_ERR) {
|
|
Packit Service |
392537 |
ndmta_mover_pause_pending (sess,
|
|
Packit Service |
392537 |
NDMP9_MOVER_PAUSE_EOF);
|
|
Packit Service |
392537 |
goto again;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
if (error != NDMP9_NO_ERR) {
|
|
Packit Service |
392537 |
ndmta_mover_halt_pending (sess,
|
|
Packit Service |
392537 |
NDMP9_MOVER_HALT_MEDIA_ERROR);
|
|
Packit Service |
392537 |
goto again;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
if (xsr_resid > 0) {
|
|
Packit Service |
392537 |
ndmta_mover_pause_pending (sess,
|
|
Packit Service |
392537 |
NDMP9_MOVER_PAUSE_EOF);
|
|
Packit Service |
392537 |
goto again;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
} else if (cur_blockno > want_blockno) {
|
|
Packit Service |
392537 |
xsr_count = cur_blockno - want_blockno;
|
|
Packit Service |
392537 |
error = ndmos_tape_mtio (sess, NDMP9_MTIO_BSR,
|
|
Packit Service |
392537 |
xsr_count, &xsr_resid);
|
|
Packit Service |
392537 |
if (error != NDMP9_NO_ERR || xsr_resid > 0) {
|
|
Packit Service |
392537 |
ndmta_mover_halt_pending (sess,
|
|
Packit Service |
392537 |
NDMP9_MOVER_HALT_MEDIA_ERROR);
|
|
Packit Service |
392537 |
goto again;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
} else {
|
|
Packit Service |
392537 |
/* in position */
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
data = ta->tape_buffer;
|
|
Packit Service |
392537 |
done_count = 0;
|
|
Packit Service |
392537 |
error = ndmos_tape_read (sess, data, count, &done_count);
|
|
Packit Service |
392537 |
did_something++;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (error == NDMP9_EOF_ERR) {
|
|
Packit Service |
392537 |
ndmta_mover_pause_pending (sess,
|
|
Packit Service |
392537 |
NDMP9_MOVER_PAUSE_EOF);
|
|
Packit Service |
392537 |
goto again;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
/* N.B. - handling of done_count = 0 here is hacked to support
|
|
Packit Service |
392537 |
* non-blocking writes to a socket in amndmjob */
|
|
Packit Service |
392537 |
if (error != NDMP9_NO_ERR) {
|
|
Packit Service |
392537 |
ndmta_mover_halt_pending (sess,
|
|
Packit Service |
392537 |
NDMP9_MOVER_HALT_MEDIA_ERROR);
|
|
Packit Service |
392537 |
goto again;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
if (done_count == 0) {
|
|
Packit Service |
392537 |
return did_something - 1;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
if (done_count != count) {
|
|
Packit Service |
392537 |
n_read = done_count;
|
|
Packit Service |
392537 |
goto again;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
ta->tb_blockno = want_blockno;
|
|
Packit Service |
392537 |
/* re-calcluate this, since record_size may be > block_size, in which
|
|
Packit Service |
392537 |
* case the record_num may not change for each block read from tape */
|
|
Packit Service |
392537 |
ta->mover_state.record_num = ta->mover_want_pos / ta->mover_state.record_size;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
record_off = ta->mover_want_pos % ta->mover_state.record_size;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
n_avail = ta->mover_state.record_size - record_off;
|
|
Packit Service |
392537 |
if (n_read > n_avail)
|
|
Packit Service |
392537 |
n_read = n_avail;
|
|
Packit Service |
392537 |
if (n_read != done_count) {
|
|
Packit Service |
392537 |
dbprintf("lost %lu bytes %lu %u\n", done_count - n_read, done_count, n_read);
|
|
Packit Service |
392537 |
n_read = done_count;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
data = &ta->tape_buffer[record_off];
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
bcopy (data, ch->data + ch->end_ix, n_read);
|
|
Packit Service |
392537 |
ch->end_ix += n_read;
|
|
Packit Service |
392537 |
ta->mover_state.bytes_moved += n_read;
|
|
Packit Service |
392537 |
ta->mover_want_pos += n_read;
|
|
Packit Service |
392537 |
ta->mover_state.bytes_left_to_read -= n_read;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
did_something++;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
goto again; /* do as much as possible */
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
void
|
|
Packit Service |
392537 |
ndmta_mover_send_notice (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (!ta->mover_notify_pending)
|
|
Packit Service |
392537 |
return;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->mover_notify_pending = 0;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
switch (ta->mover_state.state) {
|
|
Packit Service |
392537 |
case NDMP9_MOVER_STATE_HALTED:
|
|
Packit Service |
392537 |
ndma_notify_mover_halted (sess);
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case NDMP9_MOVER_STATE_PAUSED:
|
|
Packit Service |
392537 |
ndma_notify_mover_paused (sess);
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
default:
|
|
Packit Service |
392537 |
/* Hmm. Why are we here. Race? */
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
#endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
|