Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 314762 Details for
Bug 458684
GFS2: glock deadlock in page fault path
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Latest incarnation of glock_history
glock_history.patch (text/plain), 15.34 KB, created by
Robert Peterson
on 2008-08-21 22:45:40 UTC
(
hide
)
Description:
Latest incarnation of glock_history
Filename:
MIME Type:
Creator:
Robert Peterson
Created:
2008-08-21 22:45:40 UTC
Size:
15.34 KB
patch
obsolete
>diff -pur a/fs/gfs2/glock.c b/fs/gfs2/glock.c >--- a/fs/gfs2/glock.c 2008-08-21 12:16:07.000000000 -0500 >+++ b/fs/gfs2/glock.c 2008-08-21 16:49:11.000000000 -0500 >@@ -108,6 +108,57 @@ static struct workqueue_struct *glock_wo > # define GL_HASH_LOCK_SZ GFS2_GL_HASH_SIZE > #endif > >+#ifdef CONFIG_GFS2_GLOCK_DEBUG >+const char *gl_hist_funcs[] = {"gfs2_glock_get", >+ "finish EAGAIN", >+ "gfs2_glock_put", >+ "gfs2_holder_init", >+ "gfs2_glock_xmote_th", >+ "gfs2_glock_drop_th", >+ "gfs2_glock_dq", >+ "gfs2_lvb_hold", >+ "gfs2_lvb_unhold", >+ "sched_for_reclaim", >+ >+ "clear_glock", >+ "search_bucket", >+ "run_queue1", >+ "run_queue2", >+ "run_queue3", >+ "run_queue4", >+ "handle_callbk1", >+ "handle_callbk2", >+ "handle_callbk3", >+ "gfs2_holder_reinit", >+ >+ "do_error1", >+ "gfs2_mmap", >+ "gfs2_write_lock_start", >+ "gfs2_direct_IO", >+ "gfs2_readpage", >+ "gfs2_readpages", >+ "gfs2_readlinki", >+ "do_promote", >+ "finish_xmote", >+ "do_xmote1", >+ >+ "handle_callbk4", >+ "CB_NEED_E", >+ "CB_NEED_D", >+ "CB_NEED_S", >+ "do_xmote2", >+ "do_xmote3", >+ "do_xmote4", >+ "err/failed trylock", >+ "gfs2_glock_dq fastpath", >+ "LM:lock_canceled", >+ >+ "do_error2", >+ "do_error3", >+ "do_error4", >+}; >+#endif >+ > static rwlock_t gl_hash_locks[GL_HASH_LOCK_SZ]; > > static inline rwlock_t *gl_lock_addr(unsigned int x) >@@ -253,6 +304,7 @@ static struct gfs2_glock *search_bucket( > continue; > > atomic_inc(&gl->gl_ref); >+ GL_HISTORY(gl, SEARCH_BUCKET, gl->gl_state); > > return gl; > } >@@ -335,6 +387,7 @@ restart: > if (test_bit(HIF_HOLDER, &gh->gh_iflags)) > continue; > if (may_grant(gl, gh)) { >+ GL_HISTORY(gl, GFS2_DO_PROMOTE, gl->gl_state); > if (gh->gh_list.prev == &gl->gl_holders && > glops->go_lock) { > spin_unlock(&gl->gl_spin); >@@ -448,6 +501,7 @@ static void finish_xmote(struct gfs2_glo > unsigned state = ret & LM_OUT_ST_MASK; > > spin_lock(&gl->gl_spin); >+ GL_HISTORY(gl, FINISH_XMOTE, state); > state_change(gl, state); > gh = find_first_waiter(gl); > >@@ -464,12 +518,14 @@ static void finish_xmote(struct gfs2_glo > if ((gh->gh_flags & LM_FLAG_PRIORITY) == 0) > list_move_tail(&gh->gh_list, &gl->gl_holders); > gh = find_first_waiter(gl); >+ GL_HISTORY(gl, LOCK_CANCELED, state); > gl->gl_target = gh->gh_state; > goto retry; > } > /* Some error or failed "try lock" - report it */ > if ((ret & LM_OUT_ERROR) || > (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) { >+ GL_HISTORY(gl, FAILED_TRYLOCK, state); > gl->gl_target = gl->gl_state; > do_error(gl, ret); > goto out; >@@ -479,11 +535,13 @@ static void finish_xmote(struct gfs2_glo > /* Unlocked due to conversion deadlock, try again */ > case LM_ST_UNLOCKED: > retry: >+ GL_HISTORY(gl, DO_XMOTE3, state); > do_xmote(gl, gh, gl->gl_target); > break; > /* Conversion fails, unlock and try again */ > case LM_ST_SHARED: > case LM_ST_DEFERRED: >+ GL_HISTORY(gl, DO_XMOTE4, state); > do_xmote(gl, gh, LM_ST_UNLOCKED); > break; > default: /* Everything else */ >@@ -503,10 +561,13 @@ retry: > int rv; > spin_unlock(&gl->gl_spin); > rv = glops->go_xmote_bh(gl, gh); >- if (rv == -EAGAIN) >+ if (rv == -EAGAIN) { >+ GL_HISTORY(gl, FINISH_EAGAIN, state); > return; >+ } > spin_lock(&gl->gl_spin); > if (rv) { >+ GL_HISTORY(gl, DO_ERROR2, gl->gl_state); > do_error(gl, rv); > goto out; > } >@@ -552,6 +613,7 @@ static void do_xmote(struct gfs2_glock * > if ((target == LM_ST_UNLOCKED || target == LM_ST_DEFERRED) && > glops->go_inval) { > set_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags); >+ GL_HISTORY(gl, DO_ERROR3, gl->gl_state); > do_error(gl, 0); /* Fail queued try locks */ > } > spin_unlock(&gl->gl_spin); >@@ -606,6 +668,10 @@ static inline struct gfs2_holder *find_f > static void run_queue(struct gfs2_glock *gl, const int nonblock) > { > struct gfs2_holder *gh = NULL; >+ int extra_logging = 0; >+ >+ if (test_and_clear_bit(GLF_EXTRA_LOGGING, &gl->gl_flags)) >+ extra_logging = 1; > > if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) > return; >@@ -614,23 +680,37 @@ static void run_queue(struct gfs2_glock > > if (test_bit(GLF_DEMOTE, &gl->gl_flags) && > gl->gl_demote_state != gl->gl_state) { >- if (find_first_holder(gl)) >+ if (find_first_holder(gl)) { >+ if (extra_logging) >+ GL_HISTORY(gl, RUN_QUEUE1, gl->gl_state); > goto out; >- if (nonblock) >+ } >+ if (nonblock) { >+ if (extra_logging) >+ GL_HISTORY(gl, RUN_QUEUE2, gl->gl_state); > goto out_sched; >+ } > set_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags); > GLOCK_BUG_ON(gl, gl->gl_demote_state == LM_ST_EXCLUSIVE); > gl->gl_target = gl->gl_demote_state; > } else { >+ if (extra_logging) >+ GL_HISTORY(gl, RUN_QUEUE3, gl->gl_state); > if (test_bit(GLF_DEMOTE, &gl->gl_flags)) > gfs2_demote_wake(gl); >- if (do_promote(gl) == 0) >+ if (do_promote(gl) == 0) { >+ if (extra_logging) >+ GL_HISTORY(gl, RUN_QUEUE4, gl->gl_state); > goto out; >+ } > gh = find_first_waiter(gl); > gl->gl_target = gh->gh_state; >- if (!(gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) >+ if (!(gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) { >+ GL_HISTORY(gl, DO_ERROR4, gl->gl_state); > do_error(gl, 0); /* Fail queued try locks */ >+ } > } >+ GL_HISTORY(gl, DO_XMOTE1, gl->gl_state); > do_xmote(gl, gh, gl->gl_target); > return; > >@@ -704,7 +784,9 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, > gl->gl_flags = 0; > gl->gl_name = name; > atomic_set(&gl->gl_ref, 1); >+ gl->gl_changes = 0; > gl->gl_state = LM_ST_UNLOCKED; >+ GL_HISTORY(gl, GLOCK_GET, gl->gl_state); > gl->gl_target = LM_ST_UNLOCKED; > gl->gl_demote_state = LM_ST_EXCLUSIVE; > gl->gl_hash = hash; >@@ -789,6 +871,7 @@ void gfs2_holder_init(struct gfs2_glock > > void gfs2_holder_reinit(unsigned int state, unsigned flags, struct gfs2_holder *gh) > { >+ GL_HISTORY(gh->gh_gl, HOLDER_REINIT, state); > gh->gh_state = state; > gh->gh_flags = flags; > gh->gh_iflags = 0; >@@ -851,6 +934,7 @@ static void handle_callback(struct gfs2_ > gl->gl_demote_state != state) { > gl->gl_demote_state = LM_ST_UNLOCKED; > } >+ set_bit(GLF_EXTRA_LOGGING, &gl->gl_flags); > } > > /** >@@ -1012,8 +1096,10 @@ void gfs2_glock_dq(struct gfs2_holder *g > int fast_path = 0; > > spin_lock(&gl->gl_spin); >- if (gh->gh_flags & GL_NOCACHE) >+ if (gh->gh_flags & GL_NOCACHE) { >+ GL_HISTORY(gl, HANDLE_CALLBK1, LM_ST_UNLOCKED); > handle_callback(gl, LM_ST_UNLOCKED, 0, 0); >+ } > > list_del_init(&gh->gh_list); > if (find_first_holder(gl) == NULL) { >@@ -1031,10 +1117,13 @@ void gfs2_glock_dq(struct gfs2_holder *g > fast_path = 1; > } > spin_unlock(&gl->gl_spin); >- if (likely(fast_path)) >+ if (likely(fast_path)) { >+ GL_HISTORY(gl, GLOCK_DQ_FAST, gl->gl_state); > return; >+ } > > gfs2_glock_hold(gl); >+ GL_HISTORY(gl, GLOCK_DQ, gl->gl_state); > if (test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && > !test_bit(GLF_DEMOTE, &gl->gl_flags)) > delay = gl->gl_ops->go_min_hold_time; >@@ -1236,6 +1325,7 @@ int gfs2_lvb_hold(struct gfs2_glock *gl) > if (error) > return error; > gfs2_glock_hold(gl); >+ GL_HISTORY(gl, LVB_HOLD, gl->gl_state); > } > atomic_inc(&gl->gl_lvb_count); > >@@ -1253,6 +1343,7 @@ void gfs2_lvb_unhold(struct gfs2_glock * > struct gfs2_sbd *sdp = gl->gl_sbd; > > gfs2_glock_hold(gl); >+ GL_HISTORY(gl, LVM_UNHOLD, gl->gl_state); > gfs2_assert(gl->gl_sbd, atomic_read(&gl->gl_lvb_count) > 0); > if (atomic_dec_and_test(&gl->gl_lvb_count)) { > if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) >@@ -1275,11 +1366,18 @@ static void blocking_cb(struct gfs2_sbd > if (!gl) > return; > >+ if (state == LM_ST_UNLOCKED) >+ GL_HISTORY(gl, CB_NEED_E, gl->gl_state); >+ else if (state == LM_ST_DEFERRED) >+ GL_HISTORY(gl, CB_NEED_D, gl->gl_state); >+ else if (state == LM_ST_SHARED) >+ GL_HISTORY(gl, CB_NEED_S, gl->gl_state); > holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time; > if (time_before(now, holdtime)) > delay = holdtime - now; > > spin_lock(&gl->gl_spin); >+ GL_HISTORY(gl, HANDLE_CALLBK2, state); > handle_callback(gl, state, 1, delay); > spin_unlock(&gl->gl_spin); > if (queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0) >@@ -1380,6 +1478,7 @@ void gfs2_glock_schedule_for_reclaim(str > spin_lock(&sdp->sd_reclaim_lock); > if (list_empty(&gl->gl_reclaim)) { > gfs2_glock_hold(gl); >+ GL_HISTORY(gl, SF_RECLAIM, gl->gl_state); > list_add(&gl->gl_reclaim, &sdp->sd_reclaim_list); > atomic_inc(&sdp->sd_reclaim_count); > spin_unlock(&sdp->sd_reclaim_lock); >@@ -1419,6 +1518,7 @@ void gfs2_reclaim_glock(struct gfs2_sbd > spin_lock(&gl->gl_spin); > if (find_first_holder(gl) == NULL && > gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl)) { >+ GL_HISTORY(gl, HANDLE_CALLBK3, LM_ST_UNLOCKED); > handle_callback(gl, LM_ST_UNLOCKED, 0, 0); > done_callback = 1; > } >@@ -1504,6 +1604,7 @@ static void clear_glock(struct gfs2_gloc > int released; > > spin_lock(&sdp->sd_reclaim_lock); >+ GL_HISTORY(gl, CLEAR_GLOCK, gl->gl_state); > if (!list_empty(&gl->gl_reclaim)) { > list_del_init(&gl->gl_reclaim); > atomic_dec(&sdp->sd_reclaim_count); >@@ -1515,8 +1616,10 @@ static void clear_glock(struct gfs2_gloc > } > > spin_lock(&gl->gl_spin); >- if (find_first_holder(gl) == NULL && gl->gl_state != LM_ST_UNLOCKED) >+ if (find_first_holder(gl) == NULL && gl->gl_state != LM_ST_UNLOCKED) { >+ GL_HISTORY(gl, HANDLE_CALLBK4, LM_ST_UNLOCKED); > handle_callback(gl, LM_ST_UNLOCKED, 0, 0); >+ } > spin_unlock(&gl->gl_spin); > gfs2_glock_hold(gl); > if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) >@@ -1663,6 +1766,42 @@ static const char *gflags2str(char *buf, > } > > /** >+ * dump_glock_history >+ * @gi: The glock iterator >+ * @gl: the glock >+ * >+ */ >+void noinline dump_glock_hist(struct seq_file *seq, const struct gfs2_glock *gl) >+{ >+#ifdef CONFIG_GFS2_GLOCK_DEBUG >+ char gflags_buf[32]; >+ int x, x_adj; >+ >+ if (gl->gl_changes < GFS2_GLOCK_HIST_SIZE) >+ x = 0; >+ else >+ x = gl->gl_changes - GFS2_GLOCK_HIST_SIZE; >+ for (; x < gl->gl_changes; x++) { >+ x_adj = x % GFS2_GLOCK_HIST_SIZE; >+ gfs2_print_dbg(seq, " %d: %-20.20s%7ld, f: %5s tgt: %s, dmt: %s, St: %s", x, >+ gl->gl_hist[x_adj].func < HISTORY_FUNCS ? >+ gl_hist_funcs[gl->gl_hist[x_adj].func] : "???", >+ gl->gl_hist[x_adj].pid, >+ gflags2str(gflags_buf, &gl->gl_hist[x_adj].gl_flags), >+ state2str(gl->gl_hist[x_adj].target), >+ state2str(gl->gl_hist[x_adj].demote_state), >+ state2str(gl->gl_hist[x_adj].old_state)); >+ if (gl->gl_hist[x_adj].old_state == >+ gl->gl_hist[x_adj].new_state) >+ gfs2_print_dbg(seq, "\n"); >+ else >+ gfs2_print_dbg(seq, " -> %s\n", >+ state2str(gl->gl_hist[x_adj].new_state)); >+ } >+#endif >+} >+ >+/** > * __dump_glock - print information about a glock > * @seq: The seq_file struct > * @gl: the glock >@@ -1710,6 +1849,8 @@ static int __dump_glock(struct seq_file > } > if (gl->gl_state != LM_ST_UNLOCKED && glops->go_dump) > error = glops->go_dump(seq, gl); >+ if (gl->gl_state != LM_ST_UNLOCKED && glops->go_dump) >+ dump_glock_hist(seq, gl); > out: > return error; > } >Only in b/fs/gfs2: glock.c.~1~ >diff -pur a/fs/gfs2/incore.h b/fs/gfs2/incore.h >--- a/fs/gfs2/incore.h 2008-08-21 12:16:07.000000000 -0500 >+++ b/fs/gfs2/incore.h 2008-08-21 16:52:02.000000000 -0500 >@@ -168,8 +168,76 @@ enum { > GLF_LFLUSH = 7, > GLF_INVALIDATE_IN_PROGRESS = 8, > GLF_REPLY_PENDING = 9, >+ GLF_EXTRA_LOGGING = 10, > }; > >+#define CONFIG_GFS2_GLOCK_DEBUG >+ >+#ifdef CONFIG_GFS2_GLOCK_DEBUG >+#define GFS2_GLOCK_HIST_SIZE 32 >+ >+enum glock_histfuncs { >+ GLOCK_GET = 0, /* gfs2_glock_get */ >+ FINISH_EAGAIN = 1, /* finish_xmote got EAGAIN */ >+ GLOCK_PUT = 2, /* gfs2_glock_put */ >+ HOLDER_INIT = 3, /* gfs2_holder_init */ >+ XMOTE_TH = 4, /* gfs2_glock_xmote_th */ >+ DROP_TH = 5, /* gfs2_glock_drop_th */ >+ GLOCK_DQ = 6, /* gfs2_glock_dq */ >+ LVB_HOLD = 7, /* gfs2_lvb_hold */ >+ LVM_UNHOLD = 8, /* gfs2_lvb_unhold */ >+ SF_RECLAIM = 9, /* gfs2_glock_schedule_for_reclaim */ >+ >+ CLEAR_GLOCK = 10, /* clear_glock */ >+ SEARCH_BUCKET = 11, /* search_bucket */ >+ RUN_QUEUE1 = 12, /* run_queue1 */ >+ RUN_QUEUE2 = 13, /* run_queue2 */ >+ RUN_QUEUE3 = 14, /* run_queue3 */ >+ RUN_QUEUE4 = 15, /* run_queue4 */ >+ HANDLE_CALLBK1 = 16, /* handle_callback1 */ >+ HANDLE_CALLBK2 = 17, /* handle_callback2 */ >+ HANDLE_CALLBK3 = 18, /* handle_callback3 */ >+ HOLDER_REINIT = 19, /* gfs2_holder_reinit */ >+ >+ DO_ERROR1 = 20, /* do_error */ >+ GFS2_MMAP = 21, /* gfs2_mmap */ >+ GFS2_WLS = 22, /* gfs2_write_lock_start */ >+ GFS2_DIRECT_IO = 23, /* gfs2_direct_IO */ >+ GFS2_READPAGE = 24, /* gfs2_readpage */ >+ GFS2_READPAGES = 25, /* gfs2_readpages */ >+ GFS2_READLINKI = 26, /* gfs2_readlinki */ >+ GFS2_DO_PROMOTE= 27, /* gfs2_do_promote */ >+ FINISH_XMOTE = 28, /* finish_xmote */ >+ DO_XMOTE1 = 29, /* do_xmote1 */ >+ >+ HANDLE_CALLBK4 = 30, /* handle_callback4 */ >+ CB_NEED_E = 31, /* LM_CB_NEED_E */ >+ CB_NEED_D = 32, /* LM_CB_NEED_D */ >+ CB_NEED_S = 33, /* LM_CB_NEED_S */ >+ DO_XMOTE2 = 34, /* do_xmote1 */ >+ DO_XMOTE3 = 35, /* do_xmote1 */ >+ DO_XMOTE4 = 36, /* do_xmote1 */ >+ FAILED_TRYLOCK = 37, /* failed trylock in finish_xmote */ >+ GLOCK_DQ_FAST = 38, /* gfs2_glock_dq fast path */ >+ LOCK_CANCELED = 39, /* finish_xmote got LM_OUT_CANCELED from lm */ >+ >+ DO_ERROR2 = 40, /* do_error - from finish_xmote */ >+ DO_ERROR3 = 41, /* do_error - from do_xmote--inval in progress */ >+ DO_ERROR4 = 42, /* do_error - from run_queue, fail queued trylk */ >+ HISTORY_FUNCS = 43 >+}; >+ >+struct gfs2_glock_hist_ent { >+ pid_t pid; >+ unsigned int old_state; >+ unsigned int new_state; >+ unsigned int target; >+ unsigned int demote_state; >+ unsigned long gl_flags; >+ enum glock_histfuncs func; >+}; >+#endif >+ > struct gfs2_glock { > struct hlist_node gl_list; > unsigned long gl_flags; /* GLF_... */ >@@ -204,8 +272,39 @@ struct gfs2_glock { > struct list_head gl_ail_list; > atomic_t gl_ail_count; > struct work_struct gl_work; >+#ifdef CONFIG_GFS2_GLOCK_DEBUG >+ int gl_changes; >+ struct gfs2_glock_hist_ent gl_hist[GFS2_GLOCK_HIST_SIZE]; >+ spinlock_t gl_histlock; >+#endif > }; > >+#ifdef CONFIG_GFS2_GLOCK_DEBUG >+static inline void gl_history(struct gfs2_glock *gl, enum glock_histfuncs func, >+ unsigned int new_state) >+{ >+ int h; >+ >+ spin_lock(&gl->gl_histlock); >+ h = gl->gl_changes % GFS2_GLOCK_HIST_SIZE; >+ gl->gl_hist[h].func = func; >+ if (current) >+ gl->gl_hist[h].pid = current->pid; >+ else >+ gl->gl_hist[h].pid = -3; >+ gl->gl_hist[h].old_state = gl->gl_state; >+ gl->gl_hist[h].new_state = new_state; >+ gl->gl_hist[h].target = gl->gl_target; >+ gl->gl_hist[h].demote_state = gl->gl_demote_state; >+ gl->gl_hist[h].gl_flags = gl->gl_flags; >+ gl->gl_changes++; >+ spin_unlock(&gl->gl_histlock); >+} >+#define GL_HISTORY(g, f, s) gl_history(g, f, s) >+#else >+#define GL_HISTORY(g, f, s) >+#endif >+ > struct gfs2_alloc { > /* Quota stuff */ > >Only in b/fs/gfs2: incore.h.~1~ >Only in b/fs/gfs2: incore.h.~2~ >diff -pur a/fs/gfs2/main.c b/fs/gfs2/main.c >--- a/fs/gfs2/main.c 2008-08-21 12:16:07.000000000 -0500 >+++ b/fs/gfs2/main.c 2008-08-21 13:49:45.000000000 -0500 >@@ -43,6 +43,7 @@ static void gfs2_init_glock_once(void *f > SLAB_CTOR_CONSTRUCTOR) { > INIT_HLIST_NODE(&gl->gl_list); > spin_lock_init(&gl->gl_spin); >+ spin_lock_init(&gl->gl_histlock); > INIT_LIST_HEAD(&gl->gl_holders); > gl->gl_lvb = NULL; > atomic_set(&gl->gl_lvb_count, 0);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 458684
:
314028
|
314549
|
314680
|
314745
|
314760
|
314761
| 314762 |
314981
|
315157
|
315399
|
315400
|
315660
|
316226
|
316480
|
316579
|
316802