Print this page
NEX-19083 backport OS-7314 zil_commit should omit cache thrash
9962 zil_commit should omit cache thrash
Reviewed by: Matt Ahrens <matt@delphix.com>
Reviewed by: Brad Lewis <brad.lewis@delphix.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Approved by: Joshua M. Clulow <josh@sysmgr.org>


  31 
  32 #include <sys/zil.h>
  33 #include <sys/dmu_objset.h>
  34 
  35 #ifdef  __cplusplus
  36 extern "C" {
  37 #endif
  38 
  39 /*
  40  * Possbile states for a given lwb structure.
  41  *
  42  * An lwb will start out in the "closed" state, and then transition to
  43  * the "opened" state via a call to zil_lwb_write_open(). When
  44  * transitioning from "closed" to "opened" the zilog's "zl_issuer_lock"
  45  * must be held.
  46  *
  47  * After the lwb is "opened", it can transition into the "issued" state
  48  * via zil_lwb_write_issue(). Again, the zilog's "zl_issuer_lock" must
  49  * be held when making this transition.
  50  *
  51  * After the lwb's zio completes, and the vdev's are flushed, the lwb
  52  * will transition into the "done" state via zil_lwb_write_done(). When
  53  * transitioning from "issued" to "done", the zilog's "zl_lock" must be
  54  * held, *not* the "zl_issuer_lock".

  55  *
  56  * The zilog's "zl_issuer_lock" can become heavily contended in certain
  57  * workloads, so we specifically avoid acquiring that lock when
  58  * transitioning an lwb from "issued" to "done". This allows us to avoid
  59  * having to acquire the "zl_issuer_lock" for each lwb ZIO completion,
  60  * which would have added more lock contention on an already heavily
  61  * contended lock.
  62  *
  63  * Additionally, correctness when reading an lwb's state is often
  64  * acheived by exploiting the fact that these state transitions occur in
  65  * this specific order; i.e. "closed" to "opened" to "issued" to "done".
  66  *
  67  * Thus, if an lwb is in the "closed" or "opened" state, holding the
  68  * "zl_issuer_lock" will prevent a concurrent thread from transitioning
  69  * that lwb to the "issued" state. Likewise, if an lwb is already in the
  70  * "issued" state, holding the "zl_lock" will prevent a concurrent
  71  * thread from transitioning that lwb to the "done" state.
  72  */
  73 typedef enum {
  74     LWB_STATE_CLOSED,
  75     LWB_STATE_OPENED,
  76     LWB_STATE_ISSUED,
  77     LWB_STATE_DONE,

  78     LWB_NUM_STATES
  79 } lwb_state_t;
  80 
  81 /*
  82  * Log write block (lwb)
  83  *
  84  * Prior to an lwb being issued to disk via zil_lwb_write_issue(), it
  85  * will be protected by the zilog's "zl_issuer_lock". Basically, prior
  86  * to it being issued, it will only be accessed by the thread that's
  87  * holding the "zl_issuer_lock". After the lwb is issued, the zilog's
  88  * "zl_lock" is used to protect the lwb against concurrent access.
  89  */
  90 typedef struct lwb {
  91         zilog_t         *lwb_zilog;     /* back pointer to log struct */
  92         blkptr_t        lwb_blk;        /* on disk address of this log blk */
  93         boolean_t       lwb_slog;       /* lwb_blk is on SLOG device */
  94         int             lwb_nused;      /* # used bytes in buffer */
  95         int             lwb_sz;         /* size of block and buffer */
  96         lwb_state_t     lwb_state;      /* the state of this lwb */
  97         char            *lwb_buf;       /* log write buffer */




  31 
  32 #include <sys/zil.h>
  33 #include <sys/dmu_objset.h>
  34 
  35 #ifdef  __cplusplus
  36 extern "C" {
  37 #endif
  38 
  39 /*
  40  * Possbile states for a given lwb structure.
  41  *
  42  * An lwb will start out in the "closed" state, and then transition to
  43  * the "opened" state via a call to zil_lwb_write_open(). When
  44  * transitioning from "closed" to "opened" the zilog's "zl_issuer_lock"
  45  * must be held.
  46  *
  47  * After the lwb is "opened", it can transition into the "issued" state
  48  * via zil_lwb_write_issue(). Again, the zilog's "zl_issuer_lock" must
  49  * be held when making this transition.
  50  *
  51  * After the lwb's write zio completes, it transitions into the "write
  52  * done" state via zil_lwb_write_done(); and then into the "flush done"
  53  * state via zil_lwb_flush_vdevs_done(). When transitioning from
  54  * "issued" to "write done", and then from "write done" to "flush done",
  55  * the zilog's "zl_lock" must be held, *not* the "zl_issuer_lock".
  56  *
  57  * The zilog's "zl_issuer_lock" can become heavily contended in certain
  58  * workloads, so we specifically avoid acquiring that lock when
  59  * transitioning an lwb from "issued" to "done". This allows us to avoid
  60  * having to acquire the "zl_issuer_lock" for each lwb ZIO completion,
  61  * which would have added more lock contention on an already heavily
  62  * contended lock.
  63  *
  64  * Additionally, correctness when reading an lwb's state is often
  65  * acheived by exploiting the fact that these state transitions occur in
  66  * this specific order; i.e. "closed" to "opened" to "issued" to "done".
  67  *
  68  * Thus, if an lwb is in the "closed" or "opened" state, holding the
  69  * "zl_issuer_lock" will prevent a concurrent thread from transitioning
  70  * that lwb to the "issued" state. Likewise, if an lwb is already in the
  71  * "issued" state, holding the "zl_lock" will prevent a concurrent
  72  * thread from transitioning that lwb to the "write done" state.
  73  */
  74 typedef enum {
  75     LWB_STATE_CLOSED,
  76     LWB_STATE_OPENED,
  77     LWB_STATE_ISSUED,
  78     LWB_STATE_WRITE_DONE,
  79     LWB_STATE_FLUSH_DONE,
  80     LWB_NUM_STATES
  81 } lwb_state_t;
  82 
  83 /*
  84  * Log write block (lwb)
  85  *
  86  * Prior to an lwb being issued to disk via zil_lwb_write_issue(), it
  87  * will be protected by the zilog's "zl_issuer_lock". Basically, prior
  88  * to it being issued, it will only be accessed by the thread that's
  89  * holding the "zl_issuer_lock". After the lwb is issued, the zilog's
  90  * "zl_lock" is used to protect the lwb against concurrent access.
  91  */
  92 typedef struct lwb {
  93         zilog_t         *lwb_zilog;     /* back pointer to log struct */
  94         blkptr_t        lwb_blk;        /* on disk address of this log blk */
  95         boolean_t       lwb_slog;       /* lwb_blk is on SLOG device */
  96         int             lwb_nused;      /* # used bytes in buffer */
  97         int             lwb_sz;         /* size of block and buffer */
  98         lwb_state_t     lwb_state;      /* the state of this lwb */
  99         char            *lwb_buf;       /* log write buffer */