Subject: Dump Page Cache state for out of memory

From: Steffen Rumler <[email-masked]>
Date: Wed, 19 Jan 2005 11:45:13 +0100

Hi,

I'm using the following code in order to
dump the state concerning the Page Cache
related to filesystem I/O, from out_of_memory().

Steffen

--

oo_kill.c:

...
typedef struct {
     unsigned long locked;    /* number locked pages */
     unsigned long clean;     /* number clean pages */
     unsigned long dirty;     /* number dirty pages */
     struct super_block *sb;  /* related superblock */
} dump_page_cache_entry_t;

static dump_page_cache_entry_t dump_page_cache_arr[16];

static dump_page_cache_entry_t *
get_dump_cache_entry (struct super_block *sb)
{
     int i;

     for(i=0; i < 16; i++){
         if(dump_page_cache_arr[i].sb == sb)  return &dump_page_cache_arr[i];
         if(dump_page_cache_arr[i].sb == NULL){
             dump_page_cache_arr[i].sb = sb;
             return &dump_page_cache_arr[i];
         }
     }
     return &dump_page_cache_arr[15];
}

/*  dump page cache state
  */

static void dump_page_cache (void)
{
     int i;
     struct page **p = page_hash_table;
     struct page  *q;
     unsigned long flags;
     unsigned long total  = 0;
     dump_page_cache_entry_t *ep;
     struct super_block *sb;

     for(i=0; i<PAGE_HASH_SIZE; i++){

         for(q=*p;q;q=q->next_hash){

             total++;
             if(q->mapping  && q->mapping->host && (sb=q->mapping->host->i_sb)){

                 flags = q->flags;
                 ep = get_dump_cache_entry(sb);

                 if((flags & (1 << PG_locked))){
                     ep->locked++;
                 }else{
                     if((flags & (1 << PG_dirty))){
                         if(flags & (1 << PG_uptodate)){
                             ep->dirty++;
                         }
                     }else{
                         ep->clean++;
                     }
                 }
             }
         }
         p++;
     }

     printk(KERN_EMERG "%s (%d) %s(): Page Cache Status:\n", __FILE__, __LINE__, __func__);
     for(i=0; i<16; i++){

         dump_page_cache_entry_t *ce = &dump_page_cache_arr[i];

         if(ce->sb){

             printk(KERN_EMERG "%14s  clean: %-10d  locked: %-10d  dirty: %d\n",
                     ce->sb->s_type ? ce->sb->s_type->name : "???",
                     ce->clean, ce->locked, ce->dirty);
         }else{
             break;
         }
     }
     printk("%14s %d\n", "total", total);
}

...

void out_of_memory(void)
{
    ...
    dump_page_cache();
    ...
}