Whamcloud - gitweb
b=22363 fix for a race condition in linux quotas implementation
authorAndrew Perepechko <Andrew.Perepechko@Sun.COM>
Fri, 9 Apr 2010 20:31:44 +0000 (00:31 +0400)
committerJohann Lombardi <johann@sun.com>
Fri, 9 Apr 2010 21:00:21 +0000 (23:00 +0200)
dq_flags(struct dquot) access is not properly locked which could
lead to certain inconsistencies when accessing it using non-atomic
bit operations like __set_bit in do_set_dqblk.

This patch replaces non-atomic __set_bit calls with atomic set_bit
calls.

i=Johann Lombardi
i=Dmitry Zogin

lustre/kernel_patches/patches/quota-support-64-bit-quota-format.patch

index 14fe9a8..9b4cd58 100644 (file)
@@ -280,3 +280,45 @@ diff -puN fs/quotaio_v2.h~quota-support-64-bit-quota-format fs/quotaio_v2.h
  struct v2_disk_dqinfo {
        __le32 dqi_bgrace;      /* Time before block soft limit becomes hard limit */
 _
+diff -puN fs/dquot.c fs/dquot.c
+--- a/fs/dquot.c
++++ b/fs/dquot.c
+@@ -2065,32 +2065,32 @@ static int do_set_dqblk(struct dquot *dq
+       if (di->dqb_valid & QIF_SPACE) {
+               dm->dqb_curspace = di->dqb_curspace;
+               check_blim = 1;
+-              __set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
++              set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
+       }
+       if (di->dqb_valid & QIF_BLIMITS) {
+               dm->dqb_bsoftlimit = qbtos(di->dqb_bsoftlimit);
+               dm->dqb_bhardlimit = qbtos(di->dqb_bhardlimit);
+               check_blim = 1;
+-              __set_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags);
++              set_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags);
+       }
+       if (di->dqb_valid & QIF_INODES) {
+               dm->dqb_curinodes = di->dqb_curinodes;
+               check_ilim = 1;
+-              __set_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags);
++              set_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags);
+       }
+       if (di->dqb_valid & QIF_ILIMITS) {
+               dm->dqb_isoftlimit = di->dqb_isoftlimit;
+               dm->dqb_ihardlimit = di->dqb_ihardlimit;
+               check_ilim = 1;
+-              __set_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags);
++              set_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags);
+       }
+       if (di->dqb_valid & QIF_BTIME) {
+               dm->dqb_btime = di->dqb_btime;
+-              __set_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags);
++              set_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags);
+       }
+       if (di->dqb_valid & QIF_ITIME) {
+               dm->dqb_itime = di->dqb_itime;
+-              __set_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags);
++              set_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags);
+       }
+       if (check_blim) {