gboolean ndmp_connection_mover_listen( NDMPConnection *self, ndmp9_mover_mode mode, ndmp9_addr_type addr_type, DirectTCPAddr **addrs) { unsigned int naddrs, i; *addrs = NULL; g_assert(!self->startup_err); NDMP_TRANS(self, ndmp4_mover_listen) request->mode = mode; request->addr_type = addr_type; NDMP_CALL(self); if (request->addr_type != reply->connect_addr.addr_type) { g_warning("MOVER_LISTEN addr_type mismatch; got %d", reply->connect_addr.addr_type); } if (reply->connect_addr.addr_type == NDMP4_ADDR_TCP) { naddrs = reply->connect_addr.ndmp4_addr_u.tcp_addr.tcp_addr_len; *addrs = g_new0(DirectTCPAddr, naddrs+1); for (i = 0; i < naddrs; i++) { ndmp4_tcp_addr *na = &reply->connect_addr.ndmp4_addr_u.tcp_addr.tcp_addr_val[i]; (*addrs)[i].sin.sin_family = AF_INET; (*addrs)[i].sin.sin_addr.s_addr = htonl(na->ip_addr); SU_SET_PORT(&((*addrs)[i]), na->port); } } NDMP_FREE(); NDMP_END return TRUE; }
gboolean ndmp_connection_mover_connect( NDMPConnection *self, ndmp9_mover_mode mode, DirectTCPAddr *addrs) { unsigned int naddrs, i; ndmp4_tcp_addr *na; g_assert(!self->startup_err); /* count addrs */ g_assert(addrs); for (naddrs = 0; SU_GET_FAMILY(&addrs[naddrs]) != 0; naddrs++) ; /* convert addrs to an ndmp4_tcp_addr */ na = g_new0(ndmp4_tcp_addr, naddrs); for (i = 0; i < naddrs; i++) { na[i].ip_addr = ntohl(addrs[i].sin.sin_addr.s_addr); na[i].port = SU_GET_PORT(&addrs[i]); } NDMP_TRANS(self, ndmp4_mover_connect) request->mode = mode; request->addr.addr_type = NDMP4_ADDR_TCP; request->addr.ndmp4_addr_u.tcp_addr.tcp_addr_len = naddrs; request->addr.ndmp4_addr_u.tcp_addr.tcp_addr_val = na; NDMP_CALL(self); NDMP_FREE(); NDMP_END return TRUE; }
gboolean ndmp_connection_tape_get_state( NDMPConnection *self, guint64 *blocksize, guint64 *file_num, guint64 *blockno) { g_assert(!self->startup_err); NDMP_TRANS_NO_REQUEST(self, ndmp4_tape_get_state) NDMP_CALL(self); if (reply->unsupported & NDMP4_TAPE_STATE_BLOCK_SIZE_UNS) *blocksize = 0; else *blocksize = reply->block_size; if (reply->unsupported & NDMP4_TAPE_STATE_FILE_NUM_UNS) *file_num = G_MAXUINT64; else *file_num = reply->file_num; if (reply->unsupported & NDMP4_TAPE_STATE_BLOCKNO_UNS) *blockno = G_MAXUINT64; else *blockno = reply->blockno; NDMP_FREE(); NDMP_END return TRUE; }
gboolean ndmp_connection_mover_close( NDMPConnection *self) { g_assert(!self->startup_err); NDMP_TRANS_NO_REQUEST(self, ndmp4_mover_close) NDMP_CALL(self); NDMP_FREE(); NDMP_END return TRUE; }
gboolean ndmp_connection_scsi_open( NDMPConnection *self, gchar *device) { g_assert(!self->startup_err); NDMP_TRANS(self, ndmp4_scsi_open) request->device = device; NDMP_CALL(self); NDMP_FREE(); NDMP_END return TRUE; }
gboolean ndmp_connection_mover_set_record_size( NDMPConnection *self, guint32 record_size) { g_assert(!self->startup_err); NDMP_TRANS(self, ndmp4_mover_set_record_size) /* this field is "len" in ndmp4, but "record_size" in ndmp9 */ request->len = record_size; NDMP_CALL(self); NDMP_FREE(); NDMP_END return TRUE; }
gboolean ndmp_connection_mover_read( NDMPConnection *self, guint64 offset, guint64 length) { g_assert(!self->startup_err); NDMP_TRANS(self, ndmp4_mover_read) request->offset = offset; request->length = length; NDMP_CALL(self); NDMP_FREE(); NDMP_END return TRUE; }
gboolean ndmp_connection_tape_open( NDMPConnection *self, gchar *device, ndmp9_tape_open_mode mode) { g_assert(!self->startup_err); NDMP_TRANS(self, ndmp4_tape_open) request->device = device; request->mode = mode; NDMP_CALL(self); NDMP_FREE(); NDMP_END return TRUE; }
gboolean ndmp_connection_tape_mtio( NDMPConnection *self, ndmp9_tape_mtio_op tape_op, gint count, guint *resid_count) { g_assert(!self->startup_err); NDMP_TRANS(self, ndmp4_tape_mtio) request->tape_op = tape_op; request->count = count; NDMP_CALL(self); *resid_count = reply->resid_count; NDMP_FREE(); NDMP_END return TRUE; }
gboolean ndmp_connection_mover_get_state( NDMPConnection *self, ndmp9_mover_state *state, guint64 *bytes_moved, guint64 *window_offset, guint64 *window_length) { g_assert(!self->startup_err); NDMP_TRANS_NO_REQUEST(self, ndmp4_mover_get_state) NDMP_CALL(self); if (state) *state = reply->state; if (bytes_moved) *bytes_moved = reply->bytes_moved; if (window_offset) *window_offset = reply->window_offset; if (window_length) *window_length = reply->window_length; NDMP_FREE(); NDMP_END return TRUE; }
gboolean ndmp_connection_tape_read( NDMPConnection *self, gpointer buf, guint64 count, guint64 *out_count) { g_assert(!self->startup_err); *out_count = 0; NDMP_TRANS(self, ndmp4_tape_read) request->count = count; NDMP_CALL(self); *out_count = reply->data_in.data_in_len; g_memmove(buf, reply->data_in.data_in_val, *out_count); NDMP_FREE(); NDMP_END return TRUE; }
gboolean ndmp_connection_tape_write( NDMPConnection *self, gpointer buf, guint64 len, guint64 *count) { g_assert(!self->startup_err); *count = 0; NDMP_TRANS(self, ndmp4_tape_write) request->data_out.data_out_val = buf; request->data_out.data_out_len = len; NDMP_CALL(self); *count = reply->count; NDMP_FREE(); NDMP_END return TRUE; }
int ndmpd_tar_restore_starter(void *arg) { ndmpd_module_params_t *mod_params = arg; int err; ndmpd_session_t *session; ndmp_lbr_params_t *nlp; session = (ndmpd_session_t *)(mod_params->mp_daemon_cookie); *(mod_params->mp_module_cookie) = nlp = ndmp_get_nlp(session); ndmp_session_ref(session); err = ndmpd_tar_restore(session, mod_params, nlp); MOD_DONE(mod_params, err); /* nlp_params is allocated in start_recover() */ NDMP_FREE(nlp->nlp_params); NS_DEC(nrs); ndmp_session_unref(session); return (err); }
/* * ndmpd_tar_backup_starter (V2 only) * * The main backup starter function. It creates a snapshot if necessary * and calls ndmp_tar_backup to perform the actual backup. It does the cleanup * and release the snapshot at the end. */ int ndmpd_tar_backup_starter(void *arg) { ndmpd_module_params_t *mod_params = arg; int err; ndmpd_session_t *session; ndmp_lbr_params_t *nlp; session = (ndmpd_session_t *)(mod_params->mp_daemon_cookie); *(mod_params->mp_module_cookie) = nlp = ndmp_get_nlp(session); ndmp_session_ref(session); err = 0; if (fs_is_chkpntvol(nlp->nlp_backup_path) || fs_is_rdonly(nlp->nlp_backup_path) || !fs_is_chkpnt_enabled(nlp->nlp_backup_path)) NLP_SET(nlp, NLPF_CHKPNTED_PATH); else { NLP_UNSET(nlp, NLPF_CHKPNTED_PATH); if (ndmp_create_snapshot(nlp->nlp_backup_path, nlp->nlp_jstat->js_job_name) < 0) { MOD_LOG(mod_params, "Error: creating checkpoint on %s\n", nlp->nlp_backup_path); /* -1 causes halt reason to become internal error. */ err = -1; } } NDMP_LOG(LOG_DEBUG, "NLPF_CHKPNTED_PATH: %c", NDMP_YORN(NLP_ISCHKPNTED(nlp))); NDMP_LOG(LOG_DEBUG, "err: %d, update %c", err, NDMP_YORN(NLP_SHOULD_UPDATE(nlp))); if (err == 0) { err = ndmp_get_cur_bk_time(nlp, &nlp->nlp_cdate, nlp->nlp_jstat->js_job_name); if (err != 0) { NDMP_LOG(LOG_DEBUG, "err %d", err); } else { log_bk_params_v2(session, mod_params, nlp); err = ndmpd_tar_backup(session, mod_params, nlp); } } if (nlp->nlp_bkmap >= 0) { (void) dbm_free(nlp->nlp_bkmap); nlp->nlp_bkmap = -1; } if (!NLP_ISCHKPNTED(nlp)) (void) ndmp_remove_snapshot(nlp->nlp_backup_path, nlp->nlp_jstat->js_job_name); NDMP_LOG(LOG_DEBUG, "err %d, update %c", err, NDMP_YORN(NLP_SHOULD_UPDATE(nlp))); if (err == 0 && NLP_SHOULD_UPDATE(nlp)) { if (ndmpd_put_dumptime(nlp->nlp_backup_path, nlp->nlp_clevel, nlp->nlp_cdate) < 0) { err = EPERM; MOD_LOG(mod_params, "Error: updating the dumpdates file on %s\n", nlp->nlp_backup_path); } } MOD_DONE(mod_params, err); /* nlp_params is allocated in start_backup() */ NDMP_FREE(nlp->nlp_params); NS_DEC(nbk); ndmp_session_unref(session); return (err); }
/* * ndmpd_tar_restore * * Restore function that launches TAR reader thread to read from the * tape and writes the extracted files/dirs to the filesystem */ static int ndmpd_tar_restore(ndmpd_session_t *session, ndmpd_module_params_t *mod_params, ndmp_lbr_params_t *nlp) { char jname[TLM_MAX_BACKUP_JOB_NAME]; char *rspath; int err; tlm_commands_t *cmds; ndmp_tar_reader_arg_t arg; tlm_backup_restore_arg_t tlm_arg; ndmp_name *ent; pthread_t rdtp, wrtp; int i; if (mod_params->mp_operation != NDMP_DATA_OP_RECOVER) { NDMP_LOG(LOG_DEBUG, "mod_params->mp_operation != NDMP_DATA_OP_RECOVER"); return (-1); } if (nlp->nlp_restore_path[0] != '\0') rspath = nlp->nlp_restore_path; else if (nlp->nlp_restore_bk_path[0] != '\0') rspath = nlp->nlp_restore_bk_path; else rspath = ""; (void) ndmp_new_job_name(jname); if (restore_create_structs(session, jname) < 0) return (-1); nlp->nlp_jstat->js_start_ltime = time(NULL); nlp->nlp_jstat->js_start_time = time(NULL); if (!session->ns_data.dd_abort) { cmds = &nlp->nlp_cmds; cmds->tcs_reader = cmds->tcs_writer = TLM_RESTORE_RUN; cmds->tcs_command->tc_reader = TLM_RESTORE_RUN; cmds->tcs_command->tc_writer = TLM_RESTORE_RUN; NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" started.", rspath); NDMP_LOG(LOG_DEBUG, "Restoring from %s tape(s).", ndmp_data_get_mover_mode(session)); arg.tr_session = session; arg.tr_mod_params = mod_params; arg.tr_cmds = cmds; err = pthread_create(&rdtp, NULL, (funct_t)ndmp_tar_reader, (void *)&arg); if (err == 0) { tlm_cmd_wait(cmds->tcs_command, TLM_TAR_READER); } else { NDMP_LOG(LOG_DEBUG, "Launch ndmp_tar_reader: %m"); return (-1); } if (!ndmp_check_utf8magic(cmds->tcs_command)) { NDMP_LOG(LOG_DEBUG, "UTF8Magic not found!"); } else { NDMP_LOG(LOG_DEBUG, "UTF8Magic found"); } (void) memset(&tlm_arg, 0, sizeof (tlm_backup_restore_arg_t)); (void) pthread_barrier_init(&tlm_arg.ba_barrier, 0, 2); /* * Set up restore parameters */ tlm_arg.ba_commands = cmds; tlm_arg.ba_cmd = cmds->tcs_command; tlm_arg.ba_job = nlp->nlp_jstat->js_job_name; tlm_arg.ba_dir = nlp->nlp_restore_path; for (i = 0; i < nlp->nlp_nfiles; i++) { ent = (ndmp_name *)MOD_GETNAME(mod_params, i); tlm_arg.ba_sels[i] = ent->name; } if (tm_tar_ops.tm_getfile != NULL) { err = pthread_create(&wrtp, NULL, (funct_t)tm_tar_ops.tm_getfile, (void *)&tlm_arg); } else { (void) pthread_barrier_destroy(&tlm_arg.ba_barrier); NDMP_LOG(LOG_DEBUG, "Thread create tm_getfile: ops NULL"); return (-1); } if (err == 0) { (void) pthread_barrier_wait(&tlm_arg.ba_barrier); } else { (void) pthread_barrier_destroy(&tlm_arg.ba_barrier); NDMP_LOG(LOG_DEBUG, "thread create tm_getfile: %m"); return (-1); } (void) pthread_join(rdtp, NULL); (void) pthread_join(wrtp, NULL); (void) pthread_barrier_destroy(&tlm_arg.ba_barrier); nlp->nlp_jstat->js_stop_time = time(NULL); /* Send the list of un-recovered files/dirs to the client. */ (void) send_unrecovered_list(mod_params, nlp); ndmp_stop_local_reader(session, cmds); ndmp_wait_for_reader(cmds); ndmp_stop_remote_reader(session); NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" finished. (%d)", rspath, err); } else { nlp->nlp_jstat->js_stop_time = time(NULL); /* nothing restored. */ (void) send_unrecovered_list(mod_params, nlp); NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" aborted.", rspath); err = -1; } NDMP_FREE(nlp->nlp_restore_path); backup_release_structs(session); return (err); }
gboolean ndmp_connection_scsi_execute_cdb( NDMPConnection *self, guint32 flags, /* NDMP4_SCSI_DATA_{IN,OUT}; OUT = to device */ guint32 timeout, /* in ms */ gpointer cdb, gsize cdb_len, gpointer dataout, gsize dataout_len, gsize *actual_dataout_len, /* output */ gpointer datain, /* output */ gsize datain_max_len, /* output buffer size */ gsize *actual_datain_len, /* output */ guint8 *status, /* output */ gpointer ext_sense, /* output */ gsize ext_sense_max_len, /* output buffer size */ gsize *actual_ext_sense_len /* output */ ) { g_assert(!self->startup_err); if (status) *status = 0; if (actual_dataout_len) *actual_dataout_len = 0; if (actual_datain_len) *actual_datain_len = 0; if (actual_ext_sense_len) *actual_ext_sense_len = 0; NDMP_TRANS(self, ndmp4_scsi_execute_cdb) request->flags = flags; request->timeout = timeout; request->datain_len = datain_max_len; request->cdb.cdb_len = cdb_len; request->cdb.cdb_val = cdb; request->dataout.dataout_len = dataout_len; request->dataout.dataout_val = dataout; NDMP_CALL(self); if (status) *status = reply->status; if (actual_dataout_len) *actual_dataout_len = reply->dataout_len; reply->datain.datain_len = MIN(datain_max_len, reply->datain.datain_len); if (actual_datain_len) *actual_datain_len = reply->datain.datain_len; if (datain_max_len && datain) g_memmove(datain, reply->datain.datain_val, reply->datain.datain_len); reply->ext_sense.ext_sense_len = MIN(ext_sense_max_len, reply->ext_sense.ext_sense_len); if (actual_ext_sense_len) *actual_ext_sense_len = reply->ext_sense.ext_sense_len; if (ext_sense_max_len && ext_sense) g_memmove(ext_sense, reply->ext_sense.ext_sense_val, reply->ext_sense.ext_sense_len); NDMP_FREE(); NDMP_END return TRUE; }