xref: /freebsd-src/sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_util_os.c (revision e3aa18ad71782a73d3dd9dd3d526bbd2b607ca16)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 
23 #include <alloca.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <libintl.h>
27 #include <math.h>
28 #include <poll.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <strings.h>
33 #include <sys/inotify.h>
34 #include <sys/mntent.h>
35 #include <sys/mnttab.h>
36 #include <sys/stat.h>
37 #include <sys/timerfd.h>
38 #include <sys/types.h>
39 #include <sys/wait.h>
40 #include <unistd.h>
41 
42 #include <libzfs.h>
43 #include <libzfs_core.h>
44 
45 #include "../../libzfs_impl.h"
46 #include "zfs_prop.h"
47 #include <libzutil.h>
48 #include <sys/zfs_sysfs.h>
49 
50 #define	ZDIFF_SHARESDIR		"/.zfs/shares/"
51 
52 int
53 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
54 {
55 	return (ioctl(hdl->libzfs_fd, request, zc));
56 }
57 
58 const char *
59 libzfs_error_init(int error)
60 {
61 	switch (error) {
62 	case ENXIO:
63 		return (dgettext(TEXT_DOMAIN, "The ZFS modules are not "
64 		    "loaded.\nTry running 'modprobe zfs' as root "
65 		    "to load them."));
66 	case ENOENT:
67 		return (dgettext(TEXT_DOMAIN, "/dev/zfs and /proc/self/mounts "
68 		    "are required.\nTry running 'udevadm trigger' and 'mount "
69 		    "-t proc proc /proc' as root."));
70 	case ENOEXEC:
71 		return (dgettext(TEXT_DOMAIN, "The ZFS modules cannot be "
72 		    "auto-loaded.\nTry running 'modprobe zfs' as "
73 		    "root to manually load them."));
74 	case EACCES:
75 		return (dgettext(TEXT_DOMAIN, "Permission denied the "
76 		    "ZFS utilities must be run as root."));
77 	default:
78 		return (dgettext(TEXT_DOMAIN, "Failed to initialize the "
79 		    "libzfs library."));
80 	}
81 }
82 
83 /*
84  * zfs(4) is loaded by udev if there's a fstype=zfs device present,
85  * but if there isn't, load them automatically;
86  * always wait for ZFS_DEV to appear via udev.
87  *
88  * Environment variables:
89  * - ZFS_MODULE_TIMEOUT="<seconds>" - Seconds to wait for ZFS_DEV,
90  *                                    defaults to 10, max. 10 min.
91  */
92 int
93 libzfs_load_module(void)
94 {
95 	if (access(ZFS_DEV, F_OK) == 0)
96 		return (0);
97 
98 	if (access(ZFS_SYSFS_DIR, F_OK) != 0) {
99 		char *argv[] = {"modprobe", "zfs", NULL};
100 		if (libzfs_run_process("modprobe", argv, 0))
101 			return (ENOEXEC);
102 
103 		if (access(ZFS_SYSFS_DIR, F_OK) != 0)
104 			return (ENXIO);
105 	}
106 
107 	const char *timeout_str = getenv("ZFS_MODULE_TIMEOUT");
108 	int seconds = 10;
109 	if (timeout_str)
110 		seconds = MIN(strtol(timeout_str, NULL, 0), 600);
111 	struct itimerspec timeout = {.it_value.tv_sec = MAX(seconds, 0)};
112 
113 	int ino = inotify_init1(IN_CLOEXEC);
114 	if (ino == -1)
115 		return (ENOENT);
116 	inotify_add_watch(ino, ZFS_DEVDIR, IN_CREATE);
117 
118 	if (access(ZFS_DEV, F_OK) == 0) {
119 		close(ino);
120 		return (0);
121 	} else if (seconds == 0) {
122 		close(ino);
123 		return (ENOENT);
124 	}
125 
126 	size_t evsz = sizeof (struct inotify_event) + NAME_MAX + 1;
127 	struct inotify_event *ev = alloca(evsz);
128 
129 	int tout = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
130 	if (tout == -1) {
131 		close(ino);
132 		return (ENOENT);
133 	}
134 	timerfd_settime(tout, 0, &timeout, NULL);
135 
136 	int ret = ENOENT;
137 	struct pollfd pfds[] = {
138 		{.fd = ino, .events = POLLIN},
139 		{.fd = tout, .events = POLLIN},
140 	};
141 	while (poll(pfds, ARRAY_SIZE(pfds), -1) != -1) {
142 		if (pfds[0].revents & POLLIN) {
143 			verify(read(ino, ev, evsz) >
144 			    sizeof (struct inotify_event));
145 			if (strcmp(ev->name, &ZFS_DEV[sizeof (ZFS_DEVDIR)])
146 			    == 0) {
147 				ret = 0;
148 				break;
149 			}
150 		}
151 		if (pfds[1].revents & POLLIN)
152 			break;
153 	}
154 	close(tout);
155 	close(ino);
156 	return (ret);
157 }
158 
159 int
160 find_shares_object(differ_info_t *di)
161 {
162 	char fullpath[MAXPATHLEN];
163 	struct stat64 sb = { 0 };
164 
165 	(void) strlcpy(fullpath, di->dsmnt, MAXPATHLEN);
166 	(void) strlcat(fullpath, ZDIFF_SHARESDIR, MAXPATHLEN);
167 
168 	if (stat64(fullpath, &sb) != 0) {
169 		(void) snprintf(di->errbuf, sizeof (di->errbuf),
170 		    dgettext(TEXT_DOMAIN, "Cannot stat %s"), fullpath);
171 		return (zfs_error(di->zhp->zfs_hdl, EZFS_DIFF, di->errbuf));
172 	}
173 
174 	di->shares = (uint64_t)sb.st_ino;
175 	return (0);
176 }
177 
178 int
179 zfs_destroy_snaps_nvl_os(libzfs_handle_t *hdl, nvlist_t *snaps)
180 {
181 	(void) hdl, (void) snaps;
182 	return (0);
183 }
184 
185 /*
186  * Return allocated loaded module version, or NULL on error (with errno set)
187  */
188 char *
189 zfs_version_kernel(void)
190 {
191 	FILE *f = fopen(ZFS_SYSFS_DIR "/version", "re");
192 	if (f == NULL)
193 		return (NULL);
194 
195 	char *ret = NULL;
196 	size_t l;
197 	ssize_t read;
198 	if ((read = getline(&ret, &l, f)) == -1) {
199 		int err = errno;
200 		fclose(f);
201 		errno = err;
202 		return (NULL);
203 	}
204 
205 	fclose(f);
206 	if (ret[read - 1] == '\n')
207 		ret[read - 1] = '\0';
208 	return (ret);
209 }
210