[lc-checkins] CVS: linux/mm/comp_cache adaptivity.c,1.38,1.39 free.c,1.45,1.46 main.c,1.62,1.63 proc
Status: Beta
Brought to you by:
nitin_sf
|
From: Rodrigo S. de C. <rc...@us...> - 2002-08-07 18:31:02
|
Update of /cvsroot/linuxcompressed/linux/mm/comp_cache
In directory usw-pr-cvs1:/tmp/cvs-serv28260/mm/comp_cache
Modified Files:
adaptivity.c free.c main.c proc.c swapin.c swapout.c
Log Message:
Feature
o New comp_cache_stat output, including some configurations (like if
there is support for page cache, the comp page size, failed
allocations). There is also data separated for page and swap cache.
Bug fixes
o A deadlock happens when compiling the linux kernel on a host kernel
with compressed cache. It usually happens when used make -j 2/4, but
also happens with make -j 1. From the stack traces, a process hangs
waiting for a swap buffer page in comp_cache_free_locked() and all the
other processes hang trying to lock the fragment->comp_page which is
locked waiting for the swap buffer.
This deadlock might happen if the swap buffer gets unlocked when the
fragment is waiting for it, but it is locked again before the
wait_on_page() function enters the CPU. In this case, if the swap
buffer is also trying to write out a fragment in the very same comp
page as the former fragment, it will sleep to lock the comp page which
could only get unlocked when this swap buffer got unlocked (what will
not happen).
The fix was to remove the wait_on_page() to not wait for the swap
buffer. Actually, it was removed because it fixes the deadlock, but
the most important reason is that it was not needed. It had been put
there trying to fix a race which it didn't fix (the goal was to avoid
to read a page that is being written from a swap buffer).
o Once, compiling the linux kernel on a host kernel with
compressed cache, we hit a bug from a error happened
when decompressing a fragment (in the case, the error
was -4 in LZO).
After compressing a page to a static buffer in compress_page(), if it
happened that this buffer got used, we compressed it again, without
making sure that the compressed size was the same. So, we could have a
fragment set to a wrong compressed size and copy the wrong number of
bytes from the buffer to the page. Now we check if the size is the
same, freeing the fragment and getting a new one if the differ.
o After a failed writepage(), the swap buffer would not set the
fragment->swp_buffer to NULL, so it might end having its fragment
field nulled in the future, possibly when set to a fragment that is
being written. If that happens, the fragment would not be freed and
never freed by the writeout code, since it had been removed from the
LRU queue. The fix was just set swp_buffer->fragment->swp_buffer to
NULL.
o There is a potential bug in refill_swp_buffer() that can free a swap
buffer pages that has buffers. A "goto" to give up on that page and
add it back to the used list has been wrongly deleted. It has been
added back.
Cleanups
o Cleanups in the stats code and structures.
Index: adaptivity.c
===================================================================
RCS file: /cvsroot/linuxcompressed/linux/mm/comp_cache/adaptivity.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -C2 -r1.38 -r1.39
*** adaptivity.c 28 Jul 2002 15:47:04 -0000 1.38
--- adaptivity.c 7 Aug 2002 18:30:58 -0000 1.39
***************
*** 2,6 ****
* linux/mm/comp_cache/adaptivity.c
*
! * Time-stamp: <2002-07-26 17:22:32 rcastro>
*
* Linux Virtual Memory Compressed Cache
--- 2,6 ----
* linux/mm/comp_cache/adaptivity.c
*
! * Time-stamp: <2002-08-03 12:12:40 rcastro>
*
* Linux Virtual Memory Compressed Cache
***************
*** 17,20 ****
--- 17,21 ----
extern kmem_cache_t * comp_cachep;
static int fragment_failed_alloc = 0, vswap_failed_alloc = 0;
+ unsigned long failed_comp_page_allocs = 0;
/* semaphore used to avoid two concurrent instances of
***************
*** 641,646 ****
/* couldn't allocate the page */
! if (!page)
goto out_unlock;
if (!init_comp_page(&comp_page, page)) {
--- 642,649 ----
/* couldn't allocate the page */
! if (!page) {
! failed_comp_page_allocs++;
goto out_unlock;
+ }
if (!init_comp_page(&comp_page, page)) {
***************
*** 652,655 ****
--- 655,660 ----
comp_cache_free_space += COMP_PAGE_SIZE;
num_comp_pages++;
+ if (num_comp_pages > max_used_num_comp_pages)
+ max_used_num_comp_pages = num_comp_pages;
#if 0
printk("grow real %lu\n", num_comp_pages);
Index: free.c
===================================================================
RCS file: /cvsroot/linuxcompressed/linux/mm/comp_cache/free.c,v
retrieving revision 1.45
retrieving revision 1.46
diff -C2 -r1.45 -r1.46
*** free.c 31 Jul 2002 12:31:05 -0000 1.45
--- free.c 7 Aug 2002 18:30:58 -0000 1.46
***************
*** 2,6 ****
* linux/mm/comp_cache/free.c
*
! * Time-stamp: <2002-07-29 10:04:24 rcastro>
*
* Linux Virtual Memory Compressed Cache
--- 2,6 ----
* linux/mm/comp_cache/free.c
*
! * Time-stamp: <2002-08-07 12:50:00 rcastro>
*
* Linux Virtual Memory Compressed Cache
***************
*** 66,74 ****
* non-null swp_buffer. Let's warn the swap buffer that this
* page has been already removed by setting its fragment field
! * to NULL and also let's wait for the IO to finish. */
! if (fragment->swp_buffer) {
fragment->swp_buffer->fragment = NULL;
- wait_on_page(fragment->swp_buffer->page);
- }
/* compressed fragments of swap cache are accounted in
--- 66,72 ----
* non-null swp_buffer. Let's warn the swap buffer that this
* page has been already removed by setting its fragment field
! * to NULL. */
! if (fragment->swp_buffer)
fragment->swp_buffer->fragment = NULL;
/* compressed fragments of swap cache are accounted in
Index: main.c
===================================================================
RCS file: /cvsroot/linuxcompressed/linux/mm/comp_cache/main.c,v
retrieving revision 1.62
retrieving revision 1.63
diff -C2 -r1.62 -r1.63
*** main.c 1 Aug 2002 14:52:25 -0000 1.62
--- main.c 7 Aug 2002 18:30:58 -0000 1.63
***************
*** 2,6 ****
* linux/mm/comp_cache/main.c
*
! * Time-stamp: <2002-08-01 10:19:51 rcastro>
*
* Linux Virtual Memory Compressed Cache
--- 2,6 ----
* linux/mm/comp_cache/main.c
*
! * Time-stamp: <2002-08-07 15:17:28 rcastro>
*
* Linux Virtual Memory Compressed Cache
***************
*** 29,32 ****
--- 29,33 ----
unsigned long max_num_comp_pages = 0;
unsigned long min_num_comp_pages = 0;
+ unsigned long max_used_num_comp_pages = 0;
/* stores the last number of compressed pages that has been used to
***************
*** 77,81 ****
}
! 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);
--- 78,83 ----
}
! try_again:
! comp_size = compress(current_compressed_page = page, buffer_compressed = (unsigned long *) &buffer_compressed1, &algorithm);
comp_page = get_comp_cache_page(page, comp_size, &fragment, gfp_mask, priority);
***************
*** 110,115 ****
copy_page:
if (compressed(fragment)) {
! if (current_compressed_page != page)
! compress(page, buffer_compressed = (unsigned long *) &buffer_compressed2, &algorithm, state);
memcpy(page_address(comp_page->page) + fragment->offset, buffer_compressed , fragment->compressed_size);
} else
--- 112,123 ----
copy_page:
if (compressed(fragment)) {
! if (current_compressed_page != page) {
! comp_size = compress(page, buffer_compressed = (unsigned long *) &buffer_compressed2, &algorithm);
! if (comp_size != fragment->compressed_size) {
! UnlockPage(comp_page->page);
! drop_fragment(fragment);
! goto try_again;
! }
! }
memcpy(page_address(comp_page->page) + fragment->offset, buffer_compressed , fragment->compressed_size);
} else
***************
*** 211,221 ****
int i;
! min_num_comp_pages = page_to_comp_page(48);
if (!max_num_comp_pages || max_num_comp_pages < min_num_comp_pages || max_num_comp_pages > num_physpages * 0.5)
max_num_comp_pages = page_to_comp_page((unsigned long) (num_physpages * 0.5));
- if (!init_num_comp_pages || init_num_comp_pages < min_num_comp_pages || init_num_comp_pages > max_num_comp_pages)
- init_num_comp_pages = min_num_comp_pages;
new_num_comp_pages = num_comp_pages = init_num_comp_pages;
--- 219,227 ----
int i;
! max_used_num_comp_pages = init_num_comp_pages = min_num_comp_pages = page_to_comp_page(48);
if (!max_num_comp_pages || max_num_comp_pages < min_num_comp_pages || max_num_comp_pages > num_physpages * 0.5)
max_num_comp_pages = page_to_comp_page((unsigned long) (num_physpages * 0.5));
new_num_comp_pages = num_comp_pages = init_num_comp_pages;
Index: proc.c
===================================================================
RCS file: /cvsroot/linuxcompressed/linux/mm/comp_cache/proc.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -C2 -r1.23 -r1.24
*** proc.c 1 Aug 2002 14:52:25 -0000 1.23
--- proc.c 7 Aug 2002 18:30:58 -0000 1.24
***************
*** 2,6 ****
* linux/mm/comp_cache/proc.c
*
! * Time-stamp: <2002-08-01 09:03:16 rcastro>
*
* Linux Virtual Memory Compressed Cache
--- 2,6 ----
* linux/mm/comp_cache/proc.c
*
! * Time-stamp: <2002-08-07 14:43:55 rcastro>
*
* Linux Virtual Memory Compressed Cache
***************
*** 27,31 ****
extern unsigned long new_num_comp_pages, max_num_comp_pages, min_num_comp_pages;
! static struct comp_alg compression_algorithms[NUM_ALGORITHMS];
static int algorithm_min = WKDM_IDX;
static int algorithm_max = LZO_IDX;
--- 27,55 ----
extern unsigned long new_num_comp_pages, max_num_comp_pages, min_num_comp_pages;
! struct stats_summary {
! /* swap cache */
! unsigned long long comp_size_sum_swap;
! unsigned long comp_swap;
! unsigned long decomp_swap;
! unsigned long read_swap;
! unsigned long written_swap;
!
!
! /* page cache */
! unsigned long long comp_size_sum_page;
! unsigned long comp_page;
! unsigned long decomp_page;
! unsigned long read_page;
! unsigned long written_page;
!
! };
!
! static struct comp_alg {
! char name[6];
! compress_function_t * comp;
! decompress_function_t * decomp;
! struct stats_summary stats;
! } compression_algorithms[NUM_ALGORITHMS];
!
static int algorithm_min = WKDM_IDX;
static int algorithm_max = LZO_IDX;
***************
*** 49,158 ****
};
! static inline void
! comp_cache_update_page_stats(struct page * page, int state)
{
! #ifdef CONFIG_COMP_PAGE_CACHE
! if (!PageSwapCache(page))
! compression_algorithms[current_algorithm].stats.comp_page++;
! else
! #endif
! compression_algorithms[current_algorithm].stats.comp_swap++;
! if (state == DIRTY_PAGE)
! compression_algorithms[current_algorithm].stats.comp_dirty++;
! else
! compression_algorithms[current_algorithm].stats.comp_clean++;
}
! static void
! comp_cache_update_comp_stats(struct stats_page * comp_page_stats, struct page * page, int state)
{
! struct comp_alg * algorithm = &compression_algorithms[current_algorithm];
! struct stats_summary * stats = &(algorithm->stats);
!
! /* update compressed size statistics */
! if (!comp_page_stats->comp_size)
BUG();
!
! if (comp_page_stats->comp_size < stats->comp_size_min)
! stats->comp_size_min = comp_page_stats->comp_size;
!
! if (comp_page_stats->comp_size > stats->comp_size_max)
! stats->comp_size_max = comp_page_stats->comp_size;
!
! stats->comp_size_sum += comp_page_stats->comp_size;
!
! /* update comp cycles statistics */
! if (comp_page_stats->comp_cycles < stats->comp_cycles_min)
! stats->comp_cycles_min = comp_page_stats->comp_cycles;
!
! if (comp_page_stats->comp_cycles > stats->comp_cycles_max)
! stats->comp_cycles_max = comp_page_stats->comp_cycles;
!
! stats->comp_cycles_sum += comp_page_stats->comp_cycles;
!
! comp_cache_update_page_stats(page, state);
}
! static void
! comp_cache_update_decomp_stats(unsigned short alg_idx, struct stats_page * comp_page_stats, struct comp_cache_fragment * fragment)
{
! struct comp_alg * algorithm = &compression_algorithms[alg_idx];
! struct stats_summary * stats = &(algorithm->stats);
!
! /* update decomp cycles statistics */
! if (comp_page_stats->decomp_cycles < stats->decomp_cycles_min)
! stats->decomp_cycles_min = comp_page_stats->decomp_cycles;
!
! if (comp_page_stats->decomp_cycles > stats->decomp_cycles_max)
! stats->decomp_cycles_max = comp_page_stats->decomp_cycles;
!
! stats->decomp_cycles_sum += comp_page_stats->decomp_cycles;
#ifdef CONFIG_COMP_PAGE_CACHE
! if (!PageSwapCache(fragment))
! compression_algorithms[current_algorithm].stats.decomp_page++;
! else
#endif
! compression_algorithms[current_algorithm].stats.decomp_swap++;
}
! void
! comp_cache_update_writeout_stats(struct comp_cache_fragment * fragment)
{
#ifdef CONFIG_COMP_PAGE_CACHE
! if (!PageSwapCache(fragment))
! compression_algorithms[current_algorithm].stats.page_out++;
! else
#endif
! compression_algorithms[current_algorithm].stats.swap_out++;
}
! void
! comp_cache_update_faultin_stats(struct comp_cache_fragment * fragment)
{
#ifdef CONFIG_COMP_PAGE_CACHE
! if (!PageSwapCache(fragment))
! compression_algorithms[current_algorithm].stats.faultin_page++;
! else
#endif
! compression_algorithms[current_algorithm].stats.faultin_swap++;
}
!
! void
! set_fragment_algorithm(struct comp_cache_fragment * fragment, unsigned short algorithm)
{
! switch (algorithm) {
! case WKDM_IDX:
! CompFragmentSetWKdm(fragment);
! break;
! case WK4X4_IDX:
! CompFragmentSetWK4x4(fragment);
! break;
! case LZO_IDX:
! CompFragmentSetLZO(fragment);
! break;
! default:
BUG();
}
}
--- 73,168 ----
};
! int
! get_fragment_algorithm(struct comp_cache_fragment * fragment)
{
! if (CompFragmentWKdm(fragment))
! return WKDM_IDX;
! if (CompFragmentWK4x4(fragment))
! return WK4X4_IDX;
! if (CompFragmentLZO(fragment))
! return LZO_IDX;
! BUG();
! return -1;
}
! void
! set_fragment_algorithm(struct comp_cache_fragment * fragment, unsigned short algorithm)
{
! switch (algorithm) {
! case WKDM_IDX:
! CompFragmentSetWKdm(fragment);
! break;
! case WK4X4_IDX:
! CompFragmentSetWK4x4(fragment);
! break;
! case LZO_IDX:
! CompFragmentSetLZO(fragment);
! break;
! default:
BUG();
! }
}
! inline void
! comp_cache_update_read_stats(unsigned short algorithm, struct comp_cache_fragment * fragment)
{
! struct stats_summary * stats = &(compression_algorithms[algorithm].stats);
#ifdef CONFIG_COMP_PAGE_CACHE
! if (!PageSwapCache(fragment)) {
! stats->read_page++;
! return;
! }
#endif
! stats->read_swap++;
}
! inline void
! comp_cache_update_written_stats(unsigned short algorithm, struct comp_cache_fragment * fragment)
{
+ struct stats_summary * stats = &(compression_algorithms[algorithm].stats);
+
#ifdef CONFIG_COMP_PAGE_CACHE
! if (!PageSwapCache(fragment)) {
! stats->written_page++;
! return;
! }
#endif
! stats->written_swap++;
}
! static inline void
! comp_cache_update_decomp_stats(unsigned short algorithm, struct comp_cache_fragment * fragment)
{
+ struct stats_summary * stats = &(compression_algorithms[algorithm].stats);
+
#ifdef CONFIG_COMP_PAGE_CACHE
! if (!PageSwapCache(fragment)) {
! stats->decomp_page++;
! return;
! }
#endif
! stats->decomp_swap++;
}
!
! static inline void
! comp_cache_update_comp_stats(unsigned int comp_size, struct page * page)
{
! struct stats_summary * stats = &(compression_algorithms[current_algorithm].stats);
!
! /* update compressed size statistics */
! if (!comp_size)
BUG();
+
+ #ifdef CONFIG_COMP_PAGE_CACHE
+ if (!PageSwapCache(page)) {
+ stats->comp_page++;
+ stats->comp_size_sum_page += comp_size;
+ return;
}
+ #endif
+
+ stats->comp_swap++;
+ stats->comp_size_sum_swap += comp_size;
}
***************
*** 186,192 ****
int
! compress(struct page * page, void * to, unsigned short * algorithm, int state)
{
! struct stats_page comp_page_stats;
void * from = page_address(page);
--- 196,202 ----
int
! compress(struct page * page, void * to, unsigned short * algorithm)
{
! unsigned int comp_size;
void * from = page_address(page);
***************
*** 202,239 ****
spin_lock(&comp_data_lock);
! START_ZEN_TIME(comp_page_stats.myTimer);
! comp_page_stats.comp_size = compression_algorithms[current_algorithm].comp(from, to, PAGE_SIZE/4, &comp_data);
! STOP_ZEN_TIME(comp_page_stats.myTimer, comp_page_stats.comp_cycles);
spin_unlock(&comp_data_lock);
! comp_cache_update_comp_stats(&comp_page_stats, page, state);
*algorithm = current_algorithm;
! if (comp_page_stats.comp_size > PAGE_SIZE)
! comp_page_stats.comp_size = PAGE_SIZE;
! return (comp_page_stats.comp_size);
}
void
! decompress(struct comp_cache_fragment * fragment, struct page * page)
{
- struct stats_page comp_page_stats;
- unsigned int algorithm = WKDM_IDX;
void * from = page_address(fragment->comp_page->page) + fragment->offset;
void * to = page_address(page);
- if (CompFragmentWK4x4(fragment))
- algorithm = WK4X4_IDX;
- else if (CompFragmentLZO(fragment)) {
- algorithm = LZO_IDX;
- comp_data.compressed_size = fragment->compressed_size;
- }
-
spin_lock(&comp_data_lock);
! START_ZEN_TIME(comp_page_stats.myTimer);
compression_algorithms[algorithm].decomp(from, to, PAGE_SIZE/4, &comp_data);
- STOP_ZEN_TIME(comp_page_stats.myTimer, comp_page_stats.decomp_cycles);
spin_unlock(&comp_data_lock);
! comp_cache_update_decomp_stats(algorithm, &comp_page_stats, fragment);
}
--- 212,237 ----
spin_lock(&comp_data_lock);
! comp_size = compression_algorithms[current_algorithm].comp(from, to, PAGE_SIZE/4, &comp_data);
spin_unlock(&comp_data_lock);
! comp_cache_update_comp_stats(comp_size, page);
*algorithm = current_algorithm;
! if (comp_size > PAGE_SIZE)
! comp_size = PAGE_SIZE;
! return comp_size;
}
void
! decompress(struct comp_cache_fragment * fragment, struct page * page, int algorithm)
{
void * from = page_address(fragment->comp_page->page) + fragment->offset;
void * to = page_address(page);
spin_lock(&comp_data_lock);
! comp_data.compressed_size = fragment->compressed_size;
compression_algorithms[algorithm].decomp(from, to, PAGE_SIZE/4, &comp_data);
spin_unlock(&comp_data_lock);
! comp_cache_update_decomp_stats(algorithm, fragment);
}
***************
*** 258,267 ****
/* stats for algorithms */
! for (i = 0; i < NUM_ALGORITHMS; i++) {
memset((void *) &compression_algorithms[i], 0, sizeof(struct stats_summary));
- compression_algorithms[i].stats.comp_size_min = INF;
- compression_algorithms[i].stats.comp_cycles_min = INF;
- compression_algorithms[i].stats.decomp_cycles_min = INF;
- }
/* compression algorithms */
--- 256,261 ----
/* stats for algorithms */
! for (i = 0; i < NUM_ALGORITHMS; i++)
memset((void *) &compression_algorithms[i], 0, sizeof(struct stats_summary));
/* compression algorithms */
***************
*** 296,380 ****
#define current_msg ((algorithm == &compression_algorithms[current_algorithm])?"*":"")
void
print_comp_cache_stats(unsigned short alg_idx, char * page, int * length)
{
! unsigned int compression_ratio, discard_ratio;
! unsigned int mean_size, mean_comp_cycles, mean_decomp_cycles;
! unsigned long total_comp_pages, total_wout_pages, total_decomp_pages, total_faultin_pages;
!
struct comp_alg * algorithm = &compression_algorithms[alg_idx];
struct stats_summary * stats = &algorithm->stats;
! total_comp_pages = stats->comp_swap + stats->comp_page;
! total_decomp_pages = stats->decomp_swap + stats->decomp_page;
! total_wout_pages = stats->swap_out + stats->page_out;
! total_faultin_pages = stats->faultin_swap + stats->faultin_page;
!
if (!total_comp_pages)
return;
-
- *length += sprintf(page + *length, "compressed cache - statistics\n");
- *length += sprintf(page + *length, "algorithm %s%s\n", algorithm->name, current_msg);
! *length += sprintf(page + *length,
! "Compressed Pages: %8lu\n"
! " Swap Cache: %8lu\n"
! " Page Cache: %8lu\n"
! " Dirty: %8lu\n"
! " Clean: %8lu\n"
! "Decompressed Pages: %8lu\n"
! " Swap Cache: %8lu\n"
! " Page Cache: %8lu\n"
! "Written Out: %8lu\n"
! " Swap Cache: %8lu\n"
! " Page Cache: %8lu\n"
! "Faulted In: %8lu\n"
! " Swap Cache: %8lu\n"
! " Page Cache: %8lu\n",
! total_comp_pages,
! stats->comp_swap,
! stats->comp_page,
! stats->comp_dirty,
! stats->comp_clean,
! total_decomp_pages,
! stats->decomp_swap,
! stats->decomp_page,
! total_wout_pages,
! stats->swap_out,
! stats->page_out,
! total_faultin_pages,
! stats->faultin_swap,
! stats->faultin_page);
!
! mean_size = big_division(stats->comp_size_sum, total_comp_pages);
! mean_comp_cycles = big_division(stats->comp_cycles_sum, total_comp_pages);
! mean_decomp_cycles = big_division(stats->decomp_cycles_sum, total_comp_pages);
! compression_ratio = ((big_division(stats->comp_size_sum, total_comp_pages)*100)/PAGE_SIZE);
! discard_ratio = (int) ((stats->discarded_pages * 100)/total_comp_pages);
!
! *length += sprintf(page + *length,
! "Compression\n"
! " MinSize: %8d\n"
! " MaxSize: %8u\n"
! " AvgSize: %8u\n"
! " Ratio: %8d%%\n"
! " MinCycles: %8lu\n"
! " MaxCycles: %8lu\n"
! " AvgCycles: %8u\n"
! "Decompression\n"
! " MinCycles: %8lu\n"
! " MaxCycles: %8lu\n"
! " AvgCycles: %8u\n",
! stats->comp_size_min,
! stats->comp_size_max,
! mean_size,
! compression_ratio,
! stats->comp_cycles_min,
! stats->comp_cycles_max,
! mean_comp_cycles,
! stats->decomp_cycles_min,
! stats->decomp_cycles_max,
! mean_decomp_cycles);
}
--- 290,348 ----
#define current_msg ((algorithm == &compression_algorithms[current_algorithm])?"*":"")
+ #define proportion(part, total) (total?(int) ((part * 100)/(total)):0)
void
print_comp_cache_stats(unsigned short alg_idx, char * page, int * length)
{
! unsigned int compression_ratio_swap, compression_ratio_page, compression_ratio_total;
! unsigned long total_comp_pages, total_sum_comp_pages;
struct comp_alg * algorithm = &compression_algorithms[alg_idx];
struct stats_summary * stats = &algorithm->stats;
! /* swap cache */
! total_comp_pages = stats->comp_swap;
! total_sum_comp_pages = stats->comp_size_sum_swap;
!
! compression_ratio_swap = 0;
! if (stats->comp_swap)
! compression_ratio_swap = ((big_division(stats->comp_size_sum_swap, stats->comp_swap)*100)/PAGE_SIZE);
!
! /* page cache */
! total_comp_pages += stats->comp_page;
! total_sum_comp_pages += stats->comp_size_sum_page;
!
! compression_ratio_page = 0;
! if (stats->comp_page)
! compression_ratio_page = ((big_division(stats->comp_size_sum_page, stats->comp_page)*100)/PAGE_SIZE);
!
! /* total */
if (!total_comp_pages)
return;
! compression_ratio_total = ((big_division(total_sum_comp_pages, total_comp_pages)*100)/PAGE_SIZE);
!
! *length += sprintf(page + *length,
! " algorithm %s%s\n"
! " - compressed pages: %8lu (S: %3d%% P: %3d%%)\n"
! " - decompressed pages: %8lu (S: %3d%% P: %3d%%)\n"
! " - read pages: %8lu (S: %3d%% P: %3d%%)\n"
! " - written pages: %8lu (S: %3d%% P: %3d%%)\n"
! " - compression ratio: %8d%% (S: %3d%% P: %3d%%)\n",
! algorithm->name, current_msg,
! stats->comp_swap + stats->comp_page,
! proportion(stats->comp_swap, total_comp_pages),
! proportion(stats->comp_page, total_comp_pages),
! stats->decomp_swap + stats->decomp_page,
! proportion(stats->decomp_swap, stats->decomp_swap + stats->decomp_page),
! proportion(stats->decomp_page, stats->decomp_swap + stats->decomp_page),
! stats->read_swap + stats->read_page,
! proportion(stats->read_swap, stats->read_swap + stats->read_page),
! proportion(stats->read_page, stats->read_swap + stats->read_page),
! stats->written_swap + stats->written_page,
! proportion(stats->written_swap, stats->written_swap + stats->written_page),
! proportion(stats->written_page, stats->written_swap + stats->written_page),
! compression_ratio_total,
! compression_ratio_swap,
! compression_ratio_page);
}
***************
*** 484,487 ****
--- 452,470 ----
int length = 0, i;
+ length += sprintf(page + length,
+ "compressed cache - statistics\n"
+ " general\n"
+ #ifdef CONFIG_COMP_PAGE_CACHE
+ " - swap (S) and page (P) cache support\n"
+ #else
+ " - swap (S) cache support only\n"
+ #endif
+ " - maximum used size: %6lu KiB\n"
+ " - comp page size: %6lu KiB\n"
+ " - failed allocations: %6lu\n",
+ max_used_num_comp_pages << (comp_page_order + PAGE_SHIFT - 10),
+ PAGE_SIZE >> (10 - comp_page_order),
+ failed_comp_page_allocs);
+
for (i = 0; i < NUM_ALGORITHMS; i++)
print_comp_cache_stats(i, page, &length);
Index: swapin.c
===================================================================
RCS file: /cvsroot/linuxcompressed/linux/mm/comp_cache/swapin.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -C2 -r1.52 -r1.53
*** swapin.c 1 Aug 2002 15:35:46 -0000 1.52
--- swapin.c 7 Aug 2002 18:30:58 -0000 1.53
***************
*** 2,6 ****
* linux/mm/comp_cache/swapin.c
*
! * Time-stamp: <2002-08-01 12:32:01 rcastro>
*
* Linux Virtual Memory Compressed Cache
--- 2,6 ----
* linux/mm/comp_cache/swapin.c
*
! * Time-stamp: <2002-08-07 10:46:04 rcastro>
*
* Linux Virtual Memory Compressed Cache
***************
*** 69,76 ****
}
! void
decompress_fragment(struct comp_cache_fragment * fragment, struct page * page)
{
struct comp_cache_page * comp_page;
if (!fragment)
--- 69,77 ----
}
! unsigned short
decompress_fragment(struct comp_cache_fragment * fragment, struct page * page)
{
struct comp_cache_page * comp_page;
+ int algorithm = get_fragment_algorithm(fragment);
if (!fragment)
***************
*** 87,97 ****
if (compressed(fragment))
! decompress(fragment, page);
else
memcpy(page_address(page), page_address(comp_page->page) + fragment->offset, PAGE_SIZE);
! SetPageUptodate(page);
}
/* caller may hold pagecache_lock (__find_lock_page()) */
int
--- 88,101 ----
if (compressed(fragment))
! decompress(fragment, page, algorithm);
else
memcpy(page_address(page), page_address(comp_page->page) + fragment->offset, PAGE_SIZE);
! SetPageUptodate(page);
! return algorithm;
}
+ extern inline void comp_cache_update_read_stats(unsigned short, struct comp_cache_fragment *);
+
/* caller may hold pagecache_lock (__find_lock_page()) */
int
***************
*** 99,102 ****
--- 103,107 ----
{
struct comp_cache_fragment * fragment;
+ unsigned short algorithm;
int err;
***************
*** 124,131 ****
lock_page(fragment->comp_page->page);
! decompress_fragment(fragment, page);
spin_lock(&comp_cache_lock);
- comp_cache_update_faultin_stats(fragment);
if (CompFragmentTestandClearDirty(fragment))
--- 129,136 ----
lock_page(fragment->comp_page->page);
! algorithm = decompress_fragment(fragment, page);
! comp_cache_update_read_stats(algorithm, fragment);
spin_lock(&comp_cache_lock);
if (CompFragmentTestandClearDirty(fragment))
Index: swapout.c
===================================================================
RCS file: /cvsroot/linuxcompressed/linux/mm/comp_cache/swapout.c,v
retrieving revision 1.69
retrieving revision 1.70
diff -C2 -r1.69 -r1.70
*** swapout.c 1 Aug 2002 14:52:25 -0000 1.69
--- swapout.c 7 Aug 2002 18:30:58 -0000 1.70
***************
*** 2,6 ****
* /mm/comp_cache/swapout.c
*
! * Time-stamp: <2002-08-01 09:00:35 rcastro>
*
* Linux Virtual Memory Compressed Cache
--- 2,6 ----
* /mm/comp_cache/swapout.c
*
! * Time-stamp: <2002-08-07 11:04:43 rcastro>
*
* Linux Virtual Memory Compressed Cache
***************
*** 47,51 ****
if (TryLockPage(buffer_page)) {
if (!wait)
! goto add_to_dirty;
spin_unlock(&swap_buffer_lock);
lock_page(buffer_page);
--- 47,51 ----
if (TryLockPage(buffer_page)) {
if (!wait)
! goto add_to_used;
spin_unlock(&swap_buffer_lock);
lock_page(buffer_page);
***************
*** 61,64 ****
--- 61,65 ----
UnlockPage(buffer_page);
spin_lock(&swap_buffer_lock);
+ goto add_to_used;
}
spin_lock(&swap_buffer_lock);
***************
*** 71,75 ****
--- 72,78 ----
* free the fragment and should simply backout. */
if (PageDirty(buffer_page)) {
+ spin_lock(&comp_cache_lock);
if (fragment) {
+ fragment->swp_buffer = NULL;
spin_lock(&pagecache_lock);
list_del(&fragment->mapping_list);
***************
*** 80,83 ****
--- 83,87 ----
}
ClearPageDirty(buffer_page);
+ spin_unlock(&comp_cache_lock);
goto add_to_free;
}
***************
*** 96,100 ****
list_add_tail(swp_buffer_lh, &swp_free_buffer_head);
return 1;
! add_to_dirty:
list_add(swp_buffer_lh, &swp_used_buffer_head);
}
--- 100,104 ----
list_add_tail(swp_buffer_lh, &swp_free_buffer_head);
return 1;
! add_to_used:
list_add(swp_buffer_lh, &swp_used_buffer_head);
}
***************
*** 179,183 ****
}
! extern void decompress_fragment(struct comp_cache_fragment *, struct page *);
static struct swp_buffer *
--- 183,188 ----
}
! extern unsigned short decompress_fragment(struct comp_cache_fragment *, struct page *);
! extern inline void comp_cache_update_written_stats(unsigned short, struct comp_cache_fragment *);
static struct swp_buffer *
***************
*** 185,188 ****
--- 190,194 ----
struct page * buffer_page;
struct swp_buffer * swp_buffer;
+ unsigned short algorithm;
swp_buffer = find_free_swp_buffer(fragment, gfp_mask);
***************
*** 196,201 ****
lock_page(fragment->comp_page->page);
! decompress_fragment(fragment, buffer_page);
UnlockPage(fragment->comp_page->page);
buffer_page->flags &= (1 << PG_locked);
--- 202,208 ----
lock_page(fragment->comp_page->page);
! algorithm = decompress_fragment(fragment, buffer_page);
UnlockPage(fragment->comp_page->page);
+ comp_cache_update_written_stats(algorithm, fragment);
buffer_page->flags &= (1 << PG_locked);
***************
*** 293,298 ****
}
- comp_cache_update_writeout_stats(fragment);
-
if (nrpages)
continue;
--- 300,303 ----
|