From: Mateusz Polrola mateuszx.potrola@intel.com
This change adds two query items, 'HYPER_DMABUF_QUERY_PRIV_INFO_SIZE' and 'HYPER_DMABUF_QUERY_PRIV_INFO', for retrieving buffer's private info and its size.
'info' is an address of user-space buffer (user application provides this) ,where private data will be copied in case query item is 'HYPER_DMABUF_QUERY_PRIV_INFO'.
Signed-off-by: Dongwon Kim dongwon.kim@intel.com --- drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c | 7 +- drivers/xen/hyper_dmabuf/hyper_dmabuf_event.c | 6 ++ drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c | 12 ++-- drivers/xen/hyper_dmabuf/hyper_dmabuf_query.c | 97 +++++++++++++++++++++------ drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h | 6 +- include/uapi/xen/hyper_dmabuf.h | 4 +- 6 files changed, 100 insertions(+), 32 deletions(-)
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c index 87ea6ca..1c35a59 100644 --- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c @@ -168,8 +168,11 @@ ssize_t hyper_dmabuf_event_read(struct file *filp, char __user *buffer, ret -= sizeof(struct hyper_dmabuf_event_hdr);
/* nullifying hdr of the event in user buffer */ - copy_to_user(buffer + ret, &dummy_hdr, - sizeof(dummy_hdr)); + if (copy_to_user(buffer + ret, &dummy_hdr, + sizeof(dummy_hdr))) { + dev_err(hyper_dmabuf_private.device, + "failed to nullify invalid hdr already in userspace\n"); + }
ret = -EFAULT;
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_event.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_event.c index 8998a7d..3e1498c 100644 --- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_event.c +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_event.c @@ -104,6 +104,12 @@ int hyper_dmabuf_import_event(hyper_dmabuf_id_t hid)
e = kzalloc(sizeof(*e), GFP_KERNEL);
+ if (!e) { + dev_err(hyper_dmabuf_private.device, + "no space left\n"); + return -ENOMEM; + } + e->event_data.hdr.event_type = HYPER_DMABUF_NEW_IMPORT; e->event_data.hdr.hid = hid; e->event_data.data = (void*)imported_sgt_info->priv; diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c index 06f95ca..15191c2 100644 --- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c @@ -671,9 +671,8 @@ static int hyper_dmabuf_query_ioctl(struct file *filp, void *data) /* query for exported dmabuf */ sgt_info = hyper_dmabuf_find_exported(query_attr->hid); if (sgt_info) { - ret = hyper_dmabuf_query_exported(sgt_info, query_attr->item); - if (ret != -EINVAL) - query_attr->info = ret; + ret = hyper_dmabuf_query_exported(sgt_info, + query_attr->item, &query_attr->info); } else { dev_err(hyper_dmabuf_private.device, "DMA BUF {id:%d key:%d %d %d} can't be found in the export list\n", @@ -685,9 +684,8 @@ static int hyper_dmabuf_query_ioctl(struct file *filp, void *data) /* query for imported dmabuf */ imported_sgt_info = hyper_dmabuf_find_imported(query_attr->hid); if (imported_sgt_info) { - ret = hyper_dmabuf_query_imported(imported_sgt_info, query_attr->item); - if (ret != -EINVAL) - query_attr->info = ret; + ret = hyper_dmabuf_query_imported(imported_sgt_info, + query_attr->item, &query_attr->info); } else { dev_err(hyper_dmabuf_private.device, "DMA BUF {id:%d key:%d %d %d} can't be found in the imported list\n", @@ -697,7 +695,7 @@ static int hyper_dmabuf_query_ioctl(struct file *filp, void *data) } }
- return 0; + return ret; }
void hyper_dmabuf_emergency_release(struct hyper_dmabuf_sgt_info* sgt_info, diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_query.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_query.c index 2a5201b..39c9dee 100644 --- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_query.c +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_query.c @@ -27,6 +27,7 @@ */
#include <linux/dma-buf.h> +#include <linux/uaccess.h> #include "hyper_dmabuf_drv.h" #include "hyper_dmabuf_struct.h" #include "hyper_dmabuf_id.h" @@ -36,56 +37,91 @@ extern struct hyper_dmabuf_private hyper_dmabuf_private; #define HYPER_DMABUF_SIZE(nents, first_offset, last_len) \ ((nents)*PAGE_SIZE - (first_offset) - PAGE_SIZE + (last_len))
-int hyper_dmabuf_query_exported(struct hyper_dmabuf_sgt_info *sgt_info, int query) +int hyper_dmabuf_query_exported(struct hyper_dmabuf_sgt_info *sgt_info, + int query, unsigned long* info) { + int n; + switch (query) { case HYPER_DMABUF_QUERY_TYPE: - return EXPORTED; + *info = EXPORTED; + break;
/* exporting domain of this specific dmabuf*/ case HYPER_DMABUF_QUERY_EXPORTER: - return HYPER_DMABUF_DOM_ID(sgt_info->hid); + *info = HYPER_DMABUF_DOM_ID(sgt_info->hid); + break;
/* importing domain of this specific dmabuf */ case HYPER_DMABUF_QUERY_IMPORTER: - return sgt_info->hyper_dmabuf_rdomain; + *info = sgt_info->hyper_dmabuf_rdomain; + break;
/* size of dmabuf in byte */ case HYPER_DMABUF_QUERY_SIZE: - return sgt_info->dma_buf->size; + *info = sgt_info->dma_buf->size; + break;
/* whether the buffer is used by importer */ case HYPER_DMABUF_QUERY_BUSY: - return (sgt_info->importer_exported == 0) ? false : true; + *info = (sgt_info->importer_exported == 0) ? false : true; + break;
/* whether the buffer is unexported */ case HYPER_DMABUF_QUERY_UNEXPORTED: - return !sgt_info->valid; + *info = !sgt_info->valid; + break;
/* whether the buffer is scheduled to be unexported */ case HYPER_DMABUF_QUERY_DELAYED_UNEXPORTED: - return !sgt_info->unexport_scheduled; + *info = !sgt_info->unexport_scheduled; + break; + + /* size of private info attached to buffer */ + case HYPER_DMABUF_QUERY_PRIV_INFO_SIZE: + *info = sgt_info->sz_priv; + break; + + /* copy private info attached to buffer */ + case HYPER_DMABUF_QUERY_PRIV_INFO: + if (sgt_info->sz_priv > 0) { + n = copy_to_user((void __user*) *info, + sgt_info->priv, + sgt_info->sz_priv); + if (n != 0) + return -EINVAL; + } + break; + + default: + return -EINVAL; }
- return -EINVAL; + return 0; }
-int hyper_dmabuf_query_imported(struct hyper_dmabuf_imported_sgt_info *imported_sgt_info, int query) +int hyper_dmabuf_query_imported(struct hyper_dmabuf_imported_sgt_info *imported_sgt_info, + int query, unsigned long *info) { + int n; + switch (query) { case HYPER_DMABUF_QUERY_TYPE: - return IMPORTED; + *info = IMPORTED; + break;
/* exporting domain of this specific dmabuf*/ case HYPER_DMABUF_QUERY_EXPORTER: - return HYPER_DMABUF_DOM_ID(imported_sgt_info->hid); + *info = HYPER_DMABUF_DOM_ID(imported_sgt_info->hid); + break;
/* importing domain of this specific dmabuf */ case HYPER_DMABUF_QUERY_IMPORTER: - return hyper_dmabuf_private.domid; + *info = hyper_dmabuf_private.domid; + break;
/* size of dmabuf in byte */ case HYPER_DMABUF_QUERY_SIZE: @@ -93,23 +129,44 @@ int hyper_dmabuf_query_imported(struct hyper_dmabuf_imported_sgt_info *imported_ /* if local dma_buf is created (if it's ever mapped), * retrieve it directly from struct dma_buf * */ - return imported_sgt_info->dma_buf->size; + *info = imported_sgt_info->dma_buf->size; } else { /* calcuate it from given nents, frst_ofst and last_len */ - return HYPER_DMABUF_SIZE(imported_sgt_info->nents, - imported_sgt_info->frst_ofst, - imported_sgt_info->last_len); + *info = HYPER_DMABUF_SIZE(imported_sgt_info->nents, + imported_sgt_info->frst_ofst, + imported_sgt_info->last_len); } + break;
/* whether the buffer is used or not */ case HYPER_DMABUF_QUERY_BUSY: /* checks if it's used by importer */ - return (imported_sgt_info->num_importers > 0) ? true : false; + *info = (imported_sgt_info->num_importers > 0) ? true : false; + break;
/* whether the buffer is unexported */ case HYPER_DMABUF_QUERY_UNEXPORTED: - return !imported_sgt_info->valid; + *info = !imported_sgt_info->valid; + break; + /* size of private info attached to buffer */ + case HYPER_DMABUF_QUERY_PRIV_INFO_SIZE: + *info = imported_sgt_info->sz_priv; + break; + + /* copy private info attached to buffer */ + case HYPER_DMABUF_QUERY_PRIV_INFO: + if (imported_sgt_info->sz_priv > 0) { + n = copy_to_user((void __user*) *info, + imported_sgt_info->priv, + imported_sgt_info->sz_priv); + if (n != 0) + return -EINVAL; + } + break; + + default: + return -EINVAL; }
- return -EINVAL; + return 0; } diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h index 295e923..7bbb322 100644 --- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h @@ -1,8 +1,10 @@ #ifndef __HYPER_DMABUF_QUERY_H__ #define __HYPER_DMABUF_QUERY_H__
-int hyper_dmabuf_query_imported(struct hyper_dmabuf_imported_sgt_info *imported_sgt_info, int query); +int hyper_dmabuf_query_imported(struct hyper_dmabuf_imported_sgt_info *imported_sgt_info, + int query, unsigned long *info);
-int hyper_dmabuf_query_exported(struct hyper_dmabuf_sgt_info *sgt_info, int query); +int hyper_dmabuf_query_exported(struct hyper_dmabuf_sgt_info *sgt_info, + int query, unsigned long *info);
#endif // __HYPER_DMABUF_QUERY_H__ diff --git a/include/uapi/xen/hyper_dmabuf.h b/include/uapi/xen/hyper_dmabuf.h index df01b17..e18dd9b 100644 --- a/include/uapi/xen/hyper_dmabuf.h +++ b/include/uapi/xen/hyper_dmabuf.h @@ -109,7 +109,7 @@ struct ioctl_hyper_dmabuf_query { int item; /* OUT parameters */ /* Value of queried item */ - int info; + unsigned long info; };
/* DMABUF query */ @@ -122,6 +122,8 @@ enum hyper_dmabuf_query { HYPER_DMABUF_QUERY_BUSY, HYPER_DMABUF_QUERY_UNEXPORTED, HYPER_DMABUF_QUERY_DELAYED_UNEXPORTED, + HYPER_DMABUF_QUERY_PRIV_INFO_SIZE, + HYPER_DMABUF_QUERY_PRIV_INFO, };
enum hyper_dmabuf_status {