#include <linux/dm-ioctl.h>
#include <scsi/sg.h>
-#ifdef CONFIG_LIBCAP
+#ifdef CONFIG_LIBCAP_NG
#include <cap-ng.h>
#endif
#include <pwd.h>
#include <mpath_persist.h>
#endif
-#include "qemu-common.h"
+#include "qemu/help-texts.h"
#include "qapi/error.h"
#include "qemu/cutils.h"
#include "qemu/main-loop.h"
static int noisy;
static int verbose;
-#ifdef CONFIG_LIBCAP
+#ifdef CONFIG_LIBCAP_NG
static int uid = -1;
static int gid = -1;
#endif
static void compute_default_paths(void)
{
- socket_path = qemu_get_local_state_pathname("run/qemu-pr-helper.sock");
- pidfile = qemu_get_local_state_pathname("run/qemu-pr-helper.pid");
+ g_autofree char *state = qemu_get_local_state_dir();
+
+ socket_path = g_build_filename(state, "run", "qemu-pr-helper.sock", NULL);
+ pidfile = g_build_filename(state, "run", "qemu-pr-helper.pid", NULL);
}
static void usage(const char *name)
" (default '%s')\n"
" -T, --trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
" specify tracing options\n"
-#ifdef CONFIG_LIBCAP
+#ifdef CONFIG_LIBCAP_NG
" -u, --user=USER user to drop privileges to\n"
" -g, --group=GROUP group to drop privileges to\n"
#endif
io_hdr.dxferp = (char *)data->buf;
io_hdr.dxfer_len = data->sz;
ret = ioctl(data->fd, SG_IO, &io_hdr);
- status = sg_io_sense_from_errno(ret < 0 ? errno : 0, &io_hdr,
- &sense_code);
+
+ if (ret < 0) {
+ status = scsi_sense_from_errno(errno, &sense_code);
+ if (status == CHECK_CONDITION) {
+ scsi_build_sense(data->sense, sense_code);
+ }
+ } else if (io_hdr.host_status != SCSI_HOST_OK) {
+ status = scsi_sense_from_host_status(io_hdr.host_status, &sense_code);
+ if (status == CHECK_CONDITION) {
+ scsi_build_sense(data->sense, sense_code);
+ }
+ } else if (io_hdr.driver_status & SG_ERR_DRIVER_TIMEOUT) {
+ status = BUSY;
+ } else {
+ status = io_hdr.status;
+ }
+
if (status == GOOD) {
data->sz -= io_hdr.resid;
} else {
data->sz = 0;
}
- if (status == CHECK_CONDITION &&
- !(io_hdr.driver_status & SG_ERR_DRIVER_SENSE)) {
- scsi_build_sense(data->sense, sense_code);
- }
-
return status;
}
-static int do_sgio(int fd, const uint8_t *cdb, uint8_t *sense,
- uint8_t *buf, int *sz, int dir)
+static int coroutine_fn do_sgio(int fd, const uint8_t *cdb, uint8_t *sense,
+ uint8_t *buf, int *sz, int dir)
{
- ThreadPool *pool = aio_get_thread_pool(qemu_get_aio_context());
int r;
PRHelperSGIOData data = {
.dir = dir,
};
- r = thread_pool_submit_co(pool, do_sgio_worker, &data);
+ r = thread_pool_submit_co(do_sgio_worker, &data);
*sz = data.sz;
return r;
}
}
}
-static int mpath_reconstruct_sense(int fd, int r, uint8_t *sense)
+static int coroutine_fn mpath_reconstruct_sense(int fd, int r, uint8_t *sense)
{
switch (r) {
case MPATH_PR_SUCCESS:
*/
uint8_t cdb[6] = { TEST_UNIT_READY };
int sz = 0;
- int r = do_sgio(fd, cdb, sense, NULL, &sz, SG_DXFER_NONE);
+ int ret = do_sgio(fd, cdb, sense, NULL, &sz, SG_DXFER_NONE);
- if (r != GOOD) {
- return r;
+ if (ret != GOOD) {
+ return ret;
}
scsi_build_sense(sense, mpath_generic_sense(r));
return CHECK_CONDITION;
}
}
-static int multipath_pr_in(int fd, const uint8_t *cdb, uint8_t *sense,
- uint8_t *data, int sz)
+static int coroutine_fn multipath_pr_in(int fd, const uint8_t *cdb, uint8_t *sense,
+ uint8_t *data, int sz)
{
int rq_servact = cdb[1];
struct prin_resp resp;
return mpath_reconstruct_sense(fd, r, sense);
}
-static int multipath_pr_out(int fd, const uint8_t *cdb, uint8_t *sense,
- const uint8_t *param, int sz)
+static int coroutine_fn multipath_pr_out(int fd, const uint8_t *cdb, uint8_t *sense,
+ const uint8_t *param, int sz)
{
int rq_servact = cdb[1];
int rq_scope = cdb[2] >> 4;
int rq_type = cdb[2] & 0xf;
- struct prout_param_descriptor paramp;
+ g_autofree struct prout_param_descriptor *paramp = NULL;
char transportids[PR_HELPER_DATA_SIZE];
int r;
+ paramp = g_malloc0(sizeof(struct prout_param_descriptor)
+ + sizeof(struct transportid *) * MPATH_MX_TIDS);
+
if (sz < PR_OUT_FIXED_PARAM_SIZE) {
/* Illegal request, Parameter list length error. This isn't fatal;
* we have read the data, send an error without closing the socket.
* used by libmpathpersist (which, of course, will immediately
* do the opposite).
*/
- memset(¶mp, 0, sizeof(paramp));
- memcpy(¶mp.key, ¶m[0], 8);
- memcpy(¶mp.sa_key, ¶m[8], 8);
- paramp.sa_flags = param[20];
+ memcpy(¶mp->key, ¶m[0], 8);
+ memcpy(¶mp->sa_key, ¶m[8], 8);
+ paramp->sa_flags = param[20];
if (sz > PR_OUT_FIXED_PARAM_SIZE) {
size_t transportid_len;
int i, j;
return CHECK_CONDITION;
}
- paramp.trnptid_list[paramp.num_transportid++] = id;
+ assert(paramp->num_transportid < MPATH_MX_TIDS);
+ paramp->trnptid_list[paramp->num_transportid++] = id;
}
}
r = mpath_persistent_reserve_out(fd, rq_servact, rq_scope, rq_type,
- ¶mp, noisy, verbose);
+ paramp, noisy, verbose);
return mpath_reconstruct_sense(fd, r, sense);
}
#endif
-static int do_pr_in(int fd, const uint8_t *cdb, uint8_t *sense,
- uint8_t *data, int *resp_sz)
+static int coroutine_fn do_pr_in(int fd, const uint8_t *cdb, uint8_t *sense,
+ uint8_t *data, int *resp_sz)
{
#ifdef CONFIG_MPATH
if (is_mpath(fd)) {
SG_DXFER_FROM_DEV);
}
-static int do_pr_out(int fd, const uint8_t *cdb, uint8_t *sense,
- const uint8_t *param, int sz)
+static int coroutine_fn do_pr_out(int fd, const uint8_t *cdb, uint8_t *sense,
+ const uint8_t *param, int sz)
{
int resp_sz;
iov.iov_base = buf;
iov.iov_len = sz;
n_read = qio_channel_readv_full(QIO_CHANNEL(client->ioc), &iov, 1,
- &fds, &nfds, errp);
+ &fds, &nfds, 0, errp);
if (n_read == QIO_CHANNEL_ERR_BLOCK) {
qio_channel_yield(QIO_CHANNEL(client->ioc), G_IO_IN);
goto out;
}
- while (atomic_read(&state) == RUNNING) {
+ while (qatomic_read(&state) == RUNNING) {
PRHelperRequest req;
PRHelperResponse resp;
int sz;
static void termsig_handler(int signum)
{
- atomic_cmpxchg(&state, RUNNING, TERMINATE);
+ qatomic_cmpxchg(&state, RUNNING, TERMINATE);
qemu_notify_event();
}
num_active_sockets--;
}
-#ifdef CONFIG_LIBCAP
+#ifdef CONFIG_LIBCAP_NG
static int drop_privileges(void)
{
/* clear all capabilities */
int quiet = 0;
int ch;
Error *local_err = NULL;
- char *trace_file = NULL;
bool daemonize = false;
bool pidfile_specified = false;
bool socket_path_specified = false;
pidfile = g_strdup(optarg);
pidfile_specified = true;
break;
-#ifdef CONFIG_LIBCAP
+#ifdef CONFIG_LIBCAP_NG
case 'u': {
unsigned long res;
struct passwd *userinfo = getpwnam(optarg);
++loglevel;
break;
case 'T':
- g_free(trace_file);
- trace_file = trace_opt_parse(optarg);
+ trace_opt_parse(optarg);
break;
case 'V':
version(argv[0]);
if (!trace_init_backends()) {
exit(EXIT_FAILURE);
}
- trace_init_file(trace_file);
- qemu_set_log(LOG_TRACE);
+ trace_init_file();
+ qemu_set_log(LOG_TRACE, &error_fatal);
#ifdef CONFIG_MPATH
dm_init();
server_ioc = qio_channel_socket_new_fd(FIRST_SOCKET_ACTIVATION_FD,
&local_err);
if (server_ioc == NULL) {
- error_report("Failed to use socket activation: %s",
- error_get_pretty(local_err));
+ error_reportf_err(local_err,
+ "Failed to use socket activation: ");
exit(EXIT_FAILURE);
}
}
- if (qemu_init_main_loop(&local_err)) {
- error_report_err(local_err);
- exit(EXIT_FAILURE);
- }
+ qemu_init_main_loop(&error_fatal);
server_watch = qio_channel_add_watch(QIO_CHANNEL(server_ioc),
G_IO_IN,
}
}
- if ((daemonize || pidfile_specified) &&
- !qemu_write_pidfile(pidfile, &local_err)) {
- error_report_err(local_err);
- exit(EXIT_FAILURE);
+ if (daemonize || pidfile_specified) {
+ qemu_write_pidfile(pidfile, &error_fatal);
}
-#ifdef CONFIG_LIBCAP
+#ifdef CONFIG_LIBCAP_NG
if (drop_privileges() < 0) {
error_report("Failed to drop privileges: %s", strerror(errno));
exit(EXIT_FAILURE);