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