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/cmd/zed/zed_conf.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  * This file is part of the ZFS Event Daemon (ZED).
    3  *
    4  * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
    5  * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
    6  * Refer to the OpenZFS git commit log for authoritative copyright attribution.
    7  *
    8  * The contents of this file are subject to the terms of the
    9  * Common Development and Distribution License Version 1.0 (CDDL-1.0).
   10  * You can obtain a copy of the license from the top-level file
   11  * "OPENSOLARIS.LICENSE" or at <http://opensource.org/licenses/CDDL-1.0>.
   12  * You may not use this file except in compliance with the license.
   13  */
   14 
   15 #include <assert.h>
   16 #include <ctype.h>
   17 #include <dirent.h>
   18 #include <errno.h>
   19 #include <fcntl.h>
   20 #include <libgen.h>
   21 #include <limits.h>
   22 #include <stdio.h>
   23 #include <stdlib.h>
   24 #include <string.h>
   25 #include <sys/types.h>
   26 #include <sys/stat.h>
   27 #include <sys/uio.h>
   28 #include <unistd.h>
   29 #include "zed.h"
   30 #include "zed_conf.h"
   31 #include "zed_file.h"
   32 #include "zed_log.h"
   33 #include "zed_strings.h"
   34 
   35 /*
   36  * Initialise the configuration with default values.
   37  */
   38 void
   39 zed_conf_init(struct zed_conf *zcp)
   40 {
   41         memset(zcp, 0, sizeof (*zcp));
   42 
   43         /* zcp->zfs_hdl opened in zed_event_init() */
   44         /* zcp->zedlets created in zed_conf_scan_dir() */
   45 
   46         zcp->pid_fd = -1;               /* opened in zed_conf_write_pid() */
   47         zcp->state_fd = -1;             /* opened in zed_conf_open_state() */
   48         zcp->zevent_fd = -1;            /* opened in zed_event_init() */
   49 
   50         zcp->max_jobs = 16;
   51         zcp->max_zevent_buf_len = 1 << 20;
   52 
   53         if (!(zcp->pid_file = strdup(ZED_PID_FILE)) ||
   54             !(zcp->zedlet_dir = strdup(ZED_ZEDLET_DIR)) ||
   55             !(zcp->state_file = strdup(ZED_STATE_FILE)))
   56                 zed_log_die("Failed to create conf: %s", strerror(errno));
   57 }
   58 
   59 /*
   60  * Destroy the configuration [zcp].
   61  *
   62  * Note: zfs_hdl & zevent_fd are destroyed via zed_event_fini().
   63  */
   64 void
   65 zed_conf_destroy(struct zed_conf *zcp)
   66 {
   67         if (zcp->state_fd >= 0) {
   68                 if (close(zcp->state_fd) < 0)
   69                         zed_log_msg(LOG_WARNING,
   70                             "Failed to close state file \"%s\": %s",
   71                             zcp->state_file, strerror(errno));
   72                 zcp->state_fd = -1;
   73         }
   74         if (zcp->pid_file) {
   75                 if ((unlink(zcp->pid_file) < 0) && (errno != ENOENT))
   76                         zed_log_msg(LOG_WARNING,
   77                             "Failed to remove PID file \"%s\": %s",
   78                             zcp->pid_file, strerror(errno));
   79         }
   80         if (zcp->pid_fd >= 0) {
   81                 if (close(zcp->pid_fd) < 0)
   82                         zed_log_msg(LOG_WARNING,
   83                             "Failed to close PID file \"%s\": %s",
   84                             zcp->pid_file, strerror(errno));
   85                 zcp->pid_fd = -1;
   86         }
   87         if (zcp->pid_file) {
   88                 free(zcp->pid_file);
   89                 zcp->pid_file = NULL;
   90         }
   91         if (zcp->zedlet_dir) {
   92                 free(zcp->zedlet_dir);
   93                 zcp->zedlet_dir = NULL;
   94         }
   95         if (zcp->state_file) {
   96                 free(zcp->state_file);
   97                 zcp->state_file = NULL;
   98         }
   99         if (zcp->zedlets) {
  100                 zed_strings_destroy(zcp->zedlets);
  101                 zcp->zedlets = NULL;
  102         }
  103 }
  104 
  105 /*
  106  * Display command-line help and exit.
  107  *
  108  * If [got_err] is 0, output to stdout and exit normally;
  109  * otherwise, output to stderr and exit with a failure status.
  110  */
  111 static void
  112 _zed_conf_display_help(const char *prog, boolean_t got_err)
  113 {
  114         struct opt { const char *o, *d, *v; };
  115 
  116         FILE *fp = got_err ? stderr : stdout;
  117 
  118         struct opt *oo;
  119         struct opt iopts[] = {
  120                 { .o = "-h", .d = "Display help" },
  121                 { .o = "-L", .d = "Display license information" },
  122                 { .o = "-V", .d = "Display version information" },
  123                 {},
  124         };
  125         struct opt nopts[] = {
  126                 { .o = "-v", .d = "Be verbose" },
  127                 { .o = "-f", .d = "Force daemon to run" },
  128                 { .o = "-F", .d = "Run daemon in the foreground" },
  129                 { .o = "-I",
  130                     .d = "Idle daemon until kernel module is (re)loaded" },
  131                 { .o = "-M", .d = "Lock all pages in memory" },
  132                 { .o = "-P", .d = "$PATH for ZED to use (only used by ZTS)" },
  133                 { .o = "-Z", .d = "Zero state file" },
  134                 {},
  135         };
  136         struct opt vopts[] = {
  137                 { .o = "-d DIR", .d = "Read enabled ZEDLETs from DIR.",
  138                     .v = ZED_ZEDLET_DIR },
  139                 { .o = "-p FILE", .d = "Write daemon's PID to FILE.",
  140                     .v = ZED_PID_FILE },
  141                 { .o = "-s FILE", .d = "Write daemon's state to FILE.",
  142                     .v = ZED_STATE_FILE },
  143                 { .o = "-j JOBS", .d = "Start at most JOBS at once.",
  144                     .v = "16" },
  145                 { .o = "-b LEN", .d = "Cap kernel event buffer at LEN entries.",
  146                     .v = "1048576" },
  147                 {},
  148         };
  149 
  150         fprintf(fp, "Usage: %s [OPTION]...\n", (prog ? prog : "zed"));
  151         fprintf(fp, "\n");
  152         for (oo = iopts; oo->o; ++oo)
  153                 fprintf(fp, "    %*s %s\n", -8, oo->o, oo->d);
  154         fprintf(fp, "\n");
  155         for (oo = nopts; oo->o; ++oo)
  156                 fprintf(fp, "    %*s %s\n", -8, oo->o, oo->d);
  157         fprintf(fp, "\n");
  158         for (oo = vopts; oo->o; ++oo)
  159                 fprintf(fp, "    %*s %s [%s]\n", -8, oo->o, oo->d, oo->v);
  160         fprintf(fp, "\n");
  161 
  162         exit(got_err ? EXIT_FAILURE : EXIT_SUCCESS);
  163 }
  164 
  165 /*
  166  * Display license information to stdout and exit.
  167  */
  168 static void
  169 _zed_conf_display_license(void)
  170 {
  171         printf(
  172             "The ZFS Event Daemon (ZED) is distributed under the terms of the\n"
  173             "  Common Development and Distribution License (CDDL-1.0)\n"
  174             "  <http://opensource.org/licenses/CDDL-1.0>.\n"
  175             "\n"
  176             "Developed at Lawrence Livermore National Laboratory"
  177             " (LLNL-CODE-403049).\n"
  178             "\n");
  179 
  180         exit(EXIT_SUCCESS);
  181 }
  182 
  183 /*
  184  * Display version information to stdout and exit.
  185  */
  186 static void
  187 _zed_conf_display_version(void)
  188 {
  189         printf("%s-%s-%s\n",
  190             ZFS_META_NAME, ZFS_META_VERSION, ZFS_META_RELEASE);
  191 
  192         exit(EXIT_SUCCESS);
  193 }
  194 
  195 /*
  196  * Copy the [path] string to the [resultp] ptr.
  197  * If [path] is not an absolute path, prefix it with the current working dir.
  198  * If [resultp] is non-null, free its existing string before assignment.
  199  */
  200 static void
  201 _zed_conf_parse_path(char **resultp, const char *path)
  202 {
  203         char buf[PATH_MAX];
  204 
  205         assert(resultp != NULL);
  206         assert(path != NULL);
  207 
  208         if (*resultp)
  209                 free(*resultp);
  210 
  211         if (path[0] == '/') {
  212                 *resultp = strdup(path);
  213         } else {
  214                 if (!getcwd(buf, sizeof (buf)))
  215                         zed_log_die("Failed to get current working dir: %s",
  216                             strerror(errno));
  217 
  218                 if (strlcat(buf, "/", sizeof (buf)) >= sizeof (buf) ||
  219                     strlcat(buf, path, sizeof (buf)) >= sizeof (buf))
  220                         zed_log_die("Failed to copy path: %s",
  221                             strerror(ENAMETOOLONG));
  222 
  223                 *resultp = strdup(buf);
  224         }
  225 
  226         if (!*resultp)
  227                 zed_log_die("Failed to copy path: %s", strerror(ENOMEM));
  228 }
  229 
  230 /*
  231  * Parse the command-line options into the configuration [zcp].
  232  */
  233 void
  234 zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv)
  235 {
  236         const char * const opts = ":hLVd:p:P:s:vfFMZIj:b:";
  237         int opt;
  238         unsigned long raw;
  239 
  240         if (!zcp || !argv || !argv[0])
  241                 zed_log_die("Failed to parse options: Internal error");
  242 
  243         opterr = 0;                     /* suppress default getopt err msgs */
  244 
  245         while ((opt = getopt(argc, argv, opts)) != -1) {
  246                 switch (opt) {
  247                 case 'h':
  248                         _zed_conf_display_help(argv[0], B_FALSE);
  249                         break;
  250                 case 'L':
  251                         _zed_conf_display_license();
  252                         break;
  253                 case 'V':
  254                         _zed_conf_display_version();
  255                         break;
  256                 case 'd':
  257                         _zed_conf_parse_path(&zcp->zedlet_dir, optarg);
  258                         break;
  259                 case 'I':
  260                         zcp->do_idle = 1;
  261                         break;
  262                 case 'p':
  263                         _zed_conf_parse_path(&zcp->pid_file, optarg);
  264                         break;
  265                 case 'P':
  266                         _zed_conf_parse_path(&zcp->path, optarg);
  267                         break;
  268                 case 's':
  269                         _zed_conf_parse_path(&zcp->state_file, optarg);
  270                         break;
  271                 case 'v':
  272                         zcp->do_verbose = 1;
  273                         break;
  274                 case 'f':
  275                         zcp->do_force = 1;
  276                         break;
  277                 case 'F':
  278                         zcp->do_foreground = 1;
  279                         break;
  280                 case 'M':
  281                         zcp->do_memlock = 1;
  282                         break;
  283                 case 'Z':
  284                         zcp->do_zero = 1;
  285                         break;
  286                 case 'j':
  287                         errno = 0;
  288                         raw = strtoul(optarg, NULL, 0);
  289                         if (errno == ERANGE || raw > INT16_MAX) {
  290                                 zed_log_die("%lu is too many jobs", raw);
  291                         } if (raw == 0) {
  292                                 zed_log_die("0 jobs makes no sense");
  293                         } else {
  294                                 zcp->max_jobs = raw;
  295                         }
  296                         break;
  297                 case 'b':
  298                         errno = 0;
  299                         raw = strtoul(optarg, NULL, 0);
  300                         if (errno == ERANGE || raw > INT32_MAX) {
  301                                 zed_log_die("%lu is too large", raw);
  302                         } if (raw == 0) {
  303                                 zcp->max_zevent_buf_len = INT32_MAX;
  304                         } else {
  305                                 zcp->max_zevent_buf_len = raw;
  306                         }
  307                         break;
  308                 case '?':
  309                 default:
  310                         if (optopt == '?')
  311                                 _zed_conf_display_help(argv[0], B_FALSE);
  312 
  313                         fprintf(stderr, "%s: Invalid option '-%c'\n\n",
  314                             argv[0], optopt);
  315                         _zed_conf_display_help(argv[0], B_TRUE);
  316                         break;
  317                 }
  318         }
  319 }
  320 
  321 /*
  322  * Scan the [zcp] zedlet_dir for files to exec based on the event class.
  323  * Files must be executable by user, but not writable by group or other.
  324  * Dotfiles are ignored.
  325  *
  326  * Return 0 on success with an updated set of zedlets,
  327  * or -1 on error with errno set.
  328  */
  329 int
  330 zed_conf_scan_dir(struct zed_conf *zcp)
  331 {
  332         zed_strings_t *zedlets;
  333         DIR *dirp;
  334         struct dirent *direntp;
  335         char pathname[PATH_MAX];
  336         struct stat st;
  337         int n;
  338 
  339         if (!zcp) {
  340                 errno = EINVAL;
  341                 zed_log_msg(LOG_ERR, "Failed to scan zedlet dir: %s",
  342                     strerror(errno));
  343                 return (-1);
  344         }
  345         zedlets = zed_strings_create();
  346         if (!zedlets) {
  347                 errno = ENOMEM;
  348                 zed_log_msg(LOG_WARNING, "Failed to scan dir \"%s\": %s",
  349                     zcp->zedlet_dir, strerror(errno));
  350                 return (-1);
  351         }
  352         dirp = opendir(zcp->zedlet_dir);
  353         if (!dirp) {
  354                 int errno_bak = errno;
  355                 zed_log_msg(LOG_WARNING, "Failed to open dir \"%s\": %s",
  356                     zcp->zedlet_dir, strerror(errno));
  357                 zed_strings_destroy(zedlets);
  358                 errno = errno_bak;
  359                 return (-1);
  360         }
  361         while ((direntp = readdir(dirp))) {
  362                 if (direntp->d_name[0] == '.')
  363                         continue;
  364 
  365                 n = snprintf(pathname, sizeof (pathname),
  366                     "%s/%s", zcp->zedlet_dir, direntp->d_name);
  367                 if ((n < 0) || (n >= sizeof (pathname))) {
  368                         zed_log_msg(LOG_WARNING, "Failed to stat \"%s\": %s",
  369                             direntp->d_name, strerror(ENAMETOOLONG));
  370                         continue;
  371                 }
  372                 if (stat(pathname, &st) < 0) {
  373                         zed_log_msg(LOG_WARNING, "Failed to stat \"%s\": %s",
  374                             pathname, strerror(errno));
  375                         continue;
  376                 }
  377                 if (!S_ISREG(st.st_mode)) {
  378                         zed_log_msg(LOG_INFO,
  379                             "Ignoring \"%s\": not a regular file",
  380                             direntp->d_name);
  381                         continue;
  382                 }
  383                 if ((st.st_uid != 0) && !zcp->do_force) {
  384                         zed_log_msg(LOG_NOTICE,
  385                             "Ignoring \"%s\": not owned by root",
  386                             direntp->d_name);
  387                         continue;
  388                 }
  389                 if (!(st.st_mode & S_IXUSR)) {
  390                         zed_log_msg(LOG_INFO,
  391                             "Ignoring \"%s\": not executable by user",
  392                             direntp->d_name);
  393                         continue;
  394                 }
  395                 if ((st.st_mode & S_IWGRP) && !zcp->do_force) {
  396                         zed_log_msg(LOG_NOTICE,
  397                             "Ignoring \"%s\": writable by group",
  398                             direntp->d_name);
  399                         continue;
  400                 }
  401                 if ((st.st_mode & S_IWOTH) && !zcp->do_force) {
  402                         zed_log_msg(LOG_NOTICE,
  403                             "Ignoring \"%s\": writable by other",
  404                             direntp->d_name);
  405                         continue;
  406                 }
  407                 if (zed_strings_add(zedlets, NULL, direntp->d_name) < 0) {
  408                         zed_log_msg(LOG_WARNING,
  409                             "Failed to register \"%s\": %s",
  410                             direntp->d_name, strerror(errno));
  411                         continue;
  412                 }
  413                 if (zcp->do_verbose)
  414                         zed_log_msg(LOG_INFO,
  415                             "Registered zedlet \"%s\"", direntp->d_name);
  416         }
  417         if (closedir(dirp) < 0) {
  418                 int errno_bak = errno;
  419                 zed_log_msg(LOG_WARNING, "Failed to close dir \"%s\": %s",
  420                     zcp->zedlet_dir, strerror(errno));
  421                 zed_strings_destroy(zedlets);
  422                 errno = errno_bak;
  423                 return (-1);
  424         }
  425         if (zcp->zedlets)
  426                 zed_strings_destroy(zcp->zedlets);
  427 
  428         zcp->zedlets = zedlets;
  429         return (0);
  430 }
  431 
  432 /*
  433  * Write the PID file specified in [zcp].
  434  * Return 0 on success, -1 on error.
  435  *
  436  * This must be called after fork()ing to become a daemon (so the correct PID
  437  * is recorded), but before daemonization is complete and the parent process
  438  * exits (for synchronization with systemd).
  439  */
  440 int
  441 zed_conf_write_pid(struct zed_conf *zcp)
  442 {
  443         char buf[PATH_MAX];
  444         int n;
  445         char *p;
  446         mode_t mask;
  447         int rv;
  448 
  449         if (!zcp || !zcp->pid_file) {
  450                 errno = EINVAL;
  451                 zed_log_msg(LOG_ERR, "Failed to create PID file: %s",
  452                     strerror(errno));
  453                 return (-1);
  454         }
  455         assert(zcp->pid_fd == -1);
  456         /*
  457          * Create PID file directory if needed.
  458          */
  459         n = strlcpy(buf, zcp->pid_file, sizeof (buf));
  460         if (n >= sizeof (buf)) {
  461                 errno = ENAMETOOLONG;
  462                 zed_log_msg(LOG_ERR, "Failed to create PID file: %s",
  463                     strerror(errno));
  464                 goto err;
  465         }
  466         p = strrchr(buf, '/');
  467         if (p)
  468                 *p = '\0';
  469 
  470         if ((mkdirp(buf, 0755) < 0) && (errno != EEXIST)) {
  471                 zed_log_msg(LOG_ERR, "Failed to create directory \"%s\": %s",
  472                     buf, strerror(errno));
  473                 goto err;
  474         }
  475         /*
  476          * Obtain PID file lock.
  477          */
  478         mask = umask(0);
  479         umask(mask | 022);
  480         zcp->pid_fd = open(zcp->pid_file, O_RDWR | O_CREAT | O_CLOEXEC, 0644);
  481         umask(mask);
  482         if (zcp->pid_fd < 0) {
  483                 zed_log_msg(LOG_ERR, "Failed to open PID file \"%s\": %s",
  484                     zcp->pid_file, strerror(errno));
  485                 goto err;
  486         }
  487         rv = zed_file_lock(zcp->pid_fd);
  488         if (rv < 0) {
  489                 zed_log_msg(LOG_ERR, "Failed to lock PID file \"%s\": %s",
  490                     zcp->pid_file, strerror(errno));
  491                 goto err;
  492         } else if (rv > 0) {
  493                 pid_t pid = zed_file_is_locked(zcp->pid_fd);
  494                 if (pid < 0) {
  495                         zed_log_msg(LOG_ERR,
  496                             "Failed to test lock on PID file \"%s\"",
  497                             zcp->pid_file);
  498                 } else if (pid > 0) {
  499                         zed_log_msg(LOG_ERR,
  500                             "Found PID %d bound to PID file \"%s\"",
  501                             pid, zcp->pid_file);
  502                 } else {
  503                         zed_log_msg(LOG_ERR,
  504                             "Inconsistent lock state on PID file \"%s\"",
  505                             zcp->pid_file);
  506                 }
  507                 goto err;
  508         }
  509         /*
  510          * Write PID file.
  511          */
  512         n = snprintf(buf, sizeof (buf), "%d\n", (int)getpid());
  513         if ((n < 0) || (n >= sizeof (buf))) {
  514                 errno = ERANGE;
  515                 zed_log_msg(LOG_ERR, "Failed to write PID file \"%s\": %s",
  516                     zcp->pid_file, strerror(errno));
  517         } else if (write(zcp->pid_fd, buf, n) != n) {
  518                 zed_log_msg(LOG_ERR, "Failed to write PID file \"%s\": %s",
  519                     zcp->pid_file, strerror(errno));
  520         } else if (fdatasync(zcp->pid_fd) < 0) {
  521                 zed_log_msg(LOG_ERR, "Failed to sync PID file \"%s\": %s",
  522                     zcp->pid_file, strerror(errno));
  523         } else {
  524                 return (0);
  525         }
  526 
  527 err:
  528         if (zcp->pid_fd >= 0) {
  529                 (void) close(zcp->pid_fd);
  530                 zcp->pid_fd = -1;
  531         }
  532         return (-1);
  533 }
  534 
  535 /*
  536  * Open and lock the [zcp] state_file.
  537  * Return 0 on success, -1 on error.
  538  *
  539  * FIXME: Move state information into kernel.
  540  */
  541 int
  542 zed_conf_open_state(struct zed_conf *zcp)
  543 {
  544         char dirbuf[PATH_MAX];
  545         int n;
  546         char *p;
  547         int rv;
  548 
  549         if (!zcp || !zcp->state_file) {
  550                 errno = EINVAL;
  551                 zed_log_msg(LOG_ERR, "Failed to open state file: %s",
  552                     strerror(errno));
  553                 return (-1);
  554         }
  555         n = strlcpy(dirbuf, zcp->state_file, sizeof (dirbuf));
  556         if (n >= sizeof (dirbuf)) {
  557                 errno = ENAMETOOLONG;
  558                 zed_log_msg(LOG_WARNING, "Failed to open state file: %s",
  559                     strerror(errno));
  560                 return (-1);
  561         }
  562         p = strrchr(dirbuf, '/');
  563         if (p)
  564                 *p = '\0';
  565 
  566         if ((mkdirp(dirbuf, 0755) < 0) && (errno != EEXIST)) {
  567                 zed_log_msg(LOG_WARNING,
  568                     "Failed to create directory \"%s\": %s",
  569                     dirbuf, strerror(errno));
  570                 return (-1);
  571         }
  572         if (zcp->state_fd >= 0) {
  573                 if (close(zcp->state_fd) < 0) {
  574                         zed_log_msg(LOG_WARNING,
  575                             "Failed to close state file \"%s\": %s",
  576                             zcp->state_file, strerror(errno));
  577                         return (-1);
  578                 }
  579         }
  580         if (zcp->do_zero)
  581                 (void) unlink(zcp->state_file);
  582 
  583         zcp->state_fd = open(zcp->state_file,
  584             O_RDWR | O_CREAT | O_CLOEXEC, 0644);
  585         if (zcp->state_fd < 0) {
  586                 zed_log_msg(LOG_WARNING, "Failed to open state file \"%s\": %s",
  587                     zcp->state_file, strerror(errno));
  588                 return (-1);
  589         }
  590         rv = zed_file_lock(zcp->state_fd);
  591         if (rv < 0) {
  592                 zed_log_msg(LOG_WARNING, "Failed to lock state file \"%s\": %s",
  593                     zcp->state_file, strerror(errno));
  594                 return (-1);
  595         }
  596         if (rv > 0) {
  597                 pid_t pid = zed_file_is_locked(zcp->state_fd);
  598                 if (pid < 0) {
  599                         zed_log_msg(LOG_WARNING,
  600                             "Failed to test lock on state file \"%s\"",
  601                             zcp->state_file);
  602                 } else if (pid > 0) {
  603                         zed_log_msg(LOG_WARNING,
  604                             "Found PID %d bound to state file \"%s\"",
  605                             pid, zcp->state_file);
  606                 } else {
  607                         zed_log_msg(LOG_WARNING,
  608                             "Inconsistent lock state on state file \"%s\"",
  609                             zcp->state_file);
  610                 }
  611                 return (-1);
  612         }
  613         return (0);
  614 }
  615 
  616 /*
  617  * Read the opened [zcp] state_file to obtain the eid & etime of the last event
  618  * processed.  Write the state from the last event to the [eidp] & [etime] args
  619  * passed by reference.  Note that etime[] is an array of size 2.
  620  * Return 0 on success, -1 on error.
  621  */
  622 int
  623 zed_conf_read_state(struct zed_conf *zcp, uint64_t *eidp, int64_t etime[])
  624 {
  625         ssize_t len;
  626         struct iovec iov[3];
  627         ssize_t n;
  628 
  629         if (!zcp || !eidp || !etime) {
  630                 errno = EINVAL;
  631                 zed_log_msg(LOG_ERR,
  632                     "Failed to read state file: %s", strerror(errno));
  633                 return (-1);
  634         }
  635         if (lseek(zcp->state_fd, 0, SEEK_SET) == (off_t)-1) {
  636                 zed_log_msg(LOG_WARNING,
  637                     "Failed to reposition state file offset: %s",
  638                     strerror(errno));
  639                 return (-1);
  640         }
  641         len = 0;
  642         iov[0].iov_base = eidp;
  643         len += iov[0].iov_len = sizeof (*eidp);
  644         iov[1].iov_base = &etime[0];
  645         len += iov[1].iov_len = sizeof (etime[0]);
  646         iov[2].iov_base = &etime[1];
  647         len += iov[2].iov_len = sizeof (etime[1]);
  648 
  649         n = readv(zcp->state_fd, iov, 3);
  650         if (n == 0) {
  651                 *eidp = 0;
  652         } else if (n < 0) {
  653                 zed_log_msg(LOG_WARNING,
  654                     "Failed to read state file \"%s\": %s",
  655                     zcp->state_file, strerror(errno));
  656                 return (-1);
  657         } else if (n != len) {
  658                 errno = EIO;
  659                 zed_log_msg(LOG_WARNING,
  660                     "Failed to read state file \"%s\": Read %zd of %zd bytes",
  661                     zcp->state_file, n, len);
  662                 return (-1);
  663         }
  664         return (0);
  665 }
  666 
  667 /*
  668  * Write the [eid] & [etime] of the last processed event to the opened
  669  * [zcp] state_file.  Note that etime[] is an array of size 2.
  670  * Return 0 on success, -1 on error.
  671  */
  672 int
  673 zed_conf_write_state(struct zed_conf *zcp, uint64_t eid, int64_t etime[])
  674 {
  675         ssize_t len;
  676         struct iovec iov[3];
  677         ssize_t n;
  678 
  679         if (!zcp) {
  680                 errno = EINVAL;
  681                 zed_log_msg(LOG_ERR,
  682                     "Failed to write state file: %s", strerror(errno));
  683                 return (-1);
  684         }
  685         if (lseek(zcp->state_fd, 0, SEEK_SET) == (off_t)-1) {
  686                 zed_log_msg(LOG_WARNING,
  687                     "Failed to reposition state file offset: %s",
  688                     strerror(errno));
  689                 return (-1);
  690         }
  691         len = 0;
  692         iov[0].iov_base = &eid;
  693         len += iov[0].iov_len = sizeof (eid);
  694         iov[1].iov_base = &etime[0];
  695         len += iov[1].iov_len = sizeof (etime[0]);
  696         iov[2].iov_base = &etime[1];
  697         len += iov[2].iov_len = sizeof (etime[1]);
  698 
  699         n = writev(zcp->state_fd, iov, 3);
  700         if (n < 0) {
  701                 zed_log_msg(LOG_WARNING,
  702                     "Failed to write state file \"%s\": %s",
  703                     zcp->state_file, strerror(errno));
  704                 return (-1);
  705         }
  706         if (n != len) {
  707                 errno = EIO;
  708                 zed_log_msg(LOG_WARNING,
  709                     "Failed to write state file \"%s\": Wrote %zd of %zd bytes",
  710                     zcp->state_file, n, len);
  711                 return (-1);
  712         }
  713         if (fdatasync(zcp->state_fd) < 0) {
  714                 zed_log_msg(LOG_WARNING,
  715                     "Failed to sync state file \"%s\": %s",
  716                     zcp->state_file, strerror(errno));
  717                 return (-1);
  718         }
  719         return (0);
  720 }

Cache object: 4719656f2e6cd7c5fb4266fd8c90781c


[ 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.