return reply;
}
-/**
- * kdbus_cmd_msg_cancel() - cancel all pending sync requests
- * with the given cookie
- * @conn: The connection
- * @cmd: The command payload
- *
- * Return: 0 on success, or -ENOENT if no pending request with that
- * cookie was found.
- */
-int kdbus_cmd_msg_cancel(struct kdbus_conn *conn,
- struct kdbus_cmd_cancel *cmd)
-{
- struct kdbus_conn_reply *reply;
- const struct kdbus_item *item;
- struct kdbus_conn *c;
- int ret = -ENOENT;
- int i;
-
- KDBUS_ITEMS_FOREACH(item, cmd->items, KDBUS_ITEMS_SIZE(cmd, items)) {
- /* no items supported so far */
- switch (item->type) {
- default:
- return -EINVAL;
- }
- }
-
- if (atomic_read(&conn->reply_count) == 0)
- return -ENOENT;
-
- /* lock order: domain -> bus -> ep -> names -> conn */
- down_read(&conn->ep->bus->conn_rwlock);
- hash_for_each(conn->ep->bus->conn_hash, i, c, hentry) {
- if (c == conn)
- continue;
-
- mutex_lock(&c->lock);
- reply = kdbus_conn_reply_find(c, conn, cmd->cookie);
- if (reply && reply->sync) {
- kdbus_conn_reply_sync(reply, -ECANCELED);
- ret = 0;
- }
- mutex_unlock(&c->lock);
- }
- up_read(&conn->ep->bus->conn_rwlock);
-
- return ret;
-}
-
static int kdbus_conn_check_access(struct kdbus_ep *ep,
const struct kdbus_msg *msg,
struct kdbus_conn *conn_src,
/* command dispatcher */
int kdbus_cmd_msg_recv(struct kdbus_conn *conn,
struct kdbus_cmd_recv *recv);
-int kdbus_cmd_msg_cancel(struct kdbus_conn *conn,
- struct kdbus_cmd_cancel *cmd);
int kdbus_cmd_conn_info(struct kdbus_conn *conn,
struct kdbus_cmd_info *cmd_info);
int kdbus_cmd_conn_update(struct kdbus_conn *conn,
break;
}
- case KDBUS_CMD_CANCEL: {
- struct kdbus_cmd_cancel *cmd_cancel;
-
- if (!kdbus_conn_is_ordinary(conn)) {
- ret = -EOPNOTSUPP;
- break;
- }
-
- cmd_cancel = kdbus_memdup_user(buf, sizeof(*cmd_cancel),
- KDBUS_CMD_MAX_SIZE);
- if (IS_ERR(cmd_cancel)) {
- ret = PTR_ERR(cmd_cancel);
- break;
- }
-
- free_ptr = cmd_cancel;
-
- ret = kdbus_negotiate_flags(cmd_cancel, buf,
- typeof(*cmd_cancel), 0);
- if (ret < 0)
- break;
-
- ret = kdbus_items_validate(cmd_cancel->items,
- KDBUS_ITEMS_SIZE(cmd_cancel, items));
- if (ret < 0)
- break;
-
- cmd_cancel->return_flags = 0;
-
- ret = kdbus_cmd_msg_cancel(conn, cmd_cancel);
- if (ret < 0)
- break;
-
- if (kdbus_member_set_user(&cmd_cancel->return_flags, buf,
- struct kdbus_cmd_cancel,
- return_flags))
- ret = -EFAULT;
-
- break;
- }
-
case KDBUS_CMD_FREE: {
struct kdbus_cmd_free *cmd_free;
const struct kdbus_item *item;
struct kdbus_item items[0];
} __attribute__((aligned(8)));
-/**
- * struct kdbus_cmd_cancel - struct to cancel a synchronously pending message
- * @size: Overall size of this object
- * @flags: Flags for the free command. Currently unused.
- * @kernel_flags: Supported flags of CANCEL, kernel → userspace
- * @return_flags: Command return flags, kernel → userspace
- * @cookie: The cookie of the pending message
- * @items: Items to modify the command behavior
- *
- * This struct is used with the KDBUS_CMD_CANCEL ioctl.
- */
-struct kdbus_cmd_cancel {
- __u64 size;
- __u64 flags;
- __u64 kernel_flags;
- __u64 return_flags;
- __u64 cookie;
- struct kdbus_item items[0];
-} __attribute__((aligned(8)));
-
/**
* struct kdbus_cmd_free - struct to free a slice of memory in the pool
* @size: Overall size of this structure
* the kernel.
* KDBUS_CMD_RECV: Receive a message from the kernel which is
* placed in the receiver's pool.
- * KDBUS_CMD_CANCEL: Cancel a pending request of a message that
- * blocks while waiting for a reply. The parameter
- * denotes the cookie of the message in flight.
* KDBUS_CMD_FREE: Release the allocated memory in the receiver's
* pool.
* KDBUS_CMD_NAME_ACQUIRE: Request a well-known bus name to associate with
struct kdbus_cmd_send)
#define KDBUS_CMD_RECV _IOWR(KDBUS_IOCTL_MAGIC, 0x31, \
struct kdbus_cmd_recv)
-#define KDBUS_CMD_CANCEL _IOW(KDBUS_IOCTL_MAGIC, 0x32, \
- struct kdbus_cmd_cancel)
#define KDBUS_CMD_FREE _IOW(KDBUS_IOCTL_MAGIC, 0x33, \
struct kdbus_cmd_free)
the memory is no longer needed.
-7.5 Canceling messages synchronously waiting for replies
---------------------------------------------------------
-
-When a connection sends a message with KDBUS_MSG_SYNC_REPLY and blocks while
-waiting for the reply, the KDBUS_CMD_CANCEL ioctl can be used on the same file
-descriptor to cancel blocking wait, based on its cookie. If there are multiple
-messages with the same cookie that are all synchronously waiting for a reply,
-all of them will be canceled. Obviously, this is only possible in
-multi-threaded applications. Note that the original message itself still ends
-up in the receiver's pool if the reply wait is cancelled.
-
-
8. Name registry
===============================================================================
-EPIPE When sending a message, a synchronous reply from the receiving
connection was expected but the connection died before
answering
- -ECANCELED A synchronous message sending was cancelled
-ENOBUFS Too many pending messages on the receiver side
-EREMCHG Both a well-known name and a unique name (ID) was given, but
the name is not currently owned by that connection.
-ENOMSG No message of the requested priority found
-EOVERFLOW Broadcast messages have been lost
-For KDBUS_CMD_CANCEL:
-
- -EINVAL Invalid flags
- -ENOENT Pending message with the supplied cookie not found
-
For KDBUS_CMD_FREE:
-ENXIO No pool slice found at given offset