Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e2ae599 authored by David Howells's avatar David Howells Committed by Linus Torvalds
Browse files

nommu: struct vm_region's vm_usage count need not be atomic



The vm_usage count field in struct vm_region does not need to be atomic as
it's only even modified whilst nommu_region_sem is write locked.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Acked-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Cc: Greg Ungerer <gerg@snapgear.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ed5e5894
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -122,7 +122,7 @@ struct vm_region {
	unsigned long	vm_pgoff;	/* the offset in vm_file corresponding to vm_start */
	unsigned long	vm_pgoff;	/* the offset in vm_file corresponding to vm_start */
	struct file	*vm_file;	/* the backing file or NULL */
	struct file	*vm_file;	/* the backing file or NULL */


	atomic_t	vm_usage;	/* region usage count */
	int		vm_usage;	/* region usage count (access under nommu_region_sem) */
	bool		vm_icache_flushed : 1; /* true if the icache has been flushed for
	bool		vm_icache_flushed : 1; /* true if the icache has been flushed for
						* this region */
						* this region */
};
};
+7 −7
Original line number Original line Diff line number Diff line
@@ -552,11 +552,11 @@ static void free_page_series(unsigned long from, unsigned long to)
static void __put_nommu_region(struct vm_region *region)
static void __put_nommu_region(struct vm_region *region)
	__releases(nommu_region_sem)
	__releases(nommu_region_sem)
{
{
	kenter("%p{%d}", region, atomic_read(&region->vm_usage));
	kenter("%p{%d}", region, region->vm_usage);


	BUG_ON(!nommu_region_tree.rb_node);
	BUG_ON(!nommu_region_tree.rb_node);


	if (atomic_dec_and_test(&region->vm_usage)) {
	if (--region->vm_usage == 0) {
		if (region->vm_top > region->vm_start)
		if (region->vm_top > region->vm_start)
			delete_nommu_region(region);
			delete_nommu_region(region);
		up_write(&nommu_region_sem);
		up_write(&nommu_region_sem);
@@ -1205,7 +1205,7 @@ unsigned long do_mmap_pgoff(struct file *file,
	if (!vma)
	if (!vma)
		goto error_getting_vma;
		goto error_getting_vma;


	atomic_set(&region->vm_usage, 1);
	region->vm_usage = 1;
	region->vm_flags = vm_flags;
	region->vm_flags = vm_flags;
	region->vm_pgoff = pgoff;
	region->vm_pgoff = pgoff;


@@ -1272,7 +1272,7 @@ unsigned long do_mmap_pgoff(struct file *file,
			}
			}


			/* we've found a region we can share */
			/* we've found a region we can share */
			atomic_inc(&pregion->vm_usage);
			pregion->vm_usage++;
			vma->vm_region = pregion;
			vma->vm_region = pregion;
			start = pregion->vm_start;
			start = pregion->vm_start;
			start += (pgoff - pregion->vm_pgoff) << PAGE_SHIFT;
			start += (pgoff - pregion->vm_pgoff) << PAGE_SHIFT;
@@ -1289,7 +1289,7 @@ unsigned long do_mmap_pgoff(struct file *file,
					vma->vm_region = NULL;
					vma->vm_region = NULL;
					vma->vm_start = 0;
					vma->vm_start = 0;
					vma->vm_end = 0;
					vma->vm_end = 0;
					atomic_dec(&pregion->vm_usage);
					pregion->vm_usage--;
					pregion = NULL;
					pregion = NULL;
					goto error_just_free;
					goto error_just_free;
				}
				}
@@ -1444,7 +1444,7 @@ int split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
	/* we're only permitted to split anonymous regions that have a single
	/* we're only permitted to split anonymous regions that have a single
	 * owner */
	 * owner */
	if (vma->vm_file ||
	if (vma->vm_file ||
	    atomic_read(&vma->vm_region->vm_usage) != 1)
	    vma->vm_region->vm_usage != 1)
		return -ENOMEM;
		return -ENOMEM;


	if (mm->map_count >= sysctl_max_map_count)
	if (mm->map_count >= sysctl_max_map_count)
@@ -1518,7 +1518,7 @@ static int shrink_vma(struct mm_struct *mm,


	/* cut the backing region down to size */
	/* cut the backing region down to size */
	region = vma->vm_region;
	region = vma->vm_region;
	BUG_ON(atomic_read(&region->vm_usage) != 1);
	BUG_ON(region->vm_usage != 1);


	down_write(&nommu_region_sem);
	down_write(&nommu_region_sem);
	delete_nommu_region(region);
	delete_nommu_region(region);