diff options
author | Daniel De Graaf <dgdegra@tycho.nsa.gov> | 2011-02-03 12:18:59 -0500 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2011-02-14 14:08:49 -0500 |
commit | ef91082e90491ac99343a13f9aeff4669835c6cc (patch) | |
tree | d5b293c5e27225f6631c402f36ccdb9ebac25d1b /drivers/xen/gntdev.c | |
parent | 100b33c8bd8a3235fd0b7948338d6cbb3db3c63d (diff) |
xen-gntdev: Change page limit to be global instead of per-open
Because there is no limitation on how many times a user can open a
given device file, an per-file-description limit on the number of
pages granted offers little to no benefit. Change to a global limit
and remove the ioctl() as the parameter can now be changed via sysfs.
Xen tools changeset 22768:f8d801e5573e is needed to eliminate the
error this change produces in xc_gnttab_set_max_grants.
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/xen/gntdev.c')
-rw-r--r-- | drivers/xen/gntdev.c | 50 |
1 files changed, 14 insertions, 36 deletions
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 1e31cdcdae1e..23d208a219fa 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c | |||
@@ -45,15 +45,15 @@ MODULE_AUTHOR("Derek G. Murray <Derek.Murray@cl.cam.ac.uk>, " | |||
45 | "Gerd Hoffmann <kraxel@redhat.com>"); | 45 | "Gerd Hoffmann <kraxel@redhat.com>"); |
46 | MODULE_DESCRIPTION("User-space granted page access driver"); | 46 | MODULE_DESCRIPTION("User-space granted page access driver"); |
47 | 47 | ||
48 | static int limit = 1024; | 48 | static int limit = 1024*1024; |
49 | module_param(limit, int, 0644); | 49 | module_param(limit, int, 0644); |
50 | MODULE_PARM_DESC(limit, "Maximum number of grants that may be mapped at " | 50 | MODULE_PARM_DESC(limit, "Maximum number of grants that may be mapped by " |
51 | "once by a gntdev instance"); | 51 | "the gntdev device"); |
52 | |||
53 | static atomic_t pages_mapped = ATOMIC_INIT(0); | ||
52 | 54 | ||
53 | struct gntdev_priv { | 55 | struct gntdev_priv { |
54 | struct list_head maps; | 56 | struct list_head maps; |
55 | uint32_t used; | ||
56 | uint32_t limit; | ||
57 | /* lock protects maps from concurrent changes */ | 57 | /* lock protects maps from concurrent changes */ |
58 | spinlock_t lock; | 58 | spinlock_t lock; |
59 | struct mm_struct *mm; | 59 | struct mm_struct *mm; |
@@ -82,9 +82,7 @@ static void gntdev_print_maps(struct gntdev_priv *priv, | |||
82 | #ifdef DEBUG | 82 | #ifdef DEBUG |
83 | struct grant_map *map; | 83 | struct grant_map *map; |
84 | 84 | ||
85 | pr_debug("maps list (priv %p, usage %d/%d)\n", | 85 | pr_debug("%s: maps list (priv %p)\n", __func__, priv); |
86 | priv, priv->used, priv->limit); | ||
87 | |||
88 | list_for_each_entry(map, &priv->maps, next) | 86 | list_for_each_entry(map, &priv->maps, next) |
89 | pr_debug(" index %2d, count %2d %s\n", | 87 | pr_debug(" index %2d, count %2d %s\n", |
90 | map->index, map->count, | 88 | map->index, map->count, |
@@ -121,9 +119,6 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) | |||
121 | add->count = count; | 119 | add->count = count; |
122 | add->priv = priv; | 120 | add->priv = priv; |
123 | 121 | ||
124 | if (add->count + priv->used > priv->limit) | ||
125 | goto err; | ||
126 | |||
127 | return add; | 122 | return add; |
128 | 123 | ||
129 | err: | 124 | err: |
@@ -154,7 +149,6 @@ static void gntdev_add_map(struct gntdev_priv *priv, struct grant_map *add) | |||
154 | list_add_tail(&add->next, &priv->maps); | 149 | list_add_tail(&add->next, &priv->maps); |
155 | 150 | ||
156 | done: | 151 | done: |
157 | priv->used += add->count; | ||
158 | gntdev_print_maps(priv, "[new]", add->index); | 152 | gntdev_print_maps(priv, "[new]", add->index); |
159 | } | 153 | } |
160 | 154 | ||
@@ -200,7 +194,7 @@ static int gntdev_del_map(struct grant_map *map) | |||
200 | if (map->unmap_ops[i].handle) | 194 | if (map->unmap_ops[i].handle) |
201 | return -EBUSY; | 195 | return -EBUSY; |
202 | 196 | ||
203 | map->priv->used -= map->count; | 197 | atomic_sub(map->count, &pages_mapped); |
204 | list_del(&map->next); | 198 | list_del(&map->next); |
205 | return 0; | 199 | return 0; |
206 | } | 200 | } |
@@ -386,7 +380,6 @@ static int gntdev_open(struct inode *inode, struct file *flip) | |||
386 | 380 | ||
387 | INIT_LIST_HEAD(&priv->maps); | 381 | INIT_LIST_HEAD(&priv->maps); |
388 | spin_lock_init(&priv->lock); | 382 | spin_lock_init(&priv->lock); |
389 | priv->limit = limit; | ||
390 | 383 | ||
391 | priv->mm = get_task_mm(current); | 384 | priv->mm = get_task_mm(current); |
392 | if (!priv->mm) { | 385 | if (!priv->mm) { |
@@ -443,19 +436,24 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv, | |||
443 | pr_debug("priv %p, add %d\n", priv, op.count); | 436 | pr_debug("priv %p, add %d\n", priv, op.count); |
444 | if (unlikely(op.count <= 0)) | 437 | if (unlikely(op.count <= 0)) |
445 | return -EINVAL; | 438 | return -EINVAL; |
446 | if (unlikely(op.count > priv->limit)) | ||
447 | return -EINVAL; | ||
448 | 439 | ||
449 | err = -ENOMEM; | 440 | err = -ENOMEM; |
450 | map = gntdev_alloc_map(priv, op.count); | 441 | map = gntdev_alloc_map(priv, op.count); |
451 | if (!map) | 442 | if (!map) |
452 | return err; | 443 | return err; |
444 | |||
453 | if (copy_from_user(map->grants, &u->refs, | 445 | if (copy_from_user(map->grants, &u->refs, |
454 | sizeof(map->grants[0]) * op.count) != 0) { | 446 | sizeof(map->grants[0]) * op.count) != 0) { |
455 | gntdev_free_map(map); | 447 | gntdev_free_map(map); |
456 | return err; | 448 | return err; |
457 | } | 449 | } |
458 | 450 | ||
451 | if (unlikely(atomic_add_return(op.count, &pages_mapped) > limit)) { | ||
452 | pr_debug("can't map: over limit\n"); | ||
453 | gntdev_free_map(map); | ||
454 | return err; | ||
455 | } | ||
456 | |||
459 | spin_lock(&priv->lock); | 457 | spin_lock(&priv->lock); |
460 | gntdev_add_map(priv, map); | 458 | gntdev_add_map(priv, map); |
461 | op.index = map->index << PAGE_SHIFT; | 459 | op.index = map->index << PAGE_SHIFT; |
@@ -518,23 +516,6 @@ static long gntdev_ioctl_get_offset_for_vaddr(struct gntdev_priv *priv, | |||
518 | return 0; | 516 | return 0; |
519 | } | 517 | } |
520 | 518 | ||
521 | static long gntdev_ioctl_set_max_grants(struct gntdev_priv *priv, | ||
522 | struct ioctl_gntdev_set_max_grants __user *u) | ||
523 | { | ||
524 | struct ioctl_gntdev_set_max_grants op; | ||
525 | |||
526 | if (copy_from_user(&op, u, sizeof(op)) != 0) | ||
527 | return -EFAULT; | ||
528 | pr_debug("priv %p, limit %d\n", priv, op.count); | ||
529 | if (op.count > limit) | ||
530 | return -E2BIG; | ||
531 | |||
532 | spin_lock(&priv->lock); | ||
533 | priv->limit = op.count; | ||
534 | spin_unlock(&priv->lock); | ||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static long gntdev_ioctl(struct file *flip, | 519 | static long gntdev_ioctl(struct file *flip, |
539 | unsigned int cmd, unsigned long arg) | 520 | unsigned int cmd, unsigned long arg) |
540 | { | 521 | { |
@@ -551,9 +532,6 @@ static long gntdev_ioctl(struct file *flip, | |||
551 | case IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR: | 532 | case IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR: |
552 | return gntdev_ioctl_get_offset_for_vaddr(priv, ptr); | 533 | return gntdev_ioctl_get_offset_for_vaddr(priv, ptr); |
553 | 534 | ||
554 | case IOCTL_GNTDEV_SET_MAX_GRANTS: | ||
555 | return gntdev_ioctl_set_max_grants(priv, ptr); | ||
556 | |||
557 | default: | 535 | default: |
558 | pr_debug("priv %p, unknown cmd %x\n", priv, cmd); | 536 | pr_debug("priv %p, unknown cmd %x\n", priv, cmd); |
559 | return -ENOIOCTLCMD; | 537 | return -ENOIOCTLCMD; |