The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_util_os.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 https://opensource.org/licenses/CDDL-1.0.
   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  * Copyright (c) 2021 Klara, Inc.
   24  */
   25 
   26 #include <alloca.h>
   27 #include <errno.h>
   28 #include <fcntl.h>
   29 #include <libintl.h>
   30 #include <math.h>
   31 #include <poll.h>
   32 #include <stdarg.h>
   33 #include <stdio.h>
   34 #include <stdlib.h>
   35 #include <strings.h>
   36 #include <sys/inotify.h>
   37 #include <sys/mntent.h>
   38 #include <sys/mnttab.h>
   39 #include <sys/stat.h>
   40 #include <sys/timerfd.h>
   41 #include <sys/types.h>
   42 #include <sys/wait.h>
   43 #include <unistd.h>
   44 
   45 #include <libzfs.h>
   46 #include <libzfs_core.h>
   47 
   48 #include "../../libzfs_impl.h"
   49 #include "zfs_prop.h"
   50 #include <libzutil.h>
   51 #include <sys/zfs_sysfs.h>
   52 
   53 #define ZDIFF_SHARESDIR         "/.zfs/shares/"
   54 
   55 int
   56 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
   57 {
   58         return (ioctl(hdl->libzfs_fd, request, zc));
   59 }
   60 
   61 const char *
   62 libzfs_error_init(int error)
   63 {
   64         switch (error) {
   65         case ENXIO:
   66                 return (dgettext(TEXT_DOMAIN, "The ZFS modules are not "
   67                     "loaded.\nTry running 'modprobe zfs' as root "
   68                     "to load them."));
   69         case ENOENT:
   70                 return (dgettext(TEXT_DOMAIN, "/dev/zfs and /proc/self/mounts "
   71                     "are required.\nTry running 'udevadm trigger' and 'mount "
   72                     "-t proc proc /proc' as root."));
   73         case ENOEXEC:
   74                 return (dgettext(TEXT_DOMAIN, "The ZFS modules cannot be "
   75                     "auto-loaded.\nTry running 'modprobe zfs' as "
   76                     "root to manually load them."));
   77         case EACCES:
   78                 return (dgettext(TEXT_DOMAIN, "Permission denied the "
   79                     "ZFS utilities must be run as root."));
   80         default:
   81                 return (dgettext(TEXT_DOMAIN, "Failed to initialize the "
   82                     "libzfs library."));
   83         }
   84 }
   85 
   86 /*
   87  * zfs(4) is loaded by udev if there's a fstype=zfs device present,
   88  * but if there isn't, load them automatically;
   89  * always wait for ZFS_DEV to appear via udev.
   90  *
   91  * Environment variables:
   92  * - ZFS_MODULE_TIMEOUT="<seconds>" - Seconds to wait for ZFS_DEV,
   93  *                                    defaults to 10, max. 10 min.
   94  */
   95 int
   96 libzfs_load_module(void)
   97 {
   98         if (access(ZFS_DEV, F_OK) == 0)
   99                 return (0);
  100 
  101         if (access(ZFS_SYSFS_DIR, F_OK) != 0) {
  102                 char *argv[] = {(char *)"modprobe", (char *)"zfs", NULL};
  103                 if (libzfs_run_process("modprobe", argv, 0))
  104                         return (ENOEXEC);
  105 
  106                 if (access(ZFS_SYSFS_DIR, F_OK) != 0)
  107                         return (ENXIO);
  108         }
  109 
  110         const char *timeout_str = getenv("ZFS_MODULE_TIMEOUT");
  111         int seconds = 10;
  112         if (timeout_str)
  113                 seconds = MIN(strtol(timeout_str, NULL, 0), 600);
  114         struct itimerspec timeout = {.it_value.tv_sec = MAX(seconds, 0)};
  115 
  116         int ino = inotify_init1(IN_CLOEXEC);
  117         if (ino == -1)
  118                 return (ENOENT);
  119         inotify_add_watch(ino, ZFS_DEVDIR, IN_CREATE);
  120 
  121         if (access(ZFS_DEV, F_OK) == 0) {
  122                 close(ino);
  123                 return (0);
  124         } else if (seconds == 0) {
  125                 close(ino);
  126                 return (ENOENT);
  127         }
  128 
  129         size_t evsz = sizeof (struct inotify_event) + NAME_MAX + 1;
  130         struct inotify_event *ev = alloca(evsz);
  131 
  132         int tout = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
  133         if (tout == -1) {
  134                 close(ino);
  135                 return (ENOENT);
  136         }
  137         timerfd_settime(tout, 0, &timeout, NULL);
  138 
  139         int ret = ENOENT;
  140         struct pollfd pfds[] = {
  141                 {.fd = ino, .events = POLLIN},
  142                 {.fd = tout, .events = POLLIN},
  143         };
  144         while (poll(pfds, ARRAY_SIZE(pfds), -1) != -1) {
  145                 if (pfds[0].revents & POLLIN) {
  146                         verify(read(ino, ev, evsz) >
  147                             sizeof (struct inotify_event));
  148                         if (strncmp(ev->name, &ZFS_DEV[sizeof (ZFS_DEVDIR)],
  149                             ev->len) == 0) {
  150                                 ret = 0;
  151                                 break;
  152                         }
  153                 }
  154                 if (pfds[1].revents & POLLIN)
  155                         break;
  156         }
  157         close(tout);
  158         close(ino);
  159         return (ret);
  160 }
  161 
  162 int
  163 find_shares_object(differ_info_t *di)
  164 {
  165         char fullpath[MAXPATHLEN];
  166         struct stat64 sb = { 0 };
  167 
  168         (void) strlcpy(fullpath, di->dsmnt, MAXPATHLEN);
  169         (void) strlcat(fullpath, ZDIFF_SHARESDIR, MAXPATHLEN);
  170 
  171         if (stat64(fullpath, &sb) != 0) {
  172                 (void) snprintf(di->errbuf, sizeof (di->errbuf),
  173                     dgettext(TEXT_DOMAIN, "Cannot stat %s"), fullpath);
  174                 return (zfs_error(di->zhp->zfs_hdl, EZFS_DIFF, di->errbuf));
  175         }
  176 
  177         di->shares = (uint64_t)sb.st_ino;
  178         return (0);
  179 }
  180 
  181 int
  182 zfs_destroy_snaps_nvl_os(libzfs_handle_t *hdl, nvlist_t *snaps)
  183 {
  184         (void) hdl, (void) snaps;
  185         return (0);
  186 }
  187 
  188 /*
  189  * Return allocated loaded module version, or NULL on error (with errno set)
  190  */
  191 char *
  192 zfs_version_kernel(void)
  193 {
  194         FILE *f = fopen(ZFS_SYSFS_DIR "/version", "re");
  195         if (f == NULL)
  196                 return (NULL);
  197 
  198         char *ret = NULL;
  199         size_t l;
  200         ssize_t read;
  201         if ((read = getline(&ret, &l, f)) == -1) {
  202                 int err = errno;
  203                 fclose(f);
  204                 errno = err;
  205                 return (NULL);
  206         }
  207 
  208         fclose(f);
  209         if (ret[read - 1] == '\n')
  210                 ret[read - 1] = '\0';
  211         return (ret);
  212 }
  213 
  214 /*
  215  * Add or delete the given filesystem to/from the given user namespace.
  216  */
  217 int
  218 zfs_userns(zfs_handle_t *zhp, const char *nspath, int attach)
  219 {
  220         libzfs_handle_t *hdl = zhp->zfs_hdl;
  221         zfs_cmd_t zc = {"\0"};
  222         char errbuf[1024];
  223         unsigned long cmd;
  224         int ret;
  225 
  226         if (attach) {
  227                 (void) snprintf(errbuf, sizeof (errbuf),
  228                     dgettext(TEXT_DOMAIN, "cannot add '%s' to namespace"),
  229                     zhp->zfs_name);
  230         } else {
  231                 (void) snprintf(errbuf, sizeof (errbuf),
  232                     dgettext(TEXT_DOMAIN, "cannot remove '%s' from namespace"),
  233                     zhp->zfs_name);
  234         }
  235 
  236         switch (zhp->zfs_type) {
  237         case ZFS_TYPE_VOLUME:
  238                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
  239                     "volumes can not be namespaced"));
  240                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
  241         case ZFS_TYPE_SNAPSHOT:
  242                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
  243                     "snapshots can not be namespaced"));
  244                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
  245         case ZFS_TYPE_BOOKMARK:
  246                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
  247                     "bookmarks can not be namespaced"));
  248                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
  249         case ZFS_TYPE_VDEV:
  250                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
  251                     "vdevs can not be namespaced"));
  252                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
  253         case ZFS_TYPE_INVALID:
  254                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
  255                     "invalid zfs_type_t: ZFS_TYPE_INVALID"));
  256                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
  257         case ZFS_TYPE_POOL:
  258                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
  259                     "pools can not be namespaced"));
  260                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
  261         case ZFS_TYPE_FILESYSTEM:
  262                 break;
  263         }
  264         assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
  265 
  266         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
  267         zc.zc_objset_type = DMU_OST_ZFS;
  268         zc.zc_cleanup_fd = open(nspath, O_RDONLY);
  269         if (zc.zc_cleanup_fd < 0) {
  270                 return (zfs_error(hdl, EZFS_NOT_USER_NAMESPACE, errbuf));
  271         }
  272 
  273         cmd = attach ? ZFS_IOC_USERNS_ATTACH : ZFS_IOC_USERNS_DETACH;
  274         if ((ret = zfs_ioctl(hdl, cmd, &zc)) != 0)
  275                 zfs_standard_error(hdl, errno, errbuf);
  276 
  277         (void) close(zc.zc_cleanup_fd);
  278 
  279         return (ret);
  280 }

Cache object: 06843e5176655c34f170897dbf0a6574


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.