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

[Xen-devel] [PATCH v8 13/15] xen: make grant resource limits per domain



Instead of using the same global resource limits of grant tables (max.
number of grant frames, max. number of maptrack frames) for all domains
make these limits per domain. Set those per-domain limits in
grant_table_set_limits().

Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
Reviewed-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
V6:
- several changes due to new patch order

V3:
- correct error message (Paul Durrant)
---
 xen/common/compat/grant_table.c   |  31 +++-------
 xen/common/grant_table.c          | 121 ++++++++++++++++++++++++--------------
 xen/include/asm-arm/grant_table.h |   6 +-
 3 files changed, 88 insertions(+), 70 deletions(-)

diff --git a/xen/common/compat/grant_table.c b/xen/common/compat/grant_table.c
index cce3ff0b9a..ff1d678f01 100644
--- a/xen/common/compat/grant_table.c
+++ b/xen/common/compat/grant_table.c
@@ -157,21 +157,14 @@ int compat_grant_table_op(unsigned int cmd,
                 unsigned int max_frame_list_size_in_page =
                     (COMPAT_ARG_XLAT_SIZE - sizeof(*nat.setup)) /
                     sizeof(*nat.setup->frame_list.p);
-                if ( max_frame_list_size_in_page < max_grant_frames )
-                {
-                    gdprintk(XENLOG_WARNING,
-                             "max_grant_frames is too large (%u,%u)\n",
-                             max_grant_frames, max_frame_list_size_in_page);
-                    rc = -EINVAL;
-                }
-                else
-                {
+
 #define XLAT_gnttab_setup_table_HNDL_frame_list(_d_, _s_) \
-                    set_xen_guest_handle((_d_)->frame_list, (unsigned long 
*)(nat.setup + 1))
-                    XLAT_gnttab_setup_table(nat.setup, &cmp.setup);
+                set_xen_guest_handle((_d_)->frame_list, (unsigned long 
*)(nat.setup + 1))
+                XLAT_gnttab_setup_table(nat.setup, &cmp.setup);
 #undef XLAT_gnttab_setup_table_HNDL_frame_list
-                    rc = gnttab_setup_table(guest_handle_cast(nat.uop, 
gnttab_setup_table_t), 1);
-                }
+                rc = gnttab_setup_table(guest_handle_cast(nat.uop,
+                                                          
gnttab_setup_table_t),
+                                        1, max_frame_list_size_in_page);
             }
             ASSERT(rc <= 0);
             if ( rc == 0 )
@@ -294,16 +287,6 @@ int compat_grant_table_op(unsigned int cmd,
                 rc = -EFAULT;
                 break;
             }
-            if ( max_frame_list_size_in_pages <
-                 grant_to_status_frames(max_grant_frames) )
-            {
-                gdprintk(XENLOG_WARNING,
-                         "grant_to_status_frames(max_grant_frames) is too 
large (%u,%u)\n",
-                         grant_to_status_frames(max_grant_frames),
-                         max_frame_list_size_in_pages);
-                rc = -EINVAL;
-                break;
-            }
 
 #define XLAT_gnttab_get_status_frames_HNDL_frame_list(_d_, _s_) \
             set_xen_guest_handle((_d_)->frame_list, (uint64_t 
*)(nat.get_status + 1))
@@ -312,7 +295,7 @@ int compat_grant_table_op(unsigned int cmd,
 
             rc = gnttab_get_status_frames(
                 guest_handle_cast(nat.uop, gnttab_get_status_frames_t),
-                count);
+                count, max_frame_list_size_in_pages);
             if ( rc >= 0 )
             {
 #define XLAT_gnttab_get_status_frames_HNDL_frame_list(_d_, _s_) \
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index 26f9a32656..a0d8f32869 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -54,6 +54,9 @@ struct grant_table {
      * what version to use yet.
      */
     unsigned int          gt_version;
+    /* Resource limits of the domain. */
+    unsigned int          max_grant_frames;
+    unsigned int          max_maptrack_frames;
     /* Table size. Number of frames shared with guest */
     unsigned int          nr_grant_frames;
     /* Number of grant status frames shared with guest (for version 2) */
@@ -290,8 +293,8 @@ num_act_frames_from_sha_frames(const unsigned int num)
     return DIV_ROUND_UP(num * sha_per_page, ACGNT_PER_PAGE);
 }
 
-#define max_nr_active_grant_frames \
-    num_act_frames_from_sha_frames(max_grant_frames)
+#define max_nr_active_grant_frames(gt) \
+    num_act_frames_from_sha_frames(gt->max_grant_frames)
 
 static inline unsigned int
 nr_active_grant_frames(struct grant_table *gt)
@@ -528,7 +531,7 @@ get_maptrack_handle(
      * out of memory, try stealing an entry from another VCPU (in case the
      * guest isn't mapping across its VCPUs evenly).
      */
-    if ( nr_maptrack_frames(lgt) < max_maptrack_frames )
+    if ( nr_maptrack_frames(lgt) < lgt->max_maptrack_frames )
         new_mt = alloc_xenheap_page();
 
     if ( !new_mt )
@@ -1667,23 +1670,26 @@ grant_table_init(struct grant_table *gt)
 
     /* Active grant table. */
     gt->active = xzalloc_array(struct active_grant_entry *,
-                               max_nr_active_grant_frames);
+                               max_nr_active_grant_frames(gt));
     if ( gt->active == NULL )
         goto out;
 
     /* Tracking of mapped foreign frames table */
-    gt->maptrack = vzalloc(max_maptrack_frames * sizeof(*gt->maptrack));
-    if ( gt->maptrack == NULL )
-        goto out;
+    if ( gt->max_maptrack_frames )
+    {
+        gt->maptrack = vzalloc(gt->max_maptrack_frames * 
sizeof(*gt->maptrack));
+        if ( gt->maptrack == NULL )
+            goto out;
+    }
 
     /* Shared grant table. */
-    gt->shared_raw = xzalloc_array(void *, max_grant_frames);
+    gt->shared_raw = xzalloc_array(void *, gt->max_grant_frames);
     if ( gt->shared_raw == NULL )
         goto out;
 
     /* Status pages for grant table - for version 2 */
     gt->status = xzalloc_array(grant_status_t *,
-                               grant_to_status_frames(max_grant_frames));
+                               grant_to_status_frames(gt->max_grant_frames));
     if ( gt->status == NULL )
         goto out;
 
@@ -1718,8 +1724,9 @@ gnttab_grow_table(struct domain *d, unsigned int 
req_nr_frames)
     ASSERT(gt->active);
 
     if ( req_nr_frames < INITIAL_NR_GRANT_FRAMES )
-        req_nr_frames = INITIAL_NR_GRANT_FRAMES;
-    ASSERT(req_nr_frames <= max_grant_frames);
+        req_nr_frames = min_t(unsigned int, INITIAL_NR_GRANT_FRAMES,
+                                            gt->max_grant_frames);
+    ASSERT(req_nr_frames <= gt->max_grant_frames);
 
     gdprintk(XENLOG_INFO,
             "Expanding dom (%d) grant table from (%d) to (%d) frames.\n",
@@ -1777,13 +1784,15 @@ active_alloc_failed:
 
 static long
 gnttab_setup_table(
-    XEN_GUEST_HANDLE_PARAM(gnttab_setup_table_t) uop, unsigned int count)
+    XEN_GUEST_HANDLE_PARAM(gnttab_setup_table_t) uop, unsigned int count,
+    unsigned int limit_max)
 {
     struct vcpu *curr = current;
     struct gnttab_setup_table op;
     struct domain *d = NULL;
     struct grant_table *gt;
     unsigned int i;
+    long ret = 0;
 
     if ( count != 1 )
         return -EINVAL;
@@ -1791,15 +1800,6 @@ gnttab_setup_table(
     if ( unlikely(copy_from_guest(&op, uop, 1)) )
         return -EFAULT;
 
-    if ( unlikely(op.nr_frames > max_grant_frames) )
-    {
-        gdprintk(XENLOG_INFO, "Xen only supports up to %d grant-table frames"
-                " per domain.\n",
-                max_grant_frames);
-        op.status = GNTST_general_error;
-        goto out;
-    }
-
     if ( !guest_handle_okay(op.frame_list, op.nr_frames) )
         return -EFAULT;
 
@@ -1819,6 +1819,21 @@ gnttab_setup_table(
     gt = d->grant_table;
     grant_write_lock(gt);
 
+    if ( unlikely(op.nr_frames > gt->max_grant_frames) )
+    {
+        gdprintk(XENLOG_INFO, "Domain is limited to %d grant-table frames.\n",
+                gt->max_grant_frames);
+        op.status = GNTST_general_error;
+        goto unlock;
+    }
+    if ( unlikely(limit_max < gt->max_grant_frames) )
+    {
+        gdprintk(XENLOG_WARNING, "max_grant_frames is too large (%u,%u)\n",
+                 gt->max_grant_frames, limit_max);
+        ret = -EINVAL;
+        goto unlock;
+    }
+
     if ( gt->gt_version == 0 )
         gt->gt_version = 1;
 
@@ -1829,7 +1844,7 @@ gnttab_setup_table(
     {
         gdprintk(XENLOG_INFO,
                  "Expand grant table to %u failed. Current: %u Max: %u\n",
-                 op.nr_frames, nr_grant_frames(gt), max_grant_frames);
+                 op.nr_frames, nr_grant_frames(gt), gt->max_grant_frames);
         op.status = GNTST_general_error;
         goto unlock;
     }
@@ -1852,10 +1867,10 @@ gnttab_setup_table(
     if ( d )
         rcu_unlock_domain(d);
 
-    if ( unlikely(__copy_field_to_guest(uop, &op, status)) )
+    if ( !ret && unlikely(__copy_field_to_guest(uop, &op, status)) )
         return -EFAULT;
 
-    return 0;
+    return ret;
 }
 
 static long
@@ -1864,6 +1879,7 @@ gnttab_query_size(
 {
     struct gnttab_query_size op;
     struct domain *d;
+    struct grant_table *gt;
 
     if ( count != 1 )
         return -EINVAL;
@@ -1884,13 +1900,15 @@ gnttab_query_size(
         goto out;
     }
 
-    grant_read_lock(d->grant_table);
+    gt = d->grant_table;
 
-    op.nr_frames     = nr_grant_frames(d->grant_table);
-    op.max_nr_frames = max_grant_frames;
+    grant_read_lock(gt);
+
+    op.nr_frames     = nr_grant_frames(gt);
+    op.max_nr_frames = gt->max_grant_frames;
     op.status        = GNTST_okay;
 
-    grant_read_unlock(d->grant_table);
+    grant_read_unlock(gt);
 
  out:
     if ( d )
@@ -2965,14 +2983,14 @@ 
gnttab_set_version(XEN_GUEST_HANDLE_PARAM(gnttab_set_version_t) uop)
 
 static long
 gnttab_get_status_frames(XEN_GUEST_HANDLE_PARAM(gnttab_get_status_frames_t) 
uop,
-                         int count)
+                         int count, unsigned int limit_max)
 {
     gnttab_get_status_frames_t op;
     struct domain *d;
     struct grant_table *gt;
     uint64_t       gmfn;
     int i;
-    int rc;
+    int rc, ret = 0;
 
     if ( count != 1 )
         return -EINVAL;
@@ -3012,6 +3030,15 @@ 
gnttab_get_status_frames(XEN_GUEST_HANDLE_PARAM(gnttab_get_status_frames_t) uop,
         goto unlock;
     }
 
+    if ( unlikely(limit_max < grant_to_status_frames(gt->max_grant_frames)) )
+    {
+        gdprintk(XENLOG_WARNING,
+                 "grant_to_status_frames(max_grant_frames) is too large 
(%u,%u)\n",
+                 grant_to_status_frames(gt->max_grant_frames), limit_max);
+        ret = -EINVAL;
+        goto unlock;
+    }
+
     for ( i = 0; i < op.nr_frames; i++ )
     {
         gmfn = gnttab_status_gmfn(d, gt, i);
@@ -3024,10 +3051,10 @@ 
gnttab_get_status_frames(XEN_GUEST_HANDLE_PARAM(gnttab_get_status_frames_t) uop,
  out2:
     rcu_unlock_domain(d);
  out1:
-    if ( unlikely(__copy_field_to_guest(uop, &op, status)) )
+    if ( !ret && unlikely(__copy_field_to_guest(uop, &op, status)) )
         return -EFAULT;
 
-    return 0;
+    return ret;
 }
 
 static long
@@ -3320,7 +3347,7 @@ do_grant_table_op(
 
     case GNTTABOP_setup_table:
         rc = gnttab_setup_table(
-            guest_handle_cast(uop, gnttab_setup_table_t), count);
+            guest_handle_cast(uop, gnttab_setup_table_t), count, ~0);
         ASSERT(rc <= 0);
         break;
 
@@ -3369,7 +3396,7 @@ do_grant_table_op(
 
     case GNTTABOP_get_status_frames:
         rc = gnttab_get_status_frames(
-            guest_handle_cast(uop, gnttab_get_status_frames_t), count);
+            guest_handle_cast(uop, gnttab_get_status_frames_t), count, ~0);
         break;
 
     case GNTTABOP_get_version:
@@ -3442,6 +3469,8 @@ grant_table_create(
     /* Simple stuff. */
     percpu_rwlock_resource_init(&t->lock, grant_rwlock);
     spin_lock_init(&t->maptrack_lock);
+    t->max_grant_frames = max_grant_frames;
+    t->max_maptrack_frames = max_maptrack_frames;
 
     /* Okay, install the structure. */
     d->grant_table = t;
@@ -3648,6 +3677,8 @@ int grant_table_set_limits(struct domain *d, unsigned int 
grant_frames,
     struct grant_table *gt = d->grant_table;
     int ret = -EBUSY;
 
+    if ( !grant_frames )
+        return -EINVAL;
     if ( !gt )
         return -ENOENT;
 
@@ -3655,7 +3686,11 @@ int grant_table_set_limits(struct domain *d, unsigned 
int grant_frames,
 
     /* Set limits. */
     if ( !gt->active )
+    {
+        gt->max_grant_frames = grant_frames;
+        gt->max_maptrack_frames = maptrack_frames;
         ret = grant_table_init(gt);
+    }
 
     grant_write_unlock(gt);
 
@@ -3731,7 +3766,7 @@ int gnttab_map_frame(struct domain *d, unsigned long idx, 
gfn_t gfn,
     }
     else
     {
-        if ( (idx >= nr_grant_frames(gt)) && (idx < max_grant_frames) )
+        if ( (idx >= nr_grant_frames(gt)) && (idx < gt->max_grant_frames) )
             gnttab_grow_table(d, idx + 1);
 
         if ( idx < nr_grant_frames(gt) )
@@ -3759,6 +3794,12 @@ static void gnttab_usage_print(struct domain *rd)
 
     grant_read_lock(gt);
 
+    printk("grant-table for remote domain:%5d (v%d)\n"
+           "  %d frames (%d max), %d maptrack frames (%d max)\n",
+           rd->domain_id, gt->gt_version,
+           nr_grant_frames(gt), gt->max_grant_frames,
+           nr_maptrack_frames(gt), gt->max_maptrack_frames);
+
     for ( ref = 0; ref != nr_grant_entries(gt); ref++ )
     {
         struct active_grant_entry *act;
@@ -3786,12 +3827,7 @@ static void gnttab_usage_print(struct domain *rd)
             status = status_entry(gt, ref);
         }
 
-        if ( first )
-        {
-            printk("grant-table for remote domain:%5d (v%d)\n",
-                   rd->domain_id, gt->gt_version);
-            first = 0;
-        }
+        first = 0;
 
         /*      [0xXXX]  ddddd 0xXXXXXX 0xXXXXXXXX      ddddd 0xXXXXXX 0xXX */
         printk("[0x%03x]  %5d 0x%06lx 0x%08x      %5d 0x%06"PRIx64" 0x%02x\n",
@@ -3803,8 +3839,7 @@ static void gnttab_usage_print(struct domain *rd)
     grant_read_unlock(gt);
 
     if ( first )
-        printk("grant-table for remote domain:%5d ... "
-               "no active grant table entries\n", rd->domain_id);
+        printk("no active grant table entries\n");
 }
 
 static void gnttab_usage_print_all(unsigned char key)
diff --git a/xen/include/asm-arm/grant_table.h 
b/xen/include/asm-arm/grant_table.h
index 0870b5b782..9a60e4e614 100644
--- a/xen/include/asm-arm/grant_table.h
+++ b/xen/include/asm-arm/grant_table.h
@@ -26,8 +26,8 @@ static inline int replace_grant_supported(void)
     return 1;
 }
 
-#define gnttab_init_arch(gt)                                             \
-    ( ((gt)->arch.gfn = xzalloc_array(gfn_t, max_grant_frames)) == 0     \
+#define gnttab_init_arch(gt)                                               \
+    ( ((gt)->arch.gfn = xzalloc_array(gfn_t, (gt)->max_grant_frames)) == 0 \
       ? 0 : -ENOMEM )
 
 #define gnttab_destroy_arch(gt)                                          \
@@ -49,7 +49,7 @@ static inline int replace_grant_supported(void)
 
 #define gnttab_shared_gmfn(d, t, i)                                      \
     ( ((i >= nr_grant_frames(t)) &&                                      \
-       (i < max_grant_frames)) ? 0 : gfn_x(t->arch.gfn[i]))
+       (i < (t)->max_grant_frames))? 0 : gfn_x((t)->arch.gfn[i]))
 
 #define gnttab_need_iommu_mapping(d)                    \
     (is_domain_direct_mapped(d) && need_iommu(d))
-- 
2.12.3


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

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