patch for 2.1.50 zap_page_range

Bill Hawes (whawes@star.net)
Mon, 18 Aug 1997 14:29:23 -0400


This is a multi-part message in MIME format.
--------------C8A9CA36351D388CC4CCD282
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

I didn't get any comments to my previous posting about crediting the
mm->rss in free_pte, and so offer the following patch as a reasonable
fix for the problem.

When zap_page_range is releasing the mm_struct from a failed fork, the
freed pages shouldn't be credited to current->mm->rss. To fix this I've
modified free_pte to indicate whether it freed a page, and then sum the
freed pages all the way back to zap_page_range. At that point the total
credit is applied to mm->rss (which may or may not be current->mm->rss.)

This probably isn't a very important patch, but if it's worth
calculating rss in the first place, we may as well do it right.

Regards,
Bill
--------------C8A9CA36351D388CC4CCD282
Content-Type: text/plain; charset=us-ascii; name="memory_50-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="memory_50-patch"

--- mm/memory.c.old Sat Jul 19 08:12:08 1997
+++ mm/memory.c Sat Aug 16 10:00:44 1997
@@ -291,19 +299,20 @@
return error;
}

-static inline void free_pte(pte_t page)
+/*
+ * Return indicates whether a page was freed so caller can adjust rss
+ */
+static inline int free_pte(pte_t page)
{
if (pte_present(page)) {
unsigned long addr = pte_page(page);
if (MAP_NR(addr) >= max_mapnr || PageReserved(mem_map+MAP_NR(addr)))
- return;
+ return 0;
free_page(addr);
- if (current->mm->rss <= 0)
- return;
- current->mm->rss--;
- return;
+ return 1;
}
swap_free(pte_val(page));
+ return 0;
}

static inline void forget_pte(pte_t page)
@@ -314,22 +323,24 @@
}
}

-static inline void zap_pte_range(pmd_t * pmd, unsigned long address, unsigned long size)
+static inline int zap_pte_range(pmd_t * pmd, unsigned long address, unsigned long size)
{
pte_t * pte;
+ int freed;

if (pmd_none(*pmd))
- return;
+ return 0;
if (pmd_bad(*pmd)) {
printk("zap_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd));
pmd_clear(pmd);
- return;
+ return 0;
}
pte = pte_offset(pmd, address);
address &= ~PMD_MASK;
if (address + size > PMD_SIZE)
size = PMD_SIZE - address;
size >>= PAGE_SHIFT;
+ freed = 0;
for (;;) {
pte_t page;
if (!size)
@@ -340,32 +351,36 @@
if (pte_none(page))
continue;
pte_clear(pte-1);
- free_pte(page);
+ freed += free_pte(page);
}
+ return freed;
}

-static inline void zap_pmd_range(pgd_t * dir, unsigned long address, unsigned long size)
+static inline int zap_pmd_range(pgd_t * dir, unsigned long address, unsigned long size)
{
pmd_t * pmd;
unsigned long end;
+ int freed;

if (pgd_none(*dir))
- return;
+ return 0;
if (pgd_bad(*dir)) {
printk("zap_pmd_range: bad pgd (%08lx)\n", pgd_val(*dir));
pgd_clear(dir);
- return;
+ return 0;
}
pmd = pmd_offset(dir, address);
address &= ~PGDIR_MASK;
end = address + size;
if (end > PGDIR_SIZE)
end = PGDIR_SIZE;
+ freed = 0;
do {
- zap_pte_range(pmd, address, end - address);
+ freed += zap_pte_range(pmd, address, end - address);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address < end);
+ return freed;
}

/*
@@ -375,12 +390,21 @@
{
pgd_t * dir;
unsigned long end = address + size;
+ int freed = 0;

dir = pgd_offset(mm, address);
while (address < end) {
- zap_pmd_range(dir, address, end - address);
+ freed += zap_pmd_range(dir, address, end - address);
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
+ }
+ /*
+ * Update rss for the mm_struct (not necessarily current->mm)
+ */
+ if (mm->rss > 0) {
+ mm->rss -= freed;
+ if (mm->rss < 0)
+ mm->rss = 0;
}
}

--------------C8A9CA36351D388CC4CCD282--