Slab pool should by added to "Buffers"

From: miho@centrum.cz
Date: Thu Aug 15 2002 - 08:12:36 EST


Slab pool will be reclaimed when the system needs it so I think
that reporting this memory as "Used" without adding it
to "Buffers" in /proc/meminfo could lead to a confusion and
memory leak reports (After 'locate -u -c', 'free' says that i
have 200MB free memory less than before...). I tested our server
under various workloads and I needed to know exact ammount of
free physical memory to fine-tune some programs but I found
no program that uses information from both meminfo and slabinfo.
So I created a tiny utility 'rfree'
http://sourceforge.net/projects/rfree/
(output looks like 'free' but i replaced unused "Shared"
with "Slab").

This solved the problem (partly), but then I had to use vmstat
and it "pops up" again. I think better place to solve this is
kernel so that all programs that use meminfo will show correct
information without reprogramming.
I've tried that:

Add to mm/slab.c :

int slab_size(void)
{
 kmem_cache_t *cachep;
 struct list_head *q;
 struct list_head *p;
 slab_t *slabp;
 unsigned long num_slabs=0;

 down(&cache_chain_sem);
 list_for_each(p,&cache_chain) {
  cachep = list_entry(p, kmem_cache_t, next);

  spin_lock_irq(&cachep->spinlock);
  list_for_each(q,&cachep->slabs_full) {
   slabp = list_entry(q, slab_t, list); //
   if (slabp->inuse != cachep->num) //remove?
    BUG(); //
   num_slabs++;
  }
  list_for_each(q,&cachep->slabs_partial) {
   slabp = list_entry(q, slab_t, list); //
   if (slabp->inuse == cachep->num || !slabp->inuse) //remove?
    BUG(); //
   num_slabs++;
  }
  list_for_each(q,&cachep->slabs_free) {
   slabp = list_entry(q, slab_t, list); //
   if (slabp->inuse) //remove?
    BUG(); //
   num_slabs++;
  }
  spin_unlock_irq(&cachep->spinlock);
 }
 up(&cache_chain_sem);

 return num_slabs;
}

Add to include/linux/slab.h :

extern int slab_size(void);

Replace in fs/proc/proc_misc.c :

static int meminfo_read_proc(char *page, char **start, off_t off,
     int count, int *eof, void *data)
{
 struct sysinfo i;
 int len;
 int pg_size ;
 int committed;
 int slab;

 /* FIXME: needs to be in headers */
 extern atomic_t vm_committed_space;

/*
 * display in kilobytes.
 */
#define K(x) ((x) << (PAGE_SHIFT - 10))
#define B(x) ((unsigned long long)(x) << PAGE_SHIFT)
 si_meminfo(&i);
 si_swapinfo(&i);
 slab=slab_size();

 pg_size = atomic_read(&page_cache_size) - i.bufferram ;
 committed = atomic_read(&vm_committed_space);

 len = sprintf(page, " total: used: free: shared:
buffers:
cached:\n"
  "Mem: %8Lu %8Lu %8Lu %8Lu %8Lu %8Lu\n"
  "Swap: %8Lu %8Lu %8Lu\n",
  B(i.totalram), B(i.totalram-i.freeram), B(i.freeram),
  B(i.sharedram), B(i.bufferram+slab),
  B(pg_size), B(i.totalswap),
  B(i.totalswap-i.freeswap), B(i.freeswap));
 /*
  * Tagged format, for easy grepping and expansion.
  * The above will go away eventually, once the tools
  * have been updated.
  */
 len += sprintf(page+len,
  "MemTotal: %8lu kB\n"
  "MemFree: %8lu kB\n"
  "MemShared: %8lu kB\n"
  "Buffers: %8lu kB\n"
  "Cached: %8lu kB\n"
  "SwapCached: %8lu kB\n"
  "Active: %8u kB\n"
  "Inact_dirty: %8u kB\n"
  "Inact_clean: %8u kB\n"
  "Inact_target: %8u kB\n"
  "HighTotal: %8lu kB\n"
  "HighFree: %8lu kB\n"
  "LowTotal: %8lu kB\n"
  "LowFree: %8lu kB\n"
  "SwapTotal: %8lu kB\n"
  "SwapFree: %8lu kB\n"
  "Committed_AS: %8u kB\n"
  "SlabPool: %8u kB\n",
  K(i.totalram),
  K(i.freeram),
  K(i.sharedram),
  K(i.bufferram+slab),
  K(pg_size - swapper_space.nrpages),
  K(swapper_space.nrpages),
  K(nr_active_pages),
  K(nr_inactive_dirty_pages),
  K(nr_inactive_clean_pages),
  K(inactive_target()),
  K(i.totalhigh),
  K(i.freehigh),
  K(i.totalram-i.totalhigh),
  K(i.freeram-i.freehigh),
  K(i.totalswap),
  K(i.freeswap),
  K(committed),
  K(slab));

 return proc_calc_metrics(page, start, off, count, eof, len);
#undef B
#undef K
}

It works well for me but I am a newbie so I would like to know if
it is correct (SMP-safe and so on) and wethear there will be any
program in "userland" broken (except rfree of course ;-) after
that change.

I know that it is hard to compute exactly "ammount of free
memory" in VM OS but IMHO "free+cache+buffers+slab" is better
shot than just "free+cache+buffers". And I also know that adding
Slab to Buffers isn't clean, but Slab actualy behawes very
similar to Buffers in memory pressure situations and it won't
break tons of utilities applets and so on unlike adding an
additional value to meminfo.

Regards
Michal

--------------------
Žena v centru pozornosti na http://zena.centrum.cz

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu Aug 15 2002 - 22:00:39 EST