=========================================================
ϡ
Linux-3.6/Documentation/filesystems/gfs2-glocks.txt Ǥ
Ρ JF ץ < http://linuxjf.sourceforge.jp/ >
  2012/10/02
  Seiji Kaneko < skaneko at a2 dot mbn dot or dot jp >
=========================================================
#                   Glock internal locking rules
#                  ------------------------------
                  Glock å롼
                  ----------------------

#This documents the basic principles of the glock state machine
#internals. Each glock (struct gfs2_glock in fs/gfs2/incore.h)
#has two main (internal) locks:
ʸϡglock ơȥޥδŪˤ򵭺ܤΤǤ
 glock (fs/gfs2/incore.h  gfs2_glock ¤) ĤΥᥤ () 
åäƤޤ

# 1. A spinlock (gl_spin) which protects the internal state such
#    as gl_state, gl_target and the list of holders (gl_holders)
# 2. A non-blocking bit lock, GLF_LOCK, which is used to prevent other
#    threads from making calls to the DLM, etc. at the same time. If a
#    thread takes this lock, it must then call run_queue (usually via the
#    workqueue) when it releases it in order to ensure any pending tasks
#    are completed.
1. gl_spin ԥåΥå gl_stategl_targetåݻԤ
  ꥹ gl_holders ʤɤݸѤޤ
2. GLF_LOCK Υ֥å󥰥ӥåȥåΥåϡDLM ʤɤθƤӽФ
  ¾ΥåɤƱ˵ʤ褦¾ԤѤޤå
  Υå褦Ȥ硢åˤϰ³ run_queue 
   (̾ workqueue ͳ) ƤӽФơųݤΥδλǧ
   Фʤޤ

#The gl_holders list contains all the queued lock requests (not
#just the holders) associated with the glock. If there are any
#held locks, then they will be contiguous entries at the head
#of the list. Locks are granted in strictly the order that they
#are queued, except for those marked LM_FLAG_PRIORITY which are
#used only during recovery, and even then only for journal locks.
gl_holder ꥹȤˤϡñ˥åݻԤǤϤʤglock ˴Ϣ
塼äƤΥå׵᤬ǼޤݻƤå
硢ꥹȤƬϢ³ȥȤƳǼޤå㳰Τ
ʤ˥塼äͿޤ㳰ȤϡꥫХˤΤ
Ѥ LM_FLAGS_PRIORITY ե饰ΤĤ׵ǡоݤȤΤϥ㡼
åΤߤǤ

#There are three lock states that users of the glock layer can request,
#namely shared (SH), deferred (DF) and exclusive (EX). Those translate
#to the following DLM lock modes:
glock 쥤ѼԤ׵ǽʥå֤ϻĤޤͭ (SH:Shared)
ٱå (DF:Deferred)¾ (EX:Exclusive) Ǥ
 DLM å֤˰ʲΤ褦ȿǤޤ

#Glock mode    | DLM lock mode
#------------------------------
#    UN        |    IV/NL  Unlocked (no DLM lock associated with glock) or NL
#    SH        |    PR     (Protected read)
#    DF        |    CW     (Concurrent write)
#    EX        |    EX     (Exclusive)
 Glock ⡼ | DLM å⡼
------------------------------
    UN        |    IV/NL  åʤ (glock ˴Ϣ DLM åʤ) ޤ NL
    SH        |    PR     (ݸ줿ɤ߽Ф)
    DF        |    CW     (¹ԥ饤)
    EX        |    EX     (¾)

#Thus DF is basically a shared mode which is incompatible with the "normal"
#shared lock mode, SH. In GFS2 the DF mode is used exclusively for direct I/O
#operations. The glocks are basically a lock plus some routines which deal
#with cache management. The following rules apply for the cache:
Τ褦ˡŪˤ DF ϡ̾Ρ׶ͭåǤ SH Ȥߴζͭ
⡼ɤȤ֤ŤǤGFS2 ǤϡDF ⡼ɤľ I/O (Direct I/O) Ǥ
ѤƤޤ glock ϴŪˤϡå˥åԤ
äΤǤåˤϰʲε§ŬѤޤ

#Glock mode   |  Cache data | Cache Metadata | Dirty Data | Dirty Metadata
#--------------------------------------------------------------------------
#    UN       |     No      |       No       |     No     |      No
#    SH       |     Yes     |       Yes      |     No     |      No
#    DF       |     No      |       Yes      |     No     |      No
#    EX       |     Yes     |       Yes      |     Yes    |      Yes
 Glock ⡼ | Cacheǡ | Cache᥿ǡ| ƥǡ | ƥ᥿ǡ
#---------------------------------------------------------------------------------
#    UN       |       |          |          |      
#    SH       |    Ϥ     |      Ϥ      |          |      
#    DF       |       |      Ϥ      |          |      
#    EX       |    Ϥ     |      Ϥ      |    Ϥ        |      Ϥ

#These rules are implemented using the various glock operations which
#are defined for each type of glock. Not all types of glocks use
#all the modes. Only inode glocks use the DF mode for example.
ε§ϡ glock Ƥ͡ glock ѤƼ
Ƥޤ͡ʥפ glock ˤϡ⡼ɤäƤʤ
Τ⤢ޤ㤨 inode glock Τߤ DF ⡼ɤѤޤ

#Table of glock operations and per type constants:
glock ȡΰ򼨤ޤ

#Field            | Purpose
#----------------------------------------------------------------------------
#go_xmote_th      | Called before remote state change (e.g. to sync dirty data)
#go_xmote_bh      | Called after remote state change (e.g. to refill cache)
#go_inval         | Called if remote state change requires invalidating the cache
#go_demote_ok     | Returns boolean value of whether its ok to demote a glock
#                 | (e.g. checks timeout, and that there is no cached data)
#go_lock          | Called for the first local holder of a lock
#go_unlock        | Called on the final local unlock of a lock
#go_dump          | Called to print content of object for debugfs file, or on
#                 | error to dump glock to the log.
#go_type          | The type of the glock, LM_TYPE_.....
#go_callback	 | Called if the DLM sends a callback to drop this lock
#go_flags	 | GLOF_ASPACE is set, if the glock has an address space
#                 | associated with it
  ե     | Ū
----------------------------------------------------------------------------
go_xmote_th      | ⡼Ȥξѹ˸ƤФޤ (: ƥǡ sync ʤ)
go_xmote_bh      | ⡼Ȥξѹθ˸ƤФޤ (: åκɤ߹ߤʤ)
go_inval         | ⡼ȤξѲˤꡢå̵ɬפ˸
Фޤ
go_demote_ok     | glock γǽǤ뤫ɤ֤ͤޤ
                 | (: ॢȤåå夵줿ǡʤȤǧ)
go_lock          | ǤΥåκǽ (Υޥ¾ïåäƤʤ)
                 | ˸ƤФޤ
go_unlock        | ǤΥåκǸγ˸ƤФޤ
go_dump          | debugfs եΥ֥ȤƤɽ䡢
		 | ˥ glock ͤפݤ˸ƤФޤ
go_type          | glock μ̡LM_TYPE_.....
go_callback	 | DLM ΥåȤ˥Хåä˸ƤФޤ
go_flags	 | glock ˥ɥ쥹֤ϢդƤˡGLOF_ASPACE å
		 | ޤ

#The minimum hold time for each lock is the time after a remote lock
#grant for which we ignore remote demote requests. This is in order to
#prevent a situation where locks are being bounced around the cluster
#from node to node with none of the nodes making any progress. This
#tends to show up most with shared mmaped files which are being written
#to by multiple nodes. By delaying the demotion in response to a
#remote callback, that gives the userspace program time to make
#some progress before the pages are unmapped.
ƥåκǾۡɻ֤Ȥϡ⡼ȤΥåμĸ塢⡼Ȥ
γ׵̵뤹֤Ǥϡå饹ǥΡɴ֤ǤΥԥ
ݥ򷫤֤ʤޤʤʤ򤱤뤿ΤΤǤΤ褦ʶ
ϡʣΥΡɤ񤭹ޤ붦ͭ mmap եǵ꤬Ǥ
⡼ȤΥХåˤåβ٤餻뤳Ȥǡ桼
֤Υץ˥ڡޥåפ򾯤Ǥʤޤ뤳Ȥ
褦;͵Ϳޤ

#There is a plan to try and remove the go_lock and go_unlock callbacks
#if possible, in order to try and speed up the fast path though the locking.
#Also, eventually we hope to make the glock "EX" mode locally shared
#such that any local locking will be done with the i_mutex as required
#rather than via the glock.
go_lock  go_unlock Хå򡢲ǽʸ¤︺褦Ȥײ褬
ϥåϢǹ®ѥ®٤뤳ȤŪǤޤ
glock "EX" ⡼ɤǶͭơǤΥå glock ͳǤ
ʤ i_mutex ǹԤȤ˾Ūײ⤢ޤ

#Locking rules for glock operations:
glock Υåݻ롼

#Operation     |  GLF_LOCK bit lock held |  gl_spin spinlock held
#-----------------------------------------------------------------
#go_xmote_th   |       Yes               |       No
#go_xmote_bh   |       Yes               |       No
#go_inval      |       Yes               |       No
#go_demote_ok  |       Sometimes         |       Yes
#go_lock       |       Yes               |       No
#go_unlock     |       Yes               |       No
#go_dump       |       Sometimes         |       Yes
#go_callback   |       Sometimes (N/A)   |       Yes
          |  GLF_LOCK ӥåȤݻ  |  gl_spin ԥåݻ
-----------------------------------------------------------------
go_xmote_th   |       ɬ              |       
go_xmote_bh   |       ɬ              |       
go_inval      |       ɬ              |       
go_demote_ok  |       ˤ        |       ɬ
go_lock       |       ɬ              |       
go_unlock     |       ɬ              |       
go_dump       |       ˤ        |       ɬ
go_callback   |    ˤ (Ŭѳ)  |       ɬ

#N.B. Operations must not drop either the bit lock or the spinlock
#if its held on entry. go_dump and do_demote_ok must never block.
#Note that go_dump will only be called if the glock's state
#indicates that it is caching uptodate data.
:ˤϡϻǻäƤӥåȥå䥹ԥåǲ
ƤϤޤgo_dump  do_demote_ok ϥ֥åƤϤޤ
go_dump ϡglock ξ֤ǿΥǡ򥭥å夷ƤʬäƤ
ˤΤ߸ƤФ뤳ȤդƤ

#Glock locking order within GFS2:
GFS2  glock åʲ˼ޤ

# 1. i_mutex (if required)
# 2. Rename glock (for rename only)
# 3. Inode glock(s)
#    (Parents before children, inodes at "same level" with same parent in
#     lock number order)
# 4. Rgrp glock(s) (for (de)allocation operations)
# 5. Transaction glock (via gfs2_trans_begin) for non-read operations
# 6. Page lock  (always last, very important!)
 1. i_mutex (ɬפʾ)
 2. rename glock (͡ξΤ)
 3. Inode glock
     (ƤҤ˥åƱƤƱؤˤ inode Ȥå)
 4. Rgrp glock (Ƥȳ)
 5. ɤ߽ФԤʤˤĤơTransaction glock (gfs2_trans_begin ͳ)
 6. ڡå (˺Ǹǡ!)

#There are two glocks per inode. One deals with access to the inode
#itself (locking order as above), and the other, known as the iopen
#glock is used in conjunction with the i_nlink field in the inode to
#determine the lifetime of the inode in question. Locking of inodes
#is on a per-inode basis. Locking of rgrps is on a per rgrp basis.
#In general we prefer to lock local locks prior to cluster locks.
inode Ĥ glock ޤ inode ΤؤΥ򰷤 (
åϾ嵭ΤȤ)¾ (iopen glock) ϡinode  i_nlink ե
Ȥ߹碌ơоݤȤʤ inode μ̿ȽǤΤ˻Ȥޤinode Υ
åϡinode ˹Ԥޤrgrp ؤΥå rgrp ˹Ԥޤ
ޤ̾ϥ饹ååͥ褷ƻѤ褦ˤޤ


#                            Glock Statistics
#                           ------------------
			     Glock ׾
			   ------------------

#The stats are divided into two sets: those relating to the
#super block and those relating to an individual glock. The
#super block stats are done on a per cpu basis in order to
#try and reduce the overhead of gathering them. They are also
#further divided by glock type. All timings are in nanoseconds.
׾ϡѥ֥åϢΤΤȸġ glock ˴ϢΤ
ʬǤޤѥ֥åϢ׾ϡΥХإåɷڸ
Τ CPU ˹ԤޤϹ glock פʬवޤ
ñ̤ƥʥäǤ

#In the case of both the super block and glock statistics,
#the same information is gathered in each case. The super
#block timing statistics are used to provide default values for
#the glock timing statistics, so that newly created glocks
#should have, as far as possible, a sensible starting point.
#The per-glock counters are initialised to zero when the
#glock is created. The per-glock statistics are lost when
#the glock is ejected from memory.
ѥ֥å glock ξ׾󤬼ˤϡơƱ
ޤѥ֥åλ֤˴ؤϡglock λ֤˴ؤ
ɸͤ󶡤ΤѤƤꡢ줿 glock ФƤ
ǽʸ¤ʽͤꤵ褦ˤʤäƤޤglock ˤ륫
 glock  0 ˽ޤglock ׾ϡglock 
줿ݤ˾õޤ

#The statistics are divided into three pairs of mean and
#variance, plus two counters. The mean/variance pairs are
#smoothed exponential estimates and the algorithm used is
#one which will be very familiar to those used to calculation
#of round trip times in network code. See "TCP/IP Illustrated,
#Volume 1", W. Richard Stevens, sect 21.3, "Round-Trip Time Measurement",
#p. 299 and onwards. Also, Volume 2, Sect. 25.10, p. 838 and onwards.
#Unlike the TCP/IP Illustrated case, the mean and variance are
#not scaled, but are in units of integer nanoseconds.
׾ϡʿ͡ʬ 3 Ĥ 2 ĤΥ󥿤ʤޤʿ͡ʬ
ȤߤϡŪ˶ѤԤƤޤȤƤ륢르ꥺϡ
ͥåȥɤǤΥ饦ɥȥå׻֤η׻˴Ƥͤˤߤ
ΤǤ礦W. Richard Stevens  "TCP/IP Illustrated, Volume 1" 
21.3  "Round-Trip Time Measurement" p.299 ƤȡVolume 2 
25.10  p.838 Ƥ򻲾Ȥ
TCP/IP Illusrated ξȤϰۤʤꡢʿͤʬϥʥñ̤ͤǡ
ĴϤޤ

#The three pairs of mean/variance measure the following
#things:
ʿ/ʬ 3 ĤȤϰʲ̤Ǥ

# 1. DLM lock time (non-blocking requests)
# 2. DLM lock time (blocking requests)
# 3. Inter-request time (again to the DLM)
 1. DLM å (Υ֥å׵)
 2. DLM å (֥å׵)
 3. ꥯȴ֤δֳ ( DLM )

#A non-blocking request is one which will complete right
#away, whatever the state of the DLM lock in question. That
#currently means any requests when (a) the current state of
#the lock is exclusive, i.e. a lock demotion (b) the requested
#state is either null or unlocked (again, a demotion) or (c) the
#"try lock" flag is set. A blocking request covers all the other
#lock requests.
Υ֥å׵ϡȤƤ DLM åξ֤ˤ餺˽
λΤǤߤΤȤϡ(a) ߤΥåξ֤¾ (EX) Ǥ
(Ĥޤå׵Ǥ) (b) å׵ǡоݥåξ֤
null åǤä (Ʊå) (c) "try lock" ե饰
åȤƤΤ줫Ǥ뤳Ȥ̣ޤ
֥å׵ϡʳƤΥå׵򰷤ޤ
<!-- i.e. η꤬ѡ -->

#There are two counters. The first is there primarily to show
#how many lock requests have been made, and thus how much data
#has gone into the mean/variance calculations. The other counter
#is counting queuing of holders at the top layer of the glock
#code. Hopefully that number will be a lot larger than the number
#of dlm lock requests issued.
 2 ĤΥ󥿤ޤĤϼ˥å׵򼨤Τǡ
ޤʿѤʬФΤˤĤΥǡȤ줿Τ򼨤Ƥޤ⤦
ҤȤĤΥ󥿤ϡglock ɤκǾ̥٥ǥåݻԤΥ塼ϲ
ΤǤΥ󥿤οͤ dlm å׵ȯԲꤺä
Ȥ˾ޤǤ

#So why gather these statistics? There are several reasons
#we'd like to get a better idea of these timings:
Ǥϡʤ׿ͤ򽸤Τλ־򽸤θ褦Ȥ
ΤϡʲΤĤͳǤ

#1. To be able to better set the glock "min hold time"
#2. To spot performance issues more easily
#3. To improve the algorithm for selecting resource groups for
#allocation (to base it on lock wait time, rather than blindly
#using a "try lock")
1. glock  "min hold time (Ǿۡɻ)" ˤŬڤͤꤹ뤿
2. ǽưפŦФ뤿
3. ƻΥ꥽롼򥢥르ꥺ뤿 (ͤ
  "try lock (å)" ΤǤϤʤˤäƥåȻ
  Ѥ褦ˤʤäƤޤ)

#Due to the smoothing action of the updates, a step change in
#some input quantity being sampled will only fully be taken
#into account after 8 samples (or 4 for the variance) and this
#needs to be carefully considered when interpreting the
#results.
޷ˤѲʤΤȤ뤿ᡢϤγʾѹ 8 
ץˤʤޤ (ʬξ 4 ץޤ) ׻ʤᡢ
̤βκݤˤտȽǤɬפǤ

#Knowing both the time it takes a lock request to complete and
#the average time between lock requests for a glock means we
#can compute the total percentage of the time for which the
#node is able to use a glock vs. time that the rest of the
#cluster has its share. That will be very useful when setting
#the lock min hold time.
å׵᤬λޤǤפ֡ glock å׵֤ʿѷв
֤ξ狼äƤСΥΡɤ glock ѤǤ֤ȻĤΥ
饹μʬȤγ׻ǤޤϡåκǾݻ֤
뤿ˤȤƤͭѤͤǤ

#Great care has been taken to ensure that we
#measure exactly the quantities that we want, as accurately
#as possible. There are always inaccuracies in any
#measuring system, but I hope this is as accurate as we
#can reasonably make it.
ºݤɬפͤǽʸ¤Τ˼ǤƤ뤳Ȥǧ뤿ˤϡ
ʬդʧɬפޤɤ¬ꥷƥˤϤĤΤǤ
ϰϤΤʤΤˤʤäƤ뤳ȤȴԤƤޤ

#Per sb stats can be found here:
sb ׾ϰʲǤޤ
/sys/kernel/debug/gfs2/<fsname>/sbstats
#Per glock stats can be found here:
glock ׾ϰʲǤޤ
/sys/kernel/debug/gfs2/<fsname>/glstats

#Assuming that debugfs is mounted on /sys/kernel/debug and also
#that <fsname> is replaced with the name of the gfs2 filesystem
#in question.
debugfs  /sys/kernel/debug ˥ޥȤƤʤСȤʤ
gfs2 ե륷ƥ̾ <fsname> ֤ե뤫
Ǥޤ

#The abbreviations used in the output as are follows:
ϤѤάϰʲ̤Ǥ

#srtt     - Smoothed round trip time for non-blocking dlm requests
#srttvar  - Variance estimate for srtt
#srttb    - Smoothed round trip time for (potentially) blocking dlm requests
#srttvarb - Variance estimate for srttb
#sirt     - Smoothed inter-request time (for dlm requests)
#sirtvar  - Variance estimate for sirt
#dlm      - Number of dlm requests made (dcnt in glstats file)
#queue    - Number of glock requests queued (qcnt in glstats file)
srtt	 - Υ֥å dlm ׵μ֤ΰưʿ
srttvar  - srtt ʬο
srttb	 - ֥å (βǽΤ) dlm ׵μ֤ΰưʿ
srttvarb - srttb ʬο
sirt	 - dlm ꥯȤΥꥯȴ֤δֳ֤ΰưʿ
sirtvar	 - sirtb ʬο
dlm	 	 - dlm ꥯȤ׵ (glstats ե dcnt )
queue	 - 塼󥰤줿 glock ׵β (glstats ե qcnt )

#The sbstats file contains a set of these stats for each glock type (so 8 lines
#for each type) and for each cpu (one column per cpu). The glstats file contains
#a set of these stats for each glock in a similar format to the glocks file, but
#using the format mean/variance for each of the timing stats.
sbstats եˤϡ glock ˤ׾ȤǼ (
äƥפȤ 8 ) 졢Ȥߤ CPU ˳ǼƤޤ
glstats եˤϡߥ󥰾ȤƤʿͤʬѤƤ
г glocks եƱͤΥեޥåȤǤ׾ȤǼ
Ƥޤ

#The gfs2_glock_lock_time tracepoint prints out the current values of the stats
#for the glock in question, along with some addition information on each dlm
#reply that is received:
gfs2_glock_lock_time ȥ졼ݥȤϡоݤȤʤ glock ׾θ
ߤͤϤ˼ä dlm α˴ؤɲþϤ
ޤ

#status - The status of the dlm request
#flags  - The dlm request flags
#tdiff  - The time taken by this specific request
#(remaining fields as per above list)
status - dlm ׵ξ
flags  - dlm ׵ե饰
tdiff  - ΥꥯȤνפ
 (ĤΥեɤϾ嵭ꥹȤ˽)


