Keep stats on the size of the ordered list and keep track of where it's added to and removed from --- fs/gfs2/bmap.c | 2 +- fs/gfs2/file.c | 2 +- fs/gfs2/incore.h | 12 ++++++++++++ fs/gfs2/log.c | 7 +++++-- fs/gfs2/log.h | 35 +++++++++++++++++++++++++++++++++-- fs/gfs2/ops_fstype.c | 1 + fs/gfs2/quota.c | 8 ++++++++ fs/gfs2/super.c | 2 +- 8 files changed, 62 insertions(+), 7 deletions(-)
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 8569bf3..d9720ce 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -1504,7 +1504,7 @@ static int trunc_end(struct gfs2_inode *ip) ip->i_height = 0; ip->i_goal = ip->i_no_addr; gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); - gfs2_ordered_del_inode(ip); + gfs2_ordered_del_inode(ip, ORD_WHENCE_TRUNC); } ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; ip->i_diskflags &= ~GFS2_DIF_TRUNC_IN_PROG; diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 31b5986..757ec66 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -284,7 +284,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) if (error) goto out; if (new_flags & GFS2_DIF_JDATA) - gfs2_ordered_del_inode(ip); + gfs2_ordered_del_inode(ip, ORD_WHENCE_SETFLAGS); } error = gfs2_trans_begin(sdp, RES_DINODE, 0); if (error) diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 7e78d8a..6fcad2a 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -655,6 +655,17 @@ struct gfs2_pcpu_lkstats { struct gfs2_lkstats lkstats[10]; }; +struct ord_stats { + unsigned long os_ct; + unsigned long os_add; + unsigned long os_rm_trunc; + unsigned long os_rm_evict; + unsigned long os_rm_wait; + unsigned long os_rm_syncfs; + unsigned long os_rm_write; + unsigned long os_rm_setflags; +}; + struct gfs2_sbd { struct super_block *sd_vfs; struct gfs2_pcpu_lkstats __percpu *sd_lkstats; @@ -773,6 +784,7 @@ struct gfs2_sbd { struct list_head sd_log_le_revoke; struct list_head sd_log_le_ordered; + struct ord_stats sd_ord_stats; spinlock_t sd_ordered_lock; atomic_t sd_log_thresh1; diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index cc3f7d1..0257704 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -526,6 +526,7 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp) while (!list_empty(&sdp->sd_log_le_ordered)) { ip = list_entry(sdp->sd_log_le_ordered.next, struct gfs2_inode, i_ordered); list_del(&ip->i_ordered); + ord_stats_adjust(sdp, -1, ORD_WHENCE_WAIT); WARN_ON(!test_and_clear_bit(GIF_ORDERED, &ip->i_flags)); if (ip->i_inode.i_mapping->nrpages == 0) continue; @@ -536,13 +537,15 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp) spin_unlock(&sdp->sd_ordered_lock); } -void gfs2_ordered_del_inode(struct gfs2_inode *ip) +void gfs2_ordered_del_inode(struct gfs2_inode *ip, int whence) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); spin_lock(&sdp->sd_ordered_lock); - if (test_and_clear_bit(GIF_ORDERED, &ip->i_flags)) + if (test_and_clear_bit(GIF_ORDERED, &ip->i_flags)) { list_del(&ip->i_ordered); + ord_stats_adjust(sdp, -1, whence); + } spin_unlock(&sdp->sd_ordered_lock); } diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h index 3721663..bf7729c 100644 --- a/fs/gfs2/log.h +++ b/fs/gfs2/log.h @@ -48,18 +48,49 @@ static inline void gfs2_log_pointers_init(struct gfs2_sbd *sdp, sdp->sd_log_head = sdp->sd_log_tail = value; } +enum { + ORD_WHENCE_TRUNC = 0, + ORD_WHENCE_EVICT = 1, + ORD_WHENCE_WAIT = 2, + ORD_WHENCE_SYNCFS = 3, + ORD_WHENCE_ORD_WRITE = 4, + ORD_WHENCE_SETFLAGS = 5, + ORD_WHENCE_ADD = 6, +}; + +static inline void ord_stats_adjust(struct gfs2_sbd *sdp, int count, int whence) +{ + struct ord_stats *os = &sdp->sd_ord_stats; + + os->os_ct += count; + switch (whence) { + case ORD_WHENCE_TRUNC: os->os_rm_trunc += -(count); break; + case ORD_WHENCE_EVICT: os->os_rm_evict += -(count); break; + case ORD_WHENCE_WAIT: os->os_rm_wait += -(count); break; + case ORD_WHENCE_SYNCFS: os->os_rm_syncfs += -(count); break; + case ORD_WHENCE_ORD_WRITE: os->os_rm_write += -(count); break; + case ORD_WHENCE_SETFLAGS: os->os_rm_setflags += -(count); break; + + case ORD_WHENCE_ADD: os->os_add += count; break; + default: break; + } +} + static inline void gfs2_ordered_add_inode(struct gfs2_inode *ip) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); if (!test_bit(GIF_ORDERED, &ip->i_flags)) { spin_lock(&sdp->sd_ordered_lock); - if (!test_and_set_bit(GIF_ORDERED, &ip->i_flags)) + if (!test_and_set_bit(GIF_ORDERED, &ip->i_flags)) { list_add(&ip->i_ordered, &sdp->sd_log_le_ordered); + ord_stats_adjust(sdp, 1, ORD_WHENCE_ADD); + } spin_unlock(&sdp->sd_ordered_lock); } } -extern void gfs2_ordered_del_inode(struct gfs2_inode *ip); + +extern void gfs2_ordered_del_inode(struct gfs2_inode *ip, int whence); extern unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct, unsigned int ssize); diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 228f38e..378f961 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -104,6 +104,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) atomic_set(&sdp->sd_log_pinned, 0); INIT_LIST_HEAD(&sdp->sd_log_le_revoke); INIT_LIST_HEAD(&sdp->sd_log_le_ordered); + memset(&sdp->sd_ord_stats, 0, sizeof(struct ord_stats)); spin_lock_init(&sdp->sd_ordered_lock); init_waitqueue_head(&sdp->sd_log_waitq); diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 3d5f868..66c5126 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -1572,6 +1572,14 @@ int gfs2_quotad(void *data) else t = 0; finish_wait(&sdp->sd_quota_wait, &wait); + + printk(KERN_WARNING "Ord list Size:%lu +[add_inode:%lu] " + "-[trunc:%lu evict:%lu wait:%lu syncfs:%lu ord_write:%lu" + " setflags:%lu]\n", sdp->sd_ord_stats.os_ct, + sdp->sd_ord_stats.os_add, sdp->sd_ord_stats.os_rm_trunc, + sdp->sd_ord_stats.os_rm_evict, sdp->sd_ord_stats.os_rm_wait, + sdp->sd_ord_stats.os_rm_syncfs, sdp->sd_ord_stats.os_rm_write, + sdp->sd_ord_stats.os_rm_setflags); } return 0; diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 6d7fb54..ee15a50 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -1641,7 +1641,7 @@ out: /* Case 3 starts here */ truncate_inode_pages_final(&inode->i_data); gfs2_rsqa_delete(ip, NULL); - gfs2_ordered_del_inode(ip); + gfs2_ordered_del_inode(ip, ORD_WHENCE_EVICT); clear_inode(inode); gfs2_dir_hash_inval(ip); glock_clear_object(ip->i_gl, ip); -- 2.4.11