[RFC,PATCH] mm,parisc: keep track of last mmap'ed address

From: Helge Deller
Date: Thu Apr 17 2014 - 16:46:22 EST


Would the following patch be acceptable?
It adds an additional field to struct address_space which will most likely only
be used by the parisc arch.

If it's acceptable, I would like to push it through the parisc tree, if not,
I'm of course open to other ideas too.

Thanks,
Helge

PATCH:
[RFC,PATCH] mm,parisc: keep track of last mmap'ed address

Because of parisc's cache aliasing constraints we need to map shared pages at a
multiple of 4MB while most other architectures can map files at any multiple of
PAGE_SIZE. In the past this constraint was ensured by calculating a virtual
offset into this 4MB region which is based on the physical address of the
kernel mapping variable (right-shift value of filp->f_mapping by 8 bits).
Since we only have a 32bit userspace (even when running on a 64bit kernel) this
often leads to large gaps in the maps of the userspace processes and to out of
memory situations even if physical memory was still free. Of course I did
played with other variants of shifting the f_mapping value to find better
offsets but this didn't helped either.

This patch chooses a different approach.
It adds the additional field i_mmap_lastmmap to the address_space struct to
keep track of the last mapping of a shared file. With this bookkeeping it's
possible for the parisc memory allocator to
a) choose a new mapping offset if the file hasn't been mapped yet, and
b) take the last-used mapping if it was already mapped by another process.

Overall this approach leads to a more condensed memory usage on parisc because
the shared files will now be mapped much closer to each other. This is e.g.
visible with shared libraries which are now not any longer cluttered around
in the userspace process but close to each other at the top of the userspace
memory.

Signed-off-by: Helge Deller <deller@xxxxxx>

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 81048f9..f757a5c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -416,6 +416,9 @@ struct address_space {
unsigned int i_mmap_writable;/* count VM_SHARED mappings */
struct rb_root i_mmap; /* tree of private and shared mappings */
struct list_head i_mmap_nonlinear;/*list VM_NONLINEAR mappings */
+#ifdef CONFIG_MMAP_TRACKING
+ unsigned long i_mmap_lastmmap; /* address of last mmap */
+#endif
struct mutex i_mmap_mutex; /* protect tree, count, list */
/* Protected by tree_lock together with the radix tree */
unsigned long nrpages; /* number of total pages */
diff --git a/mm/mmap.c b/mm/mmap.c
index b1202cf..e2659c3 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -212,8 +212,13 @@ static void __remove_shared_vm_struct(struct vm_area_struct *vma,
{
if (vma->vm_flags & VM_DENYWRITE)
atomic_inc(&file_inode(file)->i_writecount);
- if (vma->vm_flags & VM_SHARED)
+ if (vma->vm_flags & VM_SHARED) {
mapping->i_mmap_writable--;
+#ifdef CONFIG_MMAP_TRACKING
+ if (mapping->i_mmap_writable == 0)
+ mapping->i_mmap_lastmmap = 0;
+#endif
+ }

flush_dcache_mmap_lock(mapping);
if (unlikely(vma->vm_flags & VM_NONLINEAR))
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index bb2a8ec..9518361 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -38,6 +38,9 @@ config PARISC
config MMU
def_bool y

+config MMAP_TRACKING
+ def_bool y
+
config STACK_GROWSUP
def_bool y

diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index 31ffa9b..7d8cbd1 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -36,12 +36,12 @@
#include <linux/personality.h>
#include <linux/random.h>

-/* we construct an artificial offset for the mapping based on the physical
- * address of the kernel mapping variable */
+/* the address_space struct holds a field i_mmap_lastmmap with the last mapping
+ * of this file for us */
#define GET_LAST_MMAP(filp) \
- (filp ? ((unsigned long) filp->f_mapping) >> 8 : 0UL)
+ (filp ? filp->f_mapping->i_mmap_lastmmap : 0UL)
#define SET_LAST_MMAP(filp, val) \
- { /* nothing */ }
+ { if (filp) filp->f_mapping->i_mmap_lastmmap = (val); }

static int get_offset(unsigned int last_mmap)
{
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/