diff --git a/lustre/include/lprocfs_status.h b/lustre/include/lprocfs_status.h index 4fefd59ac42f29b563b6c136658227f867733b73..8c50f59fb6363d9eafeb557fd767e748810fd088 100644 --- a/lustre/include/lprocfs_status.h +++ b/lustre/include/lprocfs_status.h @@ -609,6 +609,10 @@ extern int lprocfs_quota_rd_switch_seconds(char *page, char **start, off_t off, int count, int *eof, void *data); extern int lprocfs_quota_wr_switch_seconds(struct file *file, const char *buffer, unsigned long count, void *data); +extern int lprocfs_quota_rd_sync_blk(char *page, char **start, off_t off, + int count, int *eof, void *data); +extern int lprocfs_quota_wr_sync_blk(struct file *file, const char *buffer, + unsigned long count, void *data); extern int lprocfs_quota_rd_switch_qs(char *page, char **start, off_t off, int count, int *eof, void *data); extern int lprocfs_quota_wr_switch_qs(struct file *file, const char *buffer, diff --git a/lustre/include/lustre_quota.h b/lustre/include/lustre_quota.h index ee1d0a13ec6eb4e72d78d316660b1727454a6972..b8f24c17f9c7171812244c404563115705dd4204 100644 --- a/lustre/include/lustre_quota.h +++ b/lustre/include/lustre_quota.h @@ -264,6 +264,9 @@ struct lustre_quota_ctxt { * adjusting qunit size. How many * seconds must be waited between * enlarging and shinking qunit */ + int lqc_sync_blk; /* when blk qunit reaches this value, + * later write reqs from client + * should be sync b=16642 */ spinlock_t lqc_lock; /* guard lqc_imp_valid now */ cfs_waitq_t lqc_wait_for_qmaster; /* when mds isn't connected, threads * on osts who send the quota reqs diff --git a/lustre/quota/lproc_quota.c b/lustre/quota/lproc_quota.c index 922f2d48cdef887b924beaadc62f4ac3d6515f7f..3cb42aa29a832b34f15a4703236f1ec35e949edc 100644 --- a/lustre/quota/lproc_quota.c +++ b/lustre/quota/lproc_quota.c @@ -448,6 +448,36 @@ int lprocfs_quota_wr_switch_seconds(struct file *file, const char *buffer, } EXPORT_SYMBOL(lprocfs_quota_wr_switch_seconds); +int lprocfs_quota_rd_sync_blk(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct obd_device *obd = (struct obd_device *)data; + LASSERT(obd != NULL); + + return snprintf(page, count, "%d\n", + obd->u.obt.obt_qctxt.lqc_sync_blk); +} +EXPORT_SYMBOL(lprocfs_quota_rd_sync_blk); + +int lprocfs_quota_wr_sync_blk(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct obd_device *obd = (struct obd_device *)data; + int val, rc; + LASSERT(obd != NULL); + + rc = lprocfs_write_helper(buffer, count, &val); + if (rc) + return rc; + + if (val < 0) + return -EINVAL; + + obd->u.obt.obt_qctxt.lqc_sync_blk = val; + return count; +} +EXPORT_SYMBOL(lprocfs_quota_wr_sync_blk); + int lprocfs_quota_rd_switch_qs(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -618,6 +648,8 @@ struct lprocfs_vars lprocfs_quota_common_vars[] = { lprocfs_quota_wr_type, 0}, { "quota_switch_seconds", lprocfs_quota_rd_switch_seconds, lprocfs_quota_wr_switch_seconds, 0 }, + { "quota_sync_blk", lprocfs_quota_rd_sync_blk, + lprocfs_quota_wr_sync_blk, 0}, }; struct lprocfs_vars lprocfs_quota_master_vars[] = { diff --git a/lustre/quota/quota_context.c b/lustre/quota/quota_context.c index 0e9eb8082b96b6e1516f454a95ce05126413693e..bd22456e33daacc57ed648508a3a9da24c48568c 100644 --- a/lustre/quota/quota_context.c +++ b/lustre/quota/quota_context.c @@ -1143,6 +1143,7 @@ qctxt_init(struct obd_device *obd, dqacq_handler_t handler) qctxt->lqc_itune_sz = default_iunit_sz * default_itune_ratio / 100; qctxt->lqc_switch_seconds = 300; /* enlarging will wait 5 minutes * after the last shrinking */ + qctxt->lqc_sync_blk = 0; spin_unlock(&qctxt->lqc_lock); qctxt->lqc_lqs_hash = lustre_hash_init("LQS_HASH", 128, 128, diff --git a/lustre/quota/quota_interface.c b/lustre/quota/quota_interface.c index 6bbb8bc21a500581865e9006af6a5038c3cb6718..bb7f297c806d71f986c6e31064178aea851d8344 100644 --- a/lustre/quota/quota_interface.c +++ b/lustre/quota/quota_interface.c @@ -169,6 +169,7 @@ static int filter_quota_enforce(struct obd_device *obd, unsigned int ignore) static int filter_quota_getflag(struct obd_device *obd, struct obdo *oa) { struct obd_device_target *obt = &obd->u.obt; + struct lustre_quota_ctxt *qctxt = &obt->obt_qctxt; int err, cnt, rc = 0; struct obd_quotactl *oqctl; ENTRY; @@ -176,15 +177,42 @@ static int filter_quota_getflag(struct obd_device *obd, struct obdo *oa) if (!sb_any_quota_enabled(obt->obt_sb)) RETURN(0); - oa->o_flags &= ~(OBD_FL_NO_USRQUOTA | OBD_FL_NO_GRPQUOTA); - OBD_ALLOC_PTR(oqctl); if (!oqctl) { CERROR("Not enough memory!"); RETURN(-ENOMEM); } + /* set over quota flags for a uid/gid */ + oa->o_valid |= OBD_MD_FLUSRQUOTA | OBD_MD_FLGRPQUOTA; + oa->o_flags &= ~(OBD_FL_NO_USRQUOTA | OBD_FL_NO_GRPQUOTA); + for (cnt = 0; cnt < MAXQUOTAS; cnt++) { + struct quota_adjust_qunit oqaq_tmp; + struct lustre_qunit_size *lqs = NULL; + + oqaq_tmp.qaq_flags = cnt; + oqaq_tmp.qaq_id = (cnt == USRQUOTA) ? oa->o_uid : oa->o_gid; + + quota_search_lqs(NULL, &oqaq_tmp, qctxt, &lqs); + if (lqs) { + spin_lock(&lqs->lqs_lock); + if (lqs->lqs_bunit_sz <= qctxt->lqc_sync_blk) { + oa->o_flags |= (cnt == USRQUOTA) ? + OBD_FL_NO_USRQUOTA : OBD_FL_NO_GRPQUOTA; + CDEBUG(D_QUOTA, "set sync flag: bunit(%lu), " + "sync_blk(%d)\n", lqs->lqs_bunit_sz, + qctxt->lqc_sync_blk); + spin_unlock(&lqs->lqs_lock); + /* this is for quota_search_lqs */ + lqs_putref(lqs); + continue; + } + spin_unlock(&lqs->lqs_lock); + /* this is for quota_search_lqs */ + lqs_putref(lqs); + } + memset(oqctl, 0, sizeof(*oqctl)); oqctl->qc_cmd = Q_GETQUOTA; @@ -194,12 +222,11 @@ static int filter_quota_getflag(struct obd_device *obd, struct obdo *oa) if (err) { if (!rc) rc = err; + oa->o_valid &= ~((cnt == USRQUOTA) ? OBD_MD_FLUSRQUOTA : + OBD_MD_FLGRPQUOTA); continue; } - /* set over quota flags for a uid/gid */ - oa->o_valid |= (cnt == USRQUOTA) ? - OBD_MD_FLUSRQUOTA : OBD_MD_FLGRPQUOTA; if (oqctl->qc_dqblk.dqb_bhardlimit && (toqb(oqctl->qc_dqblk.dqb_curspace) >= oqctl->qc_dqblk.dqb_bhardlimit))