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 | O_CLOEXEC); 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 int 188 zfs_destroy_snaps_nvl_os(libzfs_handle_t *hdl, nvlist_t *snaps) 189 { 190 (void) hdl, (void) snaps; 191 return (0); 192 } 193 194 /* 195 * Fill given version buffer with zfs kernel version read from ZFS_SYSFS_DIR 196 * Returns 0 on success, and -1 on error (with errno set) 197 */ 198 int 199 zfs_version_kernel(char *version, int len) 200 { 201 int _errno; 202 int fd; 203 int rlen; 204 205 if ((fd = open(ZFS_SYSFS_DIR "/version", O_RDONLY | O_CLOEXEC)) == -1) 206 return (-1); 207 208 if ((rlen = read(fd, version, len)) == -1) { 209 version[0] = '\0'; 210 _errno = errno; 211 (void) close(fd); 212 errno = _errno; 213 return (-1); 214 } 215 216 version[rlen-1] = '\0'; /* discard '\n' */ 217 218 if (close(fd) == -1) 219 return (-1); 220 221 return (0); 222 } 223