gfs2: limit quota log messages
authorAbhi Das <adas@redhat.com>
Tue, 2 Jun 2015 16:03:04 +0000 (11:03 -0500)
committerBob Peterson <rpeterso@redhat.com>
Tue, 2 Jun 2015 16:03:04 +0000 (11:03 -0500)
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.

Signed-off-by: Abhi Das <adas@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
fs/gfs2/incore.h
fs/gfs2/quota.c

index 58b75abf6ab2f4e9e0c1b37752eba724a5b55b61..304a22315448890217fe58b3cd762ac070758f0b 100644 (file)
@@ -432,6 +432,7 @@ enum {
        QDF_CHANGE              = 1,
        QDF_LOCKED              = 2,
        QDF_REFRESH             = 3,
+       QDF_QMSG_QUIET          = 4,
 };
 
 struct gfs2_quota_data {
index 7c2003177884b17dc36dcf1bfa7ed604c54df289..dcd598aa269168c8c4eb83b85f1a463060fcea99 100644 (file)
@@ -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: