Пример #1
0
/* Note that the offset is just the caller letting us know where
 * the current file position is in the file. The use_seek arg tells
 * us that we should seek over matching data instead of writing it. */
static int write_sparse(int f, int use_seek, OFF_T offset, const char *buf, int len)
{
	int l1 = 0, l2 = 0;
	int ret;

	for (l1 = 0; l1 < len && buf[l1] == 0; l1++) {}
	for (l2 = 0; l2 < len-l1 && buf[len-(l2+1)] == 0; l2++) {}

	sparse_seek += l1;

	if (l1 == len)
		return len;

	if (sparse_seek) {
		if (sparse_past_write >= preallocated_len) {
			if (do_lseek(f, sparse_seek, SEEK_CUR) < 0)
				return -1;
		} else if (do_punch_hole(f, sparse_past_write, sparse_seek) < 0) {
			sparse_seek = 0;
			return -1;
		}
	}
	sparse_seek = l2;
	sparse_past_write = offset + len - l2;

	if (use_seek) {
		/* The in-place data already matches. */
		if (do_lseek(f, len - (l1+l2), SEEK_CUR) < 0)
			return -1;
		return len;
	}

	while ((ret = write(f, buf + l1, len - (l1+l2))) <= 0) {
		if (ret < 0 && errno == EINTR)
			continue;
		sparse_seek = 0;
		return ret;
	}

	if (ret != (int)(len - (l1+l2))) {
		sparse_seek = 0;
		return l1+ret;
	}

	return len;
}
Пример #2
0
void
test(void)
{
	unsigned long	offset;
	unsigned long	size = maxoplen;
	unsigned long	rv = random();
	unsigned long	op;

	if (simulatedopcount > 0 && testcalls == simulatedopcount)
		writefileimage();

	testcalls++;

	if (closeprob)
		closeopen = (rv >> 3) < (1u << 28) / (unsigned)closeprob;

	if (debugstart > 0 && testcalls >= debugstart)
		debug = 1;

	if (!quiet && testcalls < simulatedopcount && testcalls % 100000 == 0)
		prt("%lu...\n", testcalls);

	offset = random();
	if (randomoplen)
		size = random() % (maxoplen + 1);

	/* calculate appropriate op to run */
	if (lite)
		op = rv % OP_MAX_LITE;
	else
		op = rv % OP_MAX_FULL;

	switch (op) {
	case OP_MAPREAD:
		if (!mapped_reads)
			op = OP_READ;
		break;
	case OP_MAPWRITE:
		if (!mapped_writes)
			op = OP_WRITE;
		break;
	case OP_FALLOCATE:
		if (!fallocate_calls) {
			log4(OP_SKIPPED, OP_FALLOCATE, offset, size);
			goto out;
		}
		break;
	case OP_PUNCH_HOLE:
		if (!punch_hole_calls) {
			log4(OP_SKIPPED, OP_PUNCH_HOLE, offset, size);
			goto out;
		}
		break;
	}

	switch (op) {
	case OP_READ:
		TRIM_OFF_LEN(offset, size, file_size);
		doread(offset, size);
		break;

	case OP_WRITE:
		TRIM_OFF_LEN(offset, size, maxfilelen);
		dowrite(offset, size);
		break;

	case OP_MAPREAD:
		TRIM_OFF_LEN(offset, size, file_size);
		exit(183);
		break;

	case OP_MAPWRITE:
		TRIM_OFF_LEN(offset, size, maxfilelen);
		exit(182);
		break;

	case OP_TRUNCATE:
		if (!style)
			size = random() % maxfilelen;
		dotruncate(size);
		break;

	case OP_PUNCH_HOLE:
		TRIM_OFF_LEN(offset, size, file_size);
		do_punch_hole(offset, size);
		break;
	default:
		prterr("test: unknown operation");
		report_failure(42);
		break;
	}

out:
	if (sizechecks && testcalls > simulatedopcount)
		check_size();
	if (closeopen)
		docloseopen();
}