diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/perf_counter.c | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 195e976eb07d..c841563de043 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c | |||
@@ -1461,13 +1461,14 @@ static void perf_mmap_close(struct vm_area_struct *vma) | |||
1461 | 1461 | ||
1462 | if (atomic_dec_and_mutex_lock(&counter->mmap_count, | 1462 | if (atomic_dec_and_mutex_lock(&counter->mmap_count, |
1463 | &counter->mmap_mutex)) { | 1463 | &counter->mmap_mutex)) { |
1464 | vma->vm_mm->locked_vm -= counter->data->nr_pages + 1; | ||
1464 | perf_mmap_data_free(counter); | 1465 | perf_mmap_data_free(counter); |
1465 | mutex_unlock(&counter->mmap_mutex); | 1466 | mutex_unlock(&counter->mmap_mutex); |
1466 | } | 1467 | } |
1467 | } | 1468 | } |
1468 | 1469 | ||
1469 | static struct vm_operations_struct perf_mmap_vmops = { | 1470 | static struct vm_operations_struct perf_mmap_vmops = { |
1470 | .open = perf_mmap_open, | 1471 | .open = perf_mmap_open, |
1471 | .close = perf_mmap_close, | 1472 | .close = perf_mmap_close, |
1472 | .fault = perf_mmap_fault, | 1473 | .fault = perf_mmap_fault, |
1473 | }; | 1474 | }; |
@@ -1499,24 +1500,32 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma) | |||
1499 | if (vma->vm_pgoff != 0) | 1500 | if (vma->vm_pgoff != 0) |
1500 | return -EINVAL; | 1501 | return -EINVAL; |
1501 | 1502 | ||
1502 | locked = vma_size >> PAGE_SHIFT; | 1503 | mutex_lock(&counter->mmap_mutex); |
1503 | locked += vma->vm_mm->locked_vm; | 1504 | if (atomic_inc_not_zero(&counter->mmap_count)) { |
1505 | if (nr_pages != counter->data->nr_pages) | ||
1506 | ret = -EINVAL; | ||
1507 | goto unlock; | ||
1508 | } | ||
1509 | |||
1510 | locked = vma->vm_mm->locked_vm; | ||
1511 | locked += nr_pages + 1; | ||
1504 | 1512 | ||
1505 | lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur; | 1513 | lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur; |
1506 | lock_limit >>= PAGE_SHIFT; | 1514 | lock_limit >>= PAGE_SHIFT; |
1507 | 1515 | ||
1508 | if ((locked > lock_limit) && !capable(CAP_IPC_LOCK)) | 1516 | if ((locked > lock_limit) && !capable(CAP_IPC_LOCK)) { |
1509 | return -EPERM; | 1517 | ret = -EPERM; |
1510 | 1518 | goto unlock; | |
1511 | mutex_lock(&counter->mmap_mutex); | 1519 | } |
1512 | if (atomic_inc_not_zero(&counter->mmap_count)) | ||
1513 | goto out; | ||
1514 | 1520 | ||
1515 | WARN_ON(counter->data); | 1521 | WARN_ON(counter->data); |
1516 | ret = perf_mmap_data_alloc(counter, nr_pages); | 1522 | ret = perf_mmap_data_alloc(counter, nr_pages); |
1517 | if (!ret) | 1523 | if (ret) |
1518 | atomic_set(&counter->mmap_count, 1); | 1524 | goto unlock; |
1519 | out: | 1525 | |
1526 | atomic_set(&counter->mmap_count, 1); | ||
1527 | vma->vm_mm->locked_vm += nr_pages + 1; | ||
1528 | unlock: | ||
1520 | mutex_unlock(&counter->mmap_mutex); | 1529 | mutex_unlock(&counter->mmap_mutex); |
1521 | 1530 | ||
1522 | vma->vm_flags &= ~VM_MAYWRITE; | 1531 | vma->vm_flags &= ~VM_MAYWRITE; |