WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [linux-2.6.18-xen] xen: Variable-size gntdev support

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [linux-2.6.18-xen] xen: Variable-size gntdev support
From: "Xen patchbot-linux-2.6.18-xen" <patchbot-linux-2.6.18-xen@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 20 Mar 2008 05:41:33 -0700
Delivery-date: Thu, 20 Mar 2008 05:47:47 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1205852469 0
# Node ID 2783eccd480552523bb16f3dee5967260862ed9b
# Parent  24d797fe82519db6016a7324a9558923ab1143b5
xen: Variable-size gntdev support

This patch adds the ability to set the number of slots that may be
used for mapping grant references, using the gntdev user-space grant
reference mapping driver.

Signed-off-by: Derek Murray <Derek.Murray@xxxxxxxxxxxx>
---
 drivers/xen/gntdev/gntdev.c |  149 ++++++++++++++++++++++++++++++++++++--------
 include/xen/public/gntdev.h |   14 ++++
 2 files changed, 137 insertions(+), 26 deletions(-)

diff -r 24d797fe8251 -r 2783eccd4805 drivers/xen/gntdev/gntdev.c
--- a/drivers/xen/gntdev/gntdev.c       Tue Mar 18 11:43:42 2008 +0000
+++ b/drivers/xen/gntdev/gntdev.c       Tue Mar 18 15:01:09 2008 +0000
@@ -43,7 +43,8 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 
-#define MAX_GRANTS 128
+#define MAX_GRANTS_LIMIT   1024
+#define DEFAULT_MAX_GRANTS 128
 
 /* A slot can be in one of three states:
  *
@@ -90,7 +91,8 @@ typedef struct gntdev_file_private_data 
 typedef struct gntdev_file_private_data {
   
        /* Array of grant information. */
-       gntdev_grant_info_t grants[MAX_GRANTS];
+       gntdev_grant_info_t *grants;
+       uint32_t grants_size;
 
        /* Read/write semaphore used to protect the grants array. */
        struct rw_semaphore grants_sem;
@@ -102,7 +104,7 @@ typedef struct gntdev_file_private_data 
         * been compressed. However, this is not visible across invocations of
         * the device.
         */
-       int32_t free_list[MAX_GRANTS];
+       int32_t *free_list;
        
        /* The number of free slots in the grants array. */
        uint32_t free_list_size;
@@ -314,7 +316,7 @@ static int find_contiguous_free_range(st
 
        /* First search from the start_index to the end of the array. */
        range_length = 0;
-       for (i = start_index; i < MAX_GRANTS; ++i) {
+       for (i = start_index; i < private_data->grants_size; ++i) {
                if (private_data->grants[i].state == GNTDEV_SLOT_INVALID) {
                        if (range_length == 0) {
                                range_start = i;
@@ -343,6 +345,50 @@ static int find_contiguous_free_range(st
        return -ENOMEM;
 }
 
+static int init_private_data(gntdev_file_private_data_t *priv,
+                            uint32_t max_grants)
+{
+       int i;
+
+       /* Allocate space for the kernel-mapping of granted pages. */
+       priv->foreign_pages = 
+               alloc_empty_pages_and_pagevec(max_grants);
+       if (!priv->foreign_pages)
+               goto nomem_out;
+
+       /* Allocate the grant list and free-list. */
+       priv->grants = kmalloc(max_grants * sizeof(gntdev_grant_info_t),
+                              GFP_KERNEL);
+       if (!priv->grants)
+               goto nomem_out2;
+       priv->free_list = kmalloc(max_grants * sizeof(int32_t), GFP_KERNEL);
+       if (!priv->free_list)
+               goto nomem_out3;
+
+       /* Initialise the free-list, which contains all slots at first. */
+       for (i = 0; i < max_grants; ++i) {
+               priv->free_list[max_grants - i - 1] = i;
+               priv->grants[i].state = GNTDEV_SLOT_INVALID;
+               priv->grants[i].u.free_list_index = max_grants - i - 1;
+       }
+       priv->grants_size = max_grants;
+       priv->free_list_size = max_grants;
+       priv->next_fit_index = 0;
+
+       up_write(&priv->grants_sem);
+       up_write(&priv->free_list_sem);
+
+       return 0;
+
+nomem_out3:
+       kfree(priv->grants);
+nomem_out2:
+       free_empty_pages_and_pagevec(priv->foreign_pages, max_grants);
+nomem_out:
+       return -ENOMEM;
+
+}
+
 /* Interface functions. */
 
 /* Initialises the driver. Called when the module is loaded. */
@@ -400,7 +446,6 @@ static int gntdev_open(struct inode *ino
 static int gntdev_open(struct inode *inode, struct file *flip)
 {
        gntdev_file_private_data_t *private_data;
-       int i;
 
        try_module_get(THIS_MODULE);
 
@@ -409,21 +454,10 @@ static int gntdev_open(struct inode *ino
        if (!private_data)
                goto nomem_out;
 
-       /* Allocate space for the kernel-mapping of granted pages. */
-       private_data->foreign_pages = 
-               alloc_empty_pages_and_pagevec(MAX_GRANTS);
-       if (!private_data->foreign_pages)
-               goto nomem_out2;
-
-       /* Initialise the free-list, which contains all slots at first.
-        */
-       for (i = 0; i < MAX_GRANTS; ++i) {
-               private_data->free_list[MAX_GRANTS - i - 1] = i;
-               private_data->grants[i].state = GNTDEV_SLOT_INVALID;
-               private_data->grants[i].u.free_list_index = MAX_GRANTS - i - 1;
-       }
-       private_data->free_list_size = MAX_GRANTS;
-       private_data->next_fit_index = 0;
+       /* These will be lazily initialised by init_private_data. */
+       private_data->grants = NULL;
+       private_data->free_list = NULL;
+       private_data->foreign_pages = NULL;
 
        init_rwsem(&private_data->grants_sem);
        init_rwsem(&private_data->free_list_sem);
@@ -432,8 +466,6 @@ static int gntdev_open(struct inode *ino
 
        return 0;
 
-nomem_out2:
-       kfree(private_data);
 nomem_out:
        return -ENOMEM;
 }
@@ -445,10 +477,14 @@ static int gntdev_release(struct inode *
        if (flip->private_data) {
                gntdev_file_private_data_t *private_data = 
                        (gntdev_file_private_data_t *) flip->private_data;
-               if (private_data->foreign_pages) {
+               if (private_data->foreign_pages)
                        free_empty_pages_and_pagevec
-                               (private_data->foreign_pages, MAX_GRANTS);
-               }
+                               (private_data->foreign_pages,
+                                private_data->grants_size);
+               if (private_data->grants) 
+                       kfree(private_data->grants);
+               if (private_data->free_list)
+                       kfree(private_data->free_list);
                kfree(private_data);
        }
        module_put(THIS_MODULE);
@@ -479,7 +515,17 @@ static int gntdev_mmap (struct file *fli
                return -EINVAL;
        }
 
-       if (unlikely((size <= 0) || (size + slot_index) > MAX_GRANTS)) {
+       /* Test to make sure that the grants array has been initialised. */
+       down_read(&private_data->grants_sem);
+       if (unlikely(!private_data->grants)) {
+               up_read(&private_data->grants_sem);
+               printk(KERN_ERR "Attempted to mmap before ioctl.\n");
+               return -EINVAL;
+       }
+       up_read(&private_data->grants_sem);
+
+       if (unlikely((size <= 0) || 
+                    (size + slot_index) > private_data->grants_size)) {
                printk(KERN_ERR "Invalid number of pages or offset"
                       "(num_pages = %d, first_slot = %ld).\n",
                       size, slot_index);
@@ -789,6 +835,33 @@ static long gntdev_ioctl(struct file *fl
        gntdev_file_private_data_t *private_data = 
                (gntdev_file_private_data_t *) flip->private_data;
 
+       /* On the first invocation, we will lazily initialise the grant array
+        * and free-list.
+        */
+       if (unlikely(!private_data->grants) 
+           && likely(cmd != IOCTL_GNTDEV_SET_MAX_GRANTS)) {
+               down_write(&private_data->grants_sem);
+               
+               if (unlikely(private_data->grants)) {
+                       up_write(&private_data->grants_sem);
+                       goto private_data_initialised;
+               }
+               
+               /* Just use the default. Setting to a non-default is handled
+                * in the ioctl switch.
+                */
+               rc = init_private_data(private_data, DEFAULT_MAX_GRANTS);
+               
+               up_write(&private_data->grants_sem);
+
+               if (rc) {
+                       printk (KERN_ERR "Initialising gntdev private data "
+                               "failed.\n");
+                       return rc;
+               }
+       }
+           
+private_data_initialised:
        switch (cmd) {
        case IOCTL_GNTDEV_MAP_GRANT_REF:
        {
@@ -972,6 +1045,30 @@ static long gntdev_ioctl(struct file *fl
        get_offset_out:
                return rc;
        }
+       case IOCTL_GNTDEV_SET_MAX_GRANTS:
+       {
+               struct ioctl_gntdev_set_max_grants op;
+               if ((rc = copy_from_user(&op, 
+                                        (void __user *) arg, 
+                                        sizeof(op)))) {
+                       rc = -EFAULT;
+                       goto set_max_out;
+               }
+               down_write(&private_data->grants_sem);
+               if (private_data->grants) {
+                       rc = -EBUSY;
+                       goto set_max_unlock_out;
+               }
+               if (op.count > MAX_GRANTS_LIMIT) {
+                       rc = -EINVAL;
+                       goto set_max_unlock_out;
+               }                                                
+               rc = init_private_data(private_data, op.count);
+       set_max_unlock_out:
+               up_write(&private_data->grants_sem);
+       set_max_out:
+               return rc;
+       }
        default:
                return -ENOIOCTLCMD;
        }
diff -r 24d797fe8251 -r 2783eccd4805 include/xen/public/gntdev.h
--- a/include/xen/public/gntdev.h       Tue Mar 18 11:43:42 2008 +0000
+++ b/include/xen/public/gntdev.h       Tue Mar 18 15:01:09 2008 +0000
@@ -102,4 +102,18 @@ struct ioctl_gntdev_get_offset_for_vaddr
        uint32_t pad;
 };
 
+/*
+ * Sets the maximum number of grants that may mapped at once by this gntdev
+ * instance.
+ *
+ * N.B. This must be called before any other ioctl is performed on the device.
+ */
+#define IOCTL_GNTDEV_SET_MAX_GRANTS \
+_IOC(_IOC_NONE, 'G', 3, sizeof(struct ioctl_gntdev_set_max_grants))
+struct ioctl_gntdev_set_max_grants {
+       /* IN parameter */
+       /* The maximum number of grants that may be mapped at once. */
+       uint32_t count;
+};
+
 #endif /* __LINUX_PUBLIC_GNTDEV_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [linux-2.6.18-xen] xen: Variable-size gntdev support, Xen patchbot-linux-2.6.18-xen <=