This patch makes the quota subsystem only report once that a
particular user/group has exceeded their allotted quota.

Previously, it was possible for a program to continuously try
exceeding quota (despite receiving EDQUOT) and in turn trigger
gfs2 to issue a kernel log message about quota exceed. In theory,
this could get out of hand and flood the log and the filesystem
hosting the log files.

Resolves: rhbz#1174295
Signed-off-by: Abhi Das <a...@redhat.com>
---
 fs/gfs2/incore.h |  1 +
 fs/gfs2/quota.c  | 15 +++++++++++----
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 58b75ab..304a223 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -432,6 +432,7 @@ enum {
        QDF_CHANGE              = 1,
        QDF_LOCKED              = 2,
        QDF_REFRESH             = 3,
+       QDF_QMSG_QUIET          = 4,
 };
 
 struct gfs2_quota_data {
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 7c20031..dcd598a 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -649,6 +649,8 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change)
                slot_hold(qd);
        }
 
+       if (change < 0) /* Reset quiet flag if we freed some blocks */
+               clear_bit(QDF_QMSG_QUIET, &qd->qd_flags);
        mutex_unlock(&sdp->sd_quota_mutex);
 }
 
@@ -1187,10 +1189,13 @@ int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, 
kgid_t gid,
                        /* If no min_target specified or we don't meet
                         * min_target, return -EDQUOT */
                        if (!ap->min_target || ap->min_target > ap->allowed) {
-                               print_message(qd, "exceeded");
-                               quota_send_warning(qd->qd_id,
-                                                  sdp->sd_vfs->s_dev,
-                                                  QUOTA_NL_BHARDWARN);
+                               if (!test_and_set_bit(QDF_QMSG_QUIET,
+                                                     &qd->qd_flags)) {
+                                       print_message(qd, "exceeded");
+                                       quota_send_warning(qd->qd_id,
+                                                          sdp->sd_vfs->s_dev,
+                                                          QUOTA_NL_BHARDWARN);
+                               }
                                error = -EDQUOT;
                                break;
                        }
@@ -1685,6 +1690,8 @@ static int gfs2_set_dqblk(struct super_block *sb, struct 
kqid qid,
 
        /* Apply changes */
        error = gfs2_adjust_quota(ip, offset, 0, qd, fdq);
+       if (!error)
+               clear_bit(QDF_QMSG_QUIET, &qd->qd_flags);
 
        gfs2_trans_end(sdp);
 out_release:
-- 
1.8.1.4

Reply via email to