コード例 #1
0
/*
 * write_tar_eof
 *
 * This function is initially written for NDMP support.  It appends
 * two tar headers to the tar file, and also N more empty buffers
 * to make sure that the two tar headers will be read as a part of
 * a mover record and don't get locked because of EOM on the mover
 * side.
 */
void
write_tar_eof(tlm_cmd_t *local_commands)
{
	int i;
	long actual_size;
	tlm_buffers_t *bufs;

	/*
	 * output 2 zero filled records,
	 * TAR wants this.
	 */
	(void) get_write_buffer(sizeof (tlm_tar_hdr_t),
	    &actual_size, TRUE, local_commands);
	(void) get_write_buffer(sizeof (tlm_tar_hdr_t),
	    &actual_size, TRUE, local_commands);

	/*
	 * NDMP: Clear the rest of the buffer and write two more buffers
	 * to the tape.
	 */
	bufs = local_commands->tc_buffers;
	(void) get_write_buffer(bufs->tbs_data_transfer_size,
	    &actual_size, TRUE, local_commands);

	for (i = 0; i < NDMP_MORE_RECORDS &&
	    local_commands->tc_reader == TLM_BACKUP_RUN; i++) {
		/*
		 * We don't need the return value of get_write_buffer(),
		 * since it's already zeroed out if the buffer is returned.
		 */
		(void) get_write_buffer(bufs->tbs_data_transfer_size,
		    &actual_size, TRUE, local_commands);
	}

	bufs->tbs_buffer[bufs->tbs_buffer_in].tb_full = TRUE;
	tlm_buffer_release_in_buf(bufs);
}
コード例 #2
0
/*
 * ndmp_tar_reader
 *
 * NDMP Tar reader thread. This threads keep reading the tar
 * file from the tape and wakes up the consumer thread to extract
 * it on the disk
 */
int
ndmp_tar_reader(ndmp_tar_reader_arg_t *argp)
{
	int bidx;
	int err;
	tlm_buffer_t *buf;
	tlm_buffers_t *bufs;
	tlm_cmd_t *lcmd;	/* Local command */
	ndmpd_session_t *session;
	ndmpd_module_params_t *mod_params;
	tlm_commands_t *cmds;

	if (!argp)
		return (-1);

	session = argp->tr_session;
	mod_params = argp->tr_mod_params;
	cmds = argp->tr_cmds;

	err = 0;
	if (session == NULL) {
		NDMP_LOG(LOG_DEBUG, "session == NULL");
		err = -1;
	} else if (cmds == NULL) {
		NDMP_LOG(LOG_DEBUG, "cmds == NULL");
		err = -1;
	}

	if (err != 0) {
		tlm_cmd_signal(cmds->tcs_command, TLM_TAR_READER);
		return (err);
	}

	lcmd = cmds->tcs_command;
	bufs = lcmd->tc_buffers;

	lcmd->tc_ref++;
	cmds->tcs_reader_count++;

	/*
	 * Synchronize with our parent thread.
	 */
	tlm_cmd_signal(cmds->tcs_command, TLM_TAR_READER);

	buf = tlm_buffer_in_buf(bufs, &bidx);
	while (cmds->tcs_reader == TLM_RESTORE_RUN &&
	    lcmd->tc_reader == TLM_RESTORE_RUN) {

		if (buf->tb_full) {
			NDMP_LOG(LOG_DEBUG, "R%d", bidx);
			/*
			 * The buffer is still full, wait for the consumer
			 * thread to use it.
			 */
			tlm_buffer_out_buf_timed_wait(bufs, 100);
			buf = tlm_buffer_in_buf(bufs, NULL);
		} else {
			NDMP_LOG(LOG_DEBUG, "r%d", bidx);

			err = read_one_buf(mod_params, bufs, buf);
			if (err < 0) {
				NDMP_LOG(LOG_DEBUG,
				    "Reading buffer %d, pos: %lld",
				    bidx, session->ns_mover.md_position);

				/* Force the writer to stop. */
				buf->tb_eot = buf->tb_eof = TRUE;
				break;
			} else if (err == 1) {
				NDMP_LOG(LOG_DEBUG,
				    "operation aborted or session terminated");
				err = 0;
				break;
			}

			buf = tlm_buffer_in_buf(bufs, &bidx);
			tlm_buffer_release_in_buf(bufs);
		}
	}

	/*
	 * If the consumer is waiting for us, wake it up so that it detects
	 * we're quiting.
	 */
	lcmd->tc_writer = TLM_STOP;
	tlm_buffer_release_in_buf(bufs);
	(void) usleep(1000);

	/*
	 * Clean up.
	 */
	cmds->tcs_reader_count--;
	lcmd->tc_ref--;
	return (err);
}
コード例 #3
0
ファイル: tlm_lib.c プロジェクト: mikess/illumos-gate
/*ARGSUSED*/
char *
tlm_get_write_buffer(long want, long *actual_size,
                     tlm_buffers_t *buffers, int zero)
{
    int	buf = buffers->tbs_buffer_in;
    tlm_buffer_t *buffer = &buffers->tbs_buffer[buf];
    int	align_size = RECORDSIZE - 1;
    char	*rec;

    /*
     * make sure the allocation is in chunks of 512 bytes
     */
    want += align_size;
    want &= ~align_size;

    *actual_size = buffer->tb_buffer_size - buffer->tb_buffer_spot;
    if (*actual_size <= 0) {
        /*
         * no room, send this one
         * and wait for a free one
         */
        if (!buffer->tb_full) {
            /*
             * we are now ready to send a full buffer
             * instead of trying to get a new buffer
             *
             * do not send if we failed to get a buffer
             * on the previous call
             */
            buffer->tb_full = TRUE;

            /*
             * tell the writer that a buffer is available
             */
            tlm_buffer_release_in_buf(buffers);

            buffer = tlm_buffer_advance_in_idx(buffers);
        }

        buffer = tlm_buffer_in_buf(buffers, NULL);

        if (buffer->tb_full) {
            /*
             * wait for the writer to free up a buffer
             */
            tlm_buffer_out_buf_timed_wait(buffers, 500);
        }

        buffer = tlm_buffer_in_buf(buffers, NULL);
        if (buffer->tb_full) {
            /*
             * the next buffer is still full
             * of data from previous activity
             *
             * nothing has changed.
             */
            return (0);
        }

        buffer->tb_buffer_spot = 0;
        *actual_size = buffer->tb_buffer_size - buffer->tb_buffer_spot;
    }

    *actual_size = min(want, *actual_size);
    rec = &buffer->tb_buffer_data[buffer->tb_buffer_spot];
    buffer->tb_buffer_spot += *actual_size;
    buffers->tbs_offset += *actual_size;
    if (zero) {
        (void) memset(rec, 0, *actual_size);
    }
    return (rec);
}