Whamcloud - gitweb
Branch b1_8
authortianzy <tianzy>
Thu, 16 Jul 2009 06:40:12 +0000 (06:40 +0000)
committertianzy <tianzy>
Thu, 16 Jul 2009 06:40:12 +0000 (06:40 +0000)
Fix group quota "too many blocks" OSS crashes.

In filter_commitrw_write():
1. lquota_chkquota();
2. obdo_from_inode();
3. lquota_pending_commit();

2. has changed uid and gid in this case, then caused
lquota_chkquota() and lquota_pending_commit() to use
different uid and gid. That is the root of the bug.
b=18793
i=yong.fan
i=panda

lustre/mds/mds_open.c
lustre/mds/mds_reint.c
lustre/obdfilter/filter_io_26.c

index e0df4d2..f626d0a 100644 (file)
@@ -1017,6 +1017,7 @@ int mds_open(struct mds_update_record *rec, int offset,
         struct lvfs_dentry_params dp = LVFS_DENTRY_PARAMS_INIT;
         unsigned int qcids[MAXQUOTAS] = { current->fsuid, current->fsgid };
         unsigned int qpids[MAXQUOTAS] = { 0, 0 };
+        unsigned int ids[MAXQUOTAS] = { 0, 0 };
         int child_mode = LCK_CR;
         /* Always returning LOOKUP lock if open succesful to guard
            dentry on client. */
@@ -1208,8 +1209,10 @@ int mds_open(struct mds_update_record *rec, int offset,
                  * decide if it is out of quota or not b=14783
                  * FIXME: after CMD is used, pointer to obd_trans_info* couldn't
                  * be NULL, b=14840 */
+                ids[0] = current->fsuid;
+                ids[1] = gid;
                 lquota_chkquota(mds_quota_interface_ref, obd,
-                                current->fsuid, gid, 1, quota_pending,
+                                ids[0], ids[1], 1, quota_pending,
                                 NULL, NULL, 0);
 
                 ldlm_reply_set_disposition(rep, DISP_OPEN_CREATE);
@@ -1391,7 +1394,7 @@ found_child:
  cleanup_no_trans:
         if (quota_pending[0] || quota_pending[1])
                 lquota_pending_commit(mds_quota_interface_ref, obd,
-                                      current->fsuid, gid, quota_pending);
+                                      ids[0], ids[1], quota_pending);
         switch (cleanup_phase) {
         case 2:
                 if (rc && created) {
index c6b019e..2198e7f 100644 (file)
@@ -976,6 +976,7 @@ static int mds_reint_create(struct mds_update_record *rec, int offset,
         int created = 0;
         unsigned int qcids[MAXQUOTAS] = { current->fsuid, current->fsgid };
         unsigned int qpids[MAXQUOTAS] = { 0, 0 };
+        unsigned int ids[MAXQUOTAS] = { 0, 0 };
         struct lvfs_dentry_params dp = LVFS_DENTRY_PARAMS_INIT;
         int quota_pending[2] = {0, 0};
         unsigned int gid = current->fsgid;
@@ -1058,8 +1059,10 @@ static int mds_reint_create(struct mds_update_record *rec, int offset,
          * decide if it is out of quota or not b=14783
          * FIXME: after CMD is used, pointer to obd_trans_info* couldn't
          * be NULL, b=14840 */
-        lquota_chkquota(mds_quota_interface_ref, obd,
-                        current->fsuid, gid, 1, quota_pending, NULL, NULL, 0);
+        ids[0] = current->fsuid;
+        ids[1] = gid;
+        lquota_chkquota(mds_quota_interface_ref, obd, ids[0], ids[1],
+                        1, quota_pending, NULL, NULL, 0);
 
         switch (type) {
         case S_IFREG:{
@@ -1197,7 +1200,7 @@ cleanup:
 cleanup_no_trans:
         if (quota_pending[0] || quota_pending[1])
                 lquota_pending_commit(mds_quota_interface_ref, obd,
-                                      current->fsuid, gid, quota_pending);
+                                      ids[0], ids[1], quota_pending);
 
         if (rc && created) {
                 /* Destroy the file we just created.  This should not need
index 7a8629a..05c7053 100644 (file)
@@ -590,7 +590,7 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa,
         void *wait_handle = NULL;
         int total_size = 0;
         int quota_pending[2] = {0, 0}, quota_pages = 0;
-        unsigned int qcids[MAXQUOTAS] = {0, 0};
+        unsigned int qcids[MAXQUOTAS] = {oa->o_uid, oa->o_gid};
         int sync_journal_commit = obd->u.filter.fo_syncjournal;
         ENTRY;
 
@@ -665,7 +665,7 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa,
 
         /* we try to get enough quota to write here, and let ldiskfs
          * decide if it is out of quota or not b=14783 */
-        lquota_chkquota(filter_quota_interface_ref, obd, oa->o_uid, oa->o_gid,
+        lquota_chkquota(filter_quota_interface_ref, obd, qcids[0], qcids[1],
                         quota_pages, quota_pending, oti, inode,
                         obj->ioo_bufcnt);
 
@@ -763,7 +763,7 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa,
 cleanup:
         if (quota_pending[0] || quota_pending[1])
                 lquota_pending_commit(filter_quota_interface_ref, obd,
-                                      oa->o_uid, oa->o_gid, quota_pending);
+                                      qcids[0], qcids[1], quota_pending);
 
         filter_grant_commit(exp, niocount, res);
 
@@ -782,12 +782,18 @@ cleanup:
         }
 
         /* trigger quota pre-acquire */
-        qcids[USRQUOTA] = oa->o_uid;
-        qcids[GRPQUOTA] = oa->o_gid;
         err = lquota_adjust(filter_quota_interface_ref, obd, qcids, NULL, rc,
                             FSFILT_OP_CREATE);
-        CDEBUG(err ? D_ERROR : D_QUOTA,
-               "filter adjust qunit! (rc:%d)\n", err);
+        CDEBUG(err ? D_ERROR : D_QUOTA, "filter adjust qunit! "
+               "(rc:%d, uid:%u, gid:%u)\n", err, qcids[0], qcids[1]);
+        if (qcids[USRQUOTA] != oa->o_uid || qcids[GRPQUOTA] != oa->o_gid) {
+                qcids[0] = oa->o_uid;
+                qcids[1] = oa->o_gid;
+                err = lquota_adjust(filter_quota_interface_ref, obd, qcids,
+                                    NULL, rc, FSFILT_OP_CREATE);
+                CDEBUG(err ? D_ERROR : D_QUOTA, "filter adjust qunit! "
+                       "(rc:%d, uid:%u, gid:%u)\n", err, qcids[0], qcids[1]);
+        }
 
         for (i = 0, lnb = res; i < niocount; i++, lnb++) {
                 if (lnb->page == NULL)