diff options
Diffstat (limited to 'drivers/xen/gntalloc.c')
| -rw-r--r-- | drivers/xen/gntalloc.c | 64 |
1 files changed, 26 insertions, 38 deletions
diff --git a/drivers/xen/gntalloc.c b/drivers/xen/gntalloc.c index 787d17945418..f93f73ecefee 100644 --- a/drivers/xen/gntalloc.c +++ b/drivers/xen/gntalloc.c @@ -124,30 +124,32 @@ static int add_grefs(struct ioctl_gntalloc_alloc_gref *op, int i, rc, readonly; LIST_HEAD(queue_gref); LIST_HEAD(queue_file); - struct gntalloc_gref *gref; + struct gntalloc_gref *gref, *next; readonly = !(op->flags & GNTALLOC_FLAG_WRITABLE); - rc = -ENOMEM; for (i = 0; i < op->count; i++) { gref = kzalloc(sizeof(*gref), GFP_KERNEL); - if (!gref) + if (!gref) { + rc = -ENOMEM; goto undo; + } list_add_tail(&gref->next_gref, &queue_gref); list_add_tail(&gref->next_file, &queue_file); gref->users = 1; gref->file_index = op->index + i * PAGE_SIZE; gref->page = alloc_page(GFP_KERNEL|__GFP_ZERO); - if (!gref->page) + if (!gref->page) { + rc = -ENOMEM; goto undo; + } /* Grant foreign access to the page. */ - gref->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; + rc = gnttab_grant_foreign_access(op->domid, + xen_page_to_gfn(gref->page), + readonly); + if (rc < 0) goto undo; - } - gref_ids[i] = gref->gref_id; + gref_ids[i] = gref->gref_id = rc; } /* Add to gref lists. */ @@ -162,19 +164,11 @@ undo: mutex_lock(&gref_mutex); gref_size -= (op->count - i); - list_for_each_entry(gref, &queue_file, next_file) { - /* __del_gref does not remove from queue_file */ + list_for_each_entry_safe(gref, next, &queue_file, next_file) { + list_del(&gref->next_file); __del_gref(gref); } - /* It's possible for the target domain to map the just-allocated grant - * references by blindly guessing their IDs; if this is done, then - * __del_gref will leave them in the queue_gref list. They need to be - * added to the global list so that we can free them when they are no - * longer referenced. - */ - if (unlikely(!list_empty(&queue_gref))) - list_splice_tail(&queue_gref, &gref_list); mutex_unlock(&gref_mutex); return rc; } @@ -182,9 +176,9 @@ undo: static void __del_gref(struct gntalloc_gref *gref) { if (gref->notify.flags & UNMAP_NOTIFY_CLEAR_BYTE) { - uint8_t *tmp = kmap(gref->page); + uint8_t *tmp = kmap_local_page(gref->page); tmp[gref->notify.pgoff] = 0; - kunmap(gref->page); + kunmap_local(tmp); } if (gref->notify.flags & UNMAP_NOTIFY_SEND_EVENT) { notify_remote_via_evtchn(gref->notify.event); @@ -193,22 +187,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); + if (gref->gref_id) { + if (gref->page) + gnttab_end_foreign_access(gref->gref_id, gref->page); + else + gnttab_free_grant_reference(gref->gref_id); } gref_size--; list_del(&gref->next_gref); - if (gref->page) - __free_page(gref->page); - kfree(gref); } @@ -292,7 +280,7 @@ static long gntalloc_ioctl_alloc(struct gntalloc_file_private_data *priv, goto out; } - gref_ids = kcalloc(op.count, sizeof(gref_ids[0]), GFP_TEMPORARY); + gref_ids = kcalloc(op.count, sizeof(gref_ids[0]), GFP_KERNEL); if (!gref_ids) { rc = -ENOMEM; goto out; @@ -329,7 +317,7 @@ static long gntalloc_ioctl_alloc(struct gntalloc_file_private_data *priv, rc = -EFAULT; goto out_free; } - if (copy_to_user(arg->gref_ids, gref_ids, + if (copy_to_user(arg->gref_ids_flex, gref_ids, sizeof(gref_ids[0]) * op.count)) { rc = -EFAULT; goto out_free; @@ -495,7 +483,7 @@ static void gntalloc_vma_close(struct vm_area_struct *vma) mutex_unlock(&gref_mutex); } -static struct vm_operations_struct gntalloc_vmops = { +static const struct vm_operations_struct gntalloc_vmops = { .open = gntalloc_vma_open, .close = gntalloc_vma_close, }; @@ -505,7 +493,7 @@ static int gntalloc_mmap(struct file *filp, struct vm_area_struct *vma) struct gntalloc_file_private_data *priv = filp->private_data; struct gntalloc_vma_private_data *vm_priv; struct gntalloc_gref *gref; - int count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + int count = vma_pages(vma); int rv, i; if (!(vma->vm_flags & VM_SHARED)) { @@ -537,7 +525,7 @@ static int gntalloc_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_private_data = vm_priv; - vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; + vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP); vma->vm_ops = &gntalloc_vmops; |
