Пример #1
0
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 */
}
Пример #2
0
int
ndmta_write_quantum (struct ndm_session *sess)
{
	struct ndm_tape_agent *	ta = &sess->tape_acb;
	struct ndmchan *	ch = &sess->plumb.image_stream.chan;
	unsigned long		count = ta->mover_state.record_size;
	int			did_something = 0;
	unsigned long long	max_read;
	unsigned long long	want_window_off;
	unsigned long		want_blockno;
	unsigned long		cur_blockno;
	unsigned		n_avail, n_read, record_off;
	char *			data;
	unsigned long		done_count;
	ndmp9_error		error;

  again:
	n_read = n_avail = ndmchan_n_avail (ch);
	if (n_avail == 0) {
		/* 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 == 0) {
		/* 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;

	want_blockno = want_window_off / ta->mover_state.record_size;

	if (ta->tb_blockno != want_blockno) {
		unsigned long	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_pause_pending (sess,
						NDMP9_MOVER_PAUSE_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_pause_pending (sess,
						NDMP9_MOVER_PAUSE_MEDIA_ERROR);
				goto again;
			}
		} else {
			/* in position */
		}

		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;
		}
		if (error != NDMP9_NO_ERR) {
			ndmta_mover_pause_pending (sess,
				NDMP9_MOVER_PAUSE_MEDIA_ERROR);
			goto again;
		}
		if (done_count == 0) {
			return did_something - 1;
		}
		if (done_count != count) {
			n_read = done_count;
			goto aaa;
			ndmta_mover_pause_pending (sess,
				NDMP9_MOVER_PAUSE_MEDIA_ERROR);
			goto again;
		}
		ta->tb_blockno = want_blockno;
	}

aaa:
	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;

	data = &ta->tape_buffer[record_off];

	bcopy (data, ch->data + ch->end_ix, n_read);
	ch->end_ix += 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 */
}
Пример #3
0
int
ndmta_write_quantum (struct ndm_session *sess)
{
    struct ndm_tape_agent *	ta = &sess->tape_acb;
    struct ndmchan *	ch = &sess->plumb.image_stream.chan;
    unsigned long		count = ta->mover_state.record_size;
    int			did_something = 0;
    unsigned long long	max_read;
    unsigned long long	want_window_off;
    unsigned long		block_size;
    unsigned long		want_blockno;
    unsigned long		cur_blockno;
    unsigned		n_avail, n_read, record_off;
    char *			data;
    unsigned long		done_count;
    ndmp9_error		error;

again:
    n_read = n_avail = ndmchan_n_avail (ch);
    if (n_avail == 0) {
        /* 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 == 0) {
        /* 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) {
        unsigned long	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 */
        }

        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;
        }
        if (error != NDMP9_NO_ERR || done_count != count) {
            ndmta_mover_halt_pending (sess,
                                      NDMP9_MOVER_HALT_MEDIA_ERROR);
            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;

    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 */
}