xen: return xenstore command failures via response instead of rc

When the xenbus driver does some special handling for a Xenstore
command any error condition related to the command should be returned
via an error response instead of letting the related write operation
fail. Otherwise the user land handler might take wrong decisions
assuming the connection to Xenstore is broken.

While at it try to return the same error values xenstored would
return for those cases.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Signed-off-by: Juergen Gross <jgross@suse.com>
This commit is contained in:
Juergen Gross 2016-12-22 08:19:47 +01:00
parent 639b08810d
commit 9a6161fe73
1 changed files with 27 additions and 20 deletions

View File

@ -302,6 +302,29 @@ static void watch_fired(struct xenbus_watch *watch,
mutex_unlock(&adap->dev_data->reply_mutex); mutex_unlock(&adap->dev_data->reply_mutex);
} }
static int xenbus_command_reply(struct xenbus_file_priv *u,
unsigned int msg_type, const char *reply)
{
struct {
struct xsd_sockmsg hdr;
const char body[16];
} msg;
int rc;
msg.hdr = u->u.msg;
msg.hdr.type = msg_type;
msg.hdr.len = strlen(reply) + 1;
if (msg.hdr.len > sizeof(msg.body))
return -E2BIG;
mutex_lock(&u->reply_mutex);
rc = queue_reply(&u->read_buffers, &msg, sizeof(msg.hdr) + msg.hdr.len);
wake_up(&u->read_waitq);
mutex_unlock(&u->reply_mutex);
return rc;
}
static int xenbus_write_transaction(unsigned msg_type, static int xenbus_write_transaction(unsigned msg_type,
struct xenbus_file_priv *u) struct xenbus_file_priv *u)
{ {
@ -321,7 +344,7 @@ static int xenbus_write_transaction(unsigned msg_type,
if (trans->handle.id == u->u.msg.tx_id) if (trans->handle.id == u->u.msg.tx_id)
break; break;
if (&trans->list == &u->transactions) if (&trans->list == &u->transactions)
return -ESRCH; return xenbus_command_reply(u, XS_ERROR, "ENOENT");
} }
reply = xenbus_dev_request_and_reply(&u->u.msg); reply = xenbus_dev_request_and_reply(&u->u.msg);
@ -372,12 +395,12 @@ static int xenbus_write_watch(unsigned msg_type, struct xenbus_file_priv *u)
path = u->u.buffer + sizeof(u->u.msg); path = u->u.buffer + sizeof(u->u.msg);
token = memchr(path, 0, u->u.msg.len); token = memchr(path, 0, u->u.msg.len);
if (token == NULL) { if (token == NULL) {
rc = -EILSEQ; rc = xenbus_command_reply(u, XS_ERROR, "EINVAL");
goto out; goto out;
} }
token++; token++;
if (memchr(token, 0, u->u.msg.len - (token - path)) == NULL) { if (memchr(token, 0, u->u.msg.len - (token - path)) == NULL) {
rc = -EILSEQ; rc = xenbus_command_reply(u, XS_ERROR, "EINVAL");
goto out; goto out;
} }
@ -411,23 +434,7 @@ static int xenbus_write_watch(unsigned msg_type, struct xenbus_file_priv *u)
} }
/* Success. Synthesize a reply to say all is OK. */ /* Success. Synthesize a reply to say all is OK. */
{ rc = xenbus_command_reply(u, msg_type, "OK");
struct {
struct xsd_sockmsg hdr;
char body[3];
} __packed reply = {
{
.type = msg_type,
.len = sizeof(reply.body)
},
"OK"
};
mutex_lock(&u->reply_mutex);
rc = queue_reply(&u->read_buffers, &reply, sizeof(reply));
wake_up(&u->read_waitq);
mutex_unlock(&u->reply_mutex);
}
out: out:
return rc; return rc;