void
test_writesame10_unmap_until_end(void)
{
	int ret;
	unsigned int i;

	CHECK_FOR_DATALOSS;
	CHECK_FOR_THIN_PROVISIONING;
	CHECK_FOR_LBPWS10;
	CHECK_FOR_SBC;

	if (inq_bl->wsnz) {
	    logging(LOG_NORMAL, "[SKIPPED] WRITESAME10 does not support 0-blocks.");
	    CU_PASS("[SKIPPED] WRITESAME10 does not support 0-blocks.");
	    return;
	}

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test WRITESAME10 of 1-256 blocks at the end of the LUN by setting number-of-blocks==0");
	for (i = 1; i <= 256; i++) {
		unsigned char *buf = malloc(block_size * i);

		logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i);
		memset(buf, 0xff, block_size * i);
		ret = write10(sd, num_blocks - i,
			      i * block_size, block_size, 0, 0, 0, 0, 0, buf,
			      EXPECT_STATUS_GOOD);
		CU_ASSERT_EQUAL(ret, 0);

		logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME10", i);
		ret = writesame10(sd, num_blocks - i,
				  block_size, 0, 0, 1, 0, 0, buf,
				  EXPECT_STATUS_GOOD);
		CU_ASSERT_EQUAL(ret, 0);

		if (rc16->lbprz) {
			logging(LOG_VERBOSE, "LBPRZ is set. Read the unmapped "
				"blocks back and verify they are all zero");

			logging(LOG_VERBOSE, "Read %d blocks and verify they "
				"are now zero", i);
			ret = read10(sd, NULL, num_blocks - i,
				     i * block_size, block_size,
				     0, 0, 0, 0, 0, buf,
				     EXPECT_STATUS_GOOD);
			CU_ASSERT(all_zeroes(buf, i * block_size));
		} else {
			logging(LOG_VERBOSE, "LBPRZ is clear. Skip the read "
				"and verify zero test");
		}
		free(buf);
	}
}
Beispiel #2
0
static Indirect *find_shared(struct inode *inode,
				int depth,
				int offsets[DEPTH],
				Indirect chain[DEPTH],
				block_t *top)
{
	Indirect *partial, *p;
	int k, err;

	*top = 0;
	for (k = depth; k > 1 && !offsets[k-1]; k--)
		;
	partial = get_branch(inode, k, offsets, chain, &err);

	write_lock(&pointers_lock);
	if (!partial)
		partial = chain + k-1;
	if (!partial->key && *partial->p) {
		write_unlock(&pointers_lock);
		goto no_top;
	}
	for (p=partial;p>chain && all_zeroes((block_t*)p->bh->b_data,p->p);p--)
		;
	if (p == chain + k - 1 && p > chain) {
		p->p--;
	} else {
		*top = *p->p;
		*p->p = 0;
	}
	write_unlock(&pointers_lock);

	while(partial > p)
	{
		brelse(partial->bh);
		partial--;
	}
no_top:
	return partial;
}
void
test_writesame16_unmap(void)
{
	int ret;
	unsigned int i;
	unsigned char *buf;

	CHECK_FOR_DATALOSS;
	CHECK_FOR_THIN_PROVISIONING;
	CHECK_FOR_LBPWS;
	CHECK_FOR_SBC;

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test WRITESAME16 of 1-256 blocks at the start of the LUN");
	buf = calloc(65536, block_size);
	for (i = 1; i <= 256; i++) {
		logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i);
		memset(buf, 0xff, i * block_size);
		ret = write16(sd, 0,
			      i * block_size, block_size, 0, 0, 0, 0, 0, buf,
			      EXPECT_STATUS_GOOD);
		logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME16", i);
		memset(buf, 0, block_size);
		ret = writesame16(sd, 0,
				  block_size, i, 0, 1, 0, 0, buf,
				  EXPECT_STATUS_GOOD);
		if (ret == -2) {
			logging(LOG_NORMAL, "[SKIPPED] WRITESAME16 is not implemented.");
			CU_PASS("[SKIPPED] Target does not support WRITESAME16. Skipping test");
			goto finished;
		}
		CU_ASSERT_EQUAL(ret, 0);

		if (rc16->lbprz) {
			logging(LOG_VERBOSE, "LBPRZ is set. Read the unmapped "
				"blocks back and verify they are all zero");
			logging(LOG_VERBOSE, "Read %d blocks and verify they "
				"are now zero", i);
			ret = read16(sd, NULL, 0,
				     i * block_size, block_size,
				     0, 0, 0, 0, 0, buf,
				     EXPECT_STATUS_GOOD);
			CU_ASSERT(all_zeroes(buf, i * block_size));
		} else {
			logging(LOG_VERBOSE, "LBPRZ is clear. Skip the read "
				"and verify zero test");
		}
	}


	logging(LOG_VERBOSE, "Test WRITESAME16 of 1-256 blocks at the end of the LUN");
	for (i = 1; i <= 256; i++) {
		logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i);
		memset(buf, 0xff, i * block_size);
		ret = write16(sd, num_blocks - i,
			      i * block_size, block_size, 0, 0, 0, 0, 0, buf,
			      EXPECT_STATUS_GOOD);
		CU_ASSERT_EQUAL(ret, 0);

		logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME16", i);
		memset(buf, 0, block_size);
		ret = writesame16(sd, num_blocks - i,
				  block_size, i, 0, 1, 0, 0, buf,
				  EXPECT_STATUS_GOOD);
		CU_ASSERT_EQUAL(ret, 0);

		if (rc16->lbprz) {
			logging(LOG_VERBOSE, "LBPRZ is set. Read the unmapped "
				"blocks back and verify they are all zero");
			logging(LOG_VERBOSE, "Read %d blocks and verify they "
				"are now zero", i);
			ret = read16(sd, NULL, num_blocks - i,
				     i * block_size, block_size,
				     0, 0, 0, 0, 0, buf,
				     EXPECT_STATUS_GOOD);
			CU_ASSERT(all_zeroes(buf, i * block_size));
		} else {
			logging(LOG_VERBOSE, "LBPRZ is clear. Skip the read "
				"and verify zero test");
		}
	}

	logging(LOG_VERBOSE, "Verify that WRITESAME16 ANCHOR==1 + UNMAP==0 is invalid");
	ret = writesame16(sd, 0,
			  block_size, 1, 1, 0, 0, 0, buf,
			  EXPECT_INVALID_FIELD_IN_CDB);
	CU_ASSERT_EQUAL(ret, 0);



	if (inq_lbp->anc_sup) {
		logging(LOG_VERBOSE, "Test WRITESAME16 ANCHOR==1 + UNMAP==0");
		memset(buf, 0, block_size);
		ret = writesame16(sd, 0,
				  block_size, 1, 1, 1, 0, 0, buf,
				  EXPECT_STATUS_GOOD);
	} else {
		logging(LOG_VERBOSE, "Test WRITESAME16 ANCHOR==1 + UNMAP==0 no ANC_SUP so expecting to fail");
		ret = writesame16(sd, 0,
				  block_size, 1, 1, 1, 0, 0, buf,
				  EXPECT_INVALID_FIELD_IN_CDB);
	}

	CU_ASSERT_EQUAL(ret, 0);


	if (inq_bl == NULL) {
		logging(LOG_VERBOSE, "[FAILED] WRITESAME16 works but "
			"BlockLimits VPD is missing.");
		CU_FAIL("[FAILED] WRITESAME16 works but "
			"BlockLimits VPD is missing.");
		goto finished;
	}

	i = 256;
	if (i <= num_blocks
	    && (inq_bl->max_ws_len == 0 || inq_bl->max_ws_len >= i)) {
		logging(LOG_VERBOSE, "Block Limits VPD page reports MAX_WS_LEN "
			"as either 0 (==no limit) or >= %d. Test Unmapping "
			"%d blocks to verify that it can handle 2-byte "
			"lengths", i, i);

		logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i);
		memset(buf, 0xff, i * block_size);
		ret = write16(sd, 0,
			      i * block_size, block_size, 0, 0, 0, 0, 0, buf,
			      EXPECT_STATUS_GOOD);
		CU_ASSERT_EQUAL(ret, 0);

		logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME16", i);
		memset(buf, 0, block_size);
		ret = writesame16(sd, 0,
				  block_size, i, 0, 1, 0, 0, buf,
				  EXPECT_STATUS_GOOD);
		CU_ASSERT_EQUAL(ret, 0);

		if (rc16->lbprz) {
			logging(LOG_VERBOSE, "LBPRZ is set. Read the unmapped "
				"blocks back and verify they are all zero");

			logging(LOG_VERBOSE, "Read %d blocks and verify they "
				"are now zero", i);
			ret = read16(sd, NULL, 0,
				     i * block_size, block_size,
				     0, 0, 0, 0, 0, buf,
				     EXPECT_STATUS_GOOD);
			CU_ASSERT(all_zeroes(buf, i * block_size));
		} else {
			logging(LOG_VERBOSE, "LBPRZ is clear. Skip the read "
				"and verify zero test");
		}
	} else if (i <= num_blocks) {
		logging(LOG_VERBOSE, "Block Limits VPD page reports MAX_WS_LEN "
			"as <256. Verify that a 256 block unmap fails with "
			"INVALID_FIELD_IN_CDB.");

		logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME16", i);
		ret = writesame16(sd, 0,
				  block_size, i, 0, 1, 0, 0, buf,
				  EXPECT_INVALID_FIELD_IN_CDB);
		CU_ASSERT_EQUAL(ret, 0);
	}


	i = 65536;
	if (i <= num_blocks
	    && (inq_bl->max_ws_len == 0 || inq_bl->max_ws_len >= i)) {
		logging(LOG_VERBOSE, "Block Limits VPD page reports MAX_WS_LEN "
			"as either 0 (==no limit) or >= %d. Test Unmapping "
			"%d blocks to verify that it can handle 4-byte "
			"lengths", i, i);

		logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i);
		memset(buf, 0xff, i * block_size);
		ret = write16(sd, 0,
			      i * block_size, block_size, 0, 0, 0, 0, 0, buf,
			      EXPECT_STATUS_GOOD);
		CU_ASSERT_EQUAL(ret, 0);

		logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME16", i);
		memset(buf, 0, block_size);
		ret = writesame16(sd, 0,
				  block_size, i, 0, 1, 0, 0, buf,
				  EXPECT_STATUS_GOOD);
		CU_ASSERT_EQUAL(ret, 0);

		if (rc16->lbprz) {
			logging(LOG_VERBOSE, "LBPRZ is set. Read the unmapped "
				"blocks back and verify they are all zero");

			logging(LOG_VERBOSE, "Read %d blocks and verify they "
				"are now zero", i);
			ret = read16(sd, NULL, 0,
				     i * block_size, block_size,
				     0, 0, 0, 0, 0, buf,
				     EXPECT_STATUS_GOOD);
			CU_ASSERT(all_zeroes(buf, i * block_size));
		} else {
			logging(LOG_VERBOSE, "LBPRZ is clear. Skip the read "
				"and verify zero test");
		}
	} else if (i <= num_blocks) {
		logging(LOG_VERBOSE, "Block Limits VPD page reports MAX_WS_LEN "
			"as <256. Verify that a 256 block unmap fails with "
			"INVALID_FIELD_IN_CDB.");

		logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME16", i);
		ret = writesame16(sd, 0,
				  block_size, i, 0, 1, 0, 0, buf,
				  EXPECT_INVALID_FIELD_IN_CDB);
		CU_ASSERT_EQUAL(ret, 0);
	}

finished:
	free(buf);
}