[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [RFC PATCH 14/60] hyper_dmabuf: clean-up process based on file->f_count



Now relaese funcs checks f_count for the file instead of
our own refcount because it can't track dma_buf_get.

Also, importer now sends out HYPER_DMABUF_FIRST_EXPORT
to let the exporter know corresponding dma-buf has ever
exported on importer's side. This is to cover the case
where exporter exports a buffer and unexport it right
away before importer does first export_fd (there won't
be any dma_buf_release nofication to exporter since SGT
was never created by importer.)

After importer creates its own SGT, only condition it is
completely released is that dma_buf is unexported
(so valid == 0) and user app closes all locally
assigned FDs (when dma_buf_release is called.)
Otherwise, it needs to stay there since previously exported
FD can be reused.

Also includes minor changes;

1. flag had been changed to "bool valid" for conciseness.
2. added bool importer_exported in sgt_info as an indicator
   for usage of buffer on the importer.
3. num of pages is added (nents) to hyper_dmabuf_sgt_info
   to keep the size info in EXPORT list.
3. more minor changes and clean-ups.

Signed-off-by: Dongwon Kim <dongwon.kim@xxxxxxxxx>
Signed-off-by: Mateusz Polrola <mateuszx.potrola@xxxxxxxxx>
---
 drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c        |  1 +
 drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h        |  1 +
 drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c        | 76 ++++++++++++---------
 drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h        |  5 +-
 drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c      | 78 ++++++++++++----------
 drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c       |  2 +-
 drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h       |  2 +-
 drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c        | 34 ++++++++--
 drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h        |  2 +
 .../xen/hyper_dmabuf/hyper_dmabuf_remote_sync.c    | 10 ++-
 drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h     | 19 +++---
 .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c   |  6 +-
 12 files changed, 143 insertions(+), 93 deletions(-)

diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c 
b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c
index 5b5dae44..5a7cfa5 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c
@@ -33,6 +33,7 @@ static int hyper_dmabuf_drv_init(void)
        /* device structure initialization */
        /* currently only does work-queue initialization */
        hyper_dmabuf_private.work_queue = 
create_workqueue("hyper_dmabuf_wqueue");
+       hyper_dmabuf_private.domid = hyper_dmabuf_get_domid();
 
        ret = hyper_dmabuf_table_init();
        if (ret < 0) {
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h 
b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h
index 8778a19..ff883e1 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h
@@ -3,6 +3,7 @@
 
 struct hyper_dmabuf_private {
         struct device *device;
+       int domid;
        struct workqueue_struct *work_queue;
 };
 
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c 
b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c
index f258981..fa445e5 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c
@@ -13,6 +13,14 @@
 
 #define REFS_PER_PAGE (PAGE_SIZE/sizeof(grant_ref_t))
 
+int dmabuf_refcount(struct dma_buf *dma_buf)
+{
+       if ((dma_buf != NULL) && (dma_buf->file != NULL))
+               return file_count(dma_buf->file);
+
+       return -1;
+}
+
 /* return total number of pages referecned by a sgt
  * for pre-calculation of # of pages behind a given sgt
  */
@@ -368,8 +376,8 @@ int hyper_dmabuf_cleanup_gref_table(struct 
hyper_dmabuf_sgt_info *sgt_info) {
        struct hyper_dmabuf_shared_pages_info *shared_pages_info = 
&sgt_info->shared_pages_info;
 
        grant_ref_t *ref = shared_pages_info->top_level_page;
-       int n_2nd_level_pages = 
(sgt_info->active_sgts->sgt->nents/REFS_PER_PAGE +
-                               ((sgt_info->active_sgts->sgt->nents % 
REFS_PER_PAGE) ? 1: 0));
+       int n_2nd_level_pages = (sgt_info->nents/REFS_PER_PAGE +
+                               ((sgt_info->nents % REFS_PER_PAGE) ? 1: 0));
 
 
        if (shared_pages_info->data_refs == NULL ||
@@ -388,26 +396,28 @@ int hyper_dmabuf_cleanup_gref_table(struct 
hyper_dmabuf_sgt_info *sgt_info) {
                if (!gnttab_end_foreign_access_ref(ref[i], 1)) {
                        printk("refid still in use!!!\n");
                }
+               gnttab_free_grant_reference(ref[i]);
                i++;
        }
        free_pages((unsigned long)shared_pages_info->addr_pages, i);
 
+
        /* End foreign access for top level addressing page */
        if (gnttab_query_foreign_access(shared_pages_info->top_level_ref)) {
                printk("refid not shared !!\n");
        }
-       if (!gnttab_end_foreign_access_ref(shared_pages_info->top_level_ref, 
1)) {
-               printk("refid still in use!!!\n");
-       }
        gnttab_end_foreign_access_ref(shared_pages_info->top_level_ref, 1);
+       gnttab_free_grant_reference(shared_pages_info->top_level_ref);
+
        free_pages((unsigned long)shared_pages_info->top_level_page, 1);
 
        /* End foreign access for data pages, but do not free them */
-       for (i = 0; i < sgt_info->active_sgts->sgt->nents; i++) {
+       for (i = 0; i < sgt_info->nents; i++) {
                if 
(gnttab_query_foreign_access(shared_pages_info->data_refs[i])) {
                        printk("refid not shared !!\n");
                }
                gnttab_end_foreign_access_ref(shared_pages_info->data_refs[i], 
0);
+               gnttab_free_grant_reference(shared_pages_info->data_refs[i]);
        }
 
        kfree(shared_pages_info->data_refs);
@@ -545,6 +555,7 @@ int hyper_dmabuf_cleanup_sgt_info(struct 
hyper_dmabuf_sgt_info *sgt_info, int fo
                return -EPERM;
        }
 
+       /* force == 1 is not recommended */
        while (!list_empty(&sgt_info->va_kmapped->list)) {
                va_kmapl = list_first_entry(&sgt_info->va_kmapped->list,
                                            struct kmap_vaddr_list, list);
@@ -598,6 +609,7 @@ int hyper_dmabuf_cleanup_sgt_info(struct 
hyper_dmabuf_sgt_info *sgt_info, int fo
 
        /* close connection to dma-buf completely */
        dma_buf_put(sgt_info->dma_buf);
+       sgt_info->dma_buf = NULL;
 
        kfree(sgt_info->active_sgts);
        kfree(sgt_info->active_attached);
@@ -621,7 +633,7 @@ inline int hyper_dmabuf_sync_request_and_wait(int id, int 
ops)
        hyper_dmabuf_create_request(req, HYPER_DMABUF_OPS_TO_SOURCE, 
&operands[0]);
 
        /* send request and wait for a response */
-       ret = 
hyper_dmabuf_send_request(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(id), req, 
true);
+       ret = hyper_dmabuf_send_request(HYPER_DMABUF_DOM_ID(id), req, true);
 
        kfree(req);
 
@@ -737,30 +749,33 @@ static void hyper_dmabuf_ops_unmap(struct 
dma_buf_attachment *attachment,
        }
 }
 
-static void hyper_dmabuf_ops_release(struct dma_buf *dmabuf)
+static void hyper_dmabuf_ops_release(struct dma_buf *dma_buf)
 {
        struct hyper_dmabuf_imported_sgt_info *sgt_info;
        int ret;
+       int final_release;
 
-       if (!dmabuf->priv)
+       if (!dma_buf->priv)
                return;
 
-       sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv;
+       sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dma_buf->priv;
 
-       if (sgt_info) {
-               /* dmabuf fd is being released - decrease refcount */
-               sgt_info->ref_count--;
+       final_release = sgt_info && !sgt_info->valid &&
+                      !dmabuf_refcount(sgt_info->dma_buf);
 
-               /* if no one else in that domain is using that buffer, unmap it 
for now */
-               if (sgt_info->ref_count == 0) {
-                       hyper_dmabuf_cleanup_imported_pages(sgt_info);
-                       hyper_dmabuf_free_sgt(sgt_info->sgt);
-                       sgt_info->sgt = NULL;
-               }
+       if (!dmabuf_refcount(sgt_info->dma_buf)) {
+               sgt_info->dma_buf = NULL;
        }
 
-       ret = hyper_dmabuf_sync_request_and_wait(sgt_info->hyper_dmabuf_id,
-                                               HYPER_DMABUF_OPS_RELEASE);
+       if (final_release) {
+               hyper_dmabuf_cleanup_imported_pages(sgt_info);
+               hyper_dmabuf_free_sgt(sgt_info->sgt);
+               ret = 
hyper_dmabuf_sync_request_and_wait(sgt_info->hyper_dmabuf_id,
+                                                       
HYPER_DMABUF_OPS_RELEASE_FINAL);
+       } else {
+               ret = 
hyper_dmabuf_sync_request_and_wait(sgt_info->hyper_dmabuf_id,
+                                                       
HYPER_DMABUF_OPS_RELEASE);
+       }
 
        if (ret < 0) {
                printk("hyper_dmabuf::%s Error:send dmabuf sync request 
failed\n", __func__);
@@ -770,8 +785,7 @@ static void hyper_dmabuf_ops_release(struct dma_buf *dmabuf)
         * Check if buffer is still valid and if not remove it from imported 
list.
         * That has to be done after sending sync request
         */
-       if (sgt_info && sgt_info->ref_count == 0 &&
-           sgt_info->flags == HYPER_DMABUF_SGT_INVALID) {
+       if (final_release) {
                hyper_dmabuf_remove_imported(sgt_info->hyper_dmabuf_id);
                kfree(sgt_info);
        }
@@ -962,23 +976,21 @@ static const struct dma_buf_ops hyper_dmabuf_ops = {
 /* exporting dmabuf as fd */
 int hyper_dmabuf_export_fd(struct hyper_dmabuf_imported_sgt_info *dinfo, int 
flags)
 {
-       int fd;
-       struct dma_buf* dmabuf;
+       int fd = -1;
 
        /* call hyper_dmabuf_export_dmabuf and create
         * and bind a handle for it then release
         */
-       dmabuf = hyper_dmabuf_export_dma_buf(dinfo);
-
-       fd = dma_buf_fd(dmabuf, flags);
+       hyper_dmabuf_export_dma_buf(dinfo);
 
-       /* dmabuf fd is exported for given bufer - increase its ref count */
-       dinfo->ref_count++;
+       if (dinfo->dma_buf) {
+               fd = dma_buf_fd(dinfo->dma_buf, flags);
+       }
 
        return fd;
 }
 
-struct dma_buf* hyper_dmabuf_export_dma_buf(struct 
hyper_dmabuf_imported_sgt_info *dinfo)
+void hyper_dmabuf_export_dma_buf(struct hyper_dmabuf_imported_sgt_info *dinfo)
 {
        DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 
@@ -989,5 +1001,5 @@ struct dma_buf* hyper_dmabuf_export_dma_buf(struct 
hyper_dmabuf_imported_sgt_inf
        exp_info.flags = /* not sure about flag */0;
        exp_info.priv = dinfo;
 
-       return dma_buf_export(&exp_info);
+       dinfo->dma_buf = dma_buf_export(&exp_info);
 }
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h 
b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h
index 71c1bb0..1b0801f 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h
@@ -1,6 +1,7 @@
 #ifndef __HYPER_DMABUF_IMP_H__
 #define __HYPER_DMABUF_IMP_H__
 
+#include <linux/fs.h>
 #include "hyper_dmabuf_struct.h"
 
 /* extract pages directly from struct sg_table */
@@ -30,6 +31,8 @@ void hyper_dmabuf_free_sgt(struct sg_table *sgt);
 
 int hyper_dmabuf_export_fd(struct hyper_dmabuf_imported_sgt_info *dinfo, int 
flags);
 
-struct dma_buf* hyper_dmabuf_export_dma_buf(struct 
hyper_dmabuf_imported_sgt_info *dinfo);
+void hyper_dmabuf_export_dma_buf(struct hyper_dmabuf_imported_sgt_info *dinfo);
+
+int dmabuf_refcount(struct dma_buf *dma_buf);
 
 #endif /* __HYPER_DMABUF_IMP_H__ */
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c 
b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c
index c57acafe..e334b77 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c
@@ -107,10 +107,12 @@ static int hyper_dmabuf_export_remote(void *data)
        }
 
        /* we check if this specific attachment was already exported
-        * to the same domain and if yes, it returns hyper_dmabuf_id
-        * of pre-exported sgt */
-       ret = hyper_dmabuf_find_id(dma_buf, export_remote_attr->remote_domain);
-       if (ret != -1) {
+        * to the same domain and if yes and it's valid sgt_info,
+        * it returns hyper_dmabuf_id of pre-exported sgt_info
+        */
+       ret = hyper_dmabuf_find_id_exported(dma_buf, 
export_remote_attr->remote_domain);
+       sgt_info = hyper_dmabuf_find_exported(ret);
+       if (ret != -1 && sgt_info->valid) {
                dma_buf_put(dma_buf);
                export_remote_attr->hyper_dmabuf_id = ret;
                return 0;
@@ -135,12 +137,13 @@ static int hyper_dmabuf_export_remote(void *data)
        /* TODO: We might need to consider using port number on event channel? 
*/
        sgt_info->hyper_dmabuf_rdomain = export_remote_attr->remote_domain;
        sgt_info->dma_buf = dma_buf;
-       sgt_info->flags = 0;
+       sgt_info->valid = 1;
+       sgt_info->importer_exported = 0;
 
-       sgt_info->active_sgts = kcalloc(1, sizeof(struct sgt_list), GFP_KERNEL);
-       sgt_info->active_attached = kcalloc(1, sizeof(struct attachment_list), 
GFP_KERNEL);
-       sgt_info->va_kmapped = kcalloc(1, sizeof(struct kmap_vaddr_list), 
GFP_KERNEL);
-       sgt_info->va_vmapped = kcalloc(1, sizeof(struct vmap_vaddr_list), 
GFP_KERNEL);
+       sgt_info->active_sgts = kmalloc(sizeof(struct sgt_list), GFP_KERNEL);
+       sgt_info->active_attached = kmalloc(sizeof(struct attachment_list), 
GFP_KERNEL);
+       sgt_info->va_kmapped = kmalloc(sizeof(struct kmap_vaddr_list), 
GFP_KERNEL);
+       sgt_info->va_vmapped = kmalloc(sizeof(struct vmap_vaddr_list), 
GFP_KERNEL);
 
        sgt_info->active_sgts->sgt = sgt;
        sgt_info->active_attached->attach = attachment;
@@ -159,6 +162,8 @@ static int hyper_dmabuf_export_remote(void *data)
        if (page_info == NULL)
                goto fail_export;
 
+       sgt_info->nents = page_info->nents;
+
        /* now register it to export list */
        hyper_dmabuf_register_exported(sgt_info);
 
@@ -220,6 +225,8 @@ static int hyper_dmabuf_export_fd_ioctl(void *data)
 {
        struct ioctl_hyper_dmabuf_export_fd *export_fd_attr;
        struct hyper_dmabuf_imported_sgt_info *imported_sgt_info;
+       struct hyper_dmabuf_ring_rq *req;
+       int operand;
        int ret = 0;
 
        if (!data) {
@@ -234,35 +241,38 @@ static int hyper_dmabuf_export_fd_ioctl(void *data)
        if (imported_sgt_info == NULL) /* can't find sgt from the table */
                return -1;
 
-       /*
-        * Check if buffer was not unexported by exporter.
-        * In such exporter is waiting for importer to finish using that buffer,
-        * so do not allow export fd of such buffer anymore.
-        */
-       if (imported_sgt_info->flags == HYPER_DMABUF_SGT_INVALID) {
-               return -EINVAL;
-       }
-
        printk("%s Found buffer gref %d  off %d last len %d nents %d domain 
%d\n", __func__,
                imported_sgt_info->gref, imported_sgt_info->frst_ofst,
                imported_sgt_info->last_len, imported_sgt_info->nents,
-               
HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(imported_sgt_info->hyper_dmabuf_id));
+               HYPER_DMABUF_DOM_ID(imported_sgt_info->hyper_dmabuf_id));
 
        if (!imported_sgt_info->sgt) {
                imported_sgt_info->sgt = 
hyper_dmabuf_map_pages(imported_sgt_info->gref,
                                                        
imported_sgt_info->frst_ofst,
                                                        
imported_sgt_info->last_len,
                                                        
imported_sgt_info->nents,
-                                                       
HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(imported_sgt_info->hyper_dmabuf_id),
+                                                       
HYPER_DMABUF_DOM_ID(imported_sgt_info->hyper_dmabuf_id),
                                                        
&imported_sgt_info->shared_pages_info);
-               if (!imported_sgt_info->sgt) {
-                       printk("Failed to create sgt\n");
+
+               /* send notifiticatio for first export_fd to exporter */
+               operand = imported_sgt_info->hyper_dmabuf_id;
+               req = kcalloc(1, sizeof(*req), GFP_KERNEL);
+               hyper_dmabuf_create_request(req, HYPER_DMABUF_FIRST_EXPORT, 
&operand);
+
+               ret = hyper_dmabuf_send_request(HYPER_DMABUF_DOM_ID(operand), 
req, false);
+
+               if (!imported_sgt_info->sgt || ret) {
+                       kfree(req);
+                       printk("Failed to create sgt or notify exporter\n");
                        return -EINVAL;
                }
+               kfree(req);
        }
 
        export_fd_attr->fd = hyper_dmabuf_export_fd(imported_sgt_info, 
export_fd_attr->flags);
-       if (export_fd_attr < 0) {
+
+       if (export_fd_attr->fd < 0) {
+               /* fail to get fd */
                ret = export_fd_attr->fd;
        }
 
@@ -309,23 +319,23 @@ static int hyper_dmabuf_unexport(void *data)
        /* free msg */
        kfree(req);
 
+       /* no longer valid */
+       sgt_info->valid = 0;
+
        /*
-        * Check if any importer is still using buffer, if not clean it up 
completly,
-        * otherwise mark buffer as unexported and postpone its cleanup to time 
when
-        * importer will finish using it.
+        * Immediately clean-up if it has never been exported by importer
+        * (so no SGT is constructed on importer).
+        * clean it up later in remote sync when final release ops
+        * is called (importer does this only when there's no
+        * no consumer of locally exported FDs)
         */
-       if (list_empty(&sgt_info->active_sgts->list) &&
-           list_empty(&sgt_info->active_attached->list)) {
+       printk("before claning up buffer completly\n");
+       if (!sgt_info->importer_exported) {
                hyper_dmabuf_cleanup_sgt_info(sgt_info, false);
                hyper_dmabuf_remove_exported(unexport_attr->hyper_dmabuf_id);
                kfree(sgt_info);
-       } else {
-               sgt_info->flags = HYPER_DMABUF_SGT_UNEXPORTED;
        }
 
-       /* TODO: should we mark here that buffer was destroyed immiedetaly or 
that was postponed ? */
-       unexport_attr->status = ret;
-
        return ret;
 }
 
@@ -369,7 +379,7 @@ static int hyper_dmabuf_query(void *data)
                        if (sgt_info) {
                                query_attr->info = 0xFFFFFFFF; /* myself */
                        } else {
-                               query_attr->info = 
(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(imported_sgt_info->hyper_dmabuf_id));
+                               query_attr->info = 
(HYPER_DMABUF_DOM_ID(imported_sgt_info->hyper_dmabuf_id));
                        }
                        break;
 
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c 
b/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c
index 1420df9..18731de 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c
@@ -65,7 +65,7 @@ struct hyper_dmabuf_sgt_info *hyper_dmabuf_find_exported(int 
id)
 }
 
 /* search for pre-exported sgt and return id of it if it exist */
-int hyper_dmabuf_find_id(struct dma_buf *dmabuf, int domid)
+int hyper_dmabuf_find_id_exported(struct dma_buf *dmabuf, int domid)
 {
        struct hyper_dmabuf_info_entry_exported *info_entry;
        int bkt;
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h 
b/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h
index 463a6da..f55d06e 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h
@@ -25,7 +25,7 @@ int hyper_dmabuf_table_destroy(void);
 int hyper_dmabuf_register_exported(struct hyper_dmabuf_sgt_info *info);
 
 /* search for pre-exported sgt and return id of it if it exist */
-int hyper_dmabuf_find_id(struct dma_buf *dmabuf, int domid);
+int hyper_dmabuf_find_id_exported(struct dma_buf *dmabuf, int domid);
 
 int hyper_dmabuf_register_imported(struct hyper_dmabuf_imported_sgt_info* 
info);
 
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c 
b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c
index 97b42a4..a2d687f 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c
@@ -55,6 +55,14 @@ void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq 
*request,
                request->operands[0] = operands[0];
                break;
 
+       case HYPER_DMABUF_FIRST_EXPORT:
+               /* dmabuf fd is being created on imported side for first time */
+               /* command : HYPER_DMABUF_FIRST_EXPORT,
+                * operands0 : hyper_dmabuf_id
+                */
+               request->operands[0] = operands[0];
+               break;
+
        case HYPER_DMABUF_OPS_TO_REMOTE:
                /* notifying dmabuf map/unmap to importer (probably not needed) 
*/
                /* for dmabuf synchronization */
@@ -81,6 +89,7 @@ void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq 
*request,
 void cmd_process_work(struct work_struct *work)
 {
        struct hyper_dmabuf_imported_sgt_info *imported_sgt_info;
+       struct hyper_dmabuf_sgt_info *sgt_info;
        struct cmd_process *proc = container_of(work, struct cmd_process, work);
        struct hyper_dmabuf_ring_rq *req;
        int domid;
@@ -117,11 +126,25 @@ void cmd_process_work(struct work_struct *work)
                for (i=0; i<4; i++)
                        imported_sgt_info->private[i] = req->operands[5+i];
 
-               imported_sgt_info->flags = 0;
-               imported_sgt_info->ref_count = 0;
+               imported_sgt_info->valid = 1;
                hyper_dmabuf_register_imported(imported_sgt_info);
                break;
 
+       case HYPER_DMABUF_FIRST_EXPORT:
+               /* find a corresponding SGT for the id */
+               sgt_info = hyper_dmabuf_find_exported(req->operands[0]);
+
+               if (!sgt_info) {
+                       printk("critical err: requested sgt_info can't be found 
%d\n", req->operands[0]);
+                       break;
+               }
+
+               if (sgt_info->importer_exported)
+                       printk("warning: exported flag is not supposed to be 1 
already\n");
+
+               sgt_info->importer_exported = 1;
+               break;
+
        case HYPER_DMABUF_OPS_TO_REMOTE:
                /* notifying dmabuf map/unmap to importer (probably not needed) 
*/
                /* for dmabuf synchronization */
@@ -170,13 +193,14 @@ int hyper_dmabuf_msg_parse(int domid, struct 
hyper_dmabuf_ring_rq *req)
                        hyper_dmabuf_find_imported(req->operands[0]);
 
                if (imported_sgt_info) {
-                       /* check if buffer is still mapped and in use */
-                       if (imported_sgt_info->sgt) {
+                       /* if anything is still using dma_buf */
+                       if (imported_sgt_info->dma_buf &&
+                           dmabuf_refcount(imported_sgt_info->dma_buf) > 0) {
                                /*
                                 * Buffer is still in  use, just mark that it 
should
                                 * not be allowed to export its fd anymore.
                                 */
-                               imported_sgt_info->flags = 
HYPER_DMABUF_SGT_INVALID;
+                               imported_sgt_info->valid = 0;
                        } else {
                                /* No one is using buffer, remove it from 
imported list */
                                hyper_dmabuf_remove_imported(req->operands[0]);
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h 
b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h
index fc1365b..1e9d827 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h
@@ -3,6 +3,7 @@
 
 enum hyper_dmabuf_command {
        HYPER_DMABUF_EXPORT = 0x10,
+       HYPER_DMABUF_FIRST_EXPORT,
        HYPER_DMABUF_NOTIFY_UNEXPORT,
        HYPER_DMABUF_OPS_TO_REMOTE,
        HYPER_DMABUF_OPS_TO_SOURCE,
@@ -14,6 +15,7 @@ enum hyper_dmabuf_ops {
        HYPER_DMABUF_OPS_MAP,
        HYPER_DMABUF_OPS_UNMAP,
        HYPER_DMABUF_OPS_RELEASE,
+       HYPER_DMABUF_OPS_RELEASE_FINAL,
        HYPER_DMABUF_OPS_BEGIN_CPU_ACCESS,
        HYPER_DMABUF_OPS_END_CPU_ACCESS,
        HYPER_DMABUF_OPS_KMAP_ATOMIC,
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_remote_sync.c 
b/drivers/xen/hyper_dmabuf/hyper_dmabuf_remote_sync.c
index 61ba4ed..5017b17 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_remote_sync.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_remote_sync.c
@@ -114,13 +114,13 @@ int hyper_dmabuf_remote_sync(int id, int ops)
                kfree(sgtl);
                break;
 
-       case HYPER_DMABUF_OPS_RELEASE:
+       case HYPER_DMABUF_OPS_RELEASE_FINAL:
                /*
                 * Importer just released buffer fd, check if there is any 
other importer still using it.
                 * If not and buffer was unexported, clean up shared data and 
remove that buffer.
                 */
-                if (list_empty(&sgt_info->active_sgts->list) &&                
                                                            
list_empty(&sgt_info->active_attached->list) &&
-                    sgt_info->flags == HYPER_DMABUF_SGT_UNEXPORTED) {
+                if (list_empty(&sgt_info->active_attached->list) &&
+                    !sgt_info->valid) {
                        hyper_dmabuf_cleanup_sgt_info(sgt_info, false);
                        hyper_dmabuf_remove_exported(id);
                        kfree(sgt_info);
@@ -128,6 +128,10 @@ int hyper_dmabuf_remote_sync(int id, int ops)
 
                break;
 
+       case HYPER_DMABUF_OPS_RELEASE:
+               /* place holder */
+               break;
+
        case HYPER_DMABUF_OPS_BEGIN_CPU_ACCESS:
                ret = dma_buf_begin_cpu_access(sgt_info->dma_buf, 
DMA_BIDIRECTIONAL);
                if (!ret) {
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h 
b/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h
index 1194cf2..92e06ff 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h
@@ -6,10 +6,10 @@
 /* Importer combine source domain id with given hyper_dmabuf_id
  * to make it unique in case there are multiple exporters */
 
-#define HYPER_DMABUF_ID_IMPORTER(sdomain, id) \
-       ((((sdomain) & 0xFF) << 24) | ((id) & 0xFFFFFF))
+#define HYPER_DMABUF_ID_IMPORTER(domid, id) \
+       ((((domid) & 0xFF) << 24) | ((id) & 0xFFFFFF))
 
-#define HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(id) \
+#define HYPER_DMABUF_DOM_ID(id) \
        (((id) >> 24) & 0xFF)
 
 /* each grant_ref_t is 4 bytes, so total 4096 grant_ref_t can be
@@ -18,11 +18,6 @@
  * frame buffer) */
 #define MAX_ALLOWED_NUM_PAGES_FOR_GREF_NUM_ARRAYS 4
 
-enum hyper_dmabuf_sgt_flags {
-        HYPER_DMABUF_SGT_INVALID = 0x10,
-        HYPER_DMABUF_SGT_UNEXPORTED,
-};
-
 /* stack of mapped sgts */
 struct sgt_list {
        struct sg_table *sgt;
@@ -77,11 +72,13 @@ struct hyper_dmabuf_sgt_info {
        int hyper_dmabuf_rdomain; /* domain importing this sgt */
 
        struct dma_buf *dma_buf; /* needed to store this for freeing it later */
+       int nents; /* number of pages, which may be different than sgt->nents */
        struct sgt_list *active_sgts;
        struct attachment_list *active_attached;
        struct kmap_vaddr_list *va_kmapped;
        struct vmap_vaddr_list *va_vmapped;
-       int flags;
+       bool valid;
+       bool importer_exported; /* exported locally on importer's side */
        struct hyper_dmabuf_shared_pages_info shared_pages_info;
        int private[4]; /* device specific info (e.g. image's meta info?) */
 };
@@ -95,10 +92,10 @@ struct hyper_dmabuf_imported_sgt_info {
        int last_len;   /* length of data in the last shared page */
        int nents;      /* number of pages to be shared */
        grant_ref_t gref; /* reference number of top level addressing page of 
shared pages */
+       struct dma_buf *dma_buf;
        struct sg_table *sgt; /* sgt pointer after importing buffer */
        struct hyper_dmabuf_shared_pages_info shared_pages_info;
-       int flags;
-       int ref_count;
+       bool valid;
        int private[4]; /* device specific info (e.g. image's meta info?) */
 };
 
diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c 
b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c
index 116850e..f9e0df3 100644
--- a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c
+++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c
@@ -456,13 +456,12 @@ static irqreturn_t hyper_dmabuf_back_ring_isr(int irq, 
void *info)
        do {
                rc = ring->req_cons;
                rp = ring->sring->req_prod;
-
+               more_to_do = 0;
                while (rc != rp) {
                        if (RING_REQUEST_CONS_OVERFLOW(ring, rc))
                                break;
 
                        memcpy(&req, RING_GET_REQUEST(ring, rc), sizeof(req));
-                       printk("Got request\n");
                        ring->req_cons = ++rc;
 
                        ret = hyper_dmabuf_msg_parse(ring_info->sdomain, &req);
@@ -479,13 +478,11 @@ static irqreturn_t hyper_dmabuf_back_ring_isr(int irq, 
void *info)
                                RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(ring, 
notify);
 
                                if (notify) {
-                                       printk("Notyfing\n");
                                        notify_remote_via_irq(ring_info->irq);
                                }
                        }
 
                        RING_FINAL_CHECK_FOR_REQUESTS(ring, more_to_do);
-                       printk("Final check for requests %d\n", more_to_do);
                }
        } while (more_to_do);
 
@@ -541,7 +538,6 @@ static irqreturn_t hyper_dmabuf_front_ring_isr(int irq, 
void *info)
 
                if (i != ring->req_prod_pvt) {
                        RING_FINAL_CHECK_FOR_RESPONSES(ring, more_to_do);
-                       printk("more to do %d\n", more_to_do);
                } else {
                        ring->sring->rsp_event = i+1;
                }
-- 
2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.