[Ocfs2-test-devel] [PATCH 1/1] Ocfs2-test: Add testcase to ocfs2-test to verify refcount after punching holes.

Tao Ma tao.ma at oracle.com
Mon Feb 1 01:26:37 PST 2010


sob.

Tristan Ye wrote:
> The newly added testcase was originally aimed to expose a reflink bug on punching holes:
> 
> http://oss.oracle.com/bugzilla/show_bug.cgi?id=1216
> 
> The new testcase did following things:
> 
> 1. Prepare a oringal file with clusters.
> 
> 2. Reflink the original file to N reflinks.
> 
> 3. Punching hole randomly on original file.
> 
> 4. Verify the consistency on reflinks(expect reflinks stay unchanged)
> 
> Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
> ---
>  programs/reflink_tests/reflink_test.c       |  127 ++++++++++++++++++++++++++-
>  programs/reflink_tests/reflink_test.h       |    7 ++
>  programs/reflink_tests/reflink_test_run.sh  |   18 ++++
>  programs/reflink_tests/reflink_test_utils.c |  103 ++++++++++++++++++++++
>  4 files changed, 252 insertions(+), 3 deletions(-)
> 
> diff --git a/programs/reflink_tests/reflink_test.c b/programs/reflink_tests/reflink_test.c
> index 9c95a24..49c5990 100755
> --- a/programs/reflink_tests/reflink_test.c
> +++ b/programs/reflink_tests/reflink_test.c
> @@ -118,6 +118,7 @@ static void usage(void)
>  	       "-O enable O_DIRECT test.\n"
>  	       "-D enable destructive test.\n"
>  	       "-v enable verification for destructive test.\n"
> +	       "-H enable CoW verification test for punching holse.\n"
>  	       "-I enable inline-data test.\n"
>  	       "-x enable combination test with xattr.\n"
>  	       "-h enable holes punching and filling tests.\n"
> @@ -141,8 +142,8 @@ static int parse_opts(int argc, char **argv)
>  
>  	while (1) {
>  		c = getopt(argc, argv,
> -			   "i:d:w:IOfFbBsSrRmMW:n:N:"
> -			   "l:L:c:C:p:x:X:h:H:o:v:a:P:D:");
> +			   "i:d:w:IOfFbBsSrRHmMW:n:N:"
> +			   "l:L:c:C:p:x:X:h:o:v:a:P:D:");
>  		if (c == -1)
>  			break;
>  
> @@ -220,11 +221,12 @@ static int parse_opts(int argc, char **argv)
>  			xattr_nums = atol(optarg);
>  			break;
>  		case 'h':
> -		case 'H':
>  			test_flags |= HOLE_TEST;
>  			hole_nums = atol(optarg);
>  		case 'P':
>  			port = atol(optarg);
> +		case 'H':
> +			test_flags |= PUNH_TEST;
>  		default:
>  			break;
>  		}
> @@ -2244,6 +2246,122 @@ static int inline_test(void)
>  	return 0;
>  }
>  
> +static int verify_punch_hole_cow_test(void)
> +{
> +	int ret = 0, fd;
> +	int sub_testno = 1;
> +	char *write_pattern = NULL;
> +	char *read_pattern = NULL;
> +
> +	unsigned long i;
> +	unsigned long long offset, len, read_size;
> +	char dest[PATH_MAX];
> +
> +	printf("Test %d: Verify cow for punching holes.\n", testno++);
> +
> +        snprintf(orig_path, PATH_MAX, "%s/original_verify_cow_punch_hole_"
> +		 "refile", workplace);
> +
> +	write_pattern = malloc(clustersize);
> +	read_pattern = malloc(clustersize);
> +
> +	get_rand_buf(write_pattern, clustersize);
> +	memset(read_pattern, 0, clustersize);
> +
> +	printf("  *SubTest %d: Prepare file.\n", sub_testno++);
> +	ret = prep_orig_file_with_pattern(orig_path, file_size, clustersize,
> +					  write_pattern, 0);
> +	if (ret < 0)
> +		goto bail;
> +	printf("  *SubTest %d: Do %ld reflinks.\n", sub_testno++, ref_counts);
> +	ret = do_reflinks(orig_path, orig_path, ref_counts, 0);
> +	if (ret < 0)
> +		goto bail;
> +
> +	printf("  *SubTest %d: Punching hole to original file.\n",
> +	       sub_testno++);
> +
> +	fd = open_file(orig_path, O_RDWR);
> +	if (fd < 0)
> +		goto bail;
> +
> +	offset = 0;
> +
> +	while (offset < file_size) {
> +
> +		offset += get_rand(0, clustersize);
> +		len = get_rand(clustersize, 2 * clustersize);
> +		if ((offset + len) > file_size)
> +			len = file_size - offset;
> +
> +		ret = punch_hole(fd, offset, len);
> +		if (ret < 0) {
> +			fprintf(stderr, "failed to punch hole from %llu to "
> +				"%llu on %s\n", offset,
> +				offset + len, orig_path);
> +			close(fd);
> +			goto bail;
> +		}	
> +
> +		offset += len;
> +	}
> +	
> +	close(fd);
> +
> +	printf("  *SubTest %d: Verify reflinks after punching holes.\n",
> +	       sub_testno++);
> +
> +	for (i = 0; i < ref_counts; i++) {
> +		snprintf(dest, PATH_MAX, "%sr%ld", orig_path, i);
> +		fd = open_file(dest, O_RDONLY);
> +		if (fd < 0)
> +			goto bail;
> +
> +		offset = 0;
> +		while (offset < file_size) {
> +			if ((offset + clustersize) > file_size)
> +				read_size = file_size - offset;
> +			else
> +				read_size = clustersize;
> +                        ret = read_at(fd, read_pattern, read_size, offset);
> +			if (ret < 0) {
> +				close(fd);
> +				goto bail;
> +			}
> +			if (memcmp(read_pattern, write_pattern, read_size)) {
> +				fprintf(stderr, "Corrupted chunk found on "
> +					"reflink %s: from %llu to %llu\n",
> +					dest, offset, offset + read_size);
> +				ret = -1;
> +				close(fd);
> +				goto bail;
> +			}
> +                        offset += read_size;
> +                }
> +
> +		close(fd);
> +
> +	}
> +
> +	printf("  *SubTest %d: Unlinking reflinks and original file.\n",
> +	       sub_testno++);
> +
> +	ret = do_unlinks(orig_path, ref_counts);
> +	if (ret < 0)
> +		goto bail;
> +
> +	ret = do_unlink(orig_path);
> +
> +bail:
> +	if (write_pattern)
> +		free(write_pattern);
> +
> +	if (read_pattern)
> +		free(read_pattern);
> +
> +	return ret;
> +}
> +
>  static void run_test(void)
>  {
>  	int i;
> @@ -2288,6 +2406,9 @@ static void run_test(void)
>  		if (test_flags & VERI_TEST)
>  			verification_dest();
>  
> +		if (test_flags & PUNH_TEST)
> +			verify_punch_hole_cow_test();
> +
>  	}
>  }
>  
> diff --git a/programs/reflink_tests/reflink_test.h b/programs/reflink_tests/reflink_test.h
> index 3db48f1..2117cda 100755
> --- a/programs/reflink_tests/reflink_test.h
> +++ b/programs/reflink_tests/reflink_test.h
> @@ -77,6 +77,7 @@
>  #define INLN_TEST		0x00000800
>  #define DSCV_TEST		0x00001000
>  #define VERI_TEST		0x00002000
> +#define PUNH_TEST		0x00004000
>  
>  #define MPI_RET_SUCCESS		0
>  #define MPI_RET_FAILED		1
> @@ -131,6 +132,9 @@ int fill_pattern(unsigned long size);
>  int prep_orig_file(char *file_name, unsigned long size, int once);
>  int prep_orig_file_dio(char *file_name, unsigned long size);
>  int prep_orig_file_in_chunks(char *file_name, unsigned long chunks);
> +int prep_orig_file_with_pattern(char *file_name, unsigned long size,
> +				unsigned long chunk_size, char *pattern_buf,
> +				int once);
>  int verify_pattern(char *buf, unsigned long offset, unsigned long size);
>  int verify_orig_file(char *orig);
>  
> @@ -180,4 +184,7 @@ int semaphore_close(int sem_id);
>  int semaphore_p(int sem_id);
>  int semaphore_v(int sem_id);
>  
> +int open_file(const char *filename, int flags);
> +int punch_hole(int fd, uint64_t start, uint64_t len);
> +
>  #endif
> diff --git a/programs/reflink_tests/reflink_test_run.sh b/programs/reflink_tests/reflink_test_run.sh
> index 097a97a..840f7a2 100755
> --- a/programs/reflink_tests/reflink_test_run.sh
> +++ b/programs/reflink_tests/reflink_test_run.sh
> @@ -533,6 +533,24 @@ ${WORK_PLACE} -D >>${LOG_FILE} 2>&1
>          f_exit_or_not ${RET}
>  
>  	((TEST_NO++))
> +	f_LogRunMsg ${RUN_LOG_FILE} "[${TEST_NO}] Verificationl CoW Test On \
> +Punching Holes:"
> +	f_LogMsg ${LOG_FILE} "[${TEST_NO}] Verification CoW Test On Punching \
> +Holes, CMD:${SUDO} ${REFLINK_TEST_BIN} -i 1 -n 100 -l 3276800 -d ${DEVICE} \
> +-w ${WORK_PLACE} -H "
> +	${SUDO} ${REFLINK_TEST_BIN} -i 1 -n 100 -l 3276800 -d ${DEVICE} -w \
> +${WORK_PLACE} -H >>${LOG_FILE} 2>&1
> +	RET=$?
> +	f_echo_status ${RET} | tee -a ${RUN_LOG_FILE}
> +	f_exit_or_not ${RET}
> +	((TEST_PASS++))
> +	f_LogMsg ${LOG_FILE} "Cleanup working place"
> +	${SUDO} ${CHMOD_BIN} -R 777 ${MOUNT_POINT}  >>${LOG_FILE} 2>&1
> +	${RM_BIN} -rf ${WORK_PLACE}/* >>${LOG_FILE} 2>&1
> +	RET=$?
> +	f_exit_or_not ${RET}
> +
> +	((TEST_NO++))
>  	f_LogRunMsg ${RUN_LOG_FILE} "[${TEST_NO}] Bash & Tools Utility Test:"
>  	f_reflink_bash_utils_test 100 104857600 >>${LOG_FILE} 2>&1
>          RET=$?
> diff --git a/programs/reflink_tests/reflink_test_utils.c b/programs/reflink_tests/reflink_test_utils.c
> index 925cb41..96cb1da 100755
> --- a/programs/reflink_tests/reflink_test_utils.c
> +++ b/programs/reflink_tests/reflink_test_utils.c
> @@ -461,6 +461,70 @@ int prep_orig_file(char *file_name, unsigned long size, int once)
>  	return 0;
>  }
>  
> +int prep_orig_file_with_pattern(char *file_name, unsigned long size,
> +				unsigned long chunk_size, char *pattern_buf,
> +				int once)
> +{
> +	int fd, fdt, ret, o_ret;
> +	unsigned long offset = 0, write_size = 0;
> +	char tmp_path[PATH_MAX];
> +
> +	fd = open64(file_name, open_rw_flags, FILE_MODE);
> +	if (fd < 0) {
> +		o_ret = fd;
> +		fd = errno;
> +		fprintf(stderr, "create file %s failed:%d:%s\n", file_name, fd,
> +			strerror(fd));
> +		fd = o_ret;
> +		return fd;
> +	}
> +
> +	if (once) {
> +
> +		while (offset < size) {
> +			if ((offset + chunk_size) > size)
> +				write_size = size - offset;
> +			else
> +				write_size = chunk_size;
> +
> +			ret = write_at(fd, pattern_buf, write_size, offset);
> +			if (ret < 0)
> +				return ret;
> +
> +			offset += write_size;
> +		}
> +	} else {
> +		snprintf(tmp_path, PATH_MAX, "%s-tmp-file", file_name);
> +		fdt = open64(tmp_path, open_rw_flags, FILE_MODE);
> +
> +		unlink(tmp_path);
> +
> +		while (offset < size) {
> +
> +			if ((offset + chunk_size) > size)
> +				write_size = size - offset;
> +			else
> +				write_size = chunk_size;
> +
> +			ret = write_at(fd, pattern_buf, write_size, offset);
> +			if (ret < 0)
> +				return ret;
> +
> +			ret = write_at(fdt, pattern_buf, write_size, offset);
> +			if (ret < 0)
> +				return ret;
> +
> +			offset += write_size;
> +		}
> +
> +		close(fdt);
> +
> +	}
> +
> +	close(fd);
> +	return 0;
> +}
> +
>  int prep_orig_file_dio(char *file_name, unsigned long size)
>  {
>  	int fd, ret, o_ret, flags;
> @@ -1825,3 +1889,42 @@ int semaphore_v(int sem_id)
>  
>  	return 0;
>  }
> +
> +int open_file(const char *filename, int flags)
> +{
> +	int fd, ret, o_ret;
> +
> +	fd = open64(filename, open_rw_flags, FILE_MODE);
> +	if (fd < 0) {
> +		o_ret = fd;
> +		fd = errno;
> +		fprintf(stderr, "open file %s failed:%d:%s\n", filename, fd,
> +			strerror(fd));
> +		fd = o_ret;
> +		return -1;
> +	}
> +
> +	return fd;
> +}
> +
> +
> +int punch_hole(int fd, uint64_t start, uint64_t len)
> +{
> +	int ret;
> +	struct ocfs2_space_resv sr;
> +
> +	memset(&sr, 0, sizeof(sr));
> +	sr.l_whence = 0;
> +	sr.l_start = start;
> +	sr.l_len = len;
> +
> +	ret = ioctl(fd, OCFS2_IOC_UNRESVSP64, &sr);
> +	if (ret == -1) {
> +		fprintf(stderr, "ioctl error %d: \"%s\"\n",
> +			errno, strerror(errno));
> +		return -1;
> +	}
> +
> +	return 0;
> +
> +}



More information about the Ocfs2-test-devel mailing list