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