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 306497 Details for
Bug 447920
GFS2: deadlock running d_io w/ jdata on lock_nolock
[?]
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]
Differences between latest readv and what we gave aol
diff_from_aol (text/plain), 47.24 KB, created by
Robert Peterson
on 2008-05-23 13:43:20 UTC
(
hide
)
Description:
Differences between latest readv and what we gave aol
Filename:
MIME Type:
Creator:
Robert Peterson
Created:
2008-05-23 13:43:20 UTC
Size:
47.24 KB
patch
obsolete
>diff -pur a/fs/gfs2/glock.c b/fs/gfs2/glock.c >--- a/fs/gfs2/glock.c 2008-05-02 09:59:33.000000000 -0500 >+++ b/fs/gfs2/glock.c 2008-05-21 12:37:42.000000000 -0500 >@@ -47,10 +47,18 @@ struct gfs2_gl_hash_bucket { > struct hlist_head hb_list; > }; > >+struct gfs2_glock_iter { >+ int hash; /* hash bucket index */ >+ struct gfs2_sbd *sdp; /* incore superblock */ >+ struct gfs2_glock *gl; /* current glock struct */ >+ char string[512]; /* scratch space */ >+}; >+ > typedef void (*glock_examiner) (struct gfs2_glock * gl); > > static int gfs2_dump_lockstate(struct gfs2_sbd *sdp); >-static int dump_glock(struct gfs2_glock_iter *gi, struct gfs2_glock *gl); >+static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl); >+#define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { __dump_glock(NULL, gl); BUG(); } } while(0) > static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target); > > static DECLARE_RWSEM(gfs2_umount_flush_sem); >@@ -113,15 +121,36 @@ static inline rwlock_t *gl_lock_addr(uns > } > #endif > >-/** >- * glock_bug - Report a glock bug and dump appropriate information >- */ >-#define glock_bug(gl) \ >-{ \ >- if (spin_is_locked(&gl->gl_spin)) \ >- spin_unlock(&gl->gl_spin); \ >- dump_glock(NULL, gl); \ >- BUG(); \ >+/* copied from upstream kernel: */ >+void *__seq_open_private(struct file *f, struct seq_operations *ops, >+ int psize) >+{ >+ int rc; >+ void *private; >+ struct seq_file *seq; >+ >+ private = kzalloc(psize, GFP_KERNEL); >+ if (private == NULL) >+ goto out; >+ >+ rc = seq_open(f, ops); >+ if (rc < 0) >+ goto out_free; >+ >+ seq = f->private_data; >+ seq->private = private; >+ return private; >+ >+out_free: >+ kfree(private); >+out: >+ return NULL; >+} >+ >+int seq_open_private(struct file *filp, struct seq_operations *ops, >+ int psize) >+{ >+ return __seq_open_private(filp, ops, psize) ? 0 : -ENOMEM; > } > > /** >@@ -185,15 +214,14 @@ void gfs2_glock_hold(struct gfs2_glock * > int gfs2_glock_put(struct gfs2_glock *gl) > { > int rv = 0; >- struct gfs2_sbd *sdp = gl->gl_sbd; > > write_lock(gl_lock_addr(gl->gl_hash)); > if (atomic_dec_and_test(&gl->gl_ref)) { > hlist_del(&gl->gl_list); > write_unlock(gl_lock_addr(gl->gl_hash)); >- gfs2_assert(sdp, gl->gl_state == LM_ST_UNLOCKED); >- gfs2_assert(sdp, list_empty(&gl->gl_reclaim)); >- gfs2_assert(sdp, list_empty(&gl->gl_holders)); >+ GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_UNLOCKED); >+ GLOCK_BUG_ON(gl, !list_empty(&gl->gl_reclaim)); >+ GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders)); > glock_free(gl); > rv = 1; > goto out; >@@ -313,6 +341,7 @@ restart: > gh->gh_error = ret; > list_del_init(&gh->gh_list); > gfs2_holder_wake(gh); >+ goto restart; > } > set_bit(HIF_HOLDER, &gh->gh_iflags); > gfs2_holder_wake(gh); >@@ -334,7 +363,7 @@ restart: > * > */ > >-static void do_error(struct gfs2_glock *gl, int ret) >+static inline void do_error(struct gfs2_glock *gl, const int ret) > { > struct gfs2_holder *gh, *tmp; > >@@ -455,7 +484,7 @@ retry: > break; > default: /* Everything else */ > printk(KERN_ERR "GFS2: wanted %u got %u\n", gl->gl_target, state); >- glock_bug(gl); >+ GLOCK_BUG_ON(gl, 1); > } > spin_unlock(&gl->gl_spin); > gfs2_glock_put(gl); >@@ -467,9 +496,16 @@ retry: > gfs2_demote_wake(gl); > if (state != LM_ST_UNLOCKED) { > if (glops->go_xmote_bh) { >+ int rv; > spin_unlock(&gl->gl_spin); >- glops->go_xmote_bh(gl, gh); >+ rv = glops->go_xmote_bh(gl, gh); >+ if (rv == -EAGAIN) >+ return; > spin_lock(&gl->gl_spin); >+ if (rv) { >+ do_error(gl, rv); >+ goto out; >+ } > } > do_promote(gl); > } >@@ -509,12 +545,18 @@ static void do_xmote(struct gfs2_glock * > LM_FLAG_PRIORITY); > BUG_ON(gl->gl_state == target); > BUG_ON(gl->gl_state == gl->gl_target); >+ if ((target == LM_ST_UNLOCKED || target == LM_ST_DEFERRED) && >+ glops->go_inval) { >+ set_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags); >+ do_error(gl, 0); /* Fail queued try locks */ >+ } > spin_unlock(&gl->gl_spin); > if (glops->go_xmote_th) > glops->go_xmote_th(gl); >- if ((target == LM_ST_UNLOCKED || >- target == LM_ST_DEFERRED) && glops->go_inval) >- glops->go_inval(gl, DIO_METADATA); >+ if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags)) >+ glops->go_inval(gl, target == LM_ST_DEFERRED ? 0 : DIO_METADATA); >+ clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags); >+ > gfs2_glock_hold(gl); > if (target != LM_ST_UNLOCKED && (gl->gl_state == LM_ST_SHARED || > gl->gl_state == LM_ST_DEFERRED) && >@@ -522,10 +564,14 @@ static void do_xmote(struct gfs2_glock * > lck_flags |= LM_FLAG_TRY_1CB; > ret = gfs2_lm_lock(sdp, gl->gl_lock, gl->gl_state, target, lck_flags); > >- if (!(ret & LM_OUT_ASYNC)) >+ if (!(ret & LM_OUT_ASYNC)) { > finish_xmote(gl, ret); >- else >- gfs2_assert_warn(sdp, ret == LM_OUT_ASYNC); >+ gfs2_glock_hold(gl); >+ if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) >+ gfs2_glock_put(gl); >+ } else { >+ GLOCK_BUG_ON(gl, ret != LM_OUT_ASYNC); >+ } > spin_lock(&gl->gl_spin); > } > >@@ -560,11 +606,10 @@ static void run_queue(struct gfs2_glock > if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) > return; > >- BUG_ON(test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags)); >+ GLOCK_BUG_ON(gl, test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags)); > > if (test_bit(GLF_DEMOTE, &gl->gl_flags) && > gl->gl_demote_state != gl->gl_state) { >- do_error(gl, 0); /* Fail queued try locks */ > if (find_first_holder(gl)) > goto out; > if (nonblock) >@@ -594,15 +639,24 @@ out: > > static void glock_work_func(void *data) > { >+ unsigned long delay = 0; > struct gfs2_glock *gl = (struct gfs2_glock *)data; > >+ if (test_and_clear_bit(GLF_REPLY_PENDING, &gl->gl_flags)) >+ finish_xmote(gl, gl->gl_reply); > spin_lock(&gl->gl_spin); >- if (test_and_clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && >- gl->gl_demote_state != LM_ST_EXCLUSIVE) >- set_bit(GLF_DEMOTE, &gl->gl_flags); >+ if (test_and_clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags)) { >+ unsigned long holdtime, now = jiffies; >+ holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time; >+ if (time_before(now, holdtime)) >+ delay = holdtime - now; >+ set_bit(delay ? GLF_PENDING_DEMOTE : GLF_DEMOTE, &gl->gl_flags); >+ } > run_queue(gl, 0); > spin_unlock(&gl->gl_spin); >- gfs2_glock_put(gl); >+ if (!delay || >+ queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0) >+ gfs2_glock_put(gl); > } > > /** >@@ -801,27 +855,23 @@ static void handle_callback(struct gfs2_ > > int gfs2_glock_wait(struct gfs2_holder *gh) > { >- struct gfs2_glock *gl = gh->gh_gl; >- struct gfs2_sbd *sdp = gl->gl_sbd; >- > wait_on_holder(gh); >- if (gh->gh_error == 0) >- gfs2_assert_withdraw(sdp, test_bit(HIF_HOLDER, &gh->gh_iflags)); >- > return gh->gh_error; > } > >-void gfs2_print_dbg(struct gfs2_glock_iter *gi, const char *fmt, ...) >+void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...) > { > va_list args; > > va_start(args, fmt); >- if (gi) { >+ if (seq) { >+ struct gfs2_glock_iter *gi = seq->private; > vsprintf(gi->string, fmt, args); >- seq_printf(gi->seq, gi->string); >- } >- else >+ seq_printf(seq, gi->string); >+ } else { >+ printk(KERN_ERR " "); > vprintk(fmt, args); >+ } > va_end(args); > } > >@@ -843,35 +893,44 @@ static inline void add_to_queue(struct g > struct gfs2_holder *gh2; > int try_lock = 0; > >- BUG_ON(!gh->gh_owner_pid); >+ BUG_ON(gh->gh_owner_pid == 0); > if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags)) >- glock_bug(gl); >+ GLOCK_BUG_ON(gl, 1); > >- if ((gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) && >- test_bit(GLF_LOCK, &gl->gl_flags)) >- try_lock = 1; >+ if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) { >+ if (test_bit(GLF_LOCK, &gl->gl_flags)) >+ try_lock = 1; >+ if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags)) >+ goto fail; >+ } > > list_for_each_entry(gh2, &gl->gl_holders, gh_list) { > if (unlikely(gh2->gh_owner_pid == gh->gh_owner_pid && > (gh->gh_gl->gl_ops->go_type != LM_TYPE_FLOCK))) > goto trap_recursive; >- if (test_bit(HIF_HOLDER, &gh2->gh_iflags)) >- continue; > if (try_lock && >- !(gh2->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) { >+ !(gh2->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) && >+ !may_grant(gl, gh)) { >+fail: > gh->gh_error = GLR_TRYFAILED; > gfs2_holder_wake(gh); > return; > } >+ if (test_bit(HIF_HOLDER, &gh2->gh_iflags)) >+ continue; > if (unlikely((gh->gh_flags & LM_FLAG_PRIORITY) && !insert_pt)) > insert_pt = &gh2->gh_list; > } > if (likely(insert_pt == NULL)) { > list_add_tail(&gh->gh_list, &gl->gl_holders); >+ if (unlikely(gh->gh_flags & LM_FLAG_PRIORITY)) >+ goto do_cancel; > return; > } > list_add_tail(&gh->gh_list, insert_pt); >- if (test_bit(GLF_LOCK, &gl->gl_flags)) { >+do_cancel: >+ gh = list_entry(gl->gl_holders.next, struct gfs2_holder, gh_list); >+ if (!(gh->gh_flags & LM_FLAG_PRIORITY)) { > spin_unlock(&gl->gl_spin); > sdp->sd_lockstruct.ls_ops->lm_cancel(gl->gl_lock); > spin_lock(&gl->gl_spin); >@@ -879,16 +938,16 @@ static inline void add_to_queue(struct g > return; > > trap_recursive: >- print_symbol(KERN_WARNING "original: %s\n", gh2->gh_ip); >- printk(KERN_INFO "pid : %d\n", gh2->gh_owner_pid); >- printk(KERN_INFO "lock type: %d req lock state : %d\n", >+ print_symbol(KERN_ERR "original: %s\n", gh2->gh_ip); >+ printk(KERN_ERR "pid : %d\n", gh2->gh_owner_pid); >+ printk(KERN_ERR "lock type: %d req lock state : %d\n", > gh2->gh_gl->gl_name.ln_type, gh2->gh_state); >- print_symbol(KERN_WARNING "new: %s\n", gh->gh_ip); >- printk(KERN_INFO "pid: %d\n", gh->gh_owner_pid); >- printk(KERN_INFO "lock type: %d req lock state : %d\n", >+ print_symbol(KERN_ERR "new: %s\n", gh->gh_ip); >+ printk(KERN_ERR "pid: %d\n", gh->gh_owner_pid); >+ printk(KERN_ERR "lock type: %d req lock state : %d\n", > gh->gh_gl->gl_name.ln_type, gh->gh_state); >- printk(KERN_INFO "current lock state: %u\n", gl->gl_state); >- glock_bug(gl); >+ __dump_glock(NULL, gl); >+ BUG(); > } > > /** >@@ -952,7 +1011,7 @@ void gfs2_glock_dq(struct gfs2_holder *g > list_del_init(&gh->gh_list); > if (find_first_holder(gl) == NULL) { > if (glops->go_unlock) { >- BUG_ON(test_and_set_bit(GLF_LOCK, &gl->gl_flags)); >+ GLOCK_BUG_ON(gl, test_and_set_bit(GLF_LOCK, &gl->gl_flags)); > spin_unlock(&gl->gl_spin); > glops->go_unlock(gh); > spin_lock(&gl->gl_spin); >@@ -1256,7 +1315,8 @@ void gfs2_glock_cb(void *cb_data, unsign > gl = gfs2_glock_find(sdp, &async->lc_name); > if (gfs2_assert_warn(sdp, gl)) > return; >- finish_xmote(gl, async->lc_ret); >+ gl->gl_reply = async->lc_ret; >+ set_bit(GLF_REPLY_PENDING, &gl->gl_flags); > if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) > gfs2_glock_put(gl); > up_read(&gfs2_umount_flush_sem); >@@ -1546,12 +1606,13 @@ static const char *hflags2str(char *buf, > > /** > * dump_holder - print information about a glock holder >+ * @seq: the seq_file struct > * @gh: the glock holder > * > * Returns: 0 on success, -ENOBUFS when we run out of space > */ > >-static int dump_holder(struct gfs2_glock_iter *gi, struct gfs2_holder *gh) >+static int dump_holder(struct seq_file *seq, const struct gfs2_holder *gh) > { > struct task_struct *gh_owner = NULL; > char buffer[KSYM_SYMBOL_LEN]; >@@ -1560,7 +1621,7 @@ static int dump_holder(struct gfs2_glock > sprint_symbol(buffer, gh->gh_ip); > if (gh->gh_owner_pid) > gh_owner = find_task_by_pid(gh->gh_owner_pid); >- gfs2_print_dbg(gi, " H: s:%s f:%s e:%d p:%ld [%s] %s\n", >+ gfs2_print_dbg(seq, " H: s:%s f:%s e:%d p:%ld [%s] %s\n", > state2str(gh->gh_state), > hflags2str(flags_buf, gh->gh_flags, gh->gh_iflags), > gh->gh_error, >@@ -1569,35 +1630,39 @@ static int dump_holder(struct gfs2_glock > return 0; > } > >-static const char *gflags2str(char *buf, unsigned long gflags) >+static const char *gflags2str(char *buf, const unsigned long *gflags) > { > char *p = buf; >- if (test_bit(GLF_LOCK, &gflags)) >+ if (test_bit(GLF_LOCK, gflags)) > *p++ = 'l'; >- if (test_bit(GLF_STICKY, &gflags)) >+ if (test_bit(GLF_STICKY, gflags)) > *p++ = 's'; >- if (test_bit(GLF_DEMOTE, &gflags)) >+ if (test_bit(GLF_DEMOTE, gflags)) > *p++ = 'D'; >- if (test_bit(GLF_PENDING_DEMOTE, &gflags)) >+ if (test_bit(GLF_PENDING_DEMOTE, gflags)) > *p++ = 'd'; >- if (test_bit(GLF_DEMOTE_IN_PROGRESS, &gflags)) >+ if (test_bit(GLF_DEMOTE_IN_PROGRESS, gflags)) > *p++ = 'p'; >- if (test_bit(GLF_DIRTY, &gflags)) >+ if (test_bit(GLF_DIRTY, gflags)) > *p++ = 'y'; >- if (test_bit(GLF_LFLUSH, &gflags)) >+ if (test_bit(GLF_LFLUSH, gflags)) > *p++ = 'f'; >+ if (test_bit(GLF_INVALIDATE_IN_PROGRESS, gflags)) >+ *p++ = 'i'; >+ if (test_bit(GLF_REPLY_PENDING, gflags)) >+ *p++ = 'r'; > *p = 0; > return buf; > } > > /** >- * dump_glock - print information about a glock >- * @gi: The iteration state >+ * __dump_glock - print information about a glock >+ * @seq: The seq_file struct > * @gl: the glock > * > * The file format is as follows: > * One line per object, capital letters are used to indicate objects >- * G = glock, I = Inode, R = rgrp, H = holder. Glocks are not indented >+ * G = glock, I = Inode, R = rgrp, H = holder. Glocks are not indented, > * other objects are indented by a single space and follow the glock to > * which they are related. Fields are indicated by lower case letters > * followed by a colon and the field value, except for strings which are in >@@ -1608,24 +1673,23 @@ static const char *gflags2str(char *buf, > * Returns: 0 on success, -ENOBUFS when we run out of space > */ > >-static int dump_glock(struct gfs2_glock_iter *gi, struct gfs2_glock *gl) >+static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl) > { > const struct gfs2_glock_operations *glops = gl->gl_ops; > unsigned long long dtime; >- struct gfs2_holder *gh; >+ const struct gfs2_holder *gh; > char gflags_buf[32]; > int error = 0; > >- spin_lock(&gl->gl_spin); > dtime = jiffies - gl->gl_demote_time; > dtime *= 1000000/HZ; /* demote time in uSec */ > if (!test_bit(GLF_DEMOTE, &gl->gl_flags)) > dtime = 0; >- gfs2_print_dbg(gi, "G: s:%s n:%u/%llx f:%s t:%s d:%s/%llu l:%d a:%d r:%d\n", >+ gfs2_print_dbg(seq, "G: s:%s n:%u/%llx f:%s t:%s d:%s/%llu l:%d a:%d r:%d\n", > state2str(gl->gl_state), > gl->gl_name.ln_type, > (unsigned long long)gl->gl_name.ln_number, >- gflags2str(gflags_buf, gl->gl_flags), >+ gflags2str(gflags_buf, &gl->gl_flags), > state2str(gl->gl_target), > state2str(gl->gl_demote_state), dtime, > atomic_read(&gl->gl_lvb_count), >@@ -1633,17 +1697,25 @@ static int dump_glock(struct gfs2_glock_ > atomic_read(&gl->gl_ref)); > > list_for_each_entry(gh, &gl->gl_holders, gh_list) { >- error = dump_holder(gi, gh); >+ error = dump_holder(seq, gh); > if (error) > goto out; > } > if (gl->gl_state != LM_ST_UNLOCKED && glops->go_dump) >- error = glops->go_dump(gi, gl); >+ error = glops->go_dump(seq, gl); > out: >- spin_unlock(&gl->gl_spin); > return error; > } > >+static int dump_glock(struct seq_file *seq, struct gfs2_glock *gl) >+{ >+ int ret; >+ spin_lock(&gl->gl_spin); >+ ret = __dump_glock(seq, gl); >+ spin_unlock(&gl->gl_spin); >+ return ret; >+} >+ > /** > * gfs2_dump_lockstate - print out the current lockstate > * @sdp: the filesystem >@@ -1786,54 +1858,30 @@ static void gfs2_glock_iter_free(struct > { > if (gi->gl) > gfs2_glock_put(gi->gl); >- kfree(gi); >-} >- >-static struct gfs2_glock_iter *gfs2_glock_iter_init(struct gfs2_sbd *sdp) >-{ >- struct gfs2_glock_iter *gi; >- >- gi = kmalloc(sizeof (*gi), GFP_KERNEL); >- if (!gi) >- return NULL; >- >- gi->sdp = sdp; >- gi->hash = 0; >- gi->seq = NULL; > gi->gl = NULL; >- memset(gi->string, 0, sizeof(gi->string)); >- >- if (gfs2_glock_iter_next(gi)) { >- gfs2_glock_iter_free(gi); >- return NULL; >- } >- >- return gi; > } > >-static void *gfs2_glock_seq_start(struct seq_file *file, loff_t *pos) >+static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos) > { >- struct gfs2_glock_iter *gi; >+ struct gfs2_glock_iter *gi = seq->private; > loff_t n = *pos; > >- gi = gfs2_glock_iter_init(file->private); >- if (!gi) >- return NULL; >+ gi->hash = 0; > >- while (n--) { >+ do { > if (gfs2_glock_iter_next(gi)) { > gfs2_glock_iter_free(gi); > return NULL; > } >- } >+ } while (n--); > >- return gi; >+ return gi->gl; > } > >-static void *gfs2_glock_seq_next(struct seq_file *file, void *iter_ptr, >+static void *gfs2_glock_seq_next(struct seq_file *seq, void *iter_ptr, > loff_t *pos) > { >- struct gfs2_glock_iter *gi = iter_ptr; >+ struct gfs2_glock_iter *gi = seq->private; > > (*pos)++; > >@@ -1842,24 +1890,18 @@ static void *gfs2_glock_seq_next(struct > return NULL; > } > >- return gi; >+ return gi->gl; > } > >-static void gfs2_glock_seq_stop(struct seq_file *file, void *iter_ptr) >+static void gfs2_glock_seq_stop(struct seq_file *seq, void *iter_ptr) > { >- struct gfs2_glock_iter *gi = iter_ptr; >- if (gi) >- gfs2_glock_iter_free(gi); >+ struct gfs2_glock_iter *gi = seq->private; >+ gfs2_glock_iter_free(gi); > } > >-static int gfs2_glock_seq_show(struct seq_file *file, void *iter_ptr) >+static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr) > { >- struct gfs2_glock_iter *gi = iter_ptr; >- >- gi->seq = file; >- dump_glock(gi, gi->gl); >- >- return 0; >+ return dump_glock(seq, iter_ptr); > } > > static struct seq_operations gfs2_glock_seq_ops = { >@@ -1871,17 +1913,14 @@ static struct seq_operations gfs2_glock_ > > static int gfs2_debugfs_open(struct inode *inode, struct file *file) > { >- struct seq_file *seq; >- int ret; >- >- ret = seq_open(file, &gfs2_glock_seq_ops); >- if (ret) >- return ret; >- >- seq = file->private_data; >- seq->private = inode->i_private; >- >- return 0; >+ int ret = seq_open_private(file, &gfs2_glock_seq_ops, >+ sizeof(struct gfs2_glock_iter)); >+ if (ret == 0) { >+ struct seq_file *seq = file->private_data; >+ struct gfs2_glock_iter *gi = seq->private; >+ gi->sdp = inode->i_private; >+ } >+ return ret; > } > > static const struct file_operations gfs2_debug_fops = { >@@ -1889,7 +1928,7 @@ static const struct file_operations gfs2 > .open = gfs2_debugfs_open, > .read = seq_read, > .llseek = seq_lseek, >- .release = seq_release >+ .release = seq_release_private, > }; > > int gfs2_create_debugfs_file(struct gfs2_sbd *sdp) >diff -pur a/fs/gfs2/glock.c.~1~ b/fs/gfs2/glock.c.~1~ >--- a/fs/gfs2/glock.c.~1~ 2008-05-02 09:49:38.000000000 -0500 >+++ b/fs/gfs2/glock.c.~1~ 2008-05-21 11:14:41.000000000 -0500 >@@ -47,10 +47,18 @@ struct gfs2_gl_hash_bucket { > struct hlist_head hb_list; > }; > >+struct gfs2_glock_iter { >+ int hash; /* hash bucket index */ >+ struct gfs2_sbd *sdp; /* incore superblock */ >+ struct gfs2_glock *gl; /* current glock struct */ >+ char string[512]; /* scratch space */ >+}; >+ > typedef void (*glock_examiner) (struct gfs2_glock * gl); > > static int gfs2_dump_lockstate(struct gfs2_sbd *sdp); >-static int dump_glock(struct gfs2_glock_iter *gi, struct gfs2_glock *gl); >+static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl); >+#define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { __dump_glock(NULL, gl); BUG(); } } while(0) > static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target); > > static DECLARE_RWSEM(gfs2_umount_flush_sem); >@@ -113,15 +121,36 @@ static inline rwlock_t *gl_lock_addr(uns > } > #endif > >-/** >- * glock_bug - Report a glock bug and dump appropriate information >- */ >-#define glock_bug(gl) \ >-{ \ >- if (spin_is_locked(&gl->gl_spin)) \ >- spin_unlock(&gl->gl_spin); \ >- dump_glock(NULL, gl); \ >- BUG(); \ >+/* copied from upstream kernel: */ >+void *__seq_open_private(struct file *f, struct seq_operations *ops, >+ int psize) >+{ >+ int rc; >+ void *private; >+ struct seq_file *seq; >+ >+ private = kzalloc(psize, GFP_KERNEL); >+ if (private == NULL) >+ goto out; >+ >+ rc = seq_open(f, ops); >+ if (rc < 0) >+ goto out_free; >+ >+ seq = f->private_data; >+ seq->private = private; >+ return private; >+ >+out_free: >+ kfree(private); >+out: >+ return NULL; >+} >+ >+int seq_open_private(struct file *filp, struct seq_operations *ops, >+ int psize) >+{ >+ return __seq_open_private(filp, ops, psize) ? 0 : -ENOMEM; > } > > /** >@@ -185,15 +214,14 @@ void gfs2_glock_hold(struct gfs2_glock * > int gfs2_glock_put(struct gfs2_glock *gl) > { > int rv = 0; >- struct gfs2_sbd *sdp = gl->gl_sbd; > > write_lock(gl_lock_addr(gl->gl_hash)); > if (atomic_dec_and_test(&gl->gl_ref)) { > hlist_del(&gl->gl_list); > write_unlock(gl_lock_addr(gl->gl_hash)); >- gfs2_assert(sdp, gl->gl_state == LM_ST_UNLOCKED); >- gfs2_assert(sdp, list_empty(&gl->gl_reclaim)); >- gfs2_assert(sdp, list_empty(&gl->gl_holders)); >+ GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_UNLOCKED); >+ GLOCK_BUG_ON(gl, !list_empty(&gl->gl_reclaim)); >+ GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders)); > glock_free(gl); > rv = 1; > goto out; >@@ -313,6 +341,7 @@ restart: > gh->gh_error = ret; > list_del_init(&gh->gh_list); > gfs2_holder_wake(gh); >+ goto restart; > } > set_bit(HIF_HOLDER, &gh->gh_iflags); > gfs2_holder_wake(gh); >@@ -334,7 +363,7 @@ restart: > * > */ > >-static void do_error(struct gfs2_glock *gl, int ret) >+static inline void do_error(struct gfs2_glock *gl, const int ret) > { > struct gfs2_holder *gh, *tmp; > >@@ -395,6 +424,8 @@ static void state_change(struct gfs2_glo > > static void gfs2_demote_wake(struct gfs2_glock *gl) > { >+ gl->gl_prevdemote_state = gl->gl_demote_state; >+ gl->gl_lastdemote_place = "gfs2_demote_wake"; > gl->gl_demote_state = LM_ST_EXCLUSIVE; > clear_bit(GLF_DEMOTE, &gl->gl_flags); > smp_mb__after_clear_bit(); >@@ -455,7 +486,7 @@ retry: > break; > default: /* Everything else */ > printk(KERN_ERR "GFS2: wanted %u got %u\n", gl->gl_target, state); >- glock_bug(gl); >+ GLOCK_BUG_ON(gl, 1); > } > spin_unlock(&gl->gl_spin); > gfs2_glock_put(gl); >@@ -467,9 +498,16 @@ retry: > gfs2_demote_wake(gl); > if (state != LM_ST_UNLOCKED) { > if (glops->go_xmote_bh) { >+ int rv; > spin_unlock(&gl->gl_spin); >- glops->go_xmote_bh(gl, gh); >+ rv = glops->go_xmote_bh(gl, gh); >+ if (rv == -EAGAIN) >+ return; > spin_lock(&gl->gl_spin); >+ if (rv) { >+ do_error(gl, rv); >+ goto out; >+ } > } > do_promote(gl); > } >@@ -509,12 +547,18 @@ static void do_xmote(struct gfs2_glock * > LM_FLAG_PRIORITY); > BUG_ON(gl->gl_state == target); > BUG_ON(gl->gl_state == gl->gl_target); >+ if ((target == LM_ST_UNLOCKED || target == LM_ST_DEFERRED) && >+ glops->go_inval) { >+ set_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags); >+ do_error(gl, 0); /* Fail queued try locks */ >+ } > spin_unlock(&gl->gl_spin); > if (glops->go_xmote_th) > glops->go_xmote_th(gl); >- if ((target == LM_ST_UNLOCKED || >- target == LM_ST_DEFERRED) && glops->go_inval) >- glops->go_inval(gl, DIO_METADATA); >+ if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags)) >+ glops->go_inval(gl, target == LM_ST_DEFERRED ? 0 : DIO_METADATA); >+ clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags); >+ > gfs2_glock_hold(gl); > if (target != LM_ST_UNLOCKED && (gl->gl_state == LM_ST_SHARED || > gl->gl_state == LM_ST_DEFERRED) && >@@ -522,10 +566,14 @@ static void do_xmote(struct gfs2_glock * > lck_flags |= LM_FLAG_TRY_1CB; > ret = gfs2_lm_lock(sdp, gl->gl_lock, gl->gl_state, target, lck_flags); > >- if (!(ret & LM_OUT_ASYNC)) >+ if (!(ret & LM_OUT_ASYNC)) { > finish_xmote(gl, ret); >- else >- gfs2_assert_warn(sdp, ret == LM_OUT_ASYNC); >+ gfs2_glock_hold(gl); >+ if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) >+ gfs2_glock_put(gl); >+ } else { >+ GLOCK_BUG_ON(gl, ret != LM_OUT_ASYNC); >+ } > spin_lock(&gl->gl_spin); > } > >@@ -560,11 +608,10 @@ static void run_queue(struct gfs2_glock > if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) > return; > >- BUG_ON(test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags)); >+ GLOCK_BUG_ON(gl, test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags)); > > if (test_bit(GLF_DEMOTE, &gl->gl_flags) && > gl->gl_demote_state != gl->gl_state) { >- do_error(gl, 0); /* Fail queued try locks */ > if (find_first_holder(gl)) > goto out; > if (nonblock) >@@ -594,15 +641,24 @@ out: > > static void glock_work_func(void *data) > { >+ unsigned long delay = 0; > struct gfs2_glock *gl = (struct gfs2_glock *)data; > >+ if (test_and_clear_bit(GLF_REPLY_PENDING, &gl->gl_flags)) >+ finish_xmote(gl, gl->gl_reply); > spin_lock(&gl->gl_spin); >- if (test_and_clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && >- gl->gl_demote_state != LM_ST_EXCLUSIVE) >- set_bit(GLF_DEMOTE, &gl->gl_flags); >+ if (test_and_clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags)) { >+ unsigned long holdtime, now = jiffies; >+ holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time; >+ if (time_before(now, holdtime)) >+ delay = holdtime - now; >+ set_bit(delay ? GLF_PENDING_DEMOTE : GLF_DEMOTE, &gl->gl_flags); >+ } > run_queue(gl, 0); > spin_unlock(&gl->gl_spin); >- gfs2_glock_put(gl); >+ if (!delay || >+ queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0) >+ gfs2_glock_put(gl); > } > > /** >@@ -646,6 +702,8 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, > gl->gl_state = LM_ST_UNLOCKED; > gl->gl_target = LM_ST_UNLOCKED; > gl->gl_demote_state = LM_ST_EXCLUSIVE; >+ gl->gl_prevdemote_state = LM_ST_EXCLUSIVE; >+ gl->gl_lastdemote_place = "gfs2_glock_get"; > gl->gl_hash = hash; > gl->gl_ops = glops; > gl->gl_stamp = jiffies; >@@ -781,6 +839,8 @@ static void handle_callback(struct gfs2_ > > set_bit(bit, &gl->gl_flags); > if (gl->gl_demote_state == LM_ST_EXCLUSIVE) { >+ gl->gl_prevdemote_state = gl->gl_demote_state; >+ gl->gl_lastdemote_place = "handle_callback EX"; > gl->gl_demote_state = state; > gl->gl_demote_time = jiffies; > if (remote && gl->gl_ops->go_type == LM_TYPE_IOPEN && >@@ -788,6 +848,8 @@ static void handle_callback(struct gfs2_ > gfs2_glock_schedule_for_reclaim(gl); > } else if (gl->gl_demote_state != LM_ST_UNLOCKED && > gl->gl_demote_state != state) { >+ gl->gl_prevdemote_state = gl->gl_demote_state; >+ gl->gl_lastdemote_place = "handle_callback UN"; > gl->gl_demote_state = LM_ST_UNLOCKED; > } > } >@@ -801,27 +863,23 @@ static void handle_callback(struct gfs2_ > > int gfs2_glock_wait(struct gfs2_holder *gh) > { >- struct gfs2_glock *gl = gh->gh_gl; >- struct gfs2_sbd *sdp = gl->gl_sbd; >- > wait_on_holder(gh); >- if (gh->gh_error == 0) >- gfs2_assert_withdraw(sdp, test_bit(HIF_HOLDER, &gh->gh_iflags)); >- > return gh->gh_error; > } > >-void gfs2_print_dbg(struct gfs2_glock_iter *gi, const char *fmt, ...) >+void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...) > { > va_list args; > > va_start(args, fmt); >- if (gi) { >+ if (seq) { >+ struct gfs2_glock_iter *gi = seq->private; > vsprintf(gi->string, fmt, args); >- seq_printf(gi->seq, gi->string); >- } >- else >+ seq_printf(seq, gi->string); >+ } else { >+ printk(KERN_ERR " "); > vprintk(fmt, args); >+ } > va_end(args); > } > >@@ -843,35 +901,44 @@ static inline void add_to_queue(struct g > struct gfs2_holder *gh2; > int try_lock = 0; > >- BUG_ON(!gh->gh_owner_pid); >+ BUG_ON(gh->gh_owner_pid == 0); > if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags)) >- glock_bug(gl); >+ GLOCK_BUG_ON(gl, 1); > >- if ((gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) && >- test_bit(GLF_LOCK, &gl->gl_flags)) >- try_lock = 1; >+ if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) { >+ if (test_bit(GLF_LOCK, &gl->gl_flags)) >+ try_lock = 1; >+ if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags)) >+ goto fail; >+ } > > list_for_each_entry(gh2, &gl->gl_holders, gh_list) { > if (unlikely(gh2->gh_owner_pid == gh->gh_owner_pid && > (gh->gh_gl->gl_ops->go_type != LM_TYPE_FLOCK))) > goto trap_recursive; >- if (test_bit(HIF_HOLDER, &gh2->gh_iflags)) >- continue; > if (try_lock && >- !(gh2->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) { >+ !(gh2->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) && >+ !may_grant(gl, gh)) { >+fail: > gh->gh_error = GLR_TRYFAILED; > gfs2_holder_wake(gh); > return; > } >+ if (test_bit(HIF_HOLDER, &gh2->gh_iflags)) >+ continue; > if (unlikely((gh->gh_flags & LM_FLAG_PRIORITY) && !insert_pt)) > insert_pt = &gh2->gh_list; > } > if (likely(insert_pt == NULL)) { > list_add_tail(&gh->gh_list, &gl->gl_holders); >+ if (unlikely(gh->gh_flags & LM_FLAG_PRIORITY)) >+ goto do_cancel; > return; > } > list_add_tail(&gh->gh_list, insert_pt); >- if (test_bit(GLF_LOCK, &gl->gl_flags)) { >+do_cancel: >+ gh = list_entry(gl->gl_holders.next, struct gfs2_holder, gh_list); >+ if (!(gh->gh_flags & LM_FLAG_PRIORITY)) { > spin_unlock(&gl->gl_spin); > sdp->sd_lockstruct.ls_ops->lm_cancel(gl->gl_lock); > spin_lock(&gl->gl_spin); >@@ -879,16 +946,16 @@ static inline void add_to_queue(struct g > return; > > trap_recursive: >- print_symbol(KERN_WARNING "original: %s\n", gh2->gh_ip); >- printk(KERN_INFO "pid : %d\n", gh2->gh_owner_pid); >- printk(KERN_INFO "lock type: %d req lock state : %d\n", >+ print_symbol(KERN_ERR "original: %s\n", gh2->gh_ip); >+ printk(KERN_ERR "pid : %d\n", gh2->gh_owner_pid); >+ printk(KERN_ERR "lock type: %d req lock state : %d\n", > gh2->gh_gl->gl_name.ln_type, gh2->gh_state); >- print_symbol(KERN_WARNING "new: %s\n", gh->gh_ip); >- printk(KERN_INFO "pid: %d\n", gh->gh_owner_pid); >- printk(KERN_INFO "lock type: %d req lock state : %d\n", >+ print_symbol(KERN_ERR "new: %s\n", gh->gh_ip); >+ printk(KERN_ERR "pid: %d\n", gh->gh_owner_pid); >+ printk(KERN_ERR "lock type: %d req lock state : %d\n", > gh->gh_gl->gl_name.ln_type, gh->gh_state); >- printk(KERN_INFO "current lock state: %u\n", gl->gl_state); >- glock_bug(gl); >+ __dump_glock(NULL, gl); >+ BUG(); > } > > /** >@@ -952,7 +1019,7 @@ void gfs2_glock_dq(struct gfs2_holder *g > list_del_init(&gh->gh_list); > if (find_first_holder(gl) == NULL) { > if (glops->go_unlock) { >- BUG_ON(test_and_set_bit(GLF_LOCK, &gl->gl_flags)); >+ GLOCK_BUG_ON(gl, test_and_set_bit(GLF_LOCK, &gl->gl_flags)); > spin_unlock(&gl->gl_spin); > glops->go_unlock(gh); > spin_lock(&gl->gl_spin); >@@ -1256,7 +1323,8 @@ void gfs2_glock_cb(void *cb_data, unsign > gl = gfs2_glock_find(sdp, &async->lc_name); > if (gfs2_assert_warn(sdp, gl)) > return; >- finish_xmote(gl, async->lc_ret); >+ gl->gl_reply = async->lc_ret; >+ set_bit(GLF_REPLY_PENDING, &gl->gl_flags); > if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) > gfs2_glock_put(gl); > up_read(&gfs2_umount_flush_sem); >@@ -1546,12 +1614,13 @@ static const char *hflags2str(char *buf, > > /** > * dump_holder - print information about a glock holder >+ * @seq: the seq_file struct > * @gh: the glock holder > * > * Returns: 0 on success, -ENOBUFS when we run out of space > */ > >-static int dump_holder(struct gfs2_glock_iter *gi, struct gfs2_holder *gh) >+static int dump_holder(struct seq_file *seq, const struct gfs2_holder *gh) > { > struct task_struct *gh_owner = NULL; > char buffer[KSYM_SYMBOL_LEN]; >@@ -1560,7 +1629,7 @@ static int dump_holder(struct gfs2_glock > sprint_symbol(buffer, gh->gh_ip); > if (gh->gh_owner_pid) > gh_owner = find_task_by_pid(gh->gh_owner_pid); >- gfs2_print_dbg(gi, " H: s:%s f:%s e:%d p:%ld [%s] %s\n", >+ gfs2_print_dbg(seq, " H: s:%s f:%s e:%d p:%ld [%s] %s\n", > state2str(gh->gh_state), > hflags2str(flags_buf, gh->gh_flags, gh->gh_iflags), > gh->gh_error, >@@ -1569,35 +1638,39 @@ static int dump_holder(struct gfs2_glock > return 0; > } > >-static const char *gflags2str(char *buf, unsigned long gflags) >+static const char *gflags2str(char *buf, const unsigned long *gflags) > { > char *p = buf; >- if (test_bit(GLF_LOCK, &gflags)) >+ if (test_bit(GLF_LOCK, gflags)) > *p++ = 'l'; >- if (test_bit(GLF_STICKY, &gflags)) >+ if (test_bit(GLF_STICKY, gflags)) > *p++ = 's'; >- if (test_bit(GLF_DEMOTE, &gflags)) >+ if (test_bit(GLF_DEMOTE, gflags)) > *p++ = 'D'; >- if (test_bit(GLF_PENDING_DEMOTE, &gflags)) >+ if (test_bit(GLF_PENDING_DEMOTE, gflags)) > *p++ = 'd'; >- if (test_bit(GLF_DEMOTE_IN_PROGRESS, &gflags)) >+ if (test_bit(GLF_DEMOTE_IN_PROGRESS, gflags)) > *p++ = 'p'; >- if (test_bit(GLF_DIRTY, &gflags)) >+ if (test_bit(GLF_DIRTY, gflags)) > *p++ = 'y'; >- if (test_bit(GLF_LFLUSH, &gflags)) >+ if (test_bit(GLF_LFLUSH, gflags)) > *p++ = 'f'; >+ if (test_bit(GLF_INVALIDATE_IN_PROGRESS, gflags)) >+ *p++ = 'i'; >+ if (test_bit(GLF_REPLY_PENDING, gflags)) >+ *p++ = 'r'; > *p = 0; > return buf; > } > > /** >- * dump_glock - print information about a glock >- * @gi: The iteration state >+ * __dump_glock - print information about a glock >+ * @seq: The seq_file struct > * @gl: the glock > * > * The file format is as follows: > * One line per object, capital letters are used to indicate objects >- * G = glock, I = Inode, R = rgrp, H = holder. Glocks are not indented >+ * G = glock, I = Inode, R = rgrp, H = holder. Glocks are not indented, > * other objects are indented by a single space and follow the glock to > * which they are related. Fields are indicated by lower case letters > * followed by a colon and the field value, except for strings which are in >@@ -1608,43 +1681,50 @@ static const char *gflags2str(char *buf, > * Returns: 0 on success, -ENOBUFS when we run out of space > */ > >-static int dump_glock(struct gfs2_glock_iter *gi, struct gfs2_glock *gl) >+static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl) > { > const struct gfs2_glock_operations *glops = gl->gl_ops; > unsigned long long dtime; >- struct gfs2_holder *gh; >+ const struct gfs2_holder *gh; > char gflags_buf[32]; > int error = 0; >- int x, x_adj; > >- spin_lock(&gl->gl_spin); > dtime = jiffies - gl->gl_demote_time; > dtime *= 1000000/HZ; /* demote time in uSec */ > if (!test_bit(GLF_DEMOTE, &gl->gl_flags)) > dtime = 0; >- gfs2_print_dbg(gi, "G: s:%s n:%u/%llx f:%s t:%s d:%s/%llu l:%d a:%d r:%d\n", >+ gfs2_print_dbg(seq, "G: s:%s n:%u/%llx f:%s t:%s d:%s/%llu l:%d a:%d r:%d %s/%s\n", > state2str(gl->gl_state), > gl->gl_name.ln_type, > (unsigned long long)gl->gl_name.ln_number, >- gflags2str(gflags_buf, gl->gl_flags), >+ gflags2str(gflags_buf, &gl->gl_flags), > state2str(gl->gl_target), > state2str(gl->gl_demote_state), dtime, > atomic_read(&gl->gl_lvb_count), > atomic_read(&gl->gl_ail_count), >- atomic_read(&gl->gl_ref)); >+ atomic_read(&gl->gl_ref), >+ state2str(gl->gl_prevdemote_state), gl->gl_lastdemote_place); > > list_for_each_entry(gh, &gl->gl_holders, gh_list) { >- error = dump_holder(gi, gh); >+ error = dump_holder(seq, gh); > if (error) > goto out; > } > if (gl->gl_state != LM_ST_UNLOCKED && glops->go_dump) >- error = glops->go_dump(gi, gl); >+ error = glops->go_dump(seq, gl); > out: >- spin_unlock(&gl->gl_spin); > return error; > } > >+static int dump_glock(struct seq_file *seq, struct gfs2_glock *gl) >+{ >+ int ret; >+ spin_lock(&gl->gl_spin); >+ ret = __dump_glock(seq, gl); >+ spin_unlock(&gl->gl_spin); >+ return ret; >+} >+ > /** > * gfs2_dump_lockstate - print out the current lockstate > * @sdp: the filesystem >@@ -1787,54 +1867,30 @@ static void gfs2_glock_iter_free(struct > { > if (gi->gl) > gfs2_glock_put(gi->gl); >- kfree(gi); >-} >- >-static struct gfs2_glock_iter *gfs2_glock_iter_init(struct gfs2_sbd *sdp) >-{ >- struct gfs2_glock_iter *gi; >- >- gi = kmalloc(sizeof (*gi), GFP_KERNEL); >- if (!gi) >- return NULL; >- >- gi->sdp = sdp; >- gi->hash = 0; >- gi->seq = NULL; > gi->gl = NULL; >- memset(gi->string, 0, sizeof(gi->string)); >- >- if (gfs2_glock_iter_next(gi)) { >- gfs2_glock_iter_free(gi); >- return NULL; >- } >- >- return gi; > } > >-static void *gfs2_glock_seq_start(struct seq_file *file, loff_t *pos) >+static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos) > { >- struct gfs2_glock_iter *gi; >+ struct gfs2_glock_iter *gi = seq->private; > loff_t n = *pos; > >- gi = gfs2_glock_iter_init(file->private); >- if (!gi) >- return NULL; >+ gi->hash = 0; > >- while (n--) { >+ do { > if (gfs2_glock_iter_next(gi)) { > gfs2_glock_iter_free(gi); > return NULL; > } >- } >+ } while (n--); > >- return gi; >+ return gi->gl; > } > >-static void *gfs2_glock_seq_next(struct seq_file *file, void *iter_ptr, >+static void *gfs2_glock_seq_next(struct seq_file *seq, void *iter_ptr, > loff_t *pos) > { >- struct gfs2_glock_iter *gi = iter_ptr; >+ struct gfs2_glock_iter *gi = seq->private; > > (*pos)++; > >@@ -1843,24 +1899,18 @@ static void *gfs2_glock_seq_next(struct > return NULL; > } > >- return gi; >+ return gi->gl; > } > >-static void gfs2_glock_seq_stop(struct seq_file *file, void *iter_ptr) >+static void gfs2_glock_seq_stop(struct seq_file *seq, void *iter_ptr) > { >- struct gfs2_glock_iter *gi = iter_ptr; >- if (gi) >- gfs2_glock_iter_free(gi); >+ struct gfs2_glock_iter *gi = seq->private; >+ gfs2_glock_iter_free(gi); > } > >-static int gfs2_glock_seq_show(struct seq_file *file, void *iter_ptr) >+static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr) > { >- struct gfs2_glock_iter *gi = iter_ptr; >- >- gi->seq = file; >- dump_glock(gi, gi->gl); >- >- return 0; >+ return dump_glock(seq, iter_ptr); > } > > static struct seq_operations gfs2_glock_seq_ops = { >@@ -1872,17 +1922,14 @@ static struct seq_operations gfs2_glock_ > > static int gfs2_debugfs_open(struct inode *inode, struct file *file) > { >- struct seq_file *seq; >- int ret; >- >- ret = seq_open(file, &gfs2_glock_seq_ops); >- if (ret) >- return ret; >- >- seq = file->private_data; >- seq->private = inode->i_private; >- >- return 0; >+ int ret = seq_open_private(file, &gfs2_glock_seq_ops, >+ sizeof(struct gfs2_glock_iter)); >+ if (ret == 0) { >+ struct seq_file *seq = file->private_data; >+ struct gfs2_glock_iter *gi = seq->private; >+ gi->sdp = inode->i_private; >+ } >+ return ret; > } > > static const struct file_operations gfs2_debug_fops = { >@@ -1890,7 +1937,7 @@ static const struct file_operations gfs2 > .open = gfs2_debugfs_open, > .read = seq_read, > .llseek = seq_lseek, >- .release = seq_release >+ .release = seq_release_private, > }; > > int gfs2_create_debugfs_file(struct gfs2_sbd *sdp) >diff -pur a/fs/gfs2/glock.h b/fs/gfs2/glock.h >--- a/fs/gfs2/glock.h 2008-04-22 15:42:18.000000000 -0500 >+++ b/fs/gfs2/glock.h 2008-05-16 10:21:04.000000000 -0500 >@@ -95,7 +95,7 @@ int gfs2_glock_nq_num(struct gfs2_sbd *s > int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs); > void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs); > void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs); >-void gfs2_print_dbg(struct gfs2_glock_iter *gi, const char *fmt, ...); >+void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...); > > /** > * gfs2_glock_nq_init - intialize a holder and enqueue it on a glock >@@ -128,7 +128,6 @@ int gfs2_lvb_hold(struct gfs2_glock *gl) > void gfs2_lvb_unhold(struct gfs2_glock *gl); > > void gfs2_glock_cb(void *cb_data, unsigned int type, void *data); >- > void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl); > void gfs2_reclaim_glock(struct gfs2_sbd *sdp); > void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait); >diff -pur a/fs/gfs2/glops.c b/fs/gfs2/glops.c >--- a/fs/gfs2/glops.c 2008-05-02 08:48:08.000000000 -0500 >+++ b/fs/gfs2/glops.c 2008-05-21 12:48:26.000000000 -0500 >@@ -13,6 +13,7 @@ > #include <linux/buffer_head.h> > #include <linux/gfs2_ondisk.h> > #include <linux/lm_interface.h> >+#include <linux/bio.h> > > #include "gfs2.h" > #include "incore.h" >@@ -199,25 +200,6 @@ static void inode_go_sync(struct gfs2_gl > } > > /** >- * inode_go_xmote_bh - After promoting/demoting a glock >- * @gl: the glock >- * >- */ >- >-static void inode_go_xmote_bh(struct gfs2_glock *gl, struct gfs2_holder *gh) >-{ >- struct buffer_head *bh; >- int error; >- >- if (gl->gl_state != LM_ST_UNLOCKED && >- (!gh || !(gh->gh_flags & GL_SKIP))) { >- error = gfs2_meta_read(gl, gl->gl_name.ln_number, 0, &bh); >- if (!error) >- brelse(bh); >- } >-} >- >-/** > * inode_go_inval - prepare a inode glock to be released > * @gl: the glock > * @flags: >@@ -296,18 +278,18 @@ static int inode_go_lock(struct gfs2_hol > > /** > * inode_go_dump - print information about an inode >- * @gi: The iterator >+ * @seq: The iterator > * @ip: the inode > * > * Returns: 0 on success, -ENOBUFS when we run out of space > */ > >-static int inode_go_dump(struct gfs2_glock_iter *gi, struct gfs2_glock *gl) >+static int inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl) > { >- struct gfs2_inode *ip = gl->gl_object; >+ const struct gfs2_inode *ip = gl->gl_object; > if (ip == NULL) > return 0; >- gfs2_print_dbg(gi, " I: n:%llu/%llu t:%u f:0x%08lx\n", >+ gfs2_print_dbg(seq, " I: n:%llu/%llu t:%u f:0x%08lx\n", > (unsigned long long)ip->i_no_formal_ino, > (unsigned long long)ip->i_no_addr, > IF2DT(ip->i_inode.i_mode), ip->i_flags); >@@ -355,17 +337,17 @@ static void rgrp_go_unlock(struct gfs2_h > > /** > * rgrp_go_dump - print out an rgrp >- * @gi: The iterator >+ * @seq: The iterator > * @gl: The glock in question > * > */ > >-static int rgrp_go_dump(struct gfs2_glock_iter *gi, struct gfs2_glock *gl) >+static int rgrp_go_dump(struct seq_file *seq, const struct gfs2_glock *gl) > { >- struct gfs2_rgrpd *rgd = gl->gl_object; >+ const struct gfs2_rgrpd *rgd = gl->gl_object; > if (rgd == NULL) > return 0; >- gfs2_print_dbg(gi, " R: n:%llu\n", (unsigned long long)rgd->rd_addr); >+ gfs2_print_dbg(seq, " R: n:%llu\n", (unsigned long long)rgd->rd_addr); > return 0; > } > >@@ -394,7 +376,7 @@ static void trans_go_xmote_th(struct gfs > * > */ > >-static void trans_go_xmote_bh(struct gfs2_glock *gl, struct gfs2_holder *gh) >+static int trans_go_xmote_bh(struct gfs2_glock *gl, struct gfs2_holder *gh) > { > struct gfs2_sbd *sdp = gl->gl_sbd; > struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode); >@@ -402,8 +384,7 @@ static void trans_go_xmote_bh(struct gfs > struct gfs2_log_header_host head; > int error; > >- if (gl->gl_state != LM_ST_UNLOCKED && >- test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { >+ if (test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { > j_gl->gl_ops->go_inval(j_gl, DIO_METADATA); > > error = gfs2_find_jhead(sdp->sd_jdesc, &head); >@@ -418,6 +399,7 @@ static void trans_go_xmote_bh(struct gfs > gfs2_log_pointers_init(sdp, head.lh_blkno); > } > } >+ return 0; > } > > /** >@@ -439,13 +421,12 @@ const struct gfs2_glock_operations gfs2_ > > const struct gfs2_glock_operations gfs2_inode_glops = { > .go_xmote_th = inode_go_sync, >- .go_xmote_bh = inode_go_xmote_bh, > .go_inval = inode_go_inval, > .go_demote_ok = inode_go_demote_ok, > .go_lock = inode_go_lock, > .go_dump = inode_go_dump, > .go_type = LM_TYPE_INODE, >- .go_min_hold_time = HZ / 10, >+ .go_min_hold_time = HZ / 5, > }; > > const struct gfs2_glock_operations gfs2_rgrp_glops = { >@@ -456,7 +437,7 @@ const struct gfs2_glock_operations gfs2_ > .go_unlock = rgrp_go_unlock, > .go_dump = rgrp_go_dump, > .go_type = LM_TYPE_RGRP, >- .go_min_hold_time = HZ / 10, >+ .go_min_hold_time = HZ / 5, > }; > > const struct gfs2_glock_operations gfs2_trans_glops = { >diff -pur a/fs/gfs2/incore.h b/fs/gfs2/incore.h >--- a/fs/gfs2/incore.h 2008-05-02 09:16:26.000000000 -0500 >+++ b/fs/gfs2/incore.h 2008-05-21 12:36:33.000000000 -0500 >@@ -126,22 +126,14 @@ struct gfs2_bufdata { > struct list_head bd_ail_gl_list; > }; > >-struct gfs2_glock_iter { >- int hash; /* hash bucket index */ >- struct gfs2_sbd *sdp; /* incore superblock */ >- struct gfs2_glock *gl; /* current glock struct */ >- struct seq_file *seq; /* sequence file for debugfs */ >- char string[512]; /* scratch space */ >-}; >- > struct gfs2_glock_operations { > void (*go_xmote_th) (struct gfs2_glock *gl); >- void (*go_xmote_bh) (struct gfs2_glock *gl, struct gfs2_holder *gh); >+ int (*go_xmote_bh) (struct gfs2_glock *gl, struct gfs2_holder *gh); > void (*go_inval) (struct gfs2_glock *gl, int flags); > int (*go_demote_ok) (struct gfs2_glock *gl); > int (*go_lock) (struct gfs2_holder *gh); > void (*go_unlock) (struct gfs2_holder *gh); >- int (*go_dump)(struct gfs2_glock_iter *gi, struct gfs2_glock *gl); >+ int (*go_dump)(struct seq_file *seq, const struct gfs2_glock *gl); > const int go_type; > const unsigned long go_min_hold_time; > }; >@@ -167,13 +159,15 @@ struct gfs2_holder { > }; > > enum { >- GLF_LOCK = 1, >- GLF_STICKY = 2, >- GLF_DEMOTE = 3, >- GLF_PENDING_DEMOTE = 4, >- GLF_DEMOTE_IN_PROGRESS = 5, >- GLF_DIRTY = 6, >- GLF_LFLUSH = 7, >+ GLF_LOCK = 1, >+ GLF_STICKY = 2, >+ GLF_DEMOTE = 3, >+ GLF_PENDING_DEMOTE = 4, >+ GLF_DEMOTE_IN_PROGRESS = 5, >+ GLF_DIRTY = 6, >+ GLF_LFLUSH = 7, >+ GLF_INVALIDATE_IN_PROGRESS = 8, >+ GLF_REPLY_PENDING = 9, > }; > > struct gfs2_glock { >@@ -186,6 +180,7 @@ struct gfs2_glock { > > unsigned int gl_state; > unsigned int gl_target; >+ unsigned int gl_reply; > unsigned int gl_hash; > unsigned int gl_demote_state; /* state requested by remote node */ > unsigned long gl_demote_time; /* time of first demote request */ >diff -pur a/fs/gfs2/inode.c b/fs/gfs2/inode.c >--- a/fs/gfs2/inode.c 2008-05-02 08:48:08.000000000 -0500 >+++ b/fs/gfs2/inode.c 2008-05-21 12:50:23.000000000 -0500 >@@ -138,13 +138,13 @@ void gfs2_set_iop(struct inode *inode) > > if (S_ISREG(mode)) { > inode->i_op = &gfs2_file_iops; >- if (sdp->sd_args.ar_localflocks) >+ if (sdp->sd_args.ar_localflocks) > inode->i_fop = &gfs2_file_fops_nolock; > else > inode->i_fop = &gfs2_file_fops; > } else if (S_ISDIR(mode)) { > inode->i_op = &gfs2_dir_iops; >- if (sdp->sd_args.ar_localflocks) >+ if (sdp->sd_args.ar_localflocks) > inode->i_fop = &gfs2_dir_fops_nolock; > else > inode->i_fop = &gfs2_dir_fops; >diff -pur a/fs/gfs2/locking/dlm/lock.c b/fs/gfs2/locking/dlm/lock.c >--- a/fs/gfs2/locking/dlm/lock.c 2008-05-02 09:33:33.000000000 -0500 >+++ b/fs/gfs2/locking/dlm/lock.c 2008-05-21 10:40:55.000000000 -0500 >@@ -307,6 +307,9 @@ unsigned int gdlm_lock(void *lock, unsig > { > struct gdlm_lock *lp = lock; > >+ if (req_state == LM_ST_UNLOCKED) >+ return gdlm_unlock(lock, cur_state); >+ > clear_bit(LFL_DLM_CANCEL, &lp->flags); > if (flags & LM_FLAG_NOEXP) > set_bit(LFL_NOBLOCK, &lp->flags); >diff -pur a/fs/gfs2/locking/nolock/main.c b/fs/gfs2/locking/nolock/main.c >--- a/fs/gfs2/locking/nolock/main.c 2008-05-02 09:33:42.000000000 -0500 >+++ b/fs/gfs2/locking/nolock/main.c 2008-05-08 13:29:25.000000000 -0500 >@@ -109,6 +109,8 @@ static void nolock_put_lock(void *lock) > static unsigned int nolock_lock(void *lock, unsigned int cur_state, > unsigned int req_state, unsigned int flags) > { >+ if (req_state == LM_ST_UNLOCKED) >+ return 0; > return req_state | LM_OUT_CACHEABLE; > } > >diff -pur a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c >--- a/fs/gfs2/meta_io.c 2008-05-02 08:48:08.000000000 -0500 >+++ b/fs/gfs2/meta_io.c 2008-05-14 11:42:25.000000000 -0500 >@@ -115,7 +115,7 @@ void gfs2_meta_sync(struct gfs2_glock *g > * Returns: the buffer > */ > >-static struct buffer_head *getbuf(struct gfs2_glock *gl, u64 blkno, int create) >+struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create) > { > struct address_space *mapping = gl->gl_aspace->i_mapping; > struct gfs2_sbd *sdp = gl->gl_sbd; >@@ -183,7 +183,7 @@ static void meta_prep_new(struct buffer_ > struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno) > { > struct buffer_head *bh; >- bh = getbuf(gl, blkno, CREATE); >+ bh = gfs2_getbuf(gl, blkno, CREATE); > meta_prep_new(bh); > return bh; > } >@@ -201,7 +201,7 @@ struct buffer_head *gfs2_meta_new(struct > int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, > struct buffer_head **bhp) > { >- *bhp = getbuf(gl, blkno, CREATE); >+ *bhp = gfs2_getbuf(gl, blkno, CREATE); > if (!buffer_uptodate(*bhp)) { > ll_rw_block(READ, 1, bhp); > if (flags & DIO_WAIT) { >@@ -288,7 +288,7 @@ void gfs2_meta_wipe(struct gfs2_inode *i > struct buffer_head *bh; > > while (blen) { >- bh = getbuf(ip->i_gl, bstart, NO_CREATE); >+ bh = gfs2_getbuf(ip->i_gl, bstart, NO_CREATE); > if (bh) { > lock_buffer(bh); > gfs2_log_lock(sdp); >@@ -364,7 +364,7 @@ struct buffer_head *gfs2_meta_ra(struct > if (extlen > max_ra) > extlen = max_ra; > >- first_bh = getbuf(gl, dblock, CREATE); >+ first_bh = gfs2_getbuf(gl, dblock, CREATE); > > if (buffer_uptodate(first_bh)) > goto out; >@@ -375,7 +375,7 @@ struct buffer_head *gfs2_meta_ra(struct > extlen--; > > while (extlen) { >- bh = getbuf(gl, dblock, CREATE); >+ bh = gfs2_getbuf(gl, dblock, CREATE); > > if (!buffer_uptodate(bh) && !buffer_locked(bh)) > ll_rw_block(READA, 1, &bh); >diff -pur a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h >--- a/fs/gfs2/meta_io.h 2008-04-15 15:04:07.000000000 -0500 >+++ b/fs/gfs2/meta_io.h 2008-05-14 11:43:22.000000000 -0500 >@@ -46,6 +46,7 @@ struct buffer_head *gfs2_meta_new(struct > int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, > int flags, struct buffer_head **bhp); > int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh); >+struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create); > > void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, > int meta);
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 447920
:
306378
|
306379
|
306427
|
306428
| 306497 |
306817
|
306906
|
307044