]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libzfs/os/linux/libzfs_util_os.c
Vendor import of openzfs master @ 184df27eef0abdc7ab2105b21257f753834b936b
[FreeBSD/FreeBSD.git] / lib / libzfs / os / linux / libzfs_util_os.c
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 <errno.h>
24 #include <fcntl.h>
25 #include <libintl.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <strings.h>
30 #include <unistd.h>
31 #include <math.h>
32 #include <sys/stat.h>
33 #include <sys/mnttab.h>
34 #include <sys/mntent.h>
35 #include <sys/types.h>
36 #include <sys/wait.h>
37
38 #include <libzfs.h>
39 #include <libzfs_core.h>
40
41 #include "libzfs_impl.h"
42 #include "zfs_prop.h"
43 #include <libzutil.h>
44 #include <sys/zfs_sysfs.h>
45
46 #define ZDIFF_SHARESDIR         "/.zfs/shares/"
47
48 int
49 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
50 {
51         return (ioctl(hdl->libzfs_fd, request, zc));
52 }
53
54 const char *
55 libzfs_error_init(int error)
56 {
57         switch (error) {
58         case ENXIO:
59                 return (dgettext(TEXT_DOMAIN, "The ZFS modules are not "
60                     "loaded.\nTry running '/sbin/modprobe zfs' as root "
61                     "to load them."));
62         case ENOENT:
63                 return (dgettext(TEXT_DOMAIN, "/dev/zfs and /proc/self/mounts "
64                     "are required.\nTry running 'udevadm trigger' and 'mount "
65                     "-t proc proc /proc' as root."));
66         case ENOEXEC:
67                 return (dgettext(TEXT_DOMAIN, "The ZFS modules cannot be "
68                     "auto-loaded.\nTry running '/sbin/modprobe zfs' as "
69                     "root to manually load them."));
70         case EACCES:
71                 return (dgettext(TEXT_DOMAIN, "Permission denied the "
72                     "ZFS utilities must be run as root."));
73         default:
74                 return (dgettext(TEXT_DOMAIN, "Failed to initialize the "
75                     "libzfs library."));
76         }
77 }
78
79 static int
80 libzfs_module_loaded(const char *module)
81 {
82         const char path_prefix[] = "/sys/module/";
83         char path[256];
84
85         memcpy(path, path_prefix, sizeof (path_prefix) - 1);
86         strcpy(path + sizeof (path_prefix) - 1, module);
87
88         return (access(path, F_OK) == 0);
89 }
90
91 /*
92  * Verify the required ZFS_DEV device is available and optionally attempt
93  * to load the ZFS modules.  Under normal circumstances the modules
94  * should already have been loaded by some external mechanism.
95  *
96  * Environment variables:
97  * - ZFS_MODULE_LOADING="YES|yes|ON|on" - Attempt to load modules.
98  * - ZFS_MODULE_TIMEOUT="<seconds>"     - Seconds to wait for ZFS_DEV
99  */
100 static int
101 libzfs_load_module_impl(const char *module)
102 {
103         char *argv[4] = {"/sbin/modprobe", "-q", (char *)module, (char *)0};
104         char *load_str, *timeout_str;
105         long timeout = 10; /* seconds */
106         long busy_timeout = 10; /* milliseconds */
107         int load = 0, fd;
108         hrtime_t start;
109
110         /* Optionally request module loading */
111         if (!libzfs_module_loaded(module)) {
112                 load_str = getenv("ZFS_MODULE_LOADING");
113                 if (load_str) {
114                         if (!strncasecmp(load_str, "YES", strlen("YES")) ||
115                             !strncasecmp(load_str, "ON", strlen("ON")))
116                                 load = 1;
117                         else
118                                 load = 0;
119                 }
120
121                 if (load) {
122                         if (libzfs_run_process("/sbin/modprobe", argv, 0))
123                                 return (ENOEXEC);
124                 }
125
126                 if (!libzfs_module_loaded(module))
127                         return (ENXIO);
128         }
129
130         /*
131          * Device creation by udev is asynchronous and waiting may be
132          * required.  Busy wait for 10ms and then fall back to polling every
133          * 10ms for the allowed timeout (default 10s, max 10m).  This is
134          * done to optimize for the common case where the device is
135          * immediately available and to avoid penalizing the possible
136          * case where udev is slow or unable to create the device.
137          */
138         timeout_str = getenv("ZFS_MODULE_TIMEOUT");
139         if (timeout_str) {
140                 timeout = strtol(timeout_str, NULL, 0);
141                 timeout = MAX(MIN(timeout, (10 * 60)), 0); /* 0 <= N <= 600 */
142         }
143
144         start = gethrtime();
145         do {
146                 fd = open(ZFS_DEV, O_RDWR);
147                 if (fd >= 0) {
148                         (void) close(fd);
149                         return (0);
150                 } else if (errno != ENOENT) {
151                         return (errno);
152                 } else if (NSEC2MSEC(gethrtime() - start) < busy_timeout) {
153                         sched_yield();
154                 } else {
155                         usleep(10 * MILLISEC);
156                 }
157         } while (NSEC2MSEC(gethrtime() - start) < (timeout * MILLISEC));
158
159         return (ENOENT);
160 }
161
162 int
163 libzfs_load_module(void)
164 {
165         return (libzfs_load_module_impl(ZFS_DRIVER));
166 }
167
168 int
169 find_shares_object(differ_info_t *di)
170 {
171         char fullpath[MAXPATHLEN];
172         struct stat64 sb = { 0 };
173
174         (void) strlcpy(fullpath, di->dsmnt, MAXPATHLEN);
175         (void) strlcat(fullpath, ZDIFF_SHARESDIR, MAXPATHLEN);
176
177         if (stat64(fullpath, &sb) != 0) {
178                 (void) snprintf(di->errbuf, sizeof (di->errbuf),
179                     dgettext(TEXT_DOMAIN, "Cannot stat %s"), fullpath);
180                 return (zfs_error(di->zhp->zfs_hdl, EZFS_DIFF, di->errbuf));
181         }
182
183         di->shares = (uint64_t)sb.st_ino;
184         return (0);
185 }
186
187 /*
188  * Fill given version buffer with zfs kernel version read from ZFS_SYSFS_DIR
189  * Returns 0 on success, and -1 on error (with errno set)
190  */
191 int
192 zfs_version_kernel(char *version, int len)
193 {
194         int _errno;
195         int fd;
196         int rlen;
197
198         if ((fd = open(ZFS_SYSFS_DIR "/version", O_RDONLY)) == -1)
199                 return (-1);
200
201         if ((rlen = read(fd, version, len)) == -1) {
202                 version[0] = '\0';
203                 _errno = errno;
204                 (void) close(fd);
205                 errno = _errno;
206                 return (-1);
207         }
208
209         version[rlen-1] = '\0';  /* discard '\n' */
210
211         if (close(fd) == -1)
212                 return (-1);
213
214         return (0);
215 }