Debugging
=========

Debug code of NILFS is disabled by default.  We can enable it
as needed:

 1. Uncomment the following line of fs/Makefile.

    ... 
    ifndef CONFIG_NILFS
      EXTERNAL_BUILD=y
      CONFIG_NILFS=m
      # Uncomment below to do debug build.
   -  #CONFIG_NILFS_DEBUG=y
   +  CONFIG_NILFS_DEBUG=y
    endif

 2. Do rebuild and re-install.

    $ make clean
    $ make
    # su
    # make reinstall


This modification allows NILFS to print debug messages to the
log file (e.g. /var/log/syslog) or to the console.
It also inserts some code checking for resource leaks.

As developer's contraptions, code of NILFS includes some debug
counters and trace macros used in exhaustive checks.  These 
would help to look into leak or deadlock problems.

In addition, the code of NILFS uses many assertions.  They are
described using common kernel routines such as BUG() or
BUG_ON(), and are typically enabled independently of the debug
option.

If you find an assertion message generated by NILFS,
please let us know.


Debug message
=============

The debug message is classified according to internal
facilities:


  Facility          Description              Macro used to
  (Class)                                    print messages
  -------------------------------------------------------------
  fs                Common function or       nilfs_debug()
                    neutral code.

  page              Page operations          page_debug()

  shrinker          Shrinker for a           shrink_debug()
                    dedicated page cache 

  segment           Segment constructor      seg_debug()      

  seginfo           Summary of the segment
                    built by the segment     ---
                    constructor.

  inode             Inode operations         inode_debug()

  recovery          Recovery logic           recovery_debug()

  gc                Cleaner or               gc_debug()
                    segment allocator
  -------------------------------------------------------------

Each debug message is printed by the corresponding macro shown
in the table; they give a convenient way to classify these
messages.

The debug messages are graded into four levels (0 ~ 3) 
according to the amount of log data that they generate or how
they are detail.  This level is specified in the first argument
of the macros.  The rest of arguments is equivalent to those of 
printk().

Threshold values decide whether each debug message is printed
or not; messages with less than or equal to the threshold is
printed. messages of level 0 are always printed.  The default
value of the threshold is level 1.

For example, start and end timings of the segment construction
are traceable by the following seg_debug() macros.

        ...
        seg_debug(1, "begin\n");
        err = __construct_segment(sbi, sci);
        seg_debug(1, "end (stage=%d)\n", sci->sc_stage);

They insert their messages in the kernel log as follows.
(In the log file, time stamps and other information are also
inserted.)

 ...
 NILFS(segment) nilfs_segctor_construct: begin
 NILFS(seginfo) pseg(blk=1609,len=6) on fullseg(ind=1,blk=1025
 ->2047)
 NILFS(segment) write_segment: submitted a segment
 NILFS(segment) end_seg_bio_write: completed a segment
 NILFS(segment) __construct_segment: submitted all segments
 NILFS(segment) nilfs_segctor_construct: end (stage=6)
 ...

On the other hand, timing adding a buffer head to a segment
is described with a level 3 message; it's too detail and is
suppressed in ordinary practice.

        ...
        seg_debug(3, "adding bh(%p) to bh_arr[%d]\n",
                  bh, pbh - &SC_BH(sci, 0));
        get_bh(bh);
        *pbh = bh;
        ...

Each threshold value can be changed by the following debug
options:


      Debug             Levels of the message
      Options           to be printed
      ---------------------------------------
      -n                level 0 only           ^  Quiet
                                               |
      -v     (default)  level 0, 1             |
                                               |
      -vv               level 0-2              |
                                               |
      -vvv              level 0-3              v  Verbose
      ---------------------------------------


These options can be read or set through a proc-fs file
'/proc/fs/nilfs/debug_option'.

It shows a state of debug options in the following format.

  [-n|-vv|-vvv] <facility1> [-n|-vv|-vvv] <facility2> ...

For reads, the state of all debug options are printed:

   # modprobe nilfs
   # cd /proc/fs/nilfs
   # cat debug_option
   -v fs -v page -v shrinker -v segment -v seginfo -v inode -v
   recovery -v gc
   ...

(The specification was changed at NILFS-1.0.10; only the options
 not in the default state were printed in the older versions. )

To change the threshold, write a new state into 'debug_option'
in the same format.

   # echo "-vv segment" > debug_option
   # cat debug_option
   -v fs -v page -v shrinker -vv segment -v seginfo -v inode -v
   recovery -v gc

As above, the writing to the 'debug_option' is treated as
incremental.
(The sysfs does not support appending; redirections using '>>'
 will fail.)

To change all facilities at the same time, use a virtual 
facility 'all':

   # echo "-n all" > debug_option
   # cat debug_option
   -n fs -n page -n shrinker -n segment -n seginfo -n inode -n
   recovery -n gc

The debug options are processed from left to right.  So, the
right option overrides the left option for overlapping
designations.

   # echo "-v fs -n all -vv page" > debug_option
   # cat debug_option
   -n fs -vv page -n shrinker -n segment -n seginfo -n inode -n
   recovery -n gc


Debug counters
==============

The debug counters are enabled by changing the following
definitions in fs/Makefile. All debug counters are disabled by
default. To enable the debug counter, replace -U with -D in the
corresponding line:

  # Debug counters
  EXTRA_CFLAGS += -U NILFS_PAGE_COUNT
 -EXTRA_CFLAGS += -U NILFS_KMALLOC_COUNT
 +EXTRA_CFLAGS += -D NILFS_KMALLOC_COUNT
  EXTRA_CFLAGS += -U NILFS_BIO_COUNT
  EXTRA_CFLAGS += -U NILFS_SLAB_COUNT
  EXTRA_CFLAGS += -U NILFS_KMAP_COUNT
  EXTRA_CFLAGS += -U NILFS_ALLOCPAGE_COUNT


Available switches are as follows:


  Macro switching
  the debug counter        Description
  -------------------------------------------------------------
  NILFS_KMALLOC_COUNT      Counts memory allocations and
                           de-allocations by kmalloc()/kfree().

  NILFS_BIO_COUNT          Counts BIO allocations and
                           de-allocation.

  NILFS_SLAB_COUNT         Counts slab allocations and
                           de-allocations by kmem_cache_alloc()
                           and kmem_cache_free()

  NILFS_KMAP_COUNT         Counts kmap()/kunmap() and their 
                           variants.

  NILFS_ALLOCPAGE_COUNT    Counts page allocations and
                           de-allocations by alloc_pages() and
                           free_pages().

  NILFS_PAGE_COUNT         Counts allocations and releases of
                           file pages and inode pages.

  NILFS_BH_COUNT_DETAIL    Counts put operation for the buffer
                           heads by use.
  -------------------------------------------------------------

First five switches replace allocators and de-allocators with 
the macro wrapping original functions. The wrapped code
increases the debug counters.

The last two switches enable monitoring of events by the debug
code inserted diligently on the source files of NILFS.

The value of counters are shown in the /proc/fs/nilfs/memstat
except for NILFS_BH_COUNT_DETAIL; the counters inserted by
NILFS_BH_COUNT_DETAIL are shown in /proc/fs/nilfs/nputblk.


Trace macros
============

The following switches replace operations such as get()/put()
or lock()/unlock() with wrapper macros that involve logging to
the system log.

                  
  Trace options            Description
  -------------------------------------------------------------
  NILFS_BH_DEBUG           Logs the buffer head operations such
                           as get_bh(), put_bh(), brelse(), and
                           bforget().

  NILFS_SEMAPHORE_DEBUG    Logs P(=down) and V(=up) operations
                           of semaphores and reader/writer
                           variants.

  NILFS_SPINLOCK_DEBUG     Logs lock and unlock operations of
                           standard spinlock and irq variants.

  NILFS_LOCK_BUFFER_DEBUG  Logs lock_buffer() and
                           unlock_buffer().

  NILFS_LOCK_PAGE_DEBUG    Logs lock_page() and unlock_page().

  NILFS_KMALLOC_DEBUG      Logs kmalloc() and kfree().
  -------------------------------------------------------------

These switches are defined in fs/Makefile.

They print a large amount of data in the log, and may disturb
the log specially on the SMP-based machines.

---
debug.txt,v 1.9 2006/07/14 07:46:37 ryusuke Exp
