[lc-checkins] CVS: linux/include/linux comp_cache.h,1.99,1.100
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/include/linux In directory usw-pr-cvs1:/tmp/cvs-serv28260/include/linux Modified Files: comp_cache.h 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: comp_cache.h =================================================================== RCS file: /cvsroot/linuxcompressed/linux/include/linux/comp_cache.h,v retrieving revision 1.99 retrieving revision 1.100 diff -C2 -r1.99 -r1.100 *** comp_cache.h 1 Aug 2002 14:52:25 -0000 1.99 --- comp_cache.h 7 Aug 2002 18:30:58 -0000 1.100 *************** *** 2,6 **** * linux/mm/comp_cache.h * ! * Time-stamp: <2002-08-01 09:49:34 rcastro> * * Linux Virtual Memory Compressed Cache --- 2,6 ---- * linux/mm/comp_cache.h * ! * Time-stamp: <2002-08-07 10:51:24 rcastro> * * Linux Virtual Memory Compressed Cache *************** *** 35,39 **** #define MAX_COMPRESSED_SIZE 4500 ! extern unsigned long num_comp_pages, num_fragments, num_swapper_fragments, new_num_comp_pages, min_num_comp_pages, max_num_comp_pages, zone_num_comp_pages; struct pte_list { --- 35,40 ---- #define MAX_COMPRESSED_SIZE 4500 ! extern unsigned long num_comp_pages, num_fragments, num_swapper_fragments, new_num_comp_pages, zone_num_comp_pages; ! extern unsigned long min_num_comp_pages, max_num_comp_pages, max_used_num_comp_pages; struct pte_list { *************** *** 112,115 **** --- 113,117 ---- /* adaptivity.c */ #ifdef CONFIG_COMP_CACHE + extern unsigned long failed_comp_page_allocs; int grow_on_demand(void); int shrink_on_demand(struct comp_cache_page *); *************** *** 211,253 **** #define DISCARD_MARK 0.80 - typedef struct { - union { - volatile unsigned long long int timerValue; - struct { - volatile unsigned long int timerValueLow; - volatile unsigned long int timerValueHigh; - } separated; - } startTime; - - union { - volatile unsigned long long int timerValue; - struct { - volatile unsigned long int timerValueLow; - volatile unsigned long int timerValueHigh; - } separated; - } stopTime; - } zenTimerType; - - struct stats_summary { - unsigned long long comp_size_sum; - unsigned int comp_size_max, comp_size_min; - unsigned long long comp_cycles_sum, decomp_cycles_sum; - unsigned long comp_cycles_max, comp_cycles_min; - unsigned long decomp_cycles_max, decomp_cycles_min; - unsigned long comp_swap, decomp_swap; - unsigned long comp_page, decomp_page; - unsigned long comp_dirty, comp_clean; - unsigned long swap_out, page_out; - unsigned long faultin_swap, faultin_page; - unsigned long discarded_pages; - }; - - struct stats_page { - unsigned int comp_size; /* compressed size of a page */ - unsigned long comp_cycles; /* cycles taken for compression */ - unsigned long decomp_cycles; /* cycles taken for decompression */ - zenTimerType myTimer; /* used to calculate the cycles */ - }; - struct comp_alg_data { /* WKdm and WK4x4 */ --- 213,216 ---- *************** *** 271,306 **** struct comp_alg_data * data); - struct comp_alg { - char name[6]; - compress_function_t * comp; - decompress_function_t * decomp; - struct stats_summary stats; - }; - - #define START_ZEN_TIME(userTimer) { \ - userTimer.startTime.timerValue = 0; \ - userTimer.stopTime.timerValue = 0; \ - asm volatile ("rdtsc; movl %%edx, %0; movl %%eax, %1" \ - : "=r" (userTimer.startTime.separated.timerValueHigh), \ - "=r" (userTimer.startTime.separated.timerValueLow) \ - : \ - : "%edx", "%eax"); } - - #define STOP_ZEN_TIME(userTimer,totalTime) { \ - asm volatile ("rdtsc; movl %%edx, %0; movl %%eax, %1" \ - : "=r" (userTimer.stopTime.separated.timerValueHigh), \ - "=r" (userTimer.stopTime.separated.timerValueLow) \ - : \ - : "%edx", "%eax"); \ - totalTime = userTimer.stopTime.timerValue - userTimer.startTime.timerValue; } - /* proc.c */ #ifdef CONFIG_COMP_CACHE - void comp_cache_update_page_comp_stats(struct page *); - void comp_cache_update_writeout_stats(struct comp_cache_fragment *); - void comp_cache_update_faultin_stats(struct comp_cache_fragment *); void set_fragment_algorithm(struct comp_cache_fragment *, unsigned short); ! void decompress(struct comp_cache_fragment *, struct page *); ! int compress(struct page *, void *, unsigned short *, int); void __init comp_cache_algorithms_init(void); --- 234,242 ---- struct comp_alg_data * data); /* proc.c */ #ifdef CONFIG_COMP_CACHE void set_fragment_algorithm(struct comp_cache_fragment *, unsigned short); ! void decompress(struct comp_cache_fragment *, struct page *, int); ! int compress(struct page *, void *, unsigned short *); void __init comp_cache_algorithms_init(void); *************** *** 573,576 **** --- 509,514 ---- int comp_cache_hist_read_proc(char *, char **, off_t, int, int *, void *); int comp_cache_frag_read_proc(char *, char **, off_t, int, int *, void *); + int get_fragment_algorithm(struct comp_cache_fragment *); + #endif /* _LINUX_COMP_CACHE_H */ |