From eb057a52b73b79afa857d1d71ad512f1d463f721 Mon Sep 17 00:00:00 2001 From: tianzy Date: Thu, 16 Jul 2009 06:40:12 +0000 Subject: [PATCH] Branch b1_8 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 | 7 +++++-- lustre/mds/mds_reint.c | 9 ++++++--- lustre/obdfilter/filter_io_26.c | 20 +++++++++++++------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/lustre/mds/mds_open.c b/lustre/mds/mds_open.c index e0df4d2..f626d0a 100644 --- a/lustre/mds/mds_open.c +++ b/lustre/mds/mds_open.c @@ -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) { diff --git a/lustre/mds/mds_reint.c b/lustre/mds/mds_reint.c index c6b019e..2198e7f 100644 --- a/lustre/mds/mds_reint.c +++ b/lustre/mds/mds_reint.c @@ -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 diff --git a/lustre/obdfilter/filter_io_26.c b/lustre/obdfilter/filter_io_26.c index 7a8629a..05c7053 100644 --- a/lustre/obdfilter/filter_io_26.c +++ b/lustre/obdfilter/filter_io_26.c @@ -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) -- 1.8.3.1