From: Simon Martin <furryfuttock@gmail.com>
To: Daniel De Graaf <dgdegra@tycho.nsa.gov>
Cc: Ian Campbell <Ian.Campbell@citrix.com>, xen-devel@lists.xen.org
Subject: Re: Grant access to more than one dom
Date: Thu, 5 Jun 2014 12:10:01 -0400 [thread overview]
Message-ID: <707889333.20140605121001@gmail.com> (raw)
In-Reply-To: <1113401521.20140509100050@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 395 bytes --]
Hello Daniel,
I have been using the modified kernel driver for a few weeks now and
it seems to be doing everything I want it to. I attach the patch file,
this patches gntalloc.c and gntalloc.h.
Can you check that you are happy with the changes and then tell me
what to do to push then upstream?
Regards.
--
Best regards,
Simon mailto:furryfuttock@gmail.com
[-- Attachment #2: gntalloc.patch --]
[-- Type: application/octet-stream, Size: 7301 bytes --]
diff --git a/drivers/xen/gntalloc.c b/drivers/xen/gntalloc.c
index 787d179..60998d1 100644
--- a/drivers/xen/gntalloc.c
+++ b/drivers/xen/gntalloc.c
@@ -85,6 +85,12 @@ struct notify_info {
int event; /* Port (event channel) to notify */
};
+/* list of foreign grants associated to a given grant reference */
+struct gntalloc_share_list {
+ grant_ref_t gref_id;
+ struct list_head next_share;
+};
+
/* Metadata on a grant reference. */
struct gntalloc_gref {
struct list_head next_gref; /* list entry gref_list */
@@ -92,7 +98,7 @@ struct gntalloc_gref {
struct page *page; /* The shared page */
uint64_t file_index; /* File offset for mmap() */
unsigned int users; /* Use count - when zero, waiting on Xen */
- grant_ref_t gref_id; /* The grant reference number */
+ struct gntalloc_share_list share_list; /* The list of grant reference numbers associated with this page */
struct notify_info notify; /* Unmap notification */
};
@@ -125,6 +131,7 @@ static int add_grefs(struct ioctl_gntalloc_alloc_gref *op,
LIST_HEAD(queue_gref);
LIST_HEAD(queue_file);
struct gntalloc_gref *gref;
+ grant_ref_t gref_id;
readonly = !(op->flags & GNTALLOC_FLAG_WRITABLE);
rc = -ENOMEM;
@@ -141,13 +148,19 @@ static int add_grefs(struct ioctl_gntalloc_alloc_gref *op,
goto undo;
/* Grant foreign access to the page. */
- gref->gref_id = gnttab_grant_foreign_access(op->domid,
+ gref_id = gnttab_grant_foreign_access(op->domid,
pfn_to_mfn(page_to_pfn(gref->page)), readonly);
- if ((int)gref->gref_id < 0) {
- rc = gref->gref_id;
+ if ((int)gref_id < 0) {
+ rc = gref_id;
goto undo;
}
- gref_ids[i] = gref->gref_id;
+
+ // store the gred_id to be returned to the user so they can use it later
+ gref_ids[i] = gref_id;
+
+ // add this gref to the list for this page
+ INIT_LIST_HEAD(&gref->share_list.next_share);
+ gref->share_list.gref_id = gref_id;
}
/* Add to gref lists. */
@@ -179,8 +192,21 @@ undo:
return rc;
}
+static void __release_gref(grant_ref_t *gref_id)
+{
+ if ((*gref_id > 0) &&
+ !gnttab_query_foreign_access(*gref_id) &&
+ gnttab_end_foreign_access_ref(*gref_id, 0))
+ {
+ gnttab_free_grant_reference(*gref_id);
+ *gref_id = 0;
+ }
+}
+
static void __del_gref(struct gntalloc_gref *gref)
{
+ struct gntalloc_share_list *pos = NULL;
+
if (gref->notify.flags & UNMAP_NOTIFY_CLEAR_BYTE) {
uint8_t *tmp = kmap(gref->page);
tmp[gref->notify.pgoff] = 0;
@@ -192,16 +218,16 @@ static void __del_gref(struct gntalloc_gref *gref)
}
gref->notify.flags = 0;
-
- if (gref->gref_id > 0) {
- if (gnttab_query_foreign_access(gref->gref_id))
- return;
-
- if (!gnttab_end_foreign_access_ref(gref->gref_id, 0))
- return;
-
- gnttab_free_grant_reference(gref->gref_id);
+ while (!list_empty(&gref->share_list.next_share))
+ {
+ pos = list_first_entry(&gref->share_list.next_share,
+ struct gntalloc_share_list,
+ next_share);
+ list_del(&pos->next_share);
+ __release_gref(&pos->gref_id);
+ kfree(pos);
}
+ __release_gref(&gref->share_list.gref_id);
gref_size--;
list_del(&gref->next_gref);
@@ -337,6 +363,7 @@ static long gntalloc_ioctl_alloc(struct gntalloc_file_private_data *priv,
out_free:
kfree(gref_ids);
+
out:
return rc;
}
@@ -435,6 +462,97 @@ static long gntalloc_ioctl_unmap_notify(struct gntalloc_file_private_data *priv,
return rc;
}
+static long gntalloc_ioctl_share(struct gntalloc_file_private_data *priv, void __user *arg)
+{
+ struct ioctl_gntalloc_share_gref op;
+ struct gntalloc_gref *gref;
+ int rc;
+ int readonly;
+ grant_ref_t gref_id;
+ struct gntalloc_share_list *share_list;
+
+ if (copy_from_user(&op, arg, sizeof(op)))
+ return -EFAULT;
+
+ readonly = !(op.flags & GNTALLOC_FLAG_WRITABLE);
+ rc = -ENOMEM;
+
+ /* get the grant structure */
+ mutex_lock(&gref_mutex);
+ gref = find_grefs(priv, op.index, 1);
+
+ if (!gref) {
+ rc = -ENOENT;
+ goto share_out;
+ }
+
+ /* Grant foreign access to the page. */
+ gref_id = gnttab_grant_foreign_access(op.domid,
+ pfn_to_mfn(page_to_pfn(gref->page)), readonly);
+ if ((signed)gref_id < 0) {
+ rc = gref_id;
+ goto share_out;
+ }
+
+ // add this gref to the list for this page
+ share_list = kzalloc(sizeof(*share_list), GFP_KERNEL);
+ INIT_LIST_HEAD(&share_list->next_share);
+ share_list->gref_id = gref_id;
+ list_add_tail(&share_list->next_share, &gref->share_list.next_share);
+
+ // set output data
+ op.gref_id = gref_id;
+ rc = 0;
+
+share_out:
+ mutex_unlock(&gref_mutex);
+
+ if (!rc && copy_to_user(arg, &op, sizeof(op)))
+ rc = -EFAULT;
+
+ return rc;
+}
+
+static long gntalloc_ioctl_unshare(struct gntalloc_file_private_data *priv, void __user *arg)
+{
+ struct ioctl_gntalloc_unshare_gref op;
+ struct gntalloc_gref *gref;
+ int rc = -ENOENT;
+ struct gntalloc_share_list *pos;
+
+ if (copy_from_user(&op, arg, sizeof(op)))
+ return -EFAULT;
+
+ /* get the grant structure */
+ mutex_lock(&gref_mutex);
+ gref = find_grefs(priv, op.index, 1);
+
+ if (!gref)
+ goto unshare_out;
+
+ // search the share list for this grant ref
+ list_for_each_entry(pos, &gref->share_list.next_share, next_share) {
+ // if this is our grant ref then delete it
+ if (pos->gref_id == op.gref_id) {
+ // delete
+ list_del(&pos->next_share);
+ __release_gref(&pos->gref_id);
+ kfree(pos);
+
+ // success
+ rc = 0;
+
+ // done
+ break;
+ }
+ }
+
+unshare_out:
+ mutex_unlock(&gref_mutex);
+
+ return rc;
+}
+
static long gntalloc_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
@@ -450,6 +568,12 @@ static long gntalloc_ioctl(struct file *filp, unsigned int cmd,
case IOCTL_GNTALLOC_SET_UNMAP_NOTIFY:
return gntalloc_ioctl_unmap_notify(priv, (void __user *)arg);
+ case IOCTL_GNTALLOC_SHARE_GREF:
+ return gntalloc_ioctl_share(priv, (void __user *)arg);
+
+ case IOCTL_GNTALLOC_UNSHARE_GREF:
+ return gntalloc_ioctl_unshare(priv, (void __user *)arg);
+
default:
return -ENOIOCTLCMD;
}
diff --git a/include/uapi/xen/gntalloc.h b/include/uapi/xen/gntalloc.h
index 76bd580..20dc973 100644
--- a/include/uapi/xen/gntalloc.h
+++ b/include/uapi/xen/gntalloc.h
@@ -79,4 +79,36 @@ struct ioctl_gntalloc_unmap_notify {
/* Send an interrupt on the indicated event channel */
#define UNMAP_NOTIFY_SEND_EVENT 0x2
+/*
+ * Shares a page that has already been allocated (so we can share the smae page
+ * between more than one domain)
+ */
+#define IOCTL_GNTALLOC_SHARE_GREF \
+_IOC(_IOC_NONE, 'G', 8, sizeof(struct ioctl_gntalloc_share_gref))
+struct ioctl_gntalloc_share_gref {
+ /* IN parameters */
+ /* The ID of the domain to be given access to the grants. */
+ uint16_t domid;
+ /* Flags for this mapping */
+ uint16_t flags;
+ /* The offset used in call to mmap(). */
+ uint64_t index;
+ /* OUT parameters */
+ /* The grant references of the newly created grant */
+ uint32_t gref_id;
+};
+
+/*
+ * Unhares a page that has already been shared
+ */
+#define IOCTL_GNTALLOC_UNSHARE_GREF \
+_IOC(_IOC_NONE, 'G', 9, sizeof(struct ioctl_gntalloc_unshare_gref))
+struct ioctl_gntalloc_unshare_gref {
+ /* IN parameters */
+ /* The offset used in call to mmap(). */
+ uint64_t index;
+ /* The grant references of the newly created grant */
+ uint32_t gref_id;
+};
+
#endif /* __LINUX_PUBLIC_GNTALLOC_H__ */
[-- Attachment #3: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
next prev parent reply other threads:[~2014-06-05 16:10 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-17 14:58 Grant access to more than one dom Simon Martin
2014-04-17 15:03 ` Ian Campbell
2014-04-17 15:07 ` Simon Martin
2014-04-17 15:38 ` Simon Martin
2014-04-17 16:14 ` Ian Campbell
2014-04-17 16:57 ` Simon Martin
2014-04-17 17:16 ` Daniel De Graaf
2014-04-17 18:06 ` Simon Martin
2014-04-25 12:12 ` Simon Martin
2014-04-25 12:16 ` Ian Campbell
2014-04-25 12:18 ` Simon Martin
2014-04-25 12:28 ` Ian Campbell
2014-05-08 15:47 ` Simon Martin
2014-05-08 19:01 ` Daniel De Graaf
2014-05-08 20:03 ` Simon Martin
2014-05-08 20:23 ` Daniel De Graaf
2014-05-09 14:00 ` Simon Martin
2014-06-05 16:10 ` Simon Martin [this message]
2014-06-06 9:51 ` Ian Campbell
2014-06-06 21:02 ` Daniel De Graaf
2014-06-09 15:53 ` Simon Martin
2014-06-09 17:15 ` Daniel De Graaf
2014-06-10 18:48 ` Simon Martin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=707889333.20140605121001@gmail.com \
--to=furryfuttock@gmail.com \
--cc=Ian.Campbell@citrix.com \
--cc=dgdegra@tycho.nsa.gov \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).