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

Commit 89e004ea authored by Lee Schermerhorn's avatar Lee Schermerhorn Committed by Linus Torvalds
Browse files

SHM_LOCKED pages are unevictable



Shmem segments locked into memory via shmctl(SHM_LOCKED) should not be
kept on the normal LRU, since scanning them is a waste of time and might
throw off kswapd's balancing algorithms.  Place them on the unevictable
LRU list instead.

Use the AS_UNEVICTABLE flag to mark address_space of SHM_LOCKed shared
memory regions as unevictable.  Then these pages will be culled off the
normal LRU lists during vmscan.

Add new wrapper function to clear the mapping's unevictable state when/if
shared memory segment is munlocked.

Add 'scan_mapping_unevictable_page()' to mm/vmscan.c to scan all pages in
the shmem segment's mapping [struct address_space] for evictability now
that they're no longer locked.  If so, move them to the appropriate zone
lru list.

Changes depend on [CONFIG_]UNEVICTABLE_LRU.

[kosaki.motohiro@jp.fujitsu.com: revert shm change]
Signed-off-by: default avatarLee Schermerhorn <lee.schermerhorn@hp.com>
Signed-off-by: default avatarRik van Riel <riel@redhat.com>
Signed-off-by: default avatarKosaki Motohiro <kosaki.motohiro@jp.fujitsu.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ba9ddf49
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -700,7 +700,7 @@ static inline int page_mapped(struct page *page)
extern void show_free_areas(void);

#ifdef CONFIG_SHMEM
int shmem_lock(struct file *file, int lock, struct user_struct *user);
extern int shmem_lock(struct file *file, int lock, struct user_struct *user);
#else
static inline int shmem_lock(struct file *file, int lock,
			    struct user_struct *user)
+9 −3
Original line number Diff line number Diff line
@@ -40,14 +40,20 @@ static inline void mapping_set_unevictable(struct address_space *mapping)
	set_bit(AS_UNEVICTABLE, &mapping->flags);
}

static inline void mapping_clear_unevictable(struct address_space *mapping)
{
	clear_bit(AS_UNEVICTABLE, &mapping->flags);
}

static inline int mapping_unevictable(struct address_space *mapping)
{
	if (mapping && (mapping->flags & AS_UNEVICTABLE))
		return 1;
	return 0;
	if (likely(mapping))
		return test_bit(AS_UNEVICTABLE, &mapping->flags);
	return !!mapping;
}
#else
static inline void mapping_set_unevictable(struct address_space *mapping) { }
static inline void mapping_clear_unevictable(struct address_space *mapping) { }
static inline int mapping_unevictable(struct address_space *mapping)
{
	return 0;
+4 −0
Original line number Diff line number Diff line
@@ -232,12 +232,16 @@ static inline int zone_reclaim(struct zone *z, gfp_t mask, unsigned int order)

#ifdef CONFIG_UNEVICTABLE_LRU
extern int page_evictable(struct page *page, struct vm_area_struct *vma);
extern void scan_mapping_unevictable_pages(struct address_space *);
#else
static inline int page_evictable(struct page *page,
						struct vm_area_struct *vma)
{
	return 1;
}
static inline void scan_mapping_unevictable_pages(struct address_space *mapping)
{
}
#endif

extern int kswapd_run(int nid);
+4 −0
Original line number Diff line number Diff line
@@ -737,6 +737,10 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
	case SHM_LOCK:
	case SHM_UNLOCK:
	{
		struct file *uninitialized_var(shm_file);

		lru_add_drain_all();  /* drain pagevecs to lru lists */

		shp = shm_lock_check(ns, shmid);
		if (IS_ERR(shp)) {
			err = PTR_ERR(shp);
+4 −0
Original line number Diff line number Diff line
@@ -1477,12 +1477,16 @@ int shmem_lock(struct file *file, int lock, struct user_struct *user)
		if (!user_shm_lock(inode->i_size, user))
			goto out_nomem;
		info->flags |= VM_LOCKED;
		mapping_set_unevictable(file->f_mapping);
	}
	if (!lock && (info->flags & VM_LOCKED) && user) {
		user_shm_unlock(inode->i_size, user);
		info->flags &= ~VM_LOCKED;
		mapping_clear_unevictable(file->f_mapping);
		scan_mapping_unevictable_pages(file->f_mapping);
	}
	retval = 0;

out_nomem:
	spin_unlock(&info->lock);
	return retval;
Loading