"Fossies" - the Fresh Open Source Software Archive

Member "lxc-4.0.12/src/lxc/sync.c" (2 Feb 2022, 4096 Bytes) of package /linux/misc/lxc-4.0.12.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sync.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 4.0.10_vs_4.0.11.

    1 /* SPDX-License-Identifier: LGPL-2.1+ */
    2 
    3 #include "config.h"
    4 
    5 #include <errno.h>
    6 #include <fcntl.h>
    7 #include <sys/socket.h>
    8 #include <sys/types.h>
    9 #include <unistd.h>
   10 
   11 #include "log.h"
   12 #include "start.h"
   13 #include "sync.h"
   14 #include "utils.h"
   15 
   16 lxc_log_define(sync, lxc);
   17 
   18 bool sync_wait(int fd, int sequence)
   19 {
   20     int sync = -1;
   21     ssize_t ret;
   22 
   23     ret = lxc_read_nointr(fd, &sync, sizeof(sync));
   24     if (ret < 0)
   25         return log_error_errno(false, errno, "Sync wait failure");
   26 
   27     if (!ret)
   28         return true;
   29 
   30     if ((size_t)ret != sizeof(sync))
   31         return log_error(false, "Unexpected sync size: %zu expected %zu", (size_t)ret, sizeof(sync));
   32 
   33     if (sync == SYNC_ERROR)
   34         return log_error(false, "An error occurred in another process (expected sequence number %d)", sequence);
   35 
   36     if (sync != sequence)
   37         return log_error(false, "Invalid sequence number %d. Expected sequence number %d", sync, sequence);
   38 
   39     return true;
   40 }
   41 
   42 bool sync_wake(int fd, int sequence)
   43 {
   44     int sync = sequence;
   45 
   46     if (lxc_write_nointr(fd, &sync, sizeof(sync)) < 0)
   47         return log_error_errno(false, errno, "Sync wake failure");
   48 
   49     return true;
   50 }
   51 
   52 static bool __sync_barrier(int fd, int sequence)
   53 {
   54     if (!sync_wake(fd, sequence))
   55         return false;
   56 
   57     return sync_wait(fd, sequence + 1);
   58 }
   59 
   60 static inline const char *start_sync_to_string(int state)
   61 {
   62     switch (state) {
   63     case START_SYNC_STARTUP:
   64         return "startup";
   65     case START_SYNC_CONFIGURE:
   66         return "configure";
   67     case START_SYNC_POST_CONFIGURE:
   68         return "post-configure";
   69     case START_SYNC_CGROUP_LIMITS:
   70         return "cgroup-limits";
   71     case START_SYNC_IDMAPPED_MOUNTS:
   72         return "idmapped-mounts";
   73     case START_SYNC_FDS:
   74         return "fds";
   75     case START_SYNC_READY_START:
   76         return "ready-start";
   77     case START_SYNC_RESTART:
   78         return "restart";
   79     case START_SYNC_POST_RESTART:
   80         return "post-restart";
   81     case SYNC_ERROR:
   82         return "error";
   83     default:
   84         return "invalid sync state";
   85     }
   86 }
   87 
   88 bool lxc_sync_barrier_parent(struct lxc_handler *handler, int sequence)
   89 {
   90     TRACE("Child waking parent with sequence %s and waiting for sequence %s",
   91           start_sync_to_string(sequence), start_sync_to_string(sequence + 1));
   92     return __sync_barrier(handler->sync_sock[0], sequence);
   93 }
   94 
   95 bool lxc_sync_barrier_child(struct lxc_handler *handler, int sequence)
   96 {
   97     TRACE("Parent waking child with sequence %s and waiting with sequence %s",
   98           start_sync_to_string(sequence), start_sync_to_string(sequence + 1));
   99     return __sync_barrier(handler->sync_sock[1], sequence);
  100 }
  101 
  102 bool lxc_sync_wake_parent(struct lxc_handler *handler, int sequence)
  103 {
  104     TRACE("Child waking parent with sequence %s", start_sync_to_string(sequence));
  105     return sync_wake(handler->sync_sock[0], sequence);
  106 }
  107 
  108 bool lxc_sync_wait_parent(struct lxc_handler *handler, int sequence)
  109 {
  110     TRACE("Child waiting for parent with sequence %s", start_sync_to_string(sequence));
  111     return sync_wait(handler->sync_sock[0], sequence);
  112 }
  113 
  114 bool lxc_sync_wait_child(struct lxc_handler *handler, int sequence)
  115 {
  116     TRACE("Parent waiting for child with sequence %s", start_sync_to_string(sequence));
  117     return sync_wait(handler->sync_sock[1], sequence);
  118 }
  119 
  120 bool lxc_sync_wake_child(struct lxc_handler *handler, int sequence)
  121 {
  122     TRACE("Parent waking child with sequence %s", start_sync_to_string(sequence));
  123     return sync_wake(handler->sync_sock[1], sequence);
  124 }
  125 
  126 bool lxc_sync_init(struct lxc_handler *handler)
  127 {
  128     int ret;
  129 
  130     ret = socketpair(AF_LOCAL, SOCK_STREAM, 0, handler->sync_sock);
  131     if (ret)
  132         return log_error_errno(false, errno, "failed to create synchronization socketpair");
  133 
  134     /* Be sure we don't inherit this after the exec */
  135     ret = fcntl(handler->sync_sock[0], F_SETFD, FD_CLOEXEC);
  136     if (ret < 0)
  137         return log_error_errno(false, errno, "Failed to make socket close-on-exec");
  138 
  139     TRACE("Initialized synchronization infrastructure");
  140     return true;
  141 }
  142 
  143 void lxc_sync_fini_child(struct lxc_handler *handler)
  144 {
  145     close_prot_errno_disarm(handler->sync_sock[0]);
  146 }
  147 
  148 void lxc_sync_fini_parent(struct lxc_handler *handler)
  149 {
  150     close_prot_errno_disarm(handler->sync_sock[1]);
  151 }
  152 
  153 void lxc_sync_fini(struct lxc_handler *handler)
  154 {
  155     lxc_sync_fini_child(handler);
  156     lxc_sync_fini_parent(handler);
  157 }