xref: /freebsd/tests/sys/file/fspacectl_test.c (revision 4d846d26)
10dc332bfSKa Ho Ng /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
30dc332bfSKa Ho Ng  *
40dc332bfSKa Ho Ng  * Copyright (c) 2021 The FreeBSD Foundation
50dc332bfSKa Ho Ng  * All rights reserved.
60dc332bfSKa Ho Ng  *
70dc332bfSKa Ho Ng  * This software was developed by Ka Ho Ng under sponsorship from
80dc332bfSKa Ho Ng  * the FreeBSD Foundation.
90dc332bfSKa Ho Ng  *
100dc332bfSKa Ho Ng  * Redistribution and use in source and binary forms, with or without
110dc332bfSKa Ho Ng  * modification, are permitted provided that the following conditions
120dc332bfSKa Ho Ng  * are met:
130dc332bfSKa Ho Ng  * 1. Redistributions of source code must retain the above copyright
140dc332bfSKa Ho Ng  *    notice, this list of conditions and the following disclaimer.
150dc332bfSKa Ho Ng  * 2. Redistributions in binary form must reproduce the above copyright
160dc332bfSKa Ho Ng  *    notice, this list of conditions and the following disclaimer in the
170dc332bfSKa Ho Ng  *    documentation and/or other materials provided with the distribution.
180dc332bfSKa Ho Ng  *
190dc332bfSKa Ho Ng  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
200dc332bfSKa Ho Ng  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
210dc332bfSKa Ho Ng  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
220dc332bfSKa Ho Ng  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
230dc332bfSKa Ho Ng  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
240dc332bfSKa Ho Ng  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
250dc332bfSKa Ho Ng  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
260dc332bfSKa Ho Ng  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
270dc332bfSKa Ho Ng  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
280dc332bfSKa Ho Ng  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
290dc332bfSKa Ho Ng  * SUCH DAMAGE.
300dc332bfSKa Ho Ng  */
310dc332bfSKa Ho Ng 
320dc332bfSKa Ho Ng #include <sys/param.h>
330dc332bfSKa Ho Ng #include <sys/mount.h>
340dc332bfSKa Ho Ng #include <sys/stat.h>
350dc332bfSKa Ho Ng 
360dc332bfSKa Ho Ng #include <atf-c.h>
370dc332bfSKa Ho Ng #include <fcntl.h>
380dc332bfSKa Ho Ng #include <malloc.h>
390dc332bfSKa Ho Ng 
400dc332bfSKa Ho Ng static off_t file_max_blocks = 32;
410dc332bfSKa Ho Ng static const char byte_to_fill = 0x5f;
420dc332bfSKa Ho Ng 
430dc332bfSKa Ho Ng static int
fill(int fd,off_t offset,off_t len)440dc332bfSKa Ho Ng fill(int fd, off_t offset, off_t len)
450dc332bfSKa Ho Ng {
460dc332bfSKa Ho Ng 	int error;
470dc332bfSKa Ho Ng 	size_t blen;
480dc332bfSKa Ho Ng 	char *buf;
490dc332bfSKa Ho Ng 	struct stat statbuf;
500dc332bfSKa Ho Ng 	blksize_t blocksize;
510dc332bfSKa Ho Ng 
520dc332bfSKa Ho Ng 	if (fstat(fd, &statbuf) == -1)
530dc332bfSKa Ho Ng 		return (1);
540dc332bfSKa Ho Ng 	blocksize = statbuf.st_blksize;
550dc332bfSKa Ho Ng 	error = 0;
560dc332bfSKa Ho Ng 	buf = malloc(blocksize);
570dc332bfSKa Ho Ng 	if (buf == NULL)
580dc332bfSKa Ho Ng 		return (1);
590dc332bfSKa Ho Ng 
600dc332bfSKa Ho Ng 	while (len > 0) {
610dc332bfSKa Ho Ng 		blen = len < (off_t)blocksize ? len : blocksize;
620dc332bfSKa Ho Ng 		memset(buf, byte_to_fill, blen);
630dc332bfSKa Ho Ng 		if (pwrite(fd, buf, blen, offset) != (ssize_t)blen) {
640dc332bfSKa Ho Ng 			error = 1;
650dc332bfSKa Ho Ng 			break;
660dc332bfSKa Ho Ng 		}
670dc332bfSKa Ho Ng 		len -= blen;
680dc332bfSKa Ho Ng 		offset += blen;
690dc332bfSKa Ho Ng 	}
700dc332bfSKa Ho Ng 
710dc332bfSKa Ho Ng 	free(buf);
720dc332bfSKa Ho Ng 	return (error);
730dc332bfSKa Ho Ng }
740dc332bfSKa Ho Ng 
750dc332bfSKa Ho Ng static blksize_t
fd_get_blksize(void)760dc332bfSKa Ho Ng fd_get_blksize(void)
770dc332bfSKa Ho Ng {
780dc332bfSKa Ho Ng 	struct statfs statfsbuf;
790dc332bfSKa Ho Ng 
800dc332bfSKa Ho Ng 	if (statfs(".", &statfsbuf) == -1)
810dc332bfSKa Ho Ng 		return (-1);
820dc332bfSKa Ho Ng 	return statfsbuf.f_iosize;
830dc332bfSKa Ho Ng }
840dc332bfSKa Ho Ng 
850dc332bfSKa Ho Ng static int
check_content_dealloc(int fd,off_t hole_start,off_t hole_len,off_t file_sz)860dc332bfSKa Ho Ng check_content_dealloc(int fd, off_t hole_start, off_t hole_len, off_t file_sz)
870dc332bfSKa Ho Ng {
880dc332bfSKa Ho Ng 	int error;
890dc332bfSKa Ho Ng 	size_t blen;
900dc332bfSKa Ho Ng 	off_t offset, resid;
910dc332bfSKa Ho Ng 	struct stat statbuf;
920dc332bfSKa Ho Ng 	char *buf, *sblk;
930dc332bfSKa Ho Ng 	blksize_t blocksize;
940dc332bfSKa Ho Ng 
950dc332bfSKa Ho Ng 	blocksize = fd_get_blksize();
960dc332bfSKa Ho Ng 	if (blocksize == -1)
970dc332bfSKa Ho Ng 		return (1);
980dc332bfSKa Ho Ng 	error = 0;
990dc332bfSKa Ho Ng 	buf = malloc(blocksize * 2);
1000dc332bfSKa Ho Ng 	if (buf == NULL)
1010dc332bfSKa Ho Ng 		return (1);
1020dc332bfSKa Ho Ng 	sblk = buf + blocksize;
1030dc332bfSKa Ho Ng 
1040dc332bfSKa Ho Ng 	memset(sblk, 0, blocksize);
1050dc332bfSKa Ho Ng 
1060dc332bfSKa Ho Ng 	if ((uint64_t)hole_start + hole_len > (uint64_t)file_sz)
1070dc332bfSKa Ho Ng 		hole_len = file_sz - hole_start;
1080dc332bfSKa Ho Ng 
1090dc332bfSKa Ho Ng 	/*
1100dc332bfSKa Ho Ng 	 * Check hole is zeroed.
1110dc332bfSKa Ho Ng 	 */
1120dc332bfSKa Ho Ng 	offset = hole_start;
1130dc332bfSKa Ho Ng 	resid = hole_len;
1140dc332bfSKa Ho Ng 	while (resid > 0) {
1150dc332bfSKa Ho Ng 		blen = resid < (off_t)blocksize ? resid : blocksize;
1160dc332bfSKa Ho Ng 		if (pread(fd, buf, blen, offset) != (ssize_t)blen) {
1170dc332bfSKa Ho Ng 			error = 1;
1180dc332bfSKa Ho Ng 			break;
1190dc332bfSKa Ho Ng 		}
1200dc332bfSKa Ho Ng 		if (memcmp(buf, sblk, blen) != 0) {
1210dc332bfSKa Ho Ng 			error = 1;
1220dc332bfSKa Ho Ng 			break;
1230dc332bfSKa Ho Ng 		}
1240dc332bfSKa Ho Ng 		resid -= blen;
1250dc332bfSKa Ho Ng 		offset += blen;
1260dc332bfSKa Ho Ng 	}
1270dc332bfSKa Ho Ng 
1280dc332bfSKa Ho Ng 	memset(sblk, byte_to_fill, blocksize);
1290dc332bfSKa Ho Ng 
1300dc332bfSKa Ho Ng 	/*
1310dc332bfSKa Ho Ng 	 * Check file region before hole is zeroed.
1320dc332bfSKa Ho Ng 	 */
1330dc332bfSKa Ho Ng 	offset = 0;
1340dc332bfSKa Ho Ng 	resid = hole_start;
1350dc332bfSKa Ho Ng 	while (resid > 0) {
1360dc332bfSKa Ho Ng 		blen = resid < (off_t)blocksize ? resid : blocksize;
1370dc332bfSKa Ho Ng 		if (pread(fd, buf, blen, offset) != (ssize_t)blen) {
1380dc332bfSKa Ho Ng 			error = 1;
1390dc332bfSKa Ho Ng 			break;
1400dc332bfSKa Ho Ng 		}
1410dc332bfSKa Ho Ng 		if (memcmp(buf, sblk, blen) != 0) {
1420dc332bfSKa Ho Ng 			error = 1;
1430dc332bfSKa Ho Ng 			break;
1440dc332bfSKa Ho Ng 		}
1450dc332bfSKa Ho Ng 		resid -= blen;
1460dc332bfSKa Ho Ng 		offset += blen;
1470dc332bfSKa Ho Ng 	}
1480dc332bfSKa Ho Ng 
1490dc332bfSKa Ho Ng 	/*
1500dc332bfSKa Ho Ng 	 * Check file region after hole is zeroed.
1510dc332bfSKa Ho Ng 	 */
1520dc332bfSKa Ho Ng 	offset = hole_start + hole_len;
1530dc332bfSKa Ho Ng 	resid = file_sz - offset;
1540dc332bfSKa Ho Ng 	while (resid > 0) {
1550dc332bfSKa Ho Ng 		blen = resid < (off_t)blocksize ? resid : blocksize;
1560dc332bfSKa Ho Ng 		if (pread(fd, buf, blen, offset) != (ssize_t)blen) {
1570dc332bfSKa Ho Ng 			error = 1;
1580dc332bfSKa Ho Ng 			break;
1590dc332bfSKa Ho Ng 		}
1600dc332bfSKa Ho Ng 		if (memcmp(buf, sblk, blen) != 0) {
1610dc332bfSKa Ho Ng 			error = 1;
1620dc332bfSKa Ho Ng 			break;
1630dc332bfSKa Ho Ng 		}
1640dc332bfSKa Ho Ng 		resid -= blen;
1650dc332bfSKa Ho Ng 		offset += blen;
1660dc332bfSKa Ho Ng 	}
1670dc332bfSKa Ho Ng 
1680dc332bfSKa Ho Ng 	/*
1690dc332bfSKa Ho Ng 	 * Check file size matches with expected file size.
1700dc332bfSKa Ho Ng 	 */
1710dc332bfSKa Ho Ng 	if (fstat(fd, &statbuf) == -1)
1720dc332bfSKa Ho Ng 		error = -1;
1730dc332bfSKa Ho Ng 	if (statbuf.st_size != file_sz)
1740dc332bfSKa Ho Ng 		error = -1;
1750dc332bfSKa Ho Ng 
1760dc332bfSKa Ho Ng 	free(buf);
1770dc332bfSKa Ho Ng 	return (error);
1780dc332bfSKa Ho Ng }
1790dc332bfSKa Ho Ng 
1800dc332bfSKa Ho Ng /*
1810dc332bfSKa Ho Ng  * Check aligned deallocation
1820dc332bfSKa Ho Ng  */
1830dc332bfSKa Ho Ng ATF_TC_WITHOUT_HEAD(aligned_dealloc);
ATF_TC_BODY(aligned_dealloc,tc)1840dc332bfSKa Ho Ng ATF_TC_BODY(aligned_dealloc, tc)
1850dc332bfSKa Ho Ng {
1860dc332bfSKa Ho Ng 	struct spacectl_range range;
1870dc332bfSKa Ho Ng 	off_t offset, length;
1880dc332bfSKa Ho Ng 	blksize_t blocksize;
1890dc332bfSKa Ho Ng 	int fd;
1900dc332bfSKa Ho Ng 
1910dc332bfSKa Ho Ng 	ATF_REQUIRE((blocksize = fd_get_blksize()) != -1);
1920dc332bfSKa Ho Ng 	range.r_offset = offset = blocksize;
1930dc332bfSKa Ho Ng 	range.r_len = length = (file_max_blocks - 1) * blocksize -
1940dc332bfSKa Ho Ng 	    range.r_offset;
1950dc332bfSKa Ho Ng 
1960dc332bfSKa Ho Ng 	ATF_REQUIRE((fd = open("sys_fspacectl_testfile",
1970dc332bfSKa Ho Ng 			 O_CREAT | O_RDWR | O_TRUNC, 0600)) != -1);
1980dc332bfSKa Ho Ng 	ATF_REQUIRE(fill(fd, 0, file_max_blocks * blocksize) == 0);
1990dc332bfSKa Ho Ng 	ATF_CHECK(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0);
2000dc332bfSKa Ho Ng 	ATF_CHECK(check_content_dealloc(fd, offset, length,
2010dc332bfSKa Ho Ng 		      file_max_blocks * blocksize) == 0);
2020dc332bfSKa Ho Ng 	ATF_REQUIRE(close(fd) == 0);
2030dc332bfSKa Ho Ng }
2040dc332bfSKa Ho Ng 
2050dc332bfSKa Ho Ng /*
2060dc332bfSKa Ho Ng  * Check unaligned deallocation
2070dc332bfSKa Ho Ng  */
2080dc332bfSKa Ho Ng ATF_TC_WITHOUT_HEAD(unaligned_dealloc);
ATF_TC_BODY(unaligned_dealloc,tc)2090dc332bfSKa Ho Ng ATF_TC_BODY(unaligned_dealloc, tc)
2100dc332bfSKa Ho Ng {
2110dc332bfSKa Ho Ng 	struct spacectl_range range;
2120dc332bfSKa Ho Ng 	off_t offset, length;
2130dc332bfSKa Ho Ng 	blksize_t blocksize;
2140dc332bfSKa Ho Ng 	int fd;
2150dc332bfSKa Ho Ng 
2160dc332bfSKa Ho Ng 	ATF_REQUIRE((blocksize = fd_get_blksize()) != -1);
2170dc332bfSKa Ho Ng 	range.r_offset = offset = blocksize / 2;
2180dc332bfSKa Ho Ng 	range.r_len = length = (file_max_blocks - 1) * blocksize +
2190dc332bfSKa Ho Ng 	    blocksize / 2 - offset;
2200dc332bfSKa Ho Ng 
2210dc332bfSKa Ho Ng 	ATF_REQUIRE((fd = open("sys_fspacectl_testfile",
2220dc332bfSKa Ho Ng 			 O_CREAT | O_RDWR | O_TRUNC, 0600)) != -1);
2230dc332bfSKa Ho Ng 	ATF_REQUIRE(fill(fd, 0, file_max_blocks * blocksize) == 0);
2240dc332bfSKa Ho Ng 	ATF_CHECK(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0);
2250dc332bfSKa Ho Ng 	ATF_CHECK(check_content_dealloc(fd, offset, length,
2260dc332bfSKa Ho Ng 		      file_max_blocks * blocksize) == 0);
2270dc332bfSKa Ho Ng 	ATF_REQUIRE(close(fd) == 0);
2280dc332bfSKa Ho Ng }
2290dc332bfSKa Ho Ng 
2300dc332bfSKa Ho Ng /*
2310dc332bfSKa Ho Ng  * Check aligned deallocation from certain offset to OFF_MAX
2320dc332bfSKa Ho Ng  */
2330dc332bfSKa Ho Ng ATF_TC_WITHOUT_HEAD(aligned_dealloc_offmax);
ATF_TC_BODY(aligned_dealloc_offmax,tc)2340dc332bfSKa Ho Ng ATF_TC_BODY(aligned_dealloc_offmax, tc)
2350dc332bfSKa Ho Ng {
2360dc332bfSKa Ho Ng 	struct spacectl_range range;
2370dc332bfSKa Ho Ng 	off_t offset, length;
2380dc332bfSKa Ho Ng 	blksize_t blocksize;
2390dc332bfSKa Ho Ng 	int fd;
2400dc332bfSKa Ho Ng 
2410dc332bfSKa Ho Ng 	ATF_REQUIRE((blocksize = fd_get_blksize()) != -1);
2420dc332bfSKa Ho Ng 	range.r_offset = offset = blocksize;
2430dc332bfSKa Ho Ng 	range.r_len = length = OFF_MAX - offset;
2440dc332bfSKa Ho Ng 
2450dc332bfSKa Ho Ng 	ATF_REQUIRE((fd = open("sys_fspacectl_testfile",
2460dc332bfSKa Ho Ng 			 O_CREAT | O_RDWR | O_TRUNC, 0600)) != -1);
2470dc332bfSKa Ho Ng 	ATF_REQUIRE(fill(fd, 0, file_max_blocks * blocksize) == 0);
2480dc332bfSKa Ho Ng 	ATF_CHECK(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0);
2490dc332bfSKa Ho Ng 	ATF_CHECK(check_content_dealloc(fd, offset, length,
2500dc332bfSKa Ho Ng 		      file_max_blocks * blocksize) == 0);
2510dc332bfSKa Ho Ng 	ATF_REQUIRE(close(fd) == 0);
2520dc332bfSKa Ho Ng }
2530dc332bfSKa Ho Ng 
2540dc332bfSKa Ho Ng /*
2550dc332bfSKa Ho Ng  * Check unaligned deallocation from certain offset to OFF_MAX
2560dc332bfSKa Ho Ng  */
2570dc332bfSKa Ho Ng ATF_TC_WITHOUT_HEAD(unaligned_dealloc_offmax);
ATF_TC_BODY(unaligned_dealloc_offmax,tc)2580dc332bfSKa Ho Ng ATF_TC_BODY(unaligned_dealloc_offmax, tc)
2590dc332bfSKa Ho Ng {
2600dc332bfSKa Ho Ng 	struct spacectl_range range;
2610dc332bfSKa Ho Ng 	off_t offset, length;
2620dc332bfSKa Ho Ng 	blksize_t blocksize;
2630dc332bfSKa Ho Ng 	int fd;
2640dc332bfSKa Ho Ng 
2650dc332bfSKa Ho Ng 	ATF_REQUIRE((blocksize = fd_get_blksize()) != -1);
2660dc332bfSKa Ho Ng 	range.r_offset = offset = blocksize / 2;
2670dc332bfSKa Ho Ng 	range.r_len = length = OFF_MAX - offset;
2680dc332bfSKa Ho Ng 
2690dc332bfSKa Ho Ng 	ATF_REQUIRE((fd = open("sys_fspacectl_testfile",
2700dc332bfSKa Ho Ng 			 O_CREAT | O_RDWR | O_TRUNC, 0600)) != -1);
2710dc332bfSKa Ho Ng 	ATF_REQUIRE(fill(fd, 0, file_max_blocks * blocksize) == 0);
2720dc332bfSKa Ho Ng 	ATF_CHECK(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0);
2730dc332bfSKa Ho Ng 	ATF_CHECK(check_content_dealloc(fd, offset, length,
2740dc332bfSKa Ho Ng 		      file_max_blocks * blocksize) == 0);
2750dc332bfSKa Ho Ng 	ATF_REQUIRE(close(fd) == 0);
2760dc332bfSKa Ho Ng }
2770dc332bfSKa Ho Ng 
2780dc332bfSKa Ho Ng /*
2790dc332bfSKa Ho Ng  * Check aligned deallocation around EOF
2800dc332bfSKa Ho Ng  */
2810dc332bfSKa Ho Ng ATF_TC_WITHOUT_HEAD(aligned_dealloc_eof);
ATF_TC_BODY(aligned_dealloc_eof,tc)2820dc332bfSKa Ho Ng ATF_TC_BODY(aligned_dealloc_eof, tc)
2830dc332bfSKa Ho Ng {
2840dc332bfSKa Ho Ng 	struct spacectl_range range;
2850dc332bfSKa Ho Ng 	off_t offset, length;
2860dc332bfSKa Ho Ng 	blksize_t blocksize;
2870dc332bfSKa Ho Ng 	int fd;
2880dc332bfSKa Ho Ng 
2890dc332bfSKa Ho Ng 	ATF_REQUIRE((blocksize = fd_get_blksize()) != -1);
2900dc332bfSKa Ho Ng 	range.r_offset = offset = blocksize;
2910dc332bfSKa Ho Ng 	range.r_len = length = (file_max_blocks + 1) * blocksize -
2920dc332bfSKa Ho Ng 	    range.r_offset;
2930dc332bfSKa Ho Ng 
2940dc332bfSKa Ho Ng 	ATF_REQUIRE((fd = open("sys_fspacectl_testfile",
2950dc332bfSKa Ho Ng 			 O_CREAT | O_RDWR | O_TRUNC, 0600)) != -1);
2960dc332bfSKa Ho Ng 	ATF_REQUIRE(fill(fd, 0, file_max_blocks * blocksize) == 0);
2970dc332bfSKa Ho Ng 	ATF_CHECK(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0);
2980dc332bfSKa Ho Ng 	ATF_CHECK(check_content_dealloc(fd, offset, length,
2990dc332bfSKa Ho Ng 		      file_max_blocks * blocksize) == 0);
3000dc332bfSKa Ho Ng 	ATF_REQUIRE(close(fd) == 0);
3010dc332bfSKa Ho Ng }
3020dc332bfSKa Ho Ng 
3030dc332bfSKa Ho Ng /*
3040dc332bfSKa Ho Ng  * Check unaligned deallocation around EOF
3050dc332bfSKa Ho Ng  */
3060dc332bfSKa Ho Ng ATF_TC_WITHOUT_HEAD(unaligned_dealloc_eof);
ATF_TC_BODY(unaligned_dealloc_eof,tc)3070dc332bfSKa Ho Ng ATF_TC_BODY(unaligned_dealloc_eof, tc)
3080dc332bfSKa Ho Ng {
3090dc332bfSKa Ho Ng 	struct spacectl_range range;
3100dc332bfSKa Ho Ng 	off_t offset, length;
3110dc332bfSKa Ho Ng 	blksize_t blocksize;
3120dc332bfSKa Ho Ng 	int fd;
3130dc332bfSKa Ho Ng 
3140dc332bfSKa Ho Ng 	ATF_REQUIRE((blocksize = fd_get_blksize()) != -1);
3150dc332bfSKa Ho Ng 	range.r_offset = offset = blocksize / 2;
3160dc332bfSKa Ho Ng 	range.r_len = length = file_max_blocks * blocksize + blocksize / 2 -
3170dc332bfSKa Ho Ng 	    range.r_offset;
3180dc332bfSKa Ho Ng 
3190dc332bfSKa Ho Ng 	ATF_REQUIRE((fd = open("sys_fspacectl_testfile",
3200dc332bfSKa Ho Ng 			 O_CREAT | O_RDWR | O_TRUNC, 0600)) != -1);
3210dc332bfSKa Ho Ng 	ATF_REQUIRE(fill(fd, 0, file_max_blocks * blocksize) == 0);
3220dc332bfSKa Ho Ng 	ATF_CHECK(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0);
3230dc332bfSKa Ho Ng 	ATF_CHECK(check_content_dealloc(fd, offset, length,
3240dc332bfSKa Ho Ng 		      file_max_blocks * blocksize) == 0);
3250dc332bfSKa Ho Ng 	ATF_REQUIRE(close(fd) == 0);
3260dc332bfSKa Ho Ng }
3270dc332bfSKa Ho Ng 
ATF_TP_ADD_TCS(tp)3280dc332bfSKa Ho Ng ATF_TP_ADD_TCS(tp)
3290dc332bfSKa Ho Ng {
3300dc332bfSKa Ho Ng 	ATF_TP_ADD_TC(tp, aligned_dealloc);
3310dc332bfSKa Ho Ng 	ATF_TP_ADD_TC(tp, unaligned_dealloc);
3320dc332bfSKa Ho Ng 	ATF_TP_ADD_TC(tp, aligned_dealloc_eof);
3330dc332bfSKa Ho Ng 	ATF_TP_ADD_TC(tp, unaligned_dealloc_eof);
3340dc332bfSKa Ho Ng 	ATF_TP_ADD_TC(tp, aligned_dealloc_offmax);
3350dc332bfSKa Ho Ng 	ATF_TP_ADD_TC(tp, unaligned_dealloc_offmax);
3360dc332bfSKa Ho Ng 
3370dc332bfSKa Ho Ng 	return atf_no_error();
3380dc332bfSKa Ho Ng }
339