This patch adds a new file: /sys/fs/gfs2/*/status which will report
the status of the file system. Catting this file dumps the current
status of the file system according to various superblock variables.
For example:

Journal Checked:   1
Journal Live:      1
Withdrawn:         0
No barriers:       0
No recovery:       0
Demote:            0
No Journal ID:     1
RO Recovery:       0
Skip DLM Unlock:   0
Force AIL Flush:   0
FS Frozen:         0
Withdrawing:       0
Withdraw In Prog:  0
Remote Withdraw:   0
Withdraw Recovery: 0
sd_log_lock held:  0
statfs_spin held:  0
sd_rindex_spin:    0
sd_jindex_spin:    0
sd_trunc_lock:     0
sd_bitmap_lock:    0
sd_ordered_lock:   0
sd_ail_lock:       0
sd_log_error:      0
sd_log_flush_lock: 0
sd_log_flush_lock: 1
sd_ail1_list:      281 transactions, 11 ail1, 1 ail2
sd_ail2_list:      0 transactions, 0 ail1, 0 ail2
sd_log_revokes:    0 / 0
sd_log_in_flight:  1

Signed-off-by: Bob Peterson <rpete...@redhat.com>
---
 fs/gfs2/sys.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 113 insertions(+)

diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
index d28c41bd69b0..ea86ba5e4afb 100644
--- a/fs/gfs2/sys.c
+++ b/fs/gfs2/sys.c
@@ -63,6 +63,117 @@ static ssize_t id_show(struct gfs2_sbd *sdp, char *buf)
                        MAJOR(sdp->sd_vfs->s_dev), MINOR(sdp->sd_vfs->s_dev));
 }
 
+static int count_trans_list(struct gfs2_sbd *sdp, struct list_head *head,
+                           int *ail1, int *ail2)
+{
+       struct gfs2_trans *tr;
+       struct gfs2_bufdata *bd;
+       int unlock_spin, trans = 0;
+
+       *ail1 = *ail2 = 0;
+       unlock_spin = spin_trylock(&sdp->sd_ail_lock);
+
+       list_for_each_entry(tr, head, tr_list) {
+               trans++;
+               list_for_each_entry(bd, &tr->tr_ail1_list, bd_ail_st_list)
+                       (*ail1)++;
+               list_for_each_entry(bd, &tr->tr_ail2_list, bd_ail_st_list)
+                       (*ail2)++;
+       }
+
+       if (unlock_spin)
+               spin_unlock(&sdp->sd_ail_lock);
+
+       return trans;
+}
+
+static int count_list(struct gfs2_sbd *sdp, struct list_head *head)
+{
+       int unlock_spin, count = 0;
+       struct gfs2_bufdata *bd;
+
+       unlock_spin = spin_trylock(&sdp->sd_log_lock);
+
+       list_for_each_entry(bd, head, bd_list)
+               count++;
+       if (unlock_spin)
+               spin_unlock(&sdp->sd_log_lock);
+
+       return count;
+}
+
+static ssize_t status_show(struct gfs2_sbd *sdp, char *buf)
+{
+       unsigned long f = sdp->sd_flags;
+       int trans1, ail11, ail12, trans2, ail21, ail22;
+       unsigned int revokes;
+       ssize_t s;
+
+       trans1 = count_trans_list(sdp, &sdp->sd_ail1_list, &ail11, &ail12);
+       trans2 = count_trans_list(sdp, &sdp->sd_ail2_list, &ail21, &ail22);
+       revokes = count_list(sdp, &sdp->sd_log_revokes);
+       s= snprintf(buf, PAGE_SIZE,
+                   "Journal Checked:   %d\n"
+                   "Journal Live:      %d\n"
+                   "Withdrawn:         %d\n"
+                   "No barriers:       %d\n"
+                   "No recovery:       %d\n"
+                   "Demote:            %d\n"
+                   "No Journal ID:     %d\n"
+                   "RO Recovery:       %d\n"
+                   "Skip DLM Unlock:   %d\n"
+                   "Force AIL Flush:   %d\n"
+                   "FS Frozen:         %d\n"
+                   "Withdrawing:       %d\n"
+                   "Withdraw In Prog:  %d\n"
+                   "Remote Withdraw:   %d\n"
+                   "Withdraw Recovery: %d\n"
+                   "sd_log_lock held:  %d\n"
+                   "statfs_spin held:  %d\n"
+                   "sd_rindex_spin:    %d\n"
+                   "sd_jindex_spin:    %d\n"
+                   "sd_trunc_lock:     %d\n"
+                   "sd_bitmap_lock:    %d\n"
+                   "sd_ordered_lock:   %d\n"
+                   "sd_ail_lock:       %d\n"
+                   "sd_log_error:      %d\n"
+                   "sd_log_flush_lock: %d\n"
+                   "sd_ail1_list:      %d transactions, %d ail1, %d ail2\n"
+                   "sd_ail2_list:      %d transactions, %d ail1, %d ail2\n"
+                   "sd_log_revokes:    %d / %u\n"
+                   "sd_log_in_flight:  %d\n",
+                   test_bit(SDF_JOURNAL_CHECKED, &f),
+                   test_bit(SDF_JOURNAL_LIVE, &f),
+                   test_bit(SDF_WITHDRAWN, &f),
+                   test_bit(SDF_NOBARRIERS, &f),
+                   test_bit(SDF_NORECOVERY, &f),
+                   test_bit(SDF_DEMOTE, &f),
+                   test_bit(SDF_NOJOURNALID, &f),
+                   test_bit(SDF_RORECOVERY, &f),
+                   test_bit(SDF_SKIP_DLM_UNLOCK, &f),
+                   test_bit(SDF_FORCE_AIL_FLUSH, &f),
+                   test_bit(SDF_FS_FROZEN, &f),
+                   test_bit(SDF_WITHDRAWING, &f),
+                   test_bit(SDF_WITHDRAW_IN_PROG, &f),
+                   test_bit(SDF_REMOTE_WITHDRAW, &f),
+                   test_bit(SDF_WITHDRAW_RECOVERY, &f),
+                   spin_is_locked(&sdp->sd_log_lock),
+                   spin_is_locked(&sdp->sd_statfs_spin),
+                   spin_is_locked(&sdp->sd_rindex_spin),
+                   spin_is_locked(&sdp->sd_jindex_spin),
+                   spin_is_locked(&sdp->sd_trunc_lock),
+                   spin_is_locked(&sdp->sd_bitmap_lock),
+                   spin_is_locked(&sdp->sd_ordered_lock),
+                   spin_is_locked(&sdp->sd_ail_lock),
+                   sdp->sd_log_error,
+                   rwsem_is_locked(&sdp->sd_log_flush_lock),
+                   trans1, ail11, ail12,
+                   trans2, ail21, ail22,
+                   revokes, sdp->sd_log_num_revoke,
+                   atomic_read(&sdp->sd_log_in_flight));
+       return s;
+}
+
 static ssize_t fsname_show(struct gfs2_sbd *sdp, char *buf)
 {
        return snprintf(buf, PAGE_SIZE, "%s\n", sdp->sd_fsname);
@@ -283,6 +394,7 @@ GFS2_ATTR(quota_sync,          0200, NULL,          
quota_sync_store);
 GFS2_ATTR(quota_refresh_user,  0200, NULL,          quota_refresh_user_store);
 GFS2_ATTR(quota_refresh_group, 0200, NULL,          quota_refresh_group_store);
 GFS2_ATTR(demote_rq,           0200, NULL,         demote_rq_store);
+GFS2_ATTR(status,              0444, status_show,   NULL);
 
 static struct attribute *gfs2_attrs[] = {
        &gfs2_attr_id.attr,
@@ -295,6 +407,7 @@ static struct attribute *gfs2_attrs[] = {
        &gfs2_attr_quota_refresh_user.attr,
        &gfs2_attr_quota_refresh_group.attr,
        &gfs2_attr_demote_rq.attr,
+       &gfs2_attr_status.attr,
        NULL,
 };
 ATTRIBUTE_GROUPS(gfs2);
-- 
2.26.2

Reply via email to