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
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. */
* 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);
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) {
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;
* 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:{
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
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;
/* 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);
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);
}
/* 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)