xref: /freebsd-src/sys/contrib/openzfs/cmd/zed/zed_file.c (revision 1603881667360c015f6685131f2f25474fa67a72)
1eda14cbcSMatt Macy /*
2180f8225SMatt Macy  * This file is part of the ZFS Event Daemon (ZED).
3180f8225SMatt Macy  *
4eda14cbcSMatt Macy  * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
5eda14cbcSMatt Macy  * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
6*16038816SMartin Matuska  * Refer to the OpenZFS git commit log for authoritative copyright attribution.
7eda14cbcSMatt Macy  *
8eda14cbcSMatt Macy  * The contents of this file are subject to the terms of the
9eda14cbcSMatt Macy  * Common Development and Distribution License Version 1.0 (CDDL-1.0).
10eda14cbcSMatt Macy  * You can obtain a copy of the license from the top-level file
11eda14cbcSMatt Macy  * "OPENSOLARIS.LICENSE" or at <http://opensource.org/licenses/CDDL-1.0>.
12eda14cbcSMatt Macy  * You may not use this file except in compliance with the license.
13eda14cbcSMatt Macy  */
14eda14cbcSMatt Macy 
15*16038816SMartin Matuska #include <dirent.h>
16eda14cbcSMatt Macy #include <errno.h>
17eda14cbcSMatt Macy #include <fcntl.h>
18eda14cbcSMatt Macy #include <limits.h>
19eda14cbcSMatt Macy #include <string.h>
20eda14cbcSMatt Macy #include <sys/stat.h>
21eda14cbcSMatt Macy #include <sys/types.h>
22eda14cbcSMatt Macy #include <unistd.h>
23eda14cbcSMatt Macy #include "zed_file.h"
24eda14cbcSMatt Macy #include "zed_log.h"
25eda14cbcSMatt Macy 
26eda14cbcSMatt Macy /*
27eda14cbcSMatt Macy  * Set an exclusive advisory lock on the open file descriptor [fd].
28eda14cbcSMatt Macy  * Return 0 on success, 1 if a conflicting lock is held by another process,
29eda14cbcSMatt Macy  * or -1 on error (with errno set).
30eda14cbcSMatt Macy  */
31eda14cbcSMatt Macy int
zed_file_lock(int fd)32eda14cbcSMatt Macy zed_file_lock(int fd)
33eda14cbcSMatt Macy {
34eda14cbcSMatt Macy 	struct flock lock;
35eda14cbcSMatt Macy 
36eda14cbcSMatt Macy 	if (fd < 0) {
37eda14cbcSMatt Macy 		errno = EBADF;
38eda14cbcSMatt Macy 		return (-1);
39eda14cbcSMatt Macy 	}
40eda14cbcSMatt Macy 	lock.l_type = F_WRLCK;
41eda14cbcSMatt Macy 	lock.l_whence = SEEK_SET;
42eda14cbcSMatt Macy 	lock.l_start = 0;
43eda14cbcSMatt Macy 	lock.l_len = 0;
44eda14cbcSMatt Macy 
45eda14cbcSMatt Macy 	if (fcntl(fd, F_SETLK, &lock) < 0) {
46eda14cbcSMatt Macy 		if ((errno == EACCES) || (errno == EAGAIN))
47eda14cbcSMatt Macy 			return (1);
48eda14cbcSMatt Macy 
49eda14cbcSMatt Macy 		return (-1);
50eda14cbcSMatt Macy 	}
51eda14cbcSMatt Macy 	return (0);
52eda14cbcSMatt Macy }
53eda14cbcSMatt Macy 
54eda14cbcSMatt Macy /*
55eda14cbcSMatt Macy  * Release an advisory lock held on the open file descriptor [fd].
56eda14cbcSMatt Macy  * Return 0 on success, or -1 on error (with errno set).
57eda14cbcSMatt Macy  */
58eda14cbcSMatt Macy int
zed_file_unlock(int fd)59eda14cbcSMatt Macy zed_file_unlock(int fd)
60eda14cbcSMatt Macy {
61eda14cbcSMatt Macy 	struct flock lock;
62eda14cbcSMatt Macy 
63eda14cbcSMatt Macy 	if (fd < 0) {
64eda14cbcSMatt Macy 		errno = EBADF;
65eda14cbcSMatt Macy 		return (-1);
66eda14cbcSMatt Macy 	}
67eda14cbcSMatt Macy 	lock.l_type = F_UNLCK;
68eda14cbcSMatt Macy 	lock.l_whence = SEEK_SET;
69eda14cbcSMatt Macy 	lock.l_start = 0;
70eda14cbcSMatt Macy 	lock.l_len = 0;
71eda14cbcSMatt Macy 
72eda14cbcSMatt Macy 	if (fcntl(fd, F_SETLK, &lock) < 0)
73eda14cbcSMatt Macy 		return (-1);
74eda14cbcSMatt Macy 
75eda14cbcSMatt Macy 	return (0);
76eda14cbcSMatt Macy }
77eda14cbcSMatt Macy 
78eda14cbcSMatt Macy /*
79eda14cbcSMatt Macy  * Test whether an exclusive advisory lock could be obtained for the open
80eda14cbcSMatt Macy  * file descriptor [fd].
81eda14cbcSMatt Macy  * Return 0 if the file is not locked, >0 for the PID of another process
82eda14cbcSMatt Macy  * holding a conflicting lock, or -1 on error (with errno set).
83eda14cbcSMatt Macy  */
84eda14cbcSMatt Macy pid_t
zed_file_is_locked(int fd)85eda14cbcSMatt Macy zed_file_is_locked(int fd)
86eda14cbcSMatt Macy {
87eda14cbcSMatt Macy 	struct flock lock;
88eda14cbcSMatt Macy 
89eda14cbcSMatt Macy 	if (fd < 0) {
90eda14cbcSMatt Macy 		errno = EBADF;
91eda14cbcSMatt Macy 		return (-1);
92eda14cbcSMatt Macy 	}
93eda14cbcSMatt Macy 	lock.l_type = F_WRLCK;
94eda14cbcSMatt Macy 	lock.l_whence = SEEK_SET;
95eda14cbcSMatt Macy 	lock.l_start = 0;
96eda14cbcSMatt Macy 	lock.l_len = 0;
97eda14cbcSMatt Macy 
98eda14cbcSMatt Macy 	if (fcntl(fd, F_GETLK, &lock) < 0)
99eda14cbcSMatt Macy 		return (-1);
100eda14cbcSMatt Macy 
101eda14cbcSMatt Macy 	if (lock.l_type == F_UNLCK)
102eda14cbcSMatt Macy 		return (0);
103eda14cbcSMatt Macy 
104eda14cbcSMatt Macy 	return (lock.l_pid);
105eda14cbcSMatt Macy }
106eda14cbcSMatt Macy 
107*16038816SMartin Matuska 
108*16038816SMartin Matuska #if __APPLE__
109*16038816SMartin Matuska #define	PROC_SELF_FD "/dev/fd"
110*16038816SMartin Matuska #else /* Linux-compatible layout */
111*16038816SMartin Matuska #define	PROC_SELF_FD "/proc/self/fd"
112*16038816SMartin Matuska #endif
113*16038816SMartin Matuska 
114eda14cbcSMatt Macy /*
115eda14cbcSMatt Macy  * Close all open file descriptors greater than or equal to [lowfd].
116eda14cbcSMatt Macy  * Any errors encountered while closing file descriptors are ignored.
117eda14cbcSMatt Macy  */
118eda14cbcSMatt Macy void
zed_file_close_from(int lowfd)119eda14cbcSMatt Macy zed_file_close_from(int lowfd)
120eda14cbcSMatt Macy {
121*16038816SMartin Matuska 	int errno_bak = errno;
122*16038816SMartin Matuska 	int maxfd = 0;
123eda14cbcSMatt Macy 	int fd;
124*16038816SMartin Matuska 	DIR *fddir;
125*16038816SMartin Matuska 	struct dirent *fdent;
126eda14cbcSMatt Macy 
127*16038816SMartin Matuska 	if ((fddir = opendir(PROC_SELF_FD)) != NULL) {
128*16038816SMartin Matuska 		while ((fdent = readdir(fddir)) != NULL) {
129*16038816SMartin Matuska 			fd = atoi(fdent->d_name);
130*16038816SMartin Matuska 			if (fd > maxfd && fd != dirfd(fddir))
131*16038816SMartin Matuska 				maxfd = fd;
132*16038816SMartin Matuska 		}
133*16038816SMartin Matuska 		(void) closedir(fddir);
134eda14cbcSMatt Macy 	} else {
135*16038816SMartin Matuska 		maxfd = sysconf(_SC_OPEN_MAX);
136eda14cbcSMatt Macy 	}
137eda14cbcSMatt Macy 	for (fd = lowfd; fd < maxfd; fd++)
138eda14cbcSMatt Macy 		(void) close(fd);
139eda14cbcSMatt Macy 
140eda14cbcSMatt Macy 	errno = errno_bak;
141eda14cbcSMatt Macy }
142