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 */
|