1b855f8d1SPaolo Bonzini /* 2b855f8d1SPaolo Bonzini * Privileged helper to handle persistent reservation commands for QEMU 3b855f8d1SPaolo Bonzini * 4b855f8d1SPaolo Bonzini * Copyright (C) 2017 Red Hat, Inc. <pbonzini@redhat.com> 5b855f8d1SPaolo Bonzini * 6b855f8d1SPaolo Bonzini * Author: Paolo Bonzini <pbonzini@redhat.com> 7b855f8d1SPaolo Bonzini * 8b855f8d1SPaolo Bonzini * This program is free software; you can redistribute it and/or modify 9b855f8d1SPaolo Bonzini * it under the terms of the GNU General Public License as published by 10b855f8d1SPaolo Bonzini * the Free Software Foundation; under version 2 of the License. 11b855f8d1SPaolo Bonzini * 12b855f8d1SPaolo Bonzini * This program is distributed in the hope that it will be useful, 13b855f8d1SPaolo Bonzini * but WITHOUT ANY WARRANTY; without even the implied warranty of 14b855f8d1SPaolo Bonzini * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15b855f8d1SPaolo Bonzini * GNU General Public License for more details. 16b855f8d1SPaolo Bonzini * 17b855f8d1SPaolo Bonzini * You should have received a copy of the GNU General Public License 18b855f8d1SPaolo Bonzini * along with this program; if not, see <http://www.gnu.org/licenses/>. 19b855f8d1SPaolo Bonzini */ 20b855f8d1SPaolo Bonzini 21b855f8d1SPaolo Bonzini #include "qemu/osdep.h" 22b855f8d1SPaolo Bonzini #include <getopt.h> 23b855f8d1SPaolo Bonzini #include <sys/ioctl.h> 24b855f8d1SPaolo Bonzini #include <linux/dm-ioctl.h> 25b855f8d1SPaolo Bonzini #include <scsi/sg.h> 26b855f8d1SPaolo Bonzini 27b855f8d1SPaolo Bonzini #ifdef CONFIG_LIBCAP 28b855f8d1SPaolo Bonzini #include <cap-ng.h> 29b855f8d1SPaolo Bonzini #endif 30b855f8d1SPaolo Bonzini #include <pwd.h> 31b855f8d1SPaolo Bonzini #include <grp.h> 32b855f8d1SPaolo Bonzini 33fe8fc5aeSPaolo Bonzini #ifdef CONFIG_MPATH 34fe8fc5aeSPaolo Bonzini #include <libudev.h> 35fe8fc5aeSPaolo Bonzini #include <mpath_cmd.h> 36fe8fc5aeSPaolo Bonzini #include <mpath_persist.h> 37fe8fc5aeSPaolo Bonzini #endif 38fe8fc5aeSPaolo Bonzini 39b855f8d1SPaolo Bonzini #include "qapi/error.h" 40b855f8d1SPaolo Bonzini #include "qemu-common.h" 41b855f8d1SPaolo Bonzini #include "qemu/cutils.h" 42b855f8d1SPaolo Bonzini #include "qemu/main-loop.h" 43b855f8d1SPaolo Bonzini #include "qemu/error-report.h" 44b855f8d1SPaolo Bonzini #include "qemu/config-file.h" 45b855f8d1SPaolo Bonzini #include "qemu/bswap.h" 46b855f8d1SPaolo Bonzini #include "qemu/log.h" 47b855f8d1SPaolo Bonzini #include "qemu/systemd.h" 48b855f8d1SPaolo Bonzini #include "qapi/util.h" 49b855f8d1SPaolo Bonzini #include "qapi/qmp/qstring.h" 50b855f8d1SPaolo Bonzini #include "io/channel-socket.h" 51b855f8d1SPaolo Bonzini #include "trace/control.h" 52b855f8d1SPaolo Bonzini #include "qemu-version.h" 53b855f8d1SPaolo Bonzini 54b855f8d1SPaolo Bonzini #include "block/aio.h" 55b855f8d1SPaolo Bonzini #include "block/thread-pool.h" 56b855f8d1SPaolo Bonzini 57b855f8d1SPaolo Bonzini #include "scsi/constants.h" 58b855f8d1SPaolo Bonzini #include "scsi/utils.h" 59b855f8d1SPaolo Bonzini #include "pr-helper.h" 60b855f8d1SPaolo Bonzini 61b855f8d1SPaolo Bonzini #define PR_OUT_FIXED_PARAM_SIZE 24 62b855f8d1SPaolo Bonzini 63b855f8d1SPaolo Bonzini static char *socket_path; 64b855f8d1SPaolo Bonzini static char *pidfile; 65b855f8d1SPaolo Bonzini static enum { RUNNING, TERMINATE, TERMINATING } state; 66b855f8d1SPaolo Bonzini static QIOChannelSocket *server_ioc; 67b855f8d1SPaolo Bonzini static int server_watch; 68b855f8d1SPaolo Bonzini static int num_active_sockets = 1; 69fe8fc5aeSPaolo Bonzini static int noisy; 70b855f8d1SPaolo Bonzini static int verbose; 71b855f8d1SPaolo Bonzini 72b855f8d1SPaolo Bonzini #ifdef CONFIG_LIBCAP 73b855f8d1SPaolo Bonzini static int uid = -1; 74b855f8d1SPaolo Bonzini static int gid = -1; 75b855f8d1SPaolo Bonzini #endif 76b855f8d1SPaolo Bonzini 7750fa3325SPaolo Bonzini static void compute_default_paths(void) 7850fa3325SPaolo Bonzini { 7950fa3325SPaolo Bonzini socket_path = qemu_get_local_state_pathname("run/qemu-pr-helper.sock"); 802729d79dSMichal Privoznik pidfile = qemu_get_local_state_pathname("run/qemu-pr-helper.pid"); 8150fa3325SPaolo Bonzini } 8250fa3325SPaolo Bonzini 83b855f8d1SPaolo Bonzini static void usage(const char *name) 84b855f8d1SPaolo Bonzini { 85b855f8d1SPaolo Bonzini (printf) ( 86b855f8d1SPaolo Bonzini "Usage: %s [OPTIONS] FILE\n" 87b855f8d1SPaolo Bonzini "Persistent Reservation helper program for QEMU\n" 88b855f8d1SPaolo Bonzini "\n" 89b855f8d1SPaolo Bonzini " -h, --help display this help and exit\n" 90b855f8d1SPaolo Bonzini " -V, --version output version information and exit\n" 91b855f8d1SPaolo Bonzini "\n" 92b855f8d1SPaolo Bonzini " -d, --daemon run in the background\n" 93b855f8d1SPaolo Bonzini " -f, --pidfile=PATH PID file when running as a daemon\n" 94b855f8d1SPaolo Bonzini " (default '%s')\n" 95b855f8d1SPaolo Bonzini " -k, --socket=PATH path to the unix socket\n" 96b855f8d1SPaolo Bonzini " (default '%s')\n" 97b855f8d1SPaolo Bonzini " -T, --trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n" 98b855f8d1SPaolo Bonzini " specify tracing options\n" 99b855f8d1SPaolo Bonzini #ifdef CONFIG_LIBCAP 100b855f8d1SPaolo Bonzini " -u, --user=USER user to drop privileges to\n" 101b855f8d1SPaolo Bonzini " -g, --group=GROUP group to drop privileges to\n" 102b855f8d1SPaolo Bonzini #endif 103b855f8d1SPaolo Bonzini "\n" 104b855f8d1SPaolo Bonzini QEMU_HELP_BOTTOM "\n" 105b855f8d1SPaolo Bonzini , name, pidfile, socket_path); 106b855f8d1SPaolo Bonzini } 107b855f8d1SPaolo Bonzini 108b855f8d1SPaolo Bonzini static void version(const char *name) 109b855f8d1SPaolo Bonzini { 110b855f8d1SPaolo Bonzini printf( 1117e563bfbSThomas Huth "%s " QEMU_FULL_VERSION "\n" 112b855f8d1SPaolo Bonzini "Written by Paolo Bonzini.\n" 113b855f8d1SPaolo Bonzini "\n" 114b855f8d1SPaolo Bonzini QEMU_COPYRIGHT "\n" 115b855f8d1SPaolo Bonzini "This is free software; see the source for copying conditions. There is NO\n" 116b855f8d1SPaolo Bonzini "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" 117b855f8d1SPaolo Bonzini , name); 118b855f8d1SPaolo Bonzini } 119b855f8d1SPaolo Bonzini 120b855f8d1SPaolo Bonzini /* SG_IO support */ 121b855f8d1SPaolo Bonzini 122b855f8d1SPaolo Bonzini typedef struct PRHelperSGIOData { 123b855f8d1SPaolo Bonzini int fd; 124b855f8d1SPaolo Bonzini const uint8_t *cdb; 125b855f8d1SPaolo Bonzini uint8_t *sense; 126b855f8d1SPaolo Bonzini uint8_t *buf; 127b855f8d1SPaolo Bonzini int sz; /* input/output */ 128b855f8d1SPaolo Bonzini int dir; 129b855f8d1SPaolo Bonzini } PRHelperSGIOData; 130b855f8d1SPaolo Bonzini 131b855f8d1SPaolo Bonzini static int do_sgio_worker(void *opaque) 132b855f8d1SPaolo Bonzini { 133b855f8d1SPaolo Bonzini PRHelperSGIOData *data = opaque; 134b855f8d1SPaolo Bonzini struct sg_io_hdr io_hdr; 135b855f8d1SPaolo Bonzini int ret; 136b855f8d1SPaolo Bonzini int status; 137b855f8d1SPaolo Bonzini SCSISense sense_code; 138b855f8d1SPaolo Bonzini 139b855f8d1SPaolo Bonzini memset(data->sense, 0, PR_HELPER_SENSE_SIZE); 140b855f8d1SPaolo Bonzini memset(&io_hdr, 0, sizeof(io_hdr)); 141b855f8d1SPaolo Bonzini io_hdr.interface_id = 'S'; 142b855f8d1SPaolo Bonzini io_hdr.cmd_len = PR_HELPER_CDB_SIZE; 143b855f8d1SPaolo Bonzini io_hdr.cmdp = (uint8_t *)data->cdb; 144b855f8d1SPaolo Bonzini io_hdr.sbp = data->sense; 145b855f8d1SPaolo Bonzini io_hdr.mx_sb_len = PR_HELPER_SENSE_SIZE; 146b855f8d1SPaolo Bonzini io_hdr.timeout = 1; 147b855f8d1SPaolo Bonzini io_hdr.dxfer_direction = data->dir; 148b855f8d1SPaolo Bonzini io_hdr.dxferp = (char *)data->buf; 149b855f8d1SPaolo Bonzini io_hdr.dxfer_len = data->sz; 150b855f8d1SPaolo Bonzini ret = ioctl(data->fd, SG_IO, &io_hdr); 151b855f8d1SPaolo Bonzini status = sg_io_sense_from_errno(ret < 0 ? errno : 0, &io_hdr, 152b855f8d1SPaolo Bonzini &sense_code); 153b855f8d1SPaolo Bonzini if (status == GOOD) { 154b855f8d1SPaolo Bonzini data->sz -= io_hdr.resid; 155b855f8d1SPaolo Bonzini } else { 156b855f8d1SPaolo Bonzini data->sz = 0; 157b855f8d1SPaolo Bonzini } 158b855f8d1SPaolo Bonzini 159b855f8d1SPaolo Bonzini if (status == CHECK_CONDITION && 160b855f8d1SPaolo Bonzini !(io_hdr.driver_status & SG_ERR_DRIVER_SENSE)) { 161b855f8d1SPaolo Bonzini scsi_build_sense(data->sense, sense_code); 162b855f8d1SPaolo Bonzini } 163b855f8d1SPaolo Bonzini 164b855f8d1SPaolo Bonzini return status; 165b855f8d1SPaolo Bonzini } 166b855f8d1SPaolo Bonzini 167b855f8d1SPaolo Bonzini static int do_sgio(int fd, const uint8_t *cdb, uint8_t *sense, 168b855f8d1SPaolo Bonzini uint8_t *buf, int *sz, int dir) 169b855f8d1SPaolo Bonzini { 170b855f8d1SPaolo Bonzini ThreadPool *pool = aio_get_thread_pool(qemu_get_aio_context()); 171b855f8d1SPaolo Bonzini int r; 172b855f8d1SPaolo Bonzini 173b855f8d1SPaolo Bonzini PRHelperSGIOData data = { 174b855f8d1SPaolo Bonzini .fd = fd, 175b855f8d1SPaolo Bonzini .cdb = cdb, 176b855f8d1SPaolo Bonzini .sense = sense, 177b855f8d1SPaolo Bonzini .buf = buf, 178b855f8d1SPaolo Bonzini .sz = *sz, 179b855f8d1SPaolo Bonzini .dir = dir, 180b855f8d1SPaolo Bonzini }; 181b855f8d1SPaolo Bonzini 182b855f8d1SPaolo Bonzini r = thread_pool_submit_co(pool, do_sgio_worker, &data); 183b855f8d1SPaolo Bonzini *sz = data.sz; 184b855f8d1SPaolo Bonzini return r; 185b855f8d1SPaolo Bonzini } 186b855f8d1SPaolo Bonzini 187fe8fc5aeSPaolo Bonzini /* Device mapper interface */ 188fe8fc5aeSPaolo Bonzini 189fe8fc5aeSPaolo Bonzini #ifdef CONFIG_MPATH 190fe8fc5aeSPaolo Bonzini #define CONTROL_PATH "/dev/mapper/control" 191fe8fc5aeSPaolo Bonzini 192fe8fc5aeSPaolo Bonzini typedef struct DMData { 193fe8fc5aeSPaolo Bonzini struct dm_ioctl dm; 194fe8fc5aeSPaolo Bonzini uint8_t data[1024]; 195fe8fc5aeSPaolo Bonzini } DMData; 196fe8fc5aeSPaolo Bonzini 197fe8fc5aeSPaolo Bonzini static int control_fd; 198fe8fc5aeSPaolo Bonzini 199fe8fc5aeSPaolo Bonzini static void *dm_ioctl(int ioc, struct dm_ioctl *dm) 200fe8fc5aeSPaolo Bonzini { 201fe8fc5aeSPaolo Bonzini static DMData d; 202fe8fc5aeSPaolo Bonzini memcpy(&d.dm, dm, sizeof(d.dm)); 203fe8fc5aeSPaolo Bonzini QEMU_BUILD_BUG_ON(sizeof(d.data) < sizeof(struct dm_target_spec)); 204fe8fc5aeSPaolo Bonzini 205fe8fc5aeSPaolo Bonzini d.dm.version[0] = DM_VERSION_MAJOR; 206fe8fc5aeSPaolo Bonzini d.dm.version[1] = 0; 207fe8fc5aeSPaolo Bonzini d.dm.version[2] = 0; 208fe8fc5aeSPaolo Bonzini d.dm.data_size = 1024; 209fe8fc5aeSPaolo Bonzini d.dm.data_start = offsetof(DMData, data); 210fe8fc5aeSPaolo Bonzini if (ioctl(control_fd, ioc, &d) < 0) { 211fe8fc5aeSPaolo Bonzini return NULL; 212fe8fc5aeSPaolo Bonzini } 213fe8fc5aeSPaolo Bonzini memcpy(dm, &d.dm, sizeof(d.dm)); 214fe8fc5aeSPaolo Bonzini return &d.data; 215fe8fc5aeSPaolo Bonzini } 216fe8fc5aeSPaolo Bonzini 217fe8fc5aeSPaolo Bonzini static void *dm_dev_ioctl(int fd, int ioc, struct dm_ioctl *dm) 218fe8fc5aeSPaolo Bonzini { 219fe8fc5aeSPaolo Bonzini struct stat st; 220fe8fc5aeSPaolo Bonzini int r; 221fe8fc5aeSPaolo Bonzini 222fe8fc5aeSPaolo Bonzini r = fstat(fd, &st); 223fe8fc5aeSPaolo Bonzini if (r < 0) { 224fe8fc5aeSPaolo Bonzini perror("fstat"); 225fe8fc5aeSPaolo Bonzini exit(1); 226fe8fc5aeSPaolo Bonzini } 227fe8fc5aeSPaolo Bonzini 228fe8fc5aeSPaolo Bonzini dm->dev = st.st_rdev; 229fe8fc5aeSPaolo Bonzini return dm_ioctl(ioc, dm); 230fe8fc5aeSPaolo Bonzini } 231fe8fc5aeSPaolo Bonzini 232fe8fc5aeSPaolo Bonzini static void dm_init(void) 233fe8fc5aeSPaolo Bonzini { 234fe8fc5aeSPaolo Bonzini control_fd = open(CONTROL_PATH, O_RDWR); 235fe8fc5aeSPaolo Bonzini if (control_fd < 0) { 236fe8fc5aeSPaolo Bonzini perror("Cannot open " CONTROL_PATH); 237fe8fc5aeSPaolo Bonzini exit(1); 238fe8fc5aeSPaolo Bonzini } 239*039d4e3dSJohn Snow struct dm_ioctl dm = { }; 240fe8fc5aeSPaolo Bonzini if (!dm_ioctl(DM_VERSION, &dm)) { 241fe8fc5aeSPaolo Bonzini perror("ioctl"); 242fe8fc5aeSPaolo Bonzini exit(1); 243fe8fc5aeSPaolo Bonzini } 244fe8fc5aeSPaolo Bonzini if (dm.version[0] != DM_VERSION_MAJOR) { 245fe8fc5aeSPaolo Bonzini fprintf(stderr, "Unsupported device mapper interface"); 246fe8fc5aeSPaolo Bonzini exit(1); 247fe8fc5aeSPaolo Bonzini } 248fe8fc5aeSPaolo Bonzini } 249fe8fc5aeSPaolo Bonzini 250fe8fc5aeSPaolo Bonzini /* Variables required by libmultipath and libmpathpersist. */ 251fe8fc5aeSPaolo Bonzini QEMU_BUILD_BUG_ON(PR_HELPER_DATA_SIZE > MPATH_MAX_PARAM_LEN); 252b3f1c8c4SPaolo Bonzini static struct config *multipath_conf; 253fe8fc5aeSPaolo Bonzini unsigned mpath_mx_alloc_len = PR_HELPER_DATA_SIZE; 254fe8fc5aeSPaolo Bonzini int logsink; 255b3f1c8c4SPaolo Bonzini struct udev *udev; 256b3f1c8c4SPaolo Bonzini 257b3f1c8c4SPaolo Bonzini extern struct config *get_multipath_config(void); 258b3f1c8c4SPaolo Bonzini struct config *get_multipath_config(void) 259b3f1c8c4SPaolo Bonzini { 260b3f1c8c4SPaolo Bonzini return multipath_conf; 261b3f1c8c4SPaolo Bonzini } 262b3f1c8c4SPaolo Bonzini 263b3f1c8c4SPaolo Bonzini extern void put_multipath_config(struct config *conf); 264b3f1c8c4SPaolo Bonzini void put_multipath_config(struct config *conf) 265b3f1c8c4SPaolo Bonzini { 266b3f1c8c4SPaolo Bonzini } 267fe8fc5aeSPaolo Bonzini 268fe8fc5aeSPaolo Bonzini static void multipath_pr_init(void) 269fe8fc5aeSPaolo Bonzini { 270fe8fc5aeSPaolo Bonzini udev = udev_new(); 2711b0578f5SMurilo Opsfelder Araujo #ifdef CONFIG_MPATH_NEW_API 272b3f1c8c4SPaolo Bonzini multipath_conf = mpath_lib_init(); 2731b0578f5SMurilo Opsfelder Araujo #else 2741b0578f5SMurilo Opsfelder Araujo mpath_lib_init(udev); 2751b0578f5SMurilo Opsfelder Araujo #endif 276fe8fc5aeSPaolo Bonzini } 277fe8fc5aeSPaolo Bonzini 278fe8fc5aeSPaolo Bonzini static int is_mpath(int fd) 279fe8fc5aeSPaolo Bonzini { 280fe8fc5aeSPaolo Bonzini struct dm_ioctl dm = { .flags = DM_NOFLUSH_FLAG }; 281fe8fc5aeSPaolo Bonzini struct dm_target_spec *tgt; 282fe8fc5aeSPaolo Bonzini 283fe8fc5aeSPaolo Bonzini tgt = dm_dev_ioctl(fd, DM_TABLE_STATUS, &dm); 284fe8fc5aeSPaolo Bonzini if (!tgt) { 285fe8fc5aeSPaolo Bonzini if (errno == ENXIO) { 286fe8fc5aeSPaolo Bonzini return 0; 287fe8fc5aeSPaolo Bonzini } 288fe8fc5aeSPaolo Bonzini perror("ioctl"); 289fe8fc5aeSPaolo Bonzini exit(EXIT_FAILURE); 290fe8fc5aeSPaolo Bonzini } 291fe8fc5aeSPaolo Bonzini return !strncmp(tgt->target_type, "multipath", DM_MAX_TYPE_NAME); 292fe8fc5aeSPaolo Bonzini } 293fe8fc5aeSPaolo Bonzini 294a4a9b6eaSPaolo Bonzini static SCSISense mpath_generic_sense(int r) 295a4a9b6eaSPaolo Bonzini { 296a4a9b6eaSPaolo Bonzini switch (r) { 297a4a9b6eaSPaolo Bonzini case MPATH_PR_SENSE_NOT_READY: 298a4a9b6eaSPaolo Bonzini return SENSE_CODE(NOT_READY); 299a4a9b6eaSPaolo Bonzini case MPATH_PR_SENSE_MEDIUM_ERROR: 300a4a9b6eaSPaolo Bonzini return SENSE_CODE(READ_ERROR); 301a4a9b6eaSPaolo Bonzini case MPATH_PR_SENSE_HARDWARE_ERROR: 302a4a9b6eaSPaolo Bonzini return SENSE_CODE(TARGET_FAILURE); 303a4a9b6eaSPaolo Bonzini case MPATH_PR_SENSE_ABORTED_COMMAND: 304a4a9b6eaSPaolo Bonzini return SENSE_CODE(IO_ERROR); 305a4a9b6eaSPaolo Bonzini default: 306a4a9b6eaSPaolo Bonzini abort(); 307a4a9b6eaSPaolo Bonzini } 308a4a9b6eaSPaolo Bonzini } 309a4a9b6eaSPaolo Bonzini 310fe8fc5aeSPaolo Bonzini static int mpath_reconstruct_sense(int fd, int r, uint8_t *sense) 311fe8fc5aeSPaolo Bonzini { 312fe8fc5aeSPaolo Bonzini switch (r) { 313fe8fc5aeSPaolo Bonzini case MPATH_PR_SUCCESS: 314fe8fc5aeSPaolo Bonzini return GOOD; 315fe8fc5aeSPaolo Bonzini case MPATH_PR_SENSE_NOT_READY: 316fe8fc5aeSPaolo Bonzini case MPATH_PR_SENSE_MEDIUM_ERROR: 317fe8fc5aeSPaolo Bonzini case MPATH_PR_SENSE_HARDWARE_ERROR: 318fe8fc5aeSPaolo Bonzini case MPATH_PR_SENSE_ABORTED_COMMAND: 319fe8fc5aeSPaolo Bonzini { 320fe8fc5aeSPaolo Bonzini /* libmpathpersist ate the exact sense. Try to find it by 321fe8fc5aeSPaolo Bonzini * issuing TEST UNIT READY. 322fe8fc5aeSPaolo Bonzini */ 323fe8fc5aeSPaolo Bonzini uint8_t cdb[6] = { TEST_UNIT_READY }; 324fe8fc5aeSPaolo Bonzini int sz = 0; 325a4a9b6eaSPaolo Bonzini int r = do_sgio(fd, cdb, sense, NULL, &sz, SG_DXFER_NONE); 326a4a9b6eaSPaolo Bonzini 327a4a9b6eaSPaolo Bonzini if (r != GOOD) { 328a4a9b6eaSPaolo Bonzini return r; 329a4a9b6eaSPaolo Bonzini } 330a4a9b6eaSPaolo Bonzini scsi_build_sense(sense, mpath_generic_sense(r)); 331a4a9b6eaSPaolo Bonzini return CHECK_CONDITION; 332fe8fc5aeSPaolo Bonzini } 333fe8fc5aeSPaolo Bonzini 334fe8fc5aeSPaolo Bonzini case MPATH_PR_SENSE_UNIT_ATTENTION: 335fe8fc5aeSPaolo Bonzini /* Congratulations libmpathpersist, you ruined the Unit Attention... 336fe8fc5aeSPaolo Bonzini * Return a heavyweight one. 337fe8fc5aeSPaolo Bonzini */ 338fe8fc5aeSPaolo Bonzini scsi_build_sense(sense, SENSE_CODE(SCSI_BUS_RESET)); 339fe8fc5aeSPaolo Bonzini return CHECK_CONDITION; 340fe8fc5aeSPaolo Bonzini case MPATH_PR_SENSE_INVALID_OP: 341fe8fc5aeSPaolo Bonzini /* Only one valid sense. */ 342fe8fc5aeSPaolo Bonzini scsi_build_sense(sense, SENSE_CODE(INVALID_OPCODE)); 343fe8fc5aeSPaolo Bonzini return CHECK_CONDITION; 344fe8fc5aeSPaolo Bonzini case MPATH_PR_ILLEGAL_REQ: 345fe8fc5aeSPaolo Bonzini /* Guess. */ 346fe8fc5aeSPaolo Bonzini scsi_build_sense(sense, SENSE_CODE(INVALID_PARAM)); 347fe8fc5aeSPaolo Bonzini return CHECK_CONDITION; 348fe8fc5aeSPaolo Bonzini case MPATH_PR_NO_SENSE: 349fe8fc5aeSPaolo Bonzini scsi_build_sense(sense, SENSE_CODE(NO_SENSE)); 350fe8fc5aeSPaolo Bonzini return CHECK_CONDITION; 351fe8fc5aeSPaolo Bonzini 352fe8fc5aeSPaolo Bonzini case MPATH_PR_RESERV_CONFLICT: 353fe8fc5aeSPaolo Bonzini return RESERVATION_CONFLICT; 354fe8fc5aeSPaolo Bonzini 355fe8fc5aeSPaolo Bonzini case MPATH_PR_OTHER: 356fe8fc5aeSPaolo Bonzini default: 357fe8fc5aeSPaolo Bonzini scsi_build_sense(sense, SENSE_CODE(LUN_COMM_FAILURE)); 358fe8fc5aeSPaolo Bonzini return CHECK_CONDITION; 359fe8fc5aeSPaolo Bonzini } 360fe8fc5aeSPaolo Bonzini } 361fe8fc5aeSPaolo Bonzini 362fe8fc5aeSPaolo Bonzini static int multipath_pr_in(int fd, const uint8_t *cdb, uint8_t *sense, 363fe8fc5aeSPaolo Bonzini uint8_t *data, int sz) 364fe8fc5aeSPaolo Bonzini { 365fe8fc5aeSPaolo Bonzini int rq_servact = cdb[1]; 366fe8fc5aeSPaolo Bonzini struct prin_resp resp; 367fe8fc5aeSPaolo Bonzini size_t written; 368fe8fc5aeSPaolo Bonzini int r; 369fe8fc5aeSPaolo Bonzini 370fe8fc5aeSPaolo Bonzini switch (rq_servact) { 371fe8fc5aeSPaolo Bonzini case MPATH_PRIN_RKEY_SA: 372fe8fc5aeSPaolo Bonzini case MPATH_PRIN_RRES_SA: 373fe8fc5aeSPaolo Bonzini case MPATH_PRIN_RCAP_SA: 374fe8fc5aeSPaolo Bonzini break; 375fe8fc5aeSPaolo Bonzini case MPATH_PRIN_RFSTAT_SA: 376fe8fc5aeSPaolo Bonzini /* Nobody implements it anyway, so bail out. */ 377fe8fc5aeSPaolo Bonzini default: 378fe8fc5aeSPaolo Bonzini /* Cannot parse any other output. */ 379fe8fc5aeSPaolo Bonzini scsi_build_sense(sense, SENSE_CODE(INVALID_FIELD)); 380fe8fc5aeSPaolo Bonzini return CHECK_CONDITION; 381fe8fc5aeSPaolo Bonzini } 382fe8fc5aeSPaolo Bonzini 383fe8fc5aeSPaolo Bonzini r = mpath_persistent_reserve_in(fd, rq_servact, &resp, noisy, verbose); 384fe8fc5aeSPaolo Bonzini if (r == MPATH_PR_SUCCESS) { 385fe8fc5aeSPaolo Bonzini switch (rq_servact) { 386fe8fc5aeSPaolo Bonzini case MPATH_PRIN_RKEY_SA: 387fe8fc5aeSPaolo Bonzini case MPATH_PRIN_RRES_SA: { 388fe8fc5aeSPaolo Bonzini struct prin_readdescr *out = &resp.prin_descriptor.prin_readkeys; 389fe8fc5aeSPaolo Bonzini assert(sz >= 8); 390fe8fc5aeSPaolo Bonzini written = MIN(out->additional_length + 8, sz); 391fe8fc5aeSPaolo Bonzini stl_be_p(&data[0], out->prgeneration); 392fe8fc5aeSPaolo Bonzini stl_be_p(&data[4], out->additional_length); 393fe8fc5aeSPaolo Bonzini memcpy(&data[8], out->key_list, written - 8); 394fe8fc5aeSPaolo Bonzini break; 395fe8fc5aeSPaolo Bonzini } 396fe8fc5aeSPaolo Bonzini case MPATH_PRIN_RCAP_SA: { 397fe8fc5aeSPaolo Bonzini struct prin_capdescr *out = &resp.prin_descriptor.prin_readcap; 398fe8fc5aeSPaolo Bonzini assert(sz >= 6); 399fe8fc5aeSPaolo Bonzini written = 6; 400fe8fc5aeSPaolo Bonzini stw_be_p(&data[0], out->length); 401fe8fc5aeSPaolo Bonzini data[2] = out->flags[0]; 402fe8fc5aeSPaolo Bonzini data[3] = out->flags[1]; 403fe8fc5aeSPaolo Bonzini stw_be_p(&data[4], out->pr_type_mask); 404fe8fc5aeSPaolo Bonzini break; 405fe8fc5aeSPaolo Bonzini } 406fe8fc5aeSPaolo Bonzini default: 407fe8fc5aeSPaolo Bonzini scsi_build_sense(sense, SENSE_CODE(INVALID_OPCODE)); 408fe8fc5aeSPaolo Bonzini return CHECK_CONDITION; 409fe8fc5aeSPaolo Bonzini } 410fe8fc5aeSPaolo Bonzini assert(written <= sz); 411fe8fc5aeSPaolo Bonzini memset(data + written, 0, sz - written); 412fe8fc5aeSPaolo Bonzini } 413fe8fc5aeSPaolo Bonzini 414fe8fc5aeSPaolo Bonzini return mpath_reconstruct_sense(fd, r, sense); 415fe8fc5aeSPaolo Bonzini } 416fe8fc5aeSPaolo Bonzini 417fe8fc5aeSPaolo Bonzini static int multipath_pr_out(int fd, const uint8_t *cdb, uint8_t *sense, 418fe8fc5aeSPaolo Bonzini const uint8_t *param, int sz) 419fe8fc5aeSPaolo Bonzini { 420fe8fc5aeSPaolo Bonzini int rq_servact = cdb[1]; 421fe8fc5aeSPaolo Bonzini int rq_scope = cdb[2] >> 4; 422fe8fc5aeSPaolo Bonzini int rq_type = cdb[2] & 0xf; 423fe8fc5aeSPaolo Bonzini struct prout_param_descriptor paramp; 424fe8fc5aeSPaolo Bonzini char transportids[PR_HELPER_DATA_SIZE]; 425fe8fc5aeSPaolo Bonzini int r; 426fe8fc5aeSPaolo Bonzini 427ee8c13b8SPaolo Bonzini if (sz < PR_OUT_FIXED_PARAM_SIZE) { 428ee8c13b8SPaolo Bonzini /* Illegal request, Parameter list length error. This isn't fatal; 429ee8c13b8SPaolo Bonzini * we have read the data, send an error without closing the socket. 430ee8c13b8SPaolo Bonzini */ 431ee8c13b8SPaolo Bonzini scsi_build_sense(sense, SENSE_CODE(INVALID_PARAM_LEN)); 432ee8c13b8SPaolo Bonzini return CHECK_CONDITION; 433ee8c13b8SPaolo Bonzini } 434ee8c13b8SPaolo Bonzini 435fe8fc5aeSPaolo Bonzini switch (rq_servact) { 436fe8fc5aeSPaolo Bonzini case MPATH_PROUT_REG_SA: 437fe8fc5aeSPaolo Bonzini case MPATH_PROUT_RES_SA: 438fe8fc5aeSPaolo Bonzini case MPATH_PROUT_REL_SA: 439fe8fc5aeSPaolo Bonzini case MPATH_PROUT_CLEAR_SA: 440fe8fc5aeSPaolo Bonzini case MPATH_PROUT_PREE_SA: 441fe8fc5aeSPaolo Bonzini case MPATH_PROUT_PREE_AB_SA: 442fe8fc5aeSPaolo Bonzini case MPATH_PROUT_REG_IGN_SA: 443fe8fc5aeSPaolo Bonzini break; 444fe8fc5aeSPaolo Bonzini case MPATH_PROUT_REG_MOV_SA: 445fe8fc5aeSPaolo Bonzini /* Not supported by struct prout_param_descriptor. */ 446fe8fc5aeSPaolo Bonzini default: 447fe8fc5aeSPaolo Bonzini /* Cannot parse any other input. */ 448fe8fc5aeSPaolo Bonzini scsi_build_sense(sense, SENSE_CODE(INVALID_FIELD)); 449fe8fc5aeSPaolo Bonzini return CHECK_CONDITION; 450fe8fc5aeSPaolo Bonzini } 451fe8fc5aeSPaolo Bonzini 452fe8fc5aeSPaolo Bonzini /* Convert input data, especially transport IDs, to the structs 453fe8fc5aeSPaolo Bonzini * used by libmpathpersist (which, of course, will immediately 454fe8fc5aeSPaolo Bonzini * do the opposite). 455fe8fc5aeSPaolo Bonzini */ 456fe8fc5aeSPaolo Bonzini memset(¶mp, 0, sizeof(paramp)); 457fe8fc5aeSPaolo Bonzini memcpy(¶mp.key, ¶m[0], 8); 458fe8fc5aeSPaolo Bonzini memcpy(¶mp.sa_key, ¶m[8], 8); 459a4a9b6eaSPaolo Bonzini paramp.sa_flags = param[20]; 460fe8fc5aeSPaolo Bonzini if (sz > PR_OUT_FIXED_PARAM_SIZE) { 461fe8fc5aeSPaolo Bonzini size_t transportid_len; 462fe8fc5aeSPaolo Bonzini int i, j; 463fe8fc5aeSPaolo Bonzini if (sz < PR_OUT_FIXED_PARAM_SIZE + 4) { 464fe8fc5aeSPaolo Bonzini scsi_build_sense(sense, SENSE_CODE(INVALID_PARAM_LEN)); 465fe8fc5aeSPaolo Bonzini return CHECK_CONDITION; 466fe8fc5aeSPaolo Bonzini } 467fe8fc5aeSPaolo Bonzini transportid_len = ldl_be_p(¶m[24]) + PR_OUT_FIXED_PARAM_SIZE + 4; 468fe8fc5aeSPaolo Bonzini if (transportid_len > sz) { 469fe8fc5aeSPaolo Bonzini scsi_build_sense(sense, SENSE_CODE(INVALID_PARAM)); 470fe8fc5aeSPaolo Bonzini return CHECK_CONDITION; 471fe8fc5aeSPaolo Bonzini } 472fe8fc5aeSPaolo Bonzini for (i = PR_OUT_FIXED_PARAM_SIZE + 4, j = 0; i < transportid_len; ) { 473fe8fc5aeSPaolo Bonzini struct transportid *id = (struct transportid *) &transportids[j]; 474fe8fc5aeSPaolo Bonzini int len; 475fe8fc5aeSPaolo Bonzini 476fe8fc5aeSPaolo Bonzini id->format_code = param[i] & 0xc0; 477fe8fc5aeSPaolo Bonzini id->protocol_id = param[i] & 0x0f; 478fe8fc5aeSPaolo Bonzini switch (param[i] & 0xcf) { 479fe8fc5aeSPaolo Bonzini case 0: 480fe8fc5aeSPaolo Bonzini /* FC transport. */ 481fe8fc5aeSPaolo Bonzini if (i + 24 > transportid_len) { 482fe8fc5aeSPaolo Bonzini goto illegal_req; 483fe8fc5aeSPaolo Bonzini } 484fe8fc5aeSPaolo Bonzini memcpy(id->n_port_name, ¶m[i + 8], 8); 485fe8fc5aeSPaolo Bonzini j += offsetof(struct transportid, n_port_name[8]); 486fe8fc5aeSPaolo Bonzini i += 24; 487fe8fc5aeSPaolo Bonzini break; 488a4a9b6eaSPaolo Bonzini case 5: 489a4a9b6eaSPaolo Bonzini case 0x45: 490fe8fc5aeSPaolo Bonzini /* iSCSI transport. */ 491fe8fc5aeSPaolo Bonzini len = lduw_be_p(¶m[i + 2]); 492fe8fc5aeSPaolo Bonzini if (len > 252 || (len & 3) || i + len + 4 > transportid_len) { 493fe8fc5aeSPaolo Bonzini /* For format code 00, the standard says the maximum is 223 494fe8fc5aeSPaolo Bonzini * plus the NUL terminator. For format code 01 there is no 495fe8fc5aeSPaolo Bonzini * maximum length, but libmpathpersist ignores the first 496fe8fc5aeSPaolo Bonzini * byte of id->iscsi_name so our maximum is 252. 497fe8fc5aeSPaolo Bonzini */ 498fe8fc5aeSPaolo Bonzini goto illegal_req; 499fe8fc5aeSPaolo Bonzini } 500fe8fc5aeSPaolo Bonzini if (memchr(¶m[i + 4], 0, len) == NULL) { 501fe8fc5aeSPaolo Bonzini goto illegal_req; 502fe8fc5aeSPaolo Bonzini } 503fe8fc5aeSPaolo Bonzini memcpy(id->iscsi_name, ¶m[i + 2], len + 2); 504fe8fc5aeSPaolo Bonzini j += offsetof(struct transportid, iscsi_name[len + 2]); 505fe8fc5aeSPaolo Bonzini i += len + 4; 506fe8fc5aeSPaolo Bonzini break; 507fe8fc5aeSPaolo Bonzini case 6: 508fe8fc5aeSPaolo Bonzini /* SAS transport. */ 509fe8fc5aeSPaolo Bonzini if (i + 24 > transportid_len) { 510fe8fc5aeSPaolo Bonzini goto illegal_req; 511fe8fc5aeSPaolo Bonzini } 512fe8fc5aeSPaolo Bonzini memcpy(id->sas_address, ¶m[i + 4], 8); 513fe8fc5aeSPaolo Bonzini j += offsetof(struct transportid, sas_address[8]); 514fe8fc5aeSPaolo Bonzini i += 24; 515fe8fc5aeSPaolo Bonzini break; 516fe8fc5aeSPaolo Bonzini default: 517fe8fc5aeSPaolo Bonzini illegal_req: 518fe8fc5aeSPaolo Bonzini scsi_build_sense(sense, SENSE_CODE(INVALID_PARAM)); 519fe8fc5aeSPaolo Bonzini return CHECK_CONDITION; 520fe8fc5aeSPaolo Bonzini } 521fe8fc5aeSPaolo Bonzini 522fe8fc5aeSPaolo Bonzini paramp.trnptid_list[paramp.num_transportid++] = id; 523fe8fc5aeSPaolo Bonzini } 524fe8fc5aeSPaolo Bonzini } 525fe8fc5aeSPaolo Bonzini 526fe8fc5aeSPaolo Bonzini r = mpath_persistent_reserve_out(fd, rq_servact, rq_scope, rq_type, 527fe8fc5aeSPaolo Bonzini ¶mp, noisy, verbose); 528fe8fc5aeSPaolo Bonzini return mpath_reconstruct_sense(fd, r, sense); 529fe8fc5aeSPaolo Bonzini } 530fe8fc5aeSPaolo Bonzini #endif 531fe8fc5aeSPaolo Bonzini 532b855f8d1SPaolo Bonzini static int do_pr_in(int fd, const uint8_t *cdb, uint8_t *sense, 533b855f8d1SPaolo Bonzini uint8_t *data, int *resp_sz) 534b855f8d1SPaolo Bonzini { 535fe8fc5aeSPaolo Bonzini #ifdef CONFIG_MPATH 536fe8fc5aeSPaolo Bonzini if (is_mpath(fd)) { 537fe8fc5aeSPaolo Bonzini /* multipath_pr_in fills the whole input buffer. */ 53886933b4eSPaolo Bonzini int r = multipath_pr_in(fd, cdb, sense, data, *resp_sz); 53986933b4eSPaolo Bonzini if (r != GOOD) { 54086933b4eSPaolo Bonzini *resp_sz = 0; 54186933b4eSPaolo Bonzini } 54286933b4eSPaolo Bonzini return r; 543fe8fc5aeSPaolo Bonzini } 544fe8fc5aeSPaolo Bonzini #endif 545fe8fc5aeSPaolo Bonzini 546b855f8d1SPaolo Bonzini return do_sgio(fd, cdb, sense, data, resp_sz, 547b855f8d1SPaolo Bonzini SG_DXFER_FROM_DEV); 548b855f8d1SPaolo Bonzini } 549b855f8d1SPaolo Bonzini 550b855f8d1SPaolo Bonzini static int do_pr_out(int fd, const uint8_t *cdb, uint8_t *sense, 551b855f8d1SPaolo Bonzini const uint8_t *param, int sz) 552b855f8d1SPaolo Bonzini { 553fe8fc5aeSPaolo Bonzini int resp_sz; 554ee8c13b8SPaolo Bonzini 555ee8c13b8SPaolo Bonzini if ((fcntl(fd, F_GETFL) & O_ACCMODE) == O_RDONLY) { 556ee8c13b8SPaolo Bonzini scsi_build_sense(sense, SENSE_CODE(INVALID_OPCODE)); 557ee8c13b8SPaolo Bonzini return CHECK_CONDITION; 558ee8c13b8SPaolo Bonzini } 559ee8c13b8SPaolo Bonzini 560fe8fc5aeSPaolo Bonzini #ifdef CONFIG_MPATH 561fe8fc5aeSPaolo Bonzini if (is_mpath(fd)) { 562fe8fc5aeSPaolo Bonzini return multipath_pr_out(fd, cdb, sense, param, sz); 563fe8fc5aeSPaolo Bonzini } 564fe8fc5aeSPaolo Bonzini #endif 565fe8fc5aeSPaolo Bonzini 566fe8fc5aeSPaolo Bonzini resp_sz = sz; 567b855f8d1SPaolo Bonzini return do_sgio(fd, cdb, sense, (uint8_t *)param, &resp_sz, 568b855f8d1SPaolo Bonzini SG_DXFER_TO_DEV); 569b855f8d1SPaolo Bonzini } 570b855f8d1SPaolo Bonzini 571b855f8d1SPaolo Bonzini /* Client */ 572b855f8d1SPaolo Bonzini 573b855f8d1SPaolo Bonzini typedef struct PRHelperClient { 574b855f8d1SPaolo Bonzini QIOChannelSocket *ioc; 575b855f8d1SPaolo Bonzini Coroutine *co; 576b855f8d1SPaolo Bonzini int fd; 577b855f8d1SPaolo Bonzini uint8_t data[PR_HELPER_DATA_SIZE]; 578b855f8d1SPaolo Bonzini } PRHelperClient; 579b855f8d1SPaolo Bonzini 580b855f8d1SPaolo Bonzini typedef struct PRHelperRequest { 581b855f8d1SPaolo Bonzini int fd; 582b855f8d1SPaolo Bonzini size_t sz; 583b855f8d1SPaolo Bonzini uint8_t cdb[PR_HELPER_CDB_SIZE]; 584b855f8d1SPaolo Bonzini } PRHelperRequest; 585b855f8d1SPaolo Bonzini 586b855f8d1SPaolo Bonzini static int coroutine_fn prh_read(PRHelperClient *client, void *buf, int sz, 587b855f8d1SPaolo Bonzini Error **errp) 588b855f8d1SPaolo Bonzini { 589b855f8d1SPaolo Bonzini int ret = 0; 590b855f8d1SPaolo Bonzini 591b855f8d1SPaolo Bonzini while (sz > 0) { 592b855f8d1SPaolo Bonzini int *fds = NULL; 593b855f8d1SPaolo Bonzini size_t nfds = 0; 594b855f8d1SPaolo Bonzini int i; 595b855f8d1SPaolo Bonzini struct iovec iov; 596b855f8d1SPaolo Bonzini ssize_t n_read; 597b855f8d1SPaolo Bonzini 598b855f8d1SPaolo Bonzini iov.iov_base = buf; 599b855f8d1SPaolo Bonzini iov.iov_len = sz; 600b855f8d1SPaolo Bonzini n_read = qio_channel_readv_full(QIO_CHANNEL(client->ioc), &iov, 1, 601b855f8d1SPaolo Bonzini &fds, &nfds, errp); 602b855f8d1SPaolo Bonzini 603b855f8d1SPaolo Bonzini if (n_read == QIO_CHANNEL_ERR_BLOCK) { 604b855f8d1SPaolo Bonzini qio_channel_yield(QIO_CHANNEL(client->ioc), G_IO_IN); 605b855f8d1SPaolo Bonzini continue; 606b855f8d1SPaolo Bonzini } 607b855f8d1SPaolo Bonzini if (n_read <= 0) { 608b855f8d1SPaolo Bonzini ret = n_read ? n_read : -1; 609b855f8d1SPaolo Bonzini goto err; 610b855f8d1SPaolo Bonzini } 611b855f8d1SPaolo Bonzini 612b855f8d1SPaolo Bonzini /* Stash one file descriptor per request. */ 613b855f8d1SPaolo Bonzini if (nfds) { 614b855f8d1SPaolo Bonzini bool too_many = false; 615b855f8d1SPaolo Bonzini for (i = 0; i < nfds; i++) { 616b855f8d1SPaolo Bonzini if (client->fd == -1) { 617b855f8d1SPaolo Bonzini client->fd = fds[i]; 618b855f8d1SPaolo Bonzini } else { 619b855f8d1SPaolo Bonzini close(fds[i]); 620b855f8d1SPaolo Bonzini too_many = true; 621b855f8d1SPaolo Bonzini } 622b855f8d1SPaolo Bonzini } 623b855f8d1SPaolo Bonzini g_free(fds); 624b855f8d1SPaolo Bonzini if (too_many) { 625b855f8d1SPaolo Bonzini ret = -1; 626b855f8d1SPaolo Bonzini goto err; 627b855f8d1SPaolo Bonzini } 628b855f8d1SPaolo Bonzini } 629b855f8d1SPaolo Bonzini 630b855f8d1SPaolo Bonzini buf += n_read; 631b855f8d1SPaolo Bonzini sz -= n_read; 632b855f8d1SPaolo Bonzini } 633b855f8d1SPaolo Bonzini 634b855f8d1SPaolo Bonzini return 0; 635b855f8d1SPaolo Bonzini 636b855f8d1SPaolo Bonzini err: 637b855f8d1SPaolo Bonzini if (client->fd != -1) { 638b855f8d1SPaolo Bonzini close(client->fd); 639b855f8d1SPaolo Bonzini client->fd = -1; 640b855f8d1SPaolo Bonzini } 641b855f8d1SPaolo Bonzini return ret; 642b855f8d1SPaolo Bonzini } 643b855f8d1SPaolo Bonzini 644b855f8d1SPaolo Bonzini static int coroutine_fn prh_read_request(PRHelperClient *client, 645b855f8d1SPaolo Bonzini PRHelperRequest *req, 646b855f8d1SPaolo Bonzini PRHelperResponse *resp, Error **errp) 647b855f8d1SPaolo Bonzini { 648b855f8d1SPaolo Bonzini uint32_t sz; 649b855f8d1SPaolo Bonzini 650b855f8d1SPaolo Bonzini if (prh_read(client, req->cdb, sizeof(req->cdb), NULL) < 0) { 651b855f8d1SPaolo Bonzini return -1; 652b855f8d1SPaolo Bonzini } 653b855f8d1SPaolo Bonzini 654b855f8d1SPaolo Bonzini if (client->fd == -1) { 655b855f8d1SPaolo Bonzini error_setg(errp, "No file descriptor in request."); 656b855f8d1SPaolo Bonzini return -1; 657b855f8d1SPaolo Bonzini } 658b855f8d1SPaolo Bonzini 659b855f8d1SPaolo Bonzini if (req->cdb[0] != PERSISTENT_RESERVE_OUT && 660b855f8d1SPaolo Bonzini req->cdb[0] != PERSISTENT_RESERVE_IN) { 661b855f8d1SPaolo Bonzini error_setg(errp, "Invalid CDB, closing socket."); 662b855f8d1SPaolo Bonzini goto out_close; 663b855f8d1SPaolo Bonzini } 664b855f8d1SPaolo Bonzini 665b855f8d1SPaolo Bonzini sz = scsi_cdb_xfer(req->cdb); 666b855f8d1SPaolo Bonzini if (sz > sizeof(client->data)) { 667b855f8d1SPaolo Bonzini goto out_close; 668b855f8d1SPaolo Bonzini } 669b855f8d1SPaolo Bonzini 670b855f8d1SPaolo Bonzini if (req->cdb[0] == PERSISTENT_RESERVE_OUT) { 671b855f8d1SPaolo Bonzini if (qio_channel_read_all(QIO_CHANNEL(client->ioc), 672b855f8d1SPaolo Bonzini (char *)client->data, sz, 673b855f8d1SPaolo Bonzini errp) < 0) { 674b855f8d1SPaolo Bonzini goto out_close; 675b855f8d1SPaolo Bonzini } 676b855f8d1SPaolo Bonzini } 677b855f8d1SPaolo Bonzini 678b855f8d1SPaolo Bonzini req->fd = client->fd; 679b855f8d1SPaolo Bonzini req->sz = sz; 680b855f8d1SPaolo Bonzini client->fd = -1; 681b855f8d1SPaolo Bonzini return sz; 682b855f8d1SPaolo Bonzini 683b855f8d1SPaolo Bonzini out_close: 684b855f8d1SPaolo Bonzini close(client->fd); 685b855f8d1SPaolo Bonzini client->fd = -1; 686b855f8d1SPaolo Bonzini return -1; 687b855f8d1SPaolo Bonzini } 688b855f8d1SPaolo Bonzini 689b855f8d1SPaolo Bonzini static int coroutine_fn prh_write_response(PRHelperClient *client, 690b855f8d1SPaolo Bonzini PRHelperRequest *req, 691b855f8d1SPaolo Bonzini PRHelperResponse *resp, Error **errp) 692b855f8d1SPaolo Bonzini { 693b855f8d1SPaolo Bonzini ssize_t r; 694b855f8d1SPaolo Bonzini size_t sz; 695b855f8d1SPaolo Bonzini 696b855f8d1SPaolo Bonzini if (req->cdb[0] == PERSISTENT_RESERVE_IN && resp->result == GOOD) { 697b855f8d1SPaolo Bonzini assert(resp->sz <= req->sz && resp->sz <= sizeof(client->data)); 698b855f8d1SPaolo Bonzini } else { 699b855f8d1SPaolo Bonzini assert(resp->sz == 0); 700b855f8d1SPaolo Bonzini } 701b855f8d1SPaolo Bonzini 702b855f8d1SPaolo Bonzini sz = resp->sz; 703b855f8d1SPaolo Bonzini 704b855f8d1SPaolo Bonzini resp->result = cpu_to_be32(resp->result); 705b855f8d1SPaolo Bonzini resp->sz = cpu_to_be32(resp->sz); 706b855f8d1SPaolo Bonzini r = qio_channel_write_all(QIO_CHANNEL(client->ioc), 707b855f8d1SPaolo Bonzini (char *) resp, sizeof(*resp), errp); 708b855f8d1SPaolo Bonzini if (r < 0) { 709b855f8d1SPaolo Bonzini return r; 710b855f8d1SPaolo Bonzini } 711b855f8d1SPaolo Bonzini 712b855f8d1SPaolo Bonzini r = qio_channel_write_all(QIO_CHANNEL(client->ioc), 713b855f8d1SPaolo Bonzini (char *) client->data, 714b855f8d1SPaolo Bonzini sz, errp); 715b855f8d1SPaolo Bonzini return r < 0 ? r : 0; 716b855f8d1SPaolo Bonzini } 717b855f8d1SPaolo Bonzini 718b855f8d1SPaolo Bonzini static void coroutine_fn prh_co_entry(void *opaque) 719b855f8d1SPaolo Bonzini { 720b855f8d1SPaolo Bonzini PRHelperClient *client = opaque; 721b855f8d1SPaolo Bonzini Error *local_err = NULL; 722b855f8d1SPaolo Bonzini uint32_t flags; 723b855f8d1SPaolo Bonzini int r; 724b855f8d1SPaolo Bonzini 725b855f8d1SPaolo Bonzini qio_channel_set_blocking(QIO_CHANNEL(client->ioc), 726b855f8d1SPaolo Bonzini false, NULL); 727b855f8d1SPaolo Bonzini qio_channel_attach_aio_context(QIO_CHANNEL(client->ioc), 728b855f8d1SPaolo Bonzini qemu_get_aio_context()); 729b855f8d1SPaolo Bonzini 730b855f8d1SPaolo Bonzini /* A very simple negotiation for future extensibility. No features 731b855f8d1SPaolo Bonzini * are defined so write 0. 732b855f8d1SPaolo Bonzini */ 733b855f8d1SPaolo Bonzini flags = cpu_to_be32(0); 734b855f8d1SPaolo Bonzini r = qio_channel_write_all(QIO_CHANNEL(client->ioc), 735b855f8d1SPaolo Bonzini (char *) &flags, sizeof(flags), NULL); 736b855f8d1SPaolo Bonzini if (r < 0) { 737b855f8d1SPaolo Bonzini goto out; 738b855f8d1SPaolo Bonzini } 739b855f8d1SPaolo Bonzini 740b855f8d1SPaolo Bonzini r = qio_channel_read_all(QIO_CHANNEL(client->ioc), 741b855f8d1SPaolo Bonzini (char *) &flags, sizeof(flags), NULL); 742b855f8d1SPaolo Bonzini if (be32_to_cpu(flags) != 0 || r < 0) { 743b855f8d1SPaolo Bonzini goto out; 744b855f8d1SPaolo Bonzini } 745b855f8d1SPaolo Bonzini 746b855f8d1SPaolo Bonzini while (atomic_read(&state) == RUNNING) { 747b855f8d1SPaolo Bonzini PRHelperRequest req; 748b855f8d1SPaolo Bonzini PRHelperResponse resp; 749b855f8d1SPaolo Bonzini int sz; 750b855f8d1SPaolo Bonzini 751b855f8d1SPaolo Bonzini sz = prh_read_request(client, &req, &resp, &local_err); 752b855f8d1SPaolo Bonzini if (sz < 0) { 753b855f8d1SPaolo Bonzini break; 754b855f8d1SPaolo Bonzini } 755b855f8d1SPaolo Bonzini 756b855f8d1SPaolo Bonzini num_active_sockets++; 757b855f8d1SPaolo Bonzini if (req.cdb[0] == PERSISTENT_RESERVE_OUT) { 758b855f8d1SPaolo Bonzini r = do_pr_out(req.fd, req.cdb, resp.sense, 759b855f8d1SPaolo Bonzini client->data, sz); 760b855f8d1SPaolo Bonzini resp.sz = 0; 761b855f8d1SPaolo Bonzini } else { 762b855f8d1SPaolo Bonzini resp.sz = sizeof(client->data); 763b855f8d1SPaolo Bonzini r = do_pr_in(req.fd, req.cdb, resp.sense, 764b855f8d1SPaolo Bonzini client->data, &resp.sz); 765b855f8d1SPaolo Bonzini resp.sz = MIN(resp.sz, sz); 766b855f8d1SPaolo Bonzini } 767b855f8d1SPaolo Bonzini num_active_sockets--; 768b855f8d1SPaolo Bonzini close(req.fd); 769b855f8d1SPaolo Bonzini if (r == -1) { 770b855f8d1SPaolo Bonzini break; 771b855f8d1SPaolo Bonzini } 772b855f8d1SPaolo Bonzini resp.result = r; 773b855f8d1SPaolo Bonzini 774b855f8d1SPaolo Bonzini if (prh_write_response(client, &req, &resp, &local_err) < 0) { 775b855f8d1SPaolo Bonzini break; 776b855f8d1SPaolo Bonzini } 777b855f8d1SPaolo Bonzini } 778b855f8d1SPaolo Bonzini 779b855f8d1SPaolo Bonzini if (local_err) { 780b855f8d1SPaolo Bonzini if (verbose == 0) { 781b855f8d1SPaolo Bonzini error_free(local_err); 782b855f8d1SPaolo Bonzini } else { 783b855f8d1SPaolo Bonzini error_report_err(local_err); 784b855f8d1SPaolo Bonzini } 785b855f8d1SPaolo Bonzini } 786b855f8d1SPaolo Bonzini 787b855f8d1SPaolo Bonzini out: 788b855f8d1SPaolo Bonzini qio_channel_detach_aio_context(QIO_CHANNEL(client->ioc)); 789b855f8d1SPaolo Bonzini object_unref(OBJECT(client->ioc)); 790b855f8d1SPaolo Bonzini g_free(client); 791b855f8d1SPaolo Bonzini } 792b855f8d1SPaolo Bonzini 793b855f8d1SPaolo Bonzini static gboolean accept_client(QIOChannel *ioc, GIOCondition cond, gpointer opaque) 794b855f8d1SPaolo Bonzini { 795b855f8d1SPaolo Bonzini QIOChannelSocket *cioc; 796b855f8d1SPaolo Bonzini PRHelperClient *prh; 797b855f8d1SPaolo Bonzini 798b855f8d1SPaolo Bonzini cioc = qio_channel_socket_accept(QIO_CHANNEL_SOCKET(ioc), 799b855f8d1SPaolo Bonzini NULL); 800b855f8d1SPaolo Bonzini if (!cioc) { 801b855f8d1SPaolo Bonzini return TRUE; 802b855f8d1SPaolo Bonzini } 803b855f8d1SPaolo Bonzini 804b855f8d1SPaolo Bonzini prh = g_new(PRHelperClient, 1); 805b855f8d1SPaolo Bonzini prh->ioc = cioc; 806b855f8d1SPaolo Bonzini prh->fd = -1; 807b855f8d1SPaolo Bonzini prh->co = qemu_coroutine_create(prh_co_entry, prh); 808b855f8d1SPaolo Bonzini qemu_coroutine_enter(prh->co); 809b855f8d1SPaolo Bonzini 810b855f8d1SPaolo Bonzini return TRUE; 811b855f8d1SPaolo Bonzini } 812b855f8d1SPaolo Bonzini 813b855f8d1SPaolo Bonzini static void termsig_handler(int signum) 814b855f8d1SPaolo Bonzini { 815b855f8d1SPaolo Bonzini atomic_cmpxchg(&state, RUNNING, TERMINATE); 816b855f8d1SPaolo Bonzini qemu_notify_event(); 817b855f8d1SPaolo Bonzini } 818b855f8d1SPaolo Bonzini 819b855f8d1SPaolo Bonzini static void close_server_socket(void) 820b855f8d1SPaolo Bonzini { 821b855f8d1SPaolo Bonzini assert(server_ioc); 822b855f8d1SPaolo Bonzini 823b855f8d1SPaolo Bonzini g_source_remove(server_watch); 824b855f8d1SPaolo Bonzini server_watch = -1; 825b855f8d1SPaolo Bonzini object_unref(OBJECT(server_ioc)); 826b855f8d1SPaolo Bonzini num_active_sockets--; 827b855f8d1SPaolo Bonzini } 828b855f8d1SPaolo Bonzini 829b855f8d1SPaolo Bonzini #ifdef CONFIG_LIBCAP 830b855f8d1SPaolo Bonzini static int drop_privileges(void) 831b855f8d1SPaolo Bonzini { 832b855f8d1SPaolo Bonzini /* clear all capabilities */ 833b855f8d1SPaolo Bonzini capng_clear(CAPNG_SELECT_BOTH); 834b855f8d1SPaolo Bonzini 835b855f8d1SPaolo Bonzini if (capng_update(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, 836b855f8d1SPaolo Bonzini CAP_SYS_RAWIO) < 0) { 837b855f8d1SPaolo Bonzini return -1; 838b855f8d1SPaolo Bonzini } 839b855f8d1SPaolo Bonzini 840fe8fc5aeSPaolo Bonzini #ifdef CONFIG_MPATH 841fe8fc5aeSPaolo Bonzini /* For /dev/mapper/control ioctls */ 842fe8fc5aeSPaolo Bonzini if (capng_update(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, 843fe8fc5aeSPaolo Bonzini CAP_SYS_ADMIN) < 0) { 844fe8fc5aeSPaolo Bonzini return -1; 845fe8fc5aeSPaolo Bonzini } 846fe8fc5aeSPaolo Bonzini #endif 847fe8fc5aeSPaolo Bonzini 848b855f8d1SPaolo Bonzini /* Change user/group id, retaining the capabilities. Because file descriptors 849b855f8d1SPaolo Bonzini * are passed via SCM_RIGHTS, we don't need supplementary groups (and in 850b855f8d1SPaolo Bonzini * fact the helper can run as "nobody"). 851b855f8d1SPaolo Bonzini */ 852b855f8d1SPaolo Bonzini if (capng_change_id(uid != -1 ? uid : getuid(), 853b855f8d1SPaolo Bonzini gid != -1 ? gid : getgid(), 854b855f8d1SPaolo Bonzini CAPNG_DROP_SUPP_GRP | CAPNG_CLEAR_BOUNDING)) { 855b855f8d1SPaolo Bonzini return -1; 856b855f8d1SPaolo Bonzini } 857b855f8d1SPaolo Bonzini 858b855f8d1SPaolo Bonzini return 0; 859b855f8d1SPaolo Bonzini } 860b855f8d1SPaolo Bonzini #endif 861b855f8d1SPaolo Bonzini 862b855f8d1SPaolo Bonzini int main(int argc, char **argv) 863b855f8d1SPaolo Bonzini { 864f8e1a989SMichal Privoznik const char *sopt = "hVk:f:dT:u:g:vq"; 865b855f8d1SPaolo Bonzini struct option lopt[] = { 866b855f8d1SPaolo Bonzini { "help", no_argument, NULL, 'h' }, 867b855f8d1SPaolo Bonzini { "version", no_argument, NULL, 'V' }, 868b855f8d1SPaolo Bonzini { "socket", required_argument, NULL, 'k' }, 869f8e1a989SMichal Privoznik { "pidfile", required_argument, NULL, 'f' }, 870b855f8d1SPaolo Bonzini { "daemon", no_argument, NULL, 'd' }, 871b855f8d1SPaolo Bonzini { "trace", required_argument, NULL, 'T' }, 872b855f8d1SPaolo Bonzini { "user", required_argument, NULL, 'u' }, 873b855f8d1SPaolo Bonzini { "group", required_argument, NULL, 'g' }, 874fe8fc5aeSPaolo Bonzini { "verbose", no_argument, NULL, 'v' }, 875b855f8d1SPaolo Bonzini { "quiet", no_argument, NULL, 'q' }, 876b855f8d1SPaolo Bonzini { NULL, 0, NULL, 0 } 877b855f8d1SPaolo Bonzini }; 878b855f8d1SPaolo Bonzini int opt_ind = 0; 879fe8fc5aeSPaolo Bonzini int loglevel = 1; 880b855f8d1SPaolo Bonzini int quiet = 0; 881b855f8d1SPaolo Bonzini int ch; 882b855f8d1SPaolo Bonzini Error *local_err = NULL; 883b855f8d1SPaolo Bonzini char *trace_file = NULL; 884b855f8d1SPaolo Bonzini bool daemonize = false; 885bd6b1c83SMichal Privoznik bool pidfile_specified = false; 8862729d79dSMichal Privoznik bool socket_path_specified = false; 887b855f8d1SPaolo Bonzini unsigned socket_activation; 888b855f8d1SPaolo Bonzini 889b855f8d1SPaolo Bonzini struct sigaction sa_sigterm; 890b855f8d1SPaolo Bonzini memset(&sa_sigterm, 0, sizeof(sa_sigterm)); 891b855f8d1SPaolo Bonzini sa_sigterm.sa_handler = termsig_handler; 892b855f8d1SPaolo Bonzini sigaction(SIGTERM, &sa_sigterm, NULL); 893b855f8d1SPaolo Bonzini sigaction(SIGINT, &sa_sigterm, NULL); 894b855f8d1SPaolo Bonzini sigaction(SIGHUP, &sa_sigterm, NULL); 895b855f8d1SPaolo Bonzini 896b855f8d1SPaolo Bonzini signal(SIGPIPE, SIG_IGN); 897b855f8d1SPaolo Bonzini 898b855f8d1SPaolo Bonzini module_call_init(MODULE_INIT_TRACE); 899b855f8d1SPaolo Bonzini module_call_init(MODULE_INIT_QOM); 900b855f8d1SPaolo Bonzini qemu_add_opts(&qemu_trace_opts); 901b855f8d1SPaolo Bonzini qemu_init_exec_dir(argv[0]); 902b855f8d1SPaolo Bonzini 9032729d79dSMichal Privoznik compute_default_paths(); 904b855f8d1SPaolo Bonzini 905b855f8d1SPaolo Bonzini while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) { 906b855f8d1SPaolo Bonzini switch (ch) { 907b855f8d1SPaolo Bonzini case 'k': 9082729d79dSMichal Privoznik g_free(socket_path); 9092729d79dSMichal Privoznik socket_path = g_strdup(optarg); 9102729d79dSMichal Privoznik socket_path_specified = true; 911b855f8d1SPaolo Bonzini if (socket_path[0] != '/') { 912b855f8d1SPaolo Bonzini error_report("socket path must be absolute"); 913b855f8d1SPaolo Bonzini exit(EXIT_FAILURE); 914b855f8d1SPaolo Bonzini } 915b855f8d1SPaolo Bonzini break; 916b855f8d1SPaolo Bonzini case 'f': 917f8e1a989SMichal Privoznik g_free(pidfile); 918f8e1a989SMichal Privoznik pidfile = g_strdup(optarg); 919bd6b1c83SMichal Privoznik pidfile_specified = true; 920b855f8d1SPaolo Bonzini break; 921b855f8d1SPaolo Bonzini #ifdef CONFIG_LIBCAP 922b855f8d1SPaolo Bonzini case 'u': { 923b855f8d1SPaolo Bonzini unsigned long res; 924b855f8d1SPaolo Bonzini struct passwd *userinfo = getpwnam(optarg); 925b855f8d1SPaolo Bonzini if (userinfo) { 926b855f8d1SPaolo Bonzini uid = userinfo->pw_uid; 927b855f8d1SPaolo Bonzini } else if (qemu_strtoul(optarg, NULL, 10, &res) == 0 && 928b855f8d1SPaolo Bonzini (uid_t)res == res) { 929b855f8d1SPaolo Bonzini uid = res; 930b855f8d1SPaolo Bonzini } else { 931b855f8d1SPaolo Bonzini error_report("invalid user '%s'", optarg); 932b855f8d1SPaolo Bonzini exit(EXIT_FAILURE); 933b855f8d1SPaolo Bonzini } 934b855f8d1SPaolo Bonzini break; 935b855f8d1SPaolo Bonzini } 936b855f8d1SPaolo Bonzini case 'g': { 937b855f8d1SPaolo Bonzini unsigned long res; 938b855f8d1SPaolo Bonzini struct group *groupinfo = getgrnam(optarg); 939b855f8d1SPaolo Bonzini if (groupinfo) { 940b855f8d1SPaolo Bonzini gid = groupinfo->gr_gid; 941b855f8d1SPaolo Bonzini } else if (qemu_strtoul(optarg, NULL, 10, &res) == 0 && 942b855f8d1SPaolo Bonzini (gid_t)res == res) { 943b855f8d1SPaolo Bonzini gid = res; 944b855f8d1SPaolo Bonzini } else { 945b855f8d1SPaolo Bonzini error_report("invalid group '%s'", optarg); 946b855f8d1SPaolo Bonzini exit(EXIT_FAILURE); 947b855f8d1SPaolo Bonzini } 948b855f8d1SPaolo Bonzini break; 949b855f8d1SPaolo Bonzini } 950b855f8d1SPaolo Bonzini #else 951b855f8d1SPaolo Bonzini case 'u': 952b855f8d1SPaolo Bonzini case 'g': 953b855f8d1SPaolo Bonzini error_report("-%c not supported by this %s", ch, argv[0]); 954b855f8d1SPaolo Bonzini exit(1); 955b855f8d1SPaolo Bonzini #endif 956b855f8d1SPaolo Bonzini case 'd': 957b855f8d1SPaolo Bonzini daemonize = true; 958b855f8d1SPaolo Bonzini break; 959b855f8d1SPaolo Bonzini case 'q': 960b855f8d1SPaolo Bonzini quiet = 1; 961b855f8d1SPaolo Bonzini break; 962fe8fc5aeSPaolo Bonzini case 'v': 963fe8fc5aeSPaolo Bonzini ++loglevel; 964fe8fc5aeSPaolo Bonzini break; 965b855f8d1SPaolo Bonzini case 'T': 966b855f8d1SPaolo Bonzini g_free(trace_file); 967b855f8d1SPaolo Bonzini trace_file = trace_opt_parse(optarg); 968b855f8d1SPaolo Bonzini break; 969b855f8d1SPaolo Bonzini case 'V': 970b855f8d1SPaolo Bonzini version(argv[0]); 971b855f8d1SPaolo Bonzini exit(EXIT_SUCCESS); 972b855f8d1SPaolo Bonzini break; 973b855f8d1SPaolo Bonzini case 'h': 974b855f8d1SPaolo Bonzini usage(argv[0]); 975b855f8d1SPaolo Bonzini exit(EXIT_SUCCESS); 976b855f8d1SPaolo Bonzini break; 977b855f8d1SPaolo Bonzini case '?': 978b855f8d1SPaolo Bonzini error_report("Try `%s --help' for more information.", argv[0]); 979b855f8d1SPaolo Bonzini exit(EXIT_FAILURE); 980b855f8d1SPaolo Bonzini } 981b855f8d1SPaolo Bonzini } 982b855f8d1SPaolo Bonzini 983b855f8d1SPaolo Bonzini /* set verbosity */ 984fe8fc5aeSPaolo Bonzini noisy = !quiet && (loglevel >= 3); 985fe8fc5aeSPaolo Bonzini verbose = quiet ? 0 : MIN(loglevel, 3); 986b855f8d1SPaolo Bonzini 987b855f8d1SPaolo Bonzini if (!trace_init_backends()) { 988b855f8d1SPaolo Bonzini exit(EXIT_FAILURE); 989b855f8d1SPaolo Bonzini } 990b855f8d1SPaolo Bonzini trace_init_file(trace_file); 991b855f8d1SPaolo Bonzini qemu_set_log(LOG_TRACE); 992b855f8d1SPaolo Bonzini 993fe8fc5aeSPaolo Bonzini #ifdef CONFIG_MPATH 994fe8fc5aeSPaolo Bonzini dm_init(); 995fe8fc5aeSPaolo Bonzini multipath_pr_init(); 996fe8fc5aeSPaolo Bonzini #endif 997fe8fc5aeSPaolo Bonzini 998b855f8d1SPaolo Bonzini socket_activation = check_socket_activation(); 999b855f8d1SPaolo Bonzini if (socket_activation == 0) { 1000b855f8d1SPaolo Bonzini SocketAddress saddr; 1001b855f8d1SPaolo Bonzini saddr = (SocketAddress){ 1002b855f8d1SPaolo Bonzini .type = SOCKET_ADDRESS_TYPE_UNIX, 10032729d79dSMichal Privoznik .u.q_unix.path = socket_path, 1004b855f8d1SPaolo Bonzini }; 1005b855f8d1SPaolo Bonzini server_ioc = qio_channel_socket_new(); 1006b855f8d1SPaolo Bonzini if (qio_channel_socket_listen_sync(server_ioc, &saddr, &local_err) < 0) { 1007b855f8d1SPaolo Bonzini object_unref(OBJECT(server_ioc)); 1008b855f8d1SPaolo Bonzini error_report_err(local_err); 1009b855f8d1SPaolo Bonzini return 1; 1010b855f8d1SPaolo Bonzini } 1011b855f8d1SPaolo Bonzini } else { 1012b855f8d1SPaolo Bonzini /* Using socket activation - check user didn't use -p etc. */ 10132729d79dSMichal Privoznik if (socket_path_specified) { 10142729d79dSMichal Privoznik error_report("Unix socket can't be set when using socket activation"); 1015b855f8d1SPaolo Bonzini exit(EXIT_FAILURE); 1016b855f8d1SPaolo Bonzini } 1017b855f8d1SPaolo Bonzini 1018b855f8d1SPaolo Bonzini /* Can only listen on a single socket. */ 1019b855f8d1SPaolo Bonzini if (socket_activation > 1) { 1020b855f8d1SPaolo Bonzini error_report("%s does not support socket activation with LISTEN_FDS > 1", 1021b855f8d1SPaolo Bonzini argv[0]); 1022b855f8d1SPaolo Bonzini exit(EXIT_FAILURE); 1023b855f8d1SPaolo Bonzini } 1024b855f8d1SPaolo Bonzini server_ioc = qio_channel_socket_new_fd(FIRST_SOCKET_ACTIVATION_FD, 1025b855f8d1SPaolo Bonzini &local_err); 1026b855f8d1SPaolo Bonzini if (server_ioc == NULL) { 1027b855f8d1SPaolo Bonzini error_report("Failed to use socket activation: %s", 1028b855f8d1SPaolo Bonzini error_get_pretty(local_err)); 1029b855f8d1SPaolo Bonzini exit(EXIT_FAILURE); 1030b855f8d1SPaolo Bonzini } 1031b855f8d1SPaolo Bonzini } 1032b855f8d1SPaolo Bonzini 1033b855f8d1SPaolo Bonzini if (qemu_init_main_loop(&local_err)) { 1034b855f8d1SPaolo Bonzini error_report_err(local_err); 1035b855f8d1SPaolo Bonzini exit(EXIT_FAILURE); 1036b855f8d1SPaolo Bonzini } 1037b855f8d1SPaolo Bonzini 1038b855f8d1SPaolo Bonzini server_watch = qio_channel_add_watch(QIO_CHANNEL(server_ioc), 1039b855f8d1SPaolo Bonzini G_IO_IN, 1040b855f8d1SPaolo Bonzini accept_client, 1041b855f8d1SPaolo Bonzini NULL, NULL); 1042b855f8d1SPaolo Bonzini 1043b855f8d1SPaolo Bonzini if (daemonize) { 1044b855f8d1SPaolo Bonzini if (daemon(0, 0) < 0) { 1045b855f8d1SPaolo Bonzini error_report("Failed to daemonize: %s", strerror(errno)); 1046b855f8d1SPaolo Bonzini exit(EXIT_FAILURE); 1047b855f8d1SPaolo Bonzini } 1048b855f8d1SPaolo Bonzini } 1049b855f8d1SPaolo Bonzini 10509e6bdef2SMarc-André Lureau if ((daemonize || pidfile_specified) && 10519e6bdef2SMarc-André Lureau !qemu_write_pidfile(pidfile, &local_err)) { 10529e6bdef2SMarc-André Lureau error_report_err(local_err); 10539e6bdef2SMarc-André Lureau exit(EXIT_FAILURE); 10549e6bdef2SMarc-André Lureau } 1055bd6b1c83SMichal Privoznik 10568dc0bf26SMichal Privoznik #ifdef CONFIG_LIBCAP 10578dc0bf26SMichal Privoznik if (drop_privileges() < 0) { 10588dc0bf26SMichal Privoznik error_report("Failed to drop privileges: %s", strerror(errno)); 10598dc0bf26SMichal Privoznik exit(EXIT_FAILURE); 10608dc0bf26SMichal Privoznik } 10618dc0bf26SMichal Privoznik #endif 10628dc0bf26SMichal Privoznik 1063b855f8d1SPaolo Bonzini state = RUNNING; 1064b855f8d1SPaolo Bonzini do { 1065b855f8d1SPaolo Bonzini main_loop_wait(false); 1066b855f8d1SPaolo Bonzini if (state == TERMINATE) { 1067b855f8d1SPaolo Bonzini state = TERMINATING; 1068b855f8d1SPaolo Bonzini close_server_socket(); 1069b855f8d1SPaolo Bonzini } 1070b855f8d1SPaolo Bonzini } while (num_active_sockets > 0); 1071b855f8d1SPaolo Bonzini 1072b855f8d1SPaolo Bonzini exit(EXIT_SUCCESS); 1073b855f8d1SPaolo Bonzini } 1074