[lc-checkins] CVS: linux/mm/comp_cache free.c,1.44,1.45 main.c,1.60,1.61 swapin.c,1.49,1.50 swapout.
Status: Beta
Brought to you by:
nitin_sf
|
From: Rodrigo S. de C. <rc...@us...> - 2002-07-31 12:31:08
|
Update of /cvsroot/linuxcompressed/linux/mm/comp_cache
In directory usw-pr-cvs1:/tmp/cvs-serv23025/mm/comp_cache
Modified Files:
free.c main.c swapin.c swapout.c
Log Message:
Bug fixes
o Fixed "kernel BUG at inode.c:518". That bug happened when, after
truncating all the pages from an inode, there are still pending pages
in that mapping. That scenario could occur if a certain fragment
happens to waiting to lock its comp_page in order to be effectively
freed. In this case, the fragment got removed from comp cache data
structures, but not from the mapping data structures while waiting for
its fragment->comp_page lock, so it was taken as being in the mapping
(well, as a clean mapped page actually) in spite of having a zero
counter. That was fixed by removing the fragment from the mapping
structures too.
o Fixed "oops in ext2_check_page()" bug. That bug could happen because
a page, after being compressed in compress_clean_page(), could be
removed from page cache (in shrink_cache()) even if it is not freeable
(!is_page_cache_freeable()). So, ext2_check_page(), which assumes that
the page wouldn't be removed since it has a reference on the page,
accesses directly the page->mapping pointer and oopses, because that
pointer is set to NULL after removing from page cache. The fix was
very simple. We check, with the pagecache lock held, if the page is
freeable after compressing it. In this case, it is not removed from
page cache and is kept on the inactive list.
Cleanup
o Cleanup in lookup_comp_pages()
o find_and_dirty_page() renamed to find_or_add_page()
o __find_lock_page() does not read pages from comp cache if the page
is not found in page cache.
Index: free.c
===================================================================
RCS file: /cvsroot/linuxcompressed/linux/mm/comp_cache/free.c,v
retrieving revision 1.44
retrieving revision 1.45
diff -C2 -r1.44 -r1.45
*** free.c 28 Jul 2002 15:47:04 -0000 1.44
--- free.c 31 Jul 2002 12:31:05 -0000 1.45
***************
*** 2,6 ****
* linux/mm/comp_cache/free.c
*
! * Time-stamp: <2002-07-28 10:21:04 rcastro>
*
* Linux Virtual Memory Compressed Cache
--- 2,6 ----
* linux/mm/comp_cache/free.c
*
! * Time-stamp: <2002-07-29 10:04:24 rcastro>
*
* Linux Virtual Memory Compressed Cache
***************
*** 72,79 ****
}
- /* remove from mapping->{clean,dirty}_comp_pages */
- list_del_init(&fragment->mapping_list);
- fragment->mapping->nrpages--;
-
/* compressed fragments of swap cache are accounted in
* swapper_space.nrpages, so we need to account them
--- 72,75 ----
***************
*** 234,237 ****
--- 230,239 ----
if (!fragment)
BUG();
+
+ /* remove from mapping->{clean,dirty}_comp_pages */
+ spin_lock(&pagecache_lock);
+ list_del_init(&fragment->mapping_list);
+ fragment->mapping->nrpages--;
+ spin_unlock(&pagecache_lock);
remove_fragment_vswap(fragment);
Index: main.c
===================================================================
RCS file: /cvsroot/linuxcompressed/linux/mm/comp_cache/main.c,v
retrieving revision 1.60
retrieving revision 1.61
diff -C2 -r1.60 -r1.61
*** main.c 28 Jul 2002 15:47:04 -0000 1.60
--- main.c 31 Jul 2002 12:31:05 -0000 1.61
***************
*** 2,6 ****
* linux/mm/comp_cache/main.c
*
! * Time-stamp: <2002-07-28 10:04:28 rcastro>
*
* Linux Virtual Memory Compressed Cache
--- 2,6 ----
* linux/mm/comp_cache/main.c
*
! * Time-stamp: <2002-07-29 09:31:05 rcastro>
*
* Linux Virtual Memory Compressed Cache
***************
*** 74,78 ****
}
-
comp_size = compress(current_compressed_page = page, buffer_compressed = (unsigned long *) &buffer_compressed1, &algorithm, state);
comp_page = get_comp_cache_page(page, comp_size, &fragment, gfp_mask, priority);
--- 74,77 ----
Index: swapin.c
===================================================================
RCS file: /cvsroot/linuxcompressed/linux/mm/comp_cache/swapin.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -C2 -r1.49 -r1.50
*** swapin.c 28 Jul 2002 20:48:32 -0000 1.49
--- swapin.c 31 Jul 2002 12:31:05 -0000 1.50
***************
*** 2,6 ****
* linux/mm/comp_cache/swapin.c
*
! * Time-stamp: <2002-07-28 17:34:57 rcastro>
*
* Linux Virtual Memory Compressed Cache
--- 2,6 ----
* linux/mm/comp_cache/swapin.c
*
! * Time-stamp: <2002-07-30 12:21:21 rcastro>
*
* Linux Virtual Memory Compressed Cache
***************
*** 141,146 ****
#ifdef CONFIG_COMP_PAGE_CACHE
- extern struct page * find_and_dirty_page(struct page * new_page, struct address_space *mapping, unsigned long offset, struct page **hash);
-
static void
truncate_list_comp_pages(struct list_head * list, unsigned long start, unsigned partial)
--- 141,144 ----
***************
*** 193,210 ****
}
/* caller must hold pagecache_lock */
void
lookup_comp_pages(struct address_space * mapping)
{
! struct page **hash;
! struct page * page;
struct comp_cache_fragment * fragment;
- spin_lock(&comp_cache_lock);
-
- if (list_empty(&mapping->dirty_comp_pages))
- goto out_unlock;
-
- spin_unlock(&pagecache_lock);
/***
* This function may be called from the following code path:
--- 191,203 ----
}
+ extern struct page * find_or_add_page(struct page * new_page, struct address_space *mapping, unsigned long offset);
+
/* caller must hold pagecache_lock */
void
lookup_comp_pages(struct address_space * mapping)
{
! struct page * page, * old_page;
struct comp_cache_fragment * fragment;
/***
* This function may be called from the following code path:
***************
*** 229,235 ****
* That's why the page must be allocated with GFP_NOFS mask.
*/
page = alloc_page(GFP_NOFS);
if (!page)
! goto out_unlock;
spin_lock(&pagecache_lock);
--- 222,229 ----
* That's why the page must be allocated with GFP_NOFS mask.
*/
+ spin_unlock(&pagecache_lock);
page = alloc_page(GFP_NOFS);
if (!page)
! return;
spin_lock(&pagecache_lock);
***************
*** 239,264 ****
}
fragment = list_entry(mapping->dirty_comp_pages.next, struct comp_cache_fragment, mapping_list);
- hash = page_hash(mapping, fragment->index);
- if (!CompFragmentTestandClearDirty(fragment))
- BUG();
-
list_del(&fragment->mapping_list);
! list_add(&fragment->mapping_list, &fragment->mapping->clean_comp_pages);
!
! /* Checks if the page has been added to the page cache and add
! * this new page to the cache if the former condition is
! * false. Dirty the page in the page cache otherwise. */
! if (find_and_dirty_page(page, mapping, fragment->index, hash))
! goto out_release;
!
get_fragment(fragment);
spin_unlock(&comp_cache_lock);
lock_page(fragment->comp_page->page);
- decompress_fragment(fragment, page);
- UnlockPage(fragment->comp_page->page);
spin_lock(&comp_cache_lock);
put_fragment(fragment);
--- 233,262 ----
}
+ spin_lock(&comp_cache_lock);
+
fragment = list_entry(mapping->dirty_comp_pages.next, struct comp_cache_fragment, mapping_list);
list_del(&fragment->mapping_list);
! list_add(&fragment->mapping_list, &fragment->mapping->clean_comp_pages);
!
get_fragment(fragment);
spin_unlock(&comp_cache_lock);
+ spin_unlock(&pagecache_lock);
lock_page(fragment->comp_page->page);
+ /* Checks if the page has been added to the page cache in the
+ * meanwhile and dirty the page in this case. Otherwise, add
+ * the new page to the page cache. */
+ old_page = find_or_add_page(page, mapping, fragment->index);
+ if (!old_page) {
+ decompress_fragment(fragment, page);
+ goto free_and_dirty;
+ }
+ page_cache_release(page);
+ page = old_page;
+
+ free_and_dirty:
+ UnlockPage(fragment->comp_page->page);
spin_lock(&comp_cache_lock);
put_fragment(fragment);
***************
*** 266,278 ****
/* effectively free it */
drop_fragment(fragment);
PageClearCompCache(page);
! __set_page_dirty(page);
UnlockPage(page);
-
out_release:
page_cache_release(page);
- out_unlock:
- spin_unlock(&comp_cache_lock);
}
#endif
--- 264,274 ----
/* effectively free it */
drop_fragment(fragment);
+ spin_unlock(&comp_cache_lock);
PageClearCompCache(page);
! __set_page_dirty(page);
UnlockPage(page);
out_release:
page_cache_release(page);
}
#endif
Index: swapout.c
===================================================================
RCS file: /cvsroot/linuxcompressed/linux/mm/comp_cache/swapout.c,v
retrieving revision 1.66
retrieving revision 1.67
diff -C2 -r1.66 -r1.67
*** swapout.c 28 Jul 2002 15:47:04 -0000 1.66
--- swapout.c 31 Jul 2002 12:31:05 -0000 1.67
***************
*** 2,6 ****
* /mm/comp_cache/swapout.c
*
! * Time-stamp: <2002-07-28 11:33:53 rcastro>
*
* Linux Virtual Memory Compressed Cache
--- 2,6 ----
* /mm/comp_cache/swapout.c
*
! * Time-stamp: <2002-07-29 17:18:46 rcastro>
*
* Linux Virtual Memory Compressed Cache
***************
*** 427,430 ****
--- 427,432 ----
}
+ /* that's going to be rechecked in shrink_cache() with
+ * pagecache lock held */
if (page_count(page) - !!page->buffers == 3)
continue;
***************
*** 460,464 ****
check_references:
! /* 3 = shrink_cache() + page cache + us */
if (page_count(page) - !!page->buffers != 3)
goto failed;
--- 462,467 ----
check_references:
! /* 3 = shrink_cache() + page cache + us. That's going to be
! * rechecked in shrink_cache() with pagecache lock held */
if (page_count(page) - !!page->buffers != 3)
goto failed;
|