/* * Env list mgmt. * * Return a chunk of memory with all entries from the envlist as * one big enumeration useable for rpc to use as return value. * We allacate the memory and keep the pointer in the table handle * which gets freed on destroy of the table. */ ndmp9_pval * ndma_enumerate_env_list (struct ndm_env_table *envtab) { int i; struct ndm_env_entry * entry; /* * See if we need to allocate memory or can reuse the memory * already allocated in an earlier call. */ if (!envtab->enumerate) { envtab->enumerate = NDMOS_API_MALLOC (sizeof(ndmp9_pval) * envtab->n_env); envtab->enumerate_length = envtab->n_env; } else if (envtab->enumerate_length != envtab->n_env) { NDMOS_API_FREE (envtab->enumerate); envtab->enumerate = NDMOS_API_MALLOC (sizeof(ndmp9_pval) * envtab->n_env); envtab->enumerate_length = envtab->n_env; } if (!envtab->enumerate) { return NULL; } NDMOS_API_BZERO (envtab->enumerate, sizeof(ndmp9_pval) * envtab->n_env); i = 0; for (entry = envtab->head; entry; entry = entry->next) { memcpy (&envtab->enumerate[i], &entry->pval, sizeof(ndmp9_pval)); i++; } return envtab->enumerate; }
/* * Nlist mgmt. * * Return a chunk of memory with all entries from the nlist as * one big enumeration useable for rpc to use as return value. * We allacate the memory and keep the pointer in the table handle * which gets freed on destroy of the table. */ ndmp9_name * ndma_enumerate_nlist (struct ndm_nlist_table *nlist) { int i; struct ndm_nlist_entry * entry; /* * See if we need to allocate memory or can reuse the memory * already allocated in an earlier call. */ if (!nlist->enumerate) { nlist->enumerate = NDMOS_API_MALLOC (sizeof(ndmp9_name) * nlist->n_nlist); nlist->enumerate_length = nlist->n_nlist; } else if (nlist->enumerate_length != nlist->n_nlist) { NDMOS_API_FREE (nlist->enumerate); nlist->enumerate = NDMOS_API_MALLOC (sizeof(ndmp9_name) * nlist->n_nlist); nlist->enumerate_length = nlist->n_nlist; } if (!nlist->enumerate) { return NULL; } NDMOS_API_BZERO (nlist->enumerate, sizeof(ndmp9_name) * nlist->n_nlist); i = 0; for (entry = nlist->head; entry; entry = entry->next) { memcpy (&nlist->enumerate[i], &entry->name, sizeof(ndmp9_name)); i++; } return nlist->enumerate; }
int args_to_job_recover_nlist (void) { int not_found = 0; int i, prefix_len, len; char * dest; if (C_chdir) { prefix_len = strlen (C_chdir) + 2; } else { prefix_len = 0; } for (i = 0; (i < n_file_arg) && (i < NDM_MAX_NLIST); i++) { if (file_arg_new[i]) { len = strlen (file_arg_new[i]) + prefix_len + 1; dest = NDMOS_API_MALLOC (len); *dest = 0; if (C_chdir) { strcpy (dest, C_chdir); } if (file_arg_new[i][0] != '/') { strcat (dest, "/"); } strcat (dest, file_arg_new[i]); normalize_name (file_arg_new[i]); normalize_name (file_arg[i]); normalize_name (dest); nlist[i].original_path = file_arg[i]; nlist[i].destination_path = dest; } else { len = strlen (file_arg[i]) + prefix_len + 1; dest = NDMOS_API_MALLOC (len); *dest = 0; if (C_chdir) { strcpy (dest, C_chdir); } if (file_arg[i][0] != '/') { strcat (dest, "/"); } strcat (dest, file_arg[i]); normalize_name (file_arg[i]); normalize_name (dest); nlist[i].original_path = file_arg[i]; nlist[i].destination_path = dest; } } return not_found; /* should ALWAYS be 0 */ }
END ========== LOCAL ============ END POINT POINT REMOTE #endif #include "ndmagents.h" int ndmis_reinit_remote (struct ndm_session *sess) { struct ndm_image_stream *is = sess->plumb.image_stream; struct ndm_tape_agent * ta = sess->tape_acb; NDMOS_MACRO_ZEROFILL (&is->remote); ndmchan_initialize (&is->remote.listen_chan, "image-stream-listen"); ndmchan_initialize (&is->remote.sanity_chan, "image-stream-sanity"); ndmchan_initialize (&is->chan, "image-stream"); if (!is->buf) { is->buflen = ta->mover_state.record_size; is->buf = NDMOS_API_MALLOC (is->buflen); if (!is->buf) { return -1; } NDMOS_MACRO_ZEROFILL_SIZE (is->buf, is->buflen); } ndmchan_setbuf (&is->chan, is->buf, is->buflen); return 0; }
static ndmp9_error scsi_fail_with_sense_code(struct ndm_session *sess, ndmp9_execute_cdb_reply *reply, int status, int sense_key, int asq) { unsigned char ext_sense[] = { 0x72, /* current errors */ sense_key & SCSI_SENSE_SENSE_KEY_MASK, (asq >> 8) & 0xff, (asq ) & 0xff, 0, 0, 0, 0 }; ndmalogf(sess, 0, 3, "sending failure; status=0x%02x sense_key=0x%02x asq=0x%04x", status, sense_key, asq); reply->status = status; reply->ext_sense.ext_sense_len = sizeof(ext_sense); reply->ext_sense.ext_sense_val = NDMOS_API_MALLOC(sizeof(ext_sense)); NDMOS_API_BCOPY(ext_sense, reply->ext_sense.ext_sense_val, sizeof(ext_sense)); return NDMP9_NO_ERR; }
/* * Clone an existing media entry and add it to the Media Table. * Return entry if caller want to modify it. */ struct ndmmedia * ndma_clone_media_entry (struct ndm_media_table *mtab, struct ndmmedia *to_clone) { struct ndmmedia * me; if (mtab->n_media >= NDM_MAX_MEDIA) return NULL; me = NDMOS_API_MALLOC (sizeof(struct ndmmedia)); if (!me) { return NULL; } memcpy (me, to_clone, sizeof(struct ndmmedia)); me->index = mtab->n_media + 1; me->next = NULL; if (mtab->tail) { mtab->tail->next = me; mtab->tail = me; } else { mtab->head = me; mtab->tail = me; } mtab->n_media++; return me; }
/* * Media list mgmt. * * Create a new media entry and add it to the Media Table. * Return entry if caller want to modify it. */ struct ndmmedia * ndma_store_media (struct ndm_media_table *mtab, uint16_t element_address) { struct ndmmedia * me; if (mtab->n_media >= NDM_MAX_MEDIA) return NULL; me = NDMOS_API_MALLOC (sizeof(struct ndmmedia)); if (!me) { return NULL; } NDMOS_MACRO_ZEROFILL (me); me->valid_slot = 1; me->slot_addr = element_address; me->index = mtab->n_media + 1; me->next = NULL; if (mtab->tail) { mtab->tail->next = me; mtab->tail = me; } else { mtab->head = me; mtab->tail = me; } mtab->n_media++; return me; }
/* Initialize -- Set data structure to know value, ignore current value */ int ndmca_initialize(struct ndm_session* sess) { sess->control_acb = NDMOS_API_MALLOC(sizeof(struct ndm_control_agent)); if (!sess->control_acb) { return -1; } NDMOS_MACRO_ZEROFILL(sess->control_acb); return 0; }
/* Commission -- Get agent ready. Entire session has been initialize()d */ int ndmda_fh_commission(struct ndm_session* sess) { struct ndm_data_agent* da = sess->data_acb; struct ndmfhheap* fhh = &da->fhh; da->fhh_buf = NDMOS_API_MALLOC(NDMDA_N_FHH_BUF); if (!da->fhh_buf) return -1; // ndmfhh_commission (fhh, da->fhh_buf, sizeof *da->fhh_buf); ndmfhh_commission(fhh, da->fhh_buf, NDMDA_N_FHH_BUF); return 0; }
void ndmos_tape_register_callbacks (struct ndm_session *sess, struct ndm_tape_simulator_callbacks *callbacks) { /* * Only allow one register. */ if (!sess->ntsc) { sess->ntsc = NDMOS_API_MALLOC (sizeof(struct ndm_tape_simulator_callbacks)); memcpy(sess->ntsc, callbacks, sizeof(struct ndm_tape_simulator_callbacks)); } }
void ndmfhdb_register_callbacks(struct ndmlog* ixlog, struct ndm_fhdb_callbacks* callbacks) { /* * Only allow one register. */ if (!ixlog->nfc) { ixlog->nfc = NDMOS_API_MALLOC(sizeof(struct ndm_fhdb_callbacks)); if (ixlog->nfc) { memcpy(ixlog->nfc, callbacks, sizeof(struct ndm_fhdb_callbacks)); } } }
/* Initialize -- Set data structure to know value, ignore current value */ int ndmis_initialize (struct ndm_session *sess) { sess->plumb.image_stream = NDMOS_API_MALLOC (sizeof(struct ndm_image_stream)); if (!sess->plumb.image_stream) return -1; NDMOS_MACRO_ZEROFILL (sess->plumb.image_stream); NDMOS_MACRO_ZEROFILL (&sess->plumb.image_stream->chan); ndmis_reinit_remote (sess); sess->plumb.image_stream->data_ep.name = "DATA"; sess->plumb.image_stream->tape_ep.name = "TAPE"; return 0; }
/* Initialize -- Set data structure to know value, ignore current value */ int ndmda_initialize (struct ndm_session *sess) { sess->data_acb = NDMOS_API_MALLOC (sizeof(struct ndm_data_agent)); if (!sess->data_acb) return -1; NDMOS_MACRO_ZEROFILL (sess->data_acb); sess->data_acb->data_state.state = NDMP9_DATA_STATE_IDLE; ndmchan_initialize (&sess->data_acb->formatter_error, "dfp-error"); ndmchan_initialize (&sess->data_acb->formatter_wrap, "dfp-wrap"); ndmchan_initialize (&sess->data_acb->formatter_image, "dfp-image"); ndmda_fh_initialize (sess); return 0; }
/* Initialize -- Set data structure to know value, ignore current value */ int ndmta_initialize (struct ndm_session *sess) { int rc; sess->tape_acb = NDMOS_API_MALLOC (sizeof(struct ndm_tape_agent)); if (!sess->tape_acb) return -1; NDMOS_MACRO_ZEROFILL (sess->tape_acb); ndmta_commission (sess); rc = ndmos_tape_initialize (sess); if (rc) return rc; return 0; }
static ndmp9_error execute_cdb_inquiry (struct ndm_session *sess, ndmp9_execute_cdb_request *request, ndmp9_execute_cdb_reply *reply) { unsigned char *cdb = (unsigned char *)request->cdb.cdb_val; char *response; int response_len; char *p; /* N.B.: only page code 0 is supported */ if (request->cdb.cdb_len != 6 || request->data_dir != NDMP9_SCSI_DATA_DIR_IN || cdb[1] & 0x01 || cdb[2] != 0 || request->datain_len < 96 || ((cdb[3] << 8) + cdb[4]) < 96) return scsi_fail_with_sense_code(sess, reply, SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_KEY_ILLEGAL_REQUEST, ASQ_INVALID_FIELD_IN_CDB); response_len = 96; p = response = NDMOS_API_MALLOC(response_len); NDMOS_API_BZERO(response, response_len); *(p++) = 0x08; /* media changer */ *(p++) = 0; /* RMB=0 */ *(p++) = 6; /* VERSION=SPC-4 */ *(p++) = 2; /* !NORMACA, !HISUP, RESPONSE DATA FORMAT = 2 */ *(p++) = 92; /* remaining bytes */ *(p++) = 0; /* lots of flags, all 0 */ *(p++) = 0; /* lots of flags, all 0 */ *(p++) = 0; /* lots of flags, all 0 */ NDMOS_API_BCOPY("NDMJOB ", p, 8); p += 8; NDMOS_API_BCOPY("FakeRobot ", p, 16); p += 16; NDMOS_API_BCOPY("1.0 ", p, 4); p += 4; /* remainder is zero */ reply->datain.datain_len = response_len; reply->datain.datain_val = response; return NDMP9_NO_ERR; }
/* * Add a new entry to an environment list table. * Return entry if caller want to modify it. */ struct ndm_env_entry * ndma_store_env_list (struct ndm_env_table *envtab, ndmp9_pval *pv) { struct ndm_env_entry * entry; if (envtab->n_env >= NDM_MAX_ENV) return NULL; entry = NDMOS_API_MALLOC (sizeof(struct ndm_env_entry)); if (!entry) return NULL; entry->pval.name = NDMOS_API_STRDUP (pv->name); if (!entry->pval.name) { NDMOS_API_FREE (entry); return NULL; } entry->pval.value = NDMOS_API_STRDUP (pv->value); if (!entry->pval.value) { NDMOS_API_FREE (entry->pval.name); NDMOS_API_FREE (entry); return NULL; } entry->next = NULL; if (envtab->tail) { envtab->tail->next = entry; envtab->tail = entry; } else { envtab->head = entry; envtab->tail = entry; } envtab->n_env++; return entry; }
int ndmca_control_agent(struct ndm_session* sess) { struct ndm_job_param* job = &sess->control_acb->job; int rc = -1; if (!sess->control_acb->smc_cb) { sess->control_acb->smc_cb = NDMOS_API_MALLOC(sizeof(struct smc_ctrl_block)); NDMOS_MACRO_ZEROFILL(sess->control_acb->smc_cb); } switch (job->operation) { default: ndmalogf(sess, 0, 0, "Job operation invalid"); break; case NDM_JOB_OP_INIT_LABELS: rc = ndmca_op_init_labels(sess); break; case NDM_JOB_OP_LIST_LABELS: rc = ndmca_op_list_labels(sess); break; case NDM_JOB_OP_BACKUP: rc = ndmca_op_create_backup(sess); break; case NDM_JOB_OP_EXTRACT: rc = ndmca_op_recover_files(sess); break; case NDM_JOB_OP_TOC: rc = ndmca_op_recover_fh(sess); break; case NDM_JOB_OP_REMEDY_ROBOT: rc = ndmca_op_robot_remedy(sess); break; case NDM_JOB_OP_QUERY_AGENTS: rc = ndmca_op_query(sess); break; case NDM_JOB_OP_TEST_TAPE: #ifndef NDMOS_OPTION_NO_TEST_AGENTS rc = ndmca_op_test_tape(sess); #endif break; case NDM_JOB_OP_TEST_MOVER: #ifndef NDMOS_OPTION_NO_TEST_AGENTS rc = ndmca_op_test_mover(sess); #endif break; case NDM_JOB_OP_TEST_DATA: #ifndef NDMOS_OPTION_NO_TEST_AGENTS rc = ndmca_op_test_data(sess); #endif break; case NDM_JOB_OP_REWIND_TAPE: rc = ndmca_op_rewind_tape(sess); break; case NDM_JOB_OP_EJECT_TAPE: rc = ndmca_op_eject_tape(sess); break; case NDM_JOB_OP_MOVE_TAPE: rc = ndmca_op_move_tape(sess); break; case NDM_JOB_OP_LOAD_TAPE: rc = ndmca_op_load_tape(sess); break; case NDM_JOB_OP_UNLOAD_TAPE: rc = ndmca_op_unload_tape(sess); break; case NDM_JOB_OP_IMPORT_TAPE: rc = ndmca_op_import_tape(sess); break; case NDM_JOB_OP_EXPORT_TAPE: rc = ndmca_op_export_tape(sess); break; case NDM_JOB_OP_INIT_ELEM_STATUS: rc = ndmca_op_init_elem_status(sess); break; } return rc; }
static ndmp9_error execute_cdb_read_element_status (struct ndm_session *sess, ndmp9_execute_cdb_request *request, ndmp9_execute_cdb_reply *reply) { unsigned char *cdb = (unsigned char *)request->cdb.cdb_val; struct robot_state rs; int min_addr, max_elts; char *response; int response_len; int required_len; int num_elts = IE_COUNT + MTE_COUNT + DTE_COUNT + STORAGE_COUNT; char *p; if (request->cdb.cdb_len != 12 || request->data_dir != NDMP9_SCSI_DATA_DIR_IN) return scsi_fail_with_sense_code(sess, reply, SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_KEY_ILLEGAL_REQUEST, ASQ_INVALID_FIELD_IN_CDB); min_addr = (cdb[2] << 8) + cdb[3]; max_elts = (cdb[4] << 8) + cdb[5]; response_len = (cdb[7] << 16) + (cdb[8] << 8) + cdb[9]; if (response_len < 8) { return scsi_fail_with_sense_code(sess, reply, SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_KEY_ILLEGAL_REQUEST, ASQ_INVALID_FIELD_IN_CDB); } /* this is bogus, but we don't allow "partial" status requests */ if (min_addr > IE_FIRST || max_elts < num_elts) { return scsi_fail_with_sense_code(sess, reply, SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_KEY_ILLEGAL_REQUEST, ASQ_INVALID_FIELD_IN_CDB); } robot_state_load(sess, &rs); robot_state_save(sess, &rs); /* calculate the total space required */ required_len = 8; /* element status data header */ if (MTE_COUNT) { required_len += 8; /* element status page header */ required_len += 12 * MTE_COUNT; /* element status descriptor w/o tags */ } if (STORAGE_COUNT) { required_len += 8; /* element status page header */ required_len += 84 * STORAGE_COUNT; /* element status descriptor w/ tags */ } if (IE_COUNT) { required_len += 8; /* element status page header */ required_len += 84 * IE_COUNT; /* element status descriptor w/ tags */ } if (DTE_COUNT) { required_len += 8; /* element status page header */ required_len += 84 * DTE_COUNT; /* element status descriptor w/ tags */ } p = response = NDMOS_API_MALLOC(response_len); NDMOS_API_BZERO(response, response_len); /* write the element status data header */ *(p++) = IE_FIRST >> 8; /* first element address */ *(p++) = IE_FIRST & 0xff; *(p++) = num_elts >> 8; /* number of elements */ *(p++) = num_elts & 0xff; *(p++) = 0; /* reserved */ *(p++) = (required_len-8) >> 16; /* remaining byte count of report */ *(p++) = ((required_len-8) >> 8) & 0xff; *(p++) = (required_len-8) & 0xff; /* only fill in the rest if we have space */ if (required_len <= response_len) { int i; struct { int first, count, have_voltags, eltype; int empty_flags, full_flags; struct element_state *es; } page[4] = { { IE_FIRST, IE_COUNT, 1, 3, 0x38, 0x39, &rs.ie[0] }, { MTE_FIRST, MTE_COUNT, 0, 1, 0x00, 0x01, &rs.mte[0] }, { DTE_FIRST, DTE_COUNT, 1, 4, 0x08, 0x81, &rs.dte[0] }, { STORAGE_FIRST, STORAGE_COUNT, 1, 2, 0x08, 0x09, &rs.storage[0] }, }; for (i = 0; i < 4; i++) { int descr_size = page[i].have_voltags? 84 : 12; int totalsize = descr_size * page[i].count; int j; if (page[i].count == 0) continue; /* write the page header */ *(p++) = page[i].eltype; *(p++) = page[i].have_voltags? 0xc0 : 0; *(p++) = 0; *(p++) = descr_size; *(p++) = 0; /* reserved */ *(p++) = totalsize >> 16; *(p++) = (totalsize >> 8) & 0xff; *(p++) = totalsize & 0xff; /* and write each descriptor */ for (j = 0; j < page[i].count; j++) { int elt_addr = page[i].first + j; int src_elt = page[i].es[j].source_element; unsigned char byte9 = page[i].es[j].medium_type; if (src_elt!= 0) byte9 |= 0x80; /* SVALID */ *(p++) = elt_addr >> 8; *(p++) = elt_addr & 0xff; *(p++) = page[i].es[j].full? page[i].full_flags : page[i].empty_flags; *(p++) = 0; *(p++) = 0; *(p++) = 0; *(p++) = 0; *(p++) = 0; *(p++) = 0; *(p++) = byte9; *(p++) = src_elt >> 8; *(p++) = src_elt & 0xff; if (page[i].have_voltags) { int k; if (page[i].es[j].full) { for (k = 0; k < 32; k++) { if (!page[i].es[j].pvoltag[k]) break; p[k] = page[i].es[j].pvoltag[k]; } for (k = 0; k < 32; k++) { if (!page[i].es[j].avoltag[k]) break; p[k+36] = page[i].es[j].avoltag[k]; } } else { for (k = 0; k < 32; k++) { p[k] = p[k+36] = ' '; } } p += 72; } } } }
static ndmp9_error execute_cdb_mode_sense_6 (struct ndm_session *sess, ndmp9_execute_cdb_request *request, ndmp9_execute_cdb_reply *reply) { unsigned char *cdb = (unsigned char *)request->cdb.cdb_val; int page, subpage; char *response; int response_len; char *p; if (request->cdb.cdb_len != 6 || request->data_dir != NDMP9_SCSI_DATA_DIR_IN) return scsi_fail_with_sense_code(sess, reply, SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_KEY_ILLEGAL_REQUEST, ASQ_INVALID_FIELD_IN_CDB); page = cdb[2] & 0x3f; subpage = cdb[3]; switch ((page << 8) + subpage) { case 0x1D00: /* Element Address Assignment */ if (request->datain_len < 20 || cdb[4] < 20) return scsi_fail_with_sense_code(sess, reply, SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_KEY_ILLEGAL_REQUEST, ASQ_INVALID_FIELD_IN_CDB); response_len = 24; p = response = NDMOS_API_MALLOC(response_len); NDMOS_API_BZERO(response, response_len); *(p++) = response_len; *(p++) = 0; /* reserved medium type */ *(p++) = 0; /* reserved device-specific parameter */ *(p++) = 0; /* block descriptor length (DBD = 0 above)*/ *(p++) = 0x1D; /* page code */ *(p++) = 18; /* remaining bytes */ *(p++) = (MTE_FIRST >> 8) & 0xff; *(p++) = MTE_FIRST & 0xff; *(p++) = (MTE_COUNT >> 8) & 0xff; *(p++) = MTE_COUNT & 0xff; *(p++) = (STORAGE_FIRST >> 8) & 0xff; *(p++) = STORAGE_FIRST & 0xff; *(p++) = (STORAGE_COUNT >> 8) & 0xff; *(p++) = STORAGE_COUNT & 0xff; *(p++) = (IE_FIRST >> 8) & 0xff; *(p++) = IE_FIRST & 0xff; *(p++) = (IE_COUNT >> 8) & 0xff; *(p++) = IE_COUNT & 0xff; *(p++) = (DTE_FIRST >> 8) & 0xff; *(p++) = DTE_FIRST & 0xff; *(p++) = (DTE_COUNT >> 8) & 0xff; *(p++) = DTE_COUNT & 0xff; /* remainder is zero */ break; default: return scsi_fail_with_sense_code(sess, reply, SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_KEY_ILLEGAL_REQUEST, ASQ_INVALID_FIELD_IN_CDB); } reply->datain.datain_len = response_len; reply->datain.datain_val = response; return NDMP9_NO_ERR; }
int ndmta_write_quantum (struct ndm_session *sess) { struct ndm_tape_agent * ta = sess->tape_acb; struct ndmchan * ch = &sess->plumb.image_stream->chan; uint32_t count = ta->mover_state.record_size; int did_something = 0; uint64_t max_read; uint64_t want_window_off; uint32_t block_size; uint32_t want_blockno; uint32_t cur_blockno; unsigned n_avail, n_read, record_off; char * data; uint32_t done_count = 0; ndmp9_error error; again: n_read = n_avail = ndmchan_n_avail_record (ch, count); if (n_avail < count) { /* allow to drain */ return did_something; } if (ta->pending_change_after_drain) { if (ndmchan_n_ready (ch) > 0) { /* allow to drain */ } else { ndmta_mover_apply_pending (sess); did_something++; } return did_something; } if (n_read > ta->mover_state.bytes_left_to_read) n_read = ta->mover_state.bytes_left_to_read; if (n_read < count) { /* Active, but paused awaiting MOVER_READ request */ return did_something; /* mover blocked */ } if (ta->mover_want_pos < ta->mover_state.window_offset || ta->mover_want_pos >= ta->mover_window_end) { ndmta_mover_pause_pending (sess, NDMP9_MOVER_PAUSE_SEEK); goto again; } max_read = ta->mover_window_end - ta->mover_want_pos; if (n_read > max_read) n_read = max_read; want_window_off = ta->mover_want_pos - ta->mover_state.window_offset; /* make an estimate of the block size - the tape agent's block size, or * if it's in variable block size mode, the mover's record size: "When * in variable block mode, as indicated by a tape block_size value of * zero, the mover record size defines the actual block size used by * the tape subsystem." (NDMPv4 RFC, Section 3.6.2.1) */ block_size = ta->tape_state.block_size.value; if (!block_size) block_size = ta->mover_state.record_size; want_blockno = ta->mover_window_first_blockno + want_window_off / block_size; if (ta->tb_blockno != want_blockno) { uint32_t xsr_count, xsr_resid; ndmos_tape_sync_state(sess); cur_blockno = ta->tape_state.blockno.value; if (cur_blockno < want_blockno) { xsr_count = want_blockno - cur_blockno; error = ndmos_tape_mtio (sess, NDMP9_MTIO_FSR, xsr_count, &xsr_resid); if (error == NDMP9_EOF_ERR) { ndmta_mover_pause_pending (sess, NDMP9_MOVER_PAUSE_EOF); goto again; } if (error != NDMP9_NO_ERR) { ndmta_mover_halt_pending (sess, NDMP9_MOVER_HALT_MEDIA_ERROR); goto again; } if (xsr_resid > 0) { ndmta_mover_pause_pending (sess, NDMP9_MOVER_PAUSE_EOF); goto again; } } else if (cur_blockno > want_blockno) { xsr_count = cur_blockno - want_blockno; error = ndmos_tape_mtio (sess, NDMP9_MTIO_BSR, xsr_count, &xsr_resid); if (error != NDMP9_NO_ERR || xsr_resid > 0) { ndmta_mover_halt_pending (sess, NDMP9_MOVER_HALT_MEDIA_ERROR); goto again; } } else { /* in position */ } /* * We are about to read data into a tape buffer so make sure * we have it available. We delay allocating buffers to the * moment we first need them. */ if (!ta->tape_buffer) { ta->tape_buffer = NDMOS_API_MALLOC (NDMOS_CONST_TAPE_REC_MAX); if (!ta->tape_buffer) { ndmta_mover_pause_pending (sess, NDMP9_MOVER_HALT_NA); goto again; } } data = ta->tape_buffer; done_count = 0; error = ndmos_tape_read (sess, data, count, &done_count); did_something++; if (error == NDMP9_EOF_ERR) { ndmta_mover_pause_pending (sess, NDMP9_MOVER_PAUSE_EOF); goto again; } /* N.B. - handling of done_count = 0 here is hacked to support * non-blocking writes to a socket in amndmjob */ if (error != NDMP9_NO_ERR) { ndmta_mover_halt_pending (sess, NDMP9_MOVER_HALT_MEDIA_ERROR); goto again; } if (done_count == 0) { return did_something - 1; } if (done_count != count) { goto again; } ta->tb_blockno = want_blockno; /* re-calcluate this, since record_size may be > block_size, in which * case the record_num may not change for each block read from tape */ ta->mover_state.record_num = ta->mover_want_pos / ta->mover_state.record_size; } record_off = ta->mover_want_pos % ta->mover_state.record_size; n_avail = ta->mover_state.record_size - record_off; if (n_read > n_avail) n_read = n_avail; if (n_read != done_count) { printf("lost %lu bytes %lu %u\n", done_count - n_read, done_count, n_read); n_read = done_count; } /* * We are about to read data into a tape buffer so make sure * we have it available. We delay allocating buffers to the * moment we first need them. */ if (!ta->tape_buffer) { ta->tape_buffer = NDMOS_API_MALLOC (NDMOS_CONST_TAPE_REC_MAX); if (!ta->tape_buffer) { ndmta_mover_pause_pending (sess, NDMP9_MOVER_HALT_NA); goto again; } } data = &ta->tape_buffer[record_off]; bcopy (data, ch->data + ch->end_ix, n_read); ch->end_ix += n_read; ta->mover_state.bytes_moved += n_read; ta->mover_want_pos += n_read; ta->mover_state.bytes_left_to_read -= n_read; did_something++; goto again; /* do as much as possible */ }
/* * Add a new entry to a nlist list table. * Return entry if caller want to modify it. */ struct ndm_nlist_entry * ndma_store_nlist (struct ndm_nlist_table *nlist, ndmp9_name *nl) { struct ndm_nlist_entry * entry; if (nlist->n_nlist >= NDM_MAX_NLIST) return NULL; entry = NDMOS_API_MALLOC (sizeof(struct ndm_nlist_entry)); if (!entry) return NULL; NDMOS_MACRO_ZEROFILL (entry); entry->name.original_path = NDMOS_API_STRDUP (nl->original_path); if (!entry->name.original_path) goto bail_out; entry->name.destination_path = NDMOS_API_STRDUP (nl->destination_path); if (!entry->name.destination_path) goto bail_out; entry->name.name = NDMOS_API_STRDUP (nl->name); if (!entry->name.name) goto bail_out; entry->name.other_name = NDMOS_API_STRDUP (nl->other_name); if (!entry->name.other_name) goto bail_out; entry->name.node = nl->node; entry->name.fh_info = nl->fh_info; entry->result_err = NDMP9_UNDEFINED_ERR; entry->result_count = 0; entry->next = NULL; if (nlist->tail) { nlist->tail->next = entry; nlist->tail = entry; } else { nlist->head = entry; nlist->tail = entry; } nlist->n_nlist++; return entry; bail_out: if (entry->name.other_name) NDMOS_API_FREE (entry->name.other_name); if (entry->name.name) NDMOS_API_FREE (entry->name.name); if (entry->name.destination_path) NDMOS_API_FREE (entry->name.destination_path); if (entry->name.original_path) NDMOS_API_FREE (entry->name.original_path); NDMOS_API_FREE (entry); return NULL; }