/* * Netlink/Connector is an unreliable protocol. How long should * we wait for a response before assuming it was lost and retrying? * (If we do receive a response after this time, it will be discarded * and the response to the resent request will be waited for.
*/ #define DM_ULOG_RETRY_TIMEOUT (15 * HZ)
/* * Pre-allocated space for speed
*/ #define DM_ULOG_PREALLOCED_SIZE 512 staticstruct cn_msg *prealloced_cn_msg; staticstruct dm_ulog_request *prealloced_ulog_tfr;
/* * Parameters for this function can be either msg or tfr, but not * both. This function fills in the reply for a waiting request. * If just msg is given, then the reply is simply an ACK from userspace * that the request was received. * * Returns: 0 on success, -ENOENT on failure
*/ staticint fill_pkg(struct cn_msg *msg, struct dm_ulog_request *tfr)
{
uint32_t rtn_seq = (msg) ? msg->seq : (tfr) ? tfr->seq : 0; struct receiving_pkg *pkg;
/* * The 'receiving_pkg' entries in this list are statically * allocated on the stack in 'dm_consult_userspace'. * Each process that is waiting for a reply from the user * space server will have an entry in this list. * * We are safe to do it this way because the stack space * is unique to each process, but still addressable by * other processes.
*/
list_for_each_entry(pkg, &receiving_list, list) { if (rtn_seq != pkg->seq) continue;
if (msg) {
pkg->error = -msg->ack; /* * If we are trying again, we will need to know our * storage capacity. Otherwise, along with the * error code, we make explicit that we have no data.
*/ if (pkg->error != -EAGAIN)
*(pkg->data_size) = 0;
} elseif (tfr->data_size > *(pkg->data_size)) {
DMERR("Insufficient space to receive package [%u] (%u vs %zu)",
tfr->request_type, tfr->data_size, *(pkg->data_size));
/* * This is the connector callback that delivers data * that was sent from userspace.
*/ staticvoid cn_ulog_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{ struct dm_ulog_request *tfr = (struct dm_ulog_request *)(msg + 1);
/** * dm_consult_userspace * @uuid: log's universal unique identifier (must be DM_UUID_LEN in size) * @luid: log's local unique identifier * @request_type: found in include/linux/dm-log-userspace.h * @data: data to tx to the server * @data_size: size of data in bytes * @rdata: place to put return data from server * @rdata_size: value-result (amount of space given/amount of space used) * * rdata_size is undefined on failure. * * Memory used to communicate with userspace is zero'ed * before populating to ensure that no unwanted bits leak * from kernel space to user-space. All userspace log communications * between kernel and user space go through this function. * * Returns: 0 on success, -EXXX on failure
**/ int dm_consult_userspace(constchar *uuid, uint64_t luid, int request_type, char *data, size_t data_size, char *rdata, size_t *rdata_size)
{ int r = 0; unsignedlong tmo;
size_t dummy = 0; int overhead_size = sizeof(struct dm_ulog_request) + sizeof(struct cn_msg); struct dm_ulog_request *tfr = prealloced_ulog_tfr; struct receiving_pkg pkg;
/* * Given the space needed to hold the 'struct cn_msg' and * 'struct dm_ulog_request' - do we have enough payload * space remaining?
*/ if (data_size > (DM_ULOG_PREALLOCED_SIZE - overhead_size)) {
DMINFO("Size of tfr exceeds preallocated size"); return -EINVAL;
}
if (!rdata_size)
rdata_size = &dummy;
resend: /* * We serialize the sending of requests so we can * use the preallocated space.
*/
mutex_lock(&dm_ulog_lock);
/* * Must be valid request type (all other bits set to * zero). This reserves other bits for possible future * use.
*/
tfr->request_type = request_type & DM_ULOG_REQUEST_MASK;
tfr->data_size = data_size; if (data && data_size)
memcpy(tfr->data, data, data_size);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.