Update of /cvsroot/linuxcompressed/linux/mm
In directory usw-pr-cvs1:/tmp/cvs-serv7824/mm
Modified Files:
memory.c swapfile.c
Log Message:
This patch include changes regarding the tlb and cache flushing when
setting pte. It also fixes a stupid bug in vswap.
- comp_cache_release() split into comp_cache_release() and
comp_cache_use_address().
- comp_cache_use_address() now searches for the vma for the pte we are
going to change. If found, we flush the cache and tlb for this pte
before setting it. If not found, we count this reference for the swap
count and when this pte faults in or gets freed, we fix the counters.
- so we have to handle the cases in lookup_comp_cache() in which the
pte gets changed when we sleep to get a new page. In this case, we
check to see if the pte has changed. If it has, wow, it's time to
return and waits it to fault in again, now with the real address.
- to flush, some code was copied from rmap patch by Rik van Riel. He
has the same problem and devised a nice way to decrease complexity
when looking for the mm struct.
- real_entry field was added back to vswap_address struct
- fix a _stupid_ bug in vswap. The estimated_pages is a variable that avoids
that we assign a huge number of vswaps which are reserved (vswap which is
used but does not have a fragment, so we don't know how bit the fragment
will be). This variable was supposed to have negative values, _but_ it was
declared as unsigned long. :-(
- (in this meanwhile I tried to add a referente to the swap count for our
compressed fragment, but it turned out to perform not as well as the old
code. I intended to remove that find_comp_page() and comp_cache_free() from
comp_cache_release(), but that take less time to execute than some general
idea, so I reverted the changes).
Index: memory.c
===================================================================
RCS file: /cvsroot/linuxcompressed/linux/mm/memory.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -C2 -r1.17 -r1.18
*** memory.c 2002/01/14 12:05:08 1.17
--- memory.c 2002/01/24 22:05:03 1.18
***************
*** 103,106 ****
--- 103,107 ----
pte = pte_offset(dir, 0);
pmd_clear(dir);
+ pgtable_remove_rmap(pte);
pte_free(pte);
}
***************
*** 1103,1109 ****
--- 1104,1138 ----
int ret = 1;
+ if (vswap_address(entry)) {
+ unsigned long offset = SWP_OFFSET(entry);
+
+ if (vswap_address[offset]->real_entry.val) {
+ swp_entry_t old_entry;
+
+ remove_pte_vswap(page_table);
+
+ pte = ptep_get_and_clear(page_table);
+ flush_tlb_page(vma, address);
+ flush_cache_page(vma, address);
+
+ swap_duplicate(vswap_address[offset]->real_entry);
+ set_pte(page_table, swp_entry_to_pte(vswap_address[offset]->real_entry));
+
+ old_entry.val = entry.val;
+ entry.val = vswap_address[offset]->real_entry.val;
+
+ comp_cache_swp_free_generic(old_entry, 0);
+ }
+ }
+
+
spin_unlock(&mm->page_table_lock);
page = lookup_comp_cache(entry);
+ /* we may sleep in the above function and a vswap addressed
+ * pte can have a real address assigned in the meanwhile */
+ if (!page && !pte_same(*page_table, orig_pte))
+ return 1;
+
if (!page) {
swapin_readahead(entry);
***************
*** 1436,1439 ****
--- 1465,1469 ----
}
}
+ pgtable_add_rmap(new, mm, address);
pmd_populate(mm, pmd, new);
}
Index: swapfile.c
===================================================================
RCS file: /cvsroot/linuxcompressed/linux/mm/swapfile.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -C2 -r1.22 -r1.23
*** swapfile.c 2001/12/21 18:33:11 1.22
--- swapfile.c 2002/01/24 22:05:03 1.23
***************
*** 199,202 ****
--- 199,203 ----
{
int count;
+ swp_entry_t entry;
if (vswap_info_struct(p))
***************
*** 206,219 ****
if (count < SWAP_MAP_MAX) {
count--;
- p->swap_map[offset] = count;
if (!count) {
#ifdef CONFIG_COMP_SWAP
p->swap_comp[offset] = 0;
#endif
! /* let's keep the swap_map[offset] used for
! * the case the comp_cache_release() calls
! * swap_dup() */
! p->swap_map[offset]++;
! if (!comp_cache_release(SWP_ENTRY(p - swap_info, offset))) {
if (offset < p->lowest_bit)
p->lowest_bit = offset;
--- 207,217 ----
if (count < SWAP_MAP_MAX) {
count--;
if (!count) {
#ifdef CONFIG_COMP_SWAP
p->swap_comp[offset] = 0;
#endif
! entry = SWP_ENTRY(p - swap_info, offset);
! comp_cache_release(entry);
! if (!comp_cache_use_address(entry)) {
if (offset < p->lowest_bit)
p->lowest_bit = offset;
***************
*** 222,227 ****
nr_swap_pages++;
}
! p->swap_map[offset]--;
}
}
return count;
--- 220,227 ----
nr_swap_pages++;
}
! count = p->swap_map[offset];
! count--;
}
+ p->swap_map[offset] = count;
}
return count;
|