xref: /freebsd/sys/contrib/openzfs/tests/zfs-tests/cmd/setlease.c (revision 8a62a2a5659d1839d8799b4274c04469d7f17c78)
1*8a62a2a5SMartin Matuska // SPDX-License-Identifier: CDDL-1.0
2*8a62a2a5SMartin Matuska /*
3*8a62a2a5SMartin Matuska  * CDDL HEADER START
4*8a62a2a5SMartin Matuska  *
5*8a62a2a5SMartin Matuska  * The contents of this file are subject to the terms of the
6*8a62a2a5SMartin Matuska  * Common Development and Distribution License (the "License").
7*8a62a2a5SMartin Matuska  * You may not use this file except in compliance with the License.
8*8a62a2a5SMartin Matuska  *
9*8a62a2a5SMartin Matuska  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*8a62a2a5SMartin Matuska  * or https://opensource.org/licenses/CDDL-1.0.
11*8a62a2a5SMartin Matuska  * See the License for the specific language governing permissions
12*8a62a2a5SMartin Matuska  * and limitations under the License.
13*8a62a2a5SMartin Matuska  *
14*8a62a2a5SMartin Matuska  * When distributing Covered Code, include this CDDL HEADER in each
15*8a62a2a5SMartin Matuska  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*8a62a2a5SMartin Matuska  * If applicable, add the following below this CDDL HEADER, with the
17*8a62a2a5SMartin Matuska  * fields enclosed by brackets "[]" replaced with your own identifying
18*8a62a2a5SMartin Matuska  * information: Portions Copyright [yyyy] [name of copyright owner]
19*8a62a2a5SMartin Matuska  *
20*8a62a2a5SMartin Matuska  * CDDL HEADER END
21*8a62a2a5SMartin Matuska  */
22*8a62a2a5SMartin Matuska 
23*8a62a2a5SMartin Matuska /*
24*8a62a2a5SMartin Matuska  * Copyright (c) 2026, TrueNAS.
25*8a62a2a5SMartin Matuska  */
26*8a62a2a5SMartin Matuska 
27*8a62a2a5SMartin Matuska /*
28*8a62a2a5SMartin Matuska  * This is a sanity check test for the F_SETLEASE and F_GETLEASE fcntl() calls.
29*8a62a2a5SMartin Matuska  * We use the generic kernel implementation, but we want to be alerted if it
30*8a62a2a5SMartin Matuska  * ever breaks.
31*8a62a2a5SMartin Matuska  *
32*8a62a2a5SMartin Matuska  * This is not a comprehensive test. It would be nice if it could be!
33*8a62a2a5SMartin Matuska  */
34*8a62a2a5SMartin Matuska 
35*8a62a2a5SMartin Matuska #ifndef _GNU_SOURCE
36*8a62a2a5SMartin Matuska #define	_GNU_SOURCE
37*8a62a2a5SMartin Matuska #endif
38*8a62a2a5SMartin Matuska 
39*8a62a2a5SMartin Matuska #include <stdio.h>
40*8a62a2a5SMartin Matuska #include <unistd.h>
41*8a62a2a5SMartin Matuska #include <stdlib.h>
42*8a62a2a5SMartin Matuska #include <fcntl.h>
43*8a62a2a5SMartin Matuska #include <errno.h>
44*8a62a2a5SMartin Matuska #include <string.h>
45*8a62a2a5SMartin Matuska 
46*8a62a2a5SMartin Matuska static int
get_lease(int fd)47*8a62a2a5SMartin Matuska get_lease(int fd) {
48*8a62a2a5SMartin Matuska 	int r = fcntl(fd, F_GETLEASE);
49*8a62a2a5SMartin Matuska 	if (r < 0) {
50*8a62a2a5SMartin Matuska 		perror("fcntl(GETLEASE)");
51*8a62a2a5SMartin Matuska 		exit(2);
52*8a62a2a5SMartin Matuska 	}
53*8a62a2a5SMartin Matuska 	return (r);
54*8a62a2a5SMartin Matuska }
55*8a62a2a5SMartin Matuska 
56*8a62a2a5SMartin Matuska static int
set_lease(int fd,int lease)57*8a62a2a5SMartin Matuska set_lease(int fd, int lease) {
58*8a62a2a5SMartin Matuska 	return (fcntl(fd, F_SETLEASE, lease) < 0 ? errno : 0);
59*8a62a2a5SMartin Matuska }
60*8a62a2a5SMartin Matuska 
61*8a62a2a5SMartin Matuska static const char *lease_str[] = {
62*8a62a2a5SMartin Matuska 	[F_RDLCK] = "RDLCK",
63*8a62a2a5SMartin Matuska 	[F_WRLCK] = "WRLCK",
64*8a62a2a5SMartin Matuska 	[F_UNLCK] = "UNLCK",
65*8a62a2a5SMartin Matuska };
66*8a62a2a5SMartin Matuska 
67*8a62a2a5SMartin Matuska static void
assert_lease(int fd,int expect)68*8a62a2a5SMartin Matuska assert_lease(int fd, int expect) {
69*8a62a2a5SMartin Matuska 	int got = get_lease(fd);
70*8a62a2a5SMartin Matuska 	if (got != expect) {
71*8a62a2a5SMartin Matuska 		fprintf(stderr, "ASSERT_LEASE: expected %s [%d], got %s [%d]\n",
72*8a62a2a5SMartin Matuska 		    lease_str[expect], expect, lease_str[got], got);
73*8a62a2a5SMartin Matuska 		abort();
74*8a62a2a5SMartin Matuska 	}
75*8a62a2a5SMartin Matuska 	printf("ok: lease is %s\n", lease_str[got]);
76*8a62a2a5SMartin Matuska }
77*8a62a2a5SMartin Matuska 
78*8a62a2a5SMartin Matuska static void
assert_set_lease(int fd,int lease)79*8a62a2a5SMartin Matuska assert_set_lease(int fd, int lease) {
80*8a62a2a5SMartin Matuska 	int err = set_lease(fd, lease);
81*8a62a2a5SMartin Matuska 	if (err != 0) {
82*8a62a2a5SMartin Matuska 		fprintf(stderr, "ASSERT_SET_LEASE: tried %s [%d], error: %s\n",
83*8a62a2a5SMartin Matuska 		    lease_str[lease], lease, strerror(err));
84*8a62a2a5SMartin Matuska 		abort();
85*8a62a2a5SMartin Matuska 	}
86*8a62a2a5SMartin Matuska 	printf("ok: set lease to %s\n", lease_str[lease]);
87*8a62a2a5SMartin Matuska }
88*8a62a2a5SMartin Matuska 
89*8a62a2a5SMartin Matuska int
main(int argc,char ** argv)90*8a62a2a5SMartin Matuska main(int argc, char **argv)
91*8a62a2a5SMartin Matuska {
92*8a62a2a5SMartin Matuska 	if (argc != 2) {
93*8a62a2a5SMartin Matuska 		fprintf(stderr, "usage: %s <filename>\n", argv[0]);
94*8a62a2a5SMartin Matuska 		exit(1);
95*8a62a2a5SMartin Matuska 	}
96*8a62a2a5SMartin Matuska 
97*8a62a2a5SMartin Matuska 	/* create and open file, read+write */
98*8a62a2a5SMartin Matuska 	int fd = open(argv[1], O_CREAT|O_RDONLY, S_IRWXU|S_IRWXG|S_IRWXO);
99*8a62a2a5SMartin Matuska 	if (fd < 0) {
100*8a62a2a5SMartin Matuska 		perror("open");
101*8a62a2a5SMartin Matuska 		exit(2);
102*8a62a2a5SMartin Matuska 	}
103*8a62a2a5SMartin Matuska 	printf("ok: opened file RDONLY\n");
104*8a62a2a5SMartin Matuska 
105*8a62a2a5SMartin Matuska 	/* fd starts with no lease */
106*8a62a2a5SMartin Matuska 	assert_lease(fd, F_UNLCK);
107*8a62a2a5SMartin Matuska 
108*8a62a2a5SMartin Matuska 	/* fd is readonly, so can take read lease */
109*8a62a2a5SMartin Matuska 	assert_set_lease(fd, F_RDLCK);
110*8a62a2a5SMartin Matuska 	/* confirm read lease */
111*8a62a2a5SMartin Matuska 	assert_lease(fd, F_RDLCK);
112*8a62a2a5SMartin Matuska 
113*8a62a2a5SMartin Matuska 	/* no other openers, so can take write lease */
114*8a62a2a5SMartin Matuska 	assert_set_lease(fd, F_WRLCK);
115*8a62a2a5SMartin Matuska 	/* confirm write lease */
116*8a62a2a5SMartin Matuska 	assert_lease(fd, F_WRLCK);
117*8a62a2a5SMartin Matuska 
118*8a62a2a5SMartin Matuska 	/* release lease */
119*8a62a2a5SMartin Matuska 	assert_set_lease(fd, F_UNLCK);
120*8a62a2a5SMartin Matuska 	/* confirm lease released */
121*8a62a2a5SMartin Matuska 	assert_lease(fd, F_UNLCK);
122*8a62a2a5SMartin Matuska 
123*8a62a2a5SMartin Matuska 	close(fd);
124*8a62a2a5SMartin Matuska 
125*8a62a2a5SMartin Matuska 	return (0);
126*8a62a2a5SMartin Matuska }
127