[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 ---- |