diff --git a/lustre/ChangeLog b/lustre/ChangeLog index 24e129b78230b08fec4d19341c5b0da009f3d6b5..a100d5a70adbc417ccf4f1aca32bb8e12ac2c899 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -335,6 +335,12 @@ Details : Current xattr code updates the inode ctime in ext3_xattr_set_handle 2.0->1.8 compatibility it is necessary to delete an xattr and it should not update the ctime. +Severity : normal +Bugzilla : 15058 +Description: add quota statistics +Details : 1. sort out quota proc entries and proc code. + 2. add quota statistics + ------------------------------------------------------------------------------- diff --git a/lustre/include/lprocfs_status.h b/lustre/include/lprocfs_status.h index 997cfa7e146699b3ad6ec716f31a80738c3d1d51..697a459be610c8da2583d10eb27d80bd97534c49 100644 --- a/lustre/include/lprocfs_status.h +++ b/lustre/include/lprocfs_status.h @@ -563,6 +563,52 @@ int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer, unsigned long count, void *data); #endif +/* all quota proc functions */ +extern int lprocfs_quota_rd_bunit(char *page, char **start, off_t off, int count, + int *eof, void *data); +extern int lprocfs_quota_wr_bunit(struct file *file, const char *buffer, + unsigned long count, void *data); +extern int lprocfs_quota_rd_btune(char *page, char **start, off_t off, int count, + int *eof, void *data); +extern int lprocfs_quota_wr_btune(struct file *file, const char *buffer, + unsigned long count, void *data); +extern int lprocfs_quota_rd_iunit(char *page, char **start, off_t off, int count, + int *eof, void *data); +extern int lprocfs_quota_wr_iunit(struct file *file, const char *buffer, + unsigned long count, void *data); +extern int lprocfs_quota_rd_itune(char *page, char **start, off_t off, int count, + int *eof, void *data); +extern int lprocfs_quota_wr_itune(struct file *file, const char *buffer, + unsigned long count, void *data); +extern int lprocfs_quota_rd_type(char *page, char **start, off_t off, int count, + int *eof, void *data); +extern int lprocfs_quota_wr_type(struct file *file, const char *buffer, + unsigned long count, void *data); +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_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, + unsigned long count, void *data); +extern int lprocfs_quota_rd_boundary_factor(char *page, char **start, off_t off, + int count, int *eof, void *data); +extern int lprocfs_quota_wr_boundary_factor(struct file *file, const char *buffer, + unsigned long count, void *data); +extern int lprocfs_quota_rd_least_bunit(char *page, char **start, off_t off, + int count, int *eof, void *data); +extern int lprocfs_quota_wr_least_bunit(struct file *file, const char *buffer, + unsigned long count, void *data); +extern int lprocfs_quota_rd_least_iunit(char *page, char **start, off_t off, + int count, int *eof, void *data); +extern int lprocfs_quota_wr_least_iunit(struct file *file, const char *buffer, + unsigned long count, void *data); +extern int lprocfs_quota_rd_qs_factor(char *page, char **start, off_t off, + int count, int *eof, void *data); +extern int lprocfs_quota_wr_qs_factor(struct file *file, const char *buffer, + unsigned long count, void *data); + #else /* LPROCFS is not defined */ static inline void lprocfs_counter_add(struct lprocfs_stats *stats, diff --git a/lustre/include/lustre_quota.h b/lustre/include/lustre_quota.h index c6d7c7c53390167616f3e844b95bc0cdc38cb320..81a306e603825bec561e680f02fc3dbd92f6e66b 100644 --- a/lustre/include/lustre_quota.h +++ b/lustre/include/lustre_quota.h @@ -63,6 +63,40 @@ struct client_obd; #ifdef __KERNEL__ +#ifdef LPROCFS +enum { + LQUOTA_FIRST_STAT = 0, + /* these four are for measuring quota requests, for both of + * quota master and quota slaves */ + LQUOTA_SYNC_ACQ = LQUOTA_FIRST_STAT, + LQUOTA_SYNC_REL, + LQUOTA_ASYNC_ACQ, + LQUOTA_ASYNC_REL, + /* these four measure how much time I/O threads spend on dealing + * with quota before and after writing data or creating files, + * only for quota slaves(lquota_chkquota and lquota_pending_commit) */ + LQUOTA_WAIT_FOR_CHK_BLK, + LQUOTA_WAIT_FOR_CHK_INO, + LQUOTA_WAIT_FOR_COMMIT_BLK, + LQUOTA_WAIT_FOR_COMMIT_INO, + /* these two are for measuring time waiting return of quota reqs + * (qctxt_wait_pending_dqacq), only for quota salves */ + LQUOTA_WAIT_PENDING_BLK_QUOTA, + LQUOTA_WAIT_PENDING_INO_QUOTA, + /* these two are for those when they are calling + * qctxt_wait_pending_dqacq, the quota req has returned already, + * only for quota salves */ + LQUOTA_NOWAIT_PENDING_BLK_QUOTA, + LQUOTA_NOWAIT_PENDING_INO_QUOTA, + /* these are for quota ctl */ + LQUOTA_QUOTA_CTL, + /* these are for adjust quota qunit, for both of + * quota master and quota slaves */ + LQUOTA_ADJUST_QUNIT, + LQUOTA_LAST_STAT +}; +#endif /* LPROCFS */ + /* structures to access admin quotafile */ struct lustre_mem_dqinfo { unsigned int dqi_bgrace; @@ -226,6 +260,8 @@ struct lustre_quota_ctxt { * seconds must be waited between * enlarging and shinking qunit */ spinlock_t lqc_lock; /* guard lqc_imp_valid now */ + struct proc_dir_entry *lqc_proc_dir; + struct lprocfs_stats *lqc_stats; /* lquota statistics */ }; #define LQC_HASH_BODY(qctxt) (qctxt->lqc_lqs_hash_body) @@ -369,8 +405,9 @@ typedef struct { obd_flag, obd_flag); /* For adjusting qunit size b=10600 */ - int (*quota_adjust_qunit) (struct obd_export *exp, struct - quota_adjust_qunit *oqaq); + int (*quota_adjust_qunit) (struct obd_export *exp, + struct quota_adjust_qunit *oqaq, + struct lustre_quota_ctxt *qctxt); } quota_interface_t; @@ -590,31 +627,6 @@ static inline int lquota_pending_commit(quota_interface_t *interface, RETURN(rc); } -int lprocfs_quota_rd_bunit(char *page, char **start, off_t off, int count, - int *eof, void *data); -int lprocfs_quota_wr_bunit(struct file *file, const char *buffer, - unsigned long count, void *data); -int lprocfs_quota_rd_btune(char *page, char **start, off_t off, int count, - int *eof, void *data); -int lprocfs_quota_wr_btune(struct file *file, const char *buffer, - unsigned long count, void *data); -int lprocfs_quota_rd_iunit(char *page, char **start, off_t off, int count, - int *eof, void *data); -int lprocfs_quota_wr_iunit(struct file *file, const char *buffer, - unsigned long count, void *data); -int lprocfs_quota_rd_itune(char *page, char **start, off_t off, int count, - int *eof, void *data); -int lprocfs_quota_wr_itune(struct file *file, const char *buffer, - unsigned long count, void *data); -int lprocfs_quota_rd_type(char *page, char **start, off_t off, int count, - int *eof, void *data); -int lprocfs_quota_wr_type(struct file *file, const char *buffer, - unsigned long count, void *data); -int lprocfs_quota_rd_switch_seconds(char *page, char **start, off_t off, - int count, int *eof, void *data); -int lprocfs_quota_wr_switch_seconds(struct file *file, const char *buffer, - unsigned long count, void *data); - #ifndef __KERNEL__ extern quota_interface_t osc_quota_interface; extern quota_interface_t mdc_quota_interface; diff --git a/lustre/include/obd.h b/lustre/include/obd.h index 7cccdb5d49db4e3343710e38b88dd01bf36c3d8f..e3556cfdc95a84fd72fa714befdbac32512499e3 100644 --- a/lustre/include/obd.h +++ b/lustre/include/obd.h @@ -1109,7 +1109,8 @@ struct obd_ops { int (*o_quotacheck)(struct obd_export *, struct obd_quotactl *); int (*o_quotactl)(struct obd_export *, struct obd_quotactl *); int (*o_quota_adjust_qunit)(struct obd_export *exp, - struct quota_adjust_qunit *oqaq); + struct quota_adjust_qunit *oqaq, + struct lustre_quota_ctxt *qctxt); int (*o_ping)(struct obd_export *exp); diff --git a/lustre/include/obd_class.h b/lustre/include/obd_class.h index f370f3f05649bfdeaf6102d63d786f1278fccc56..dee007ff5701298b910b6db8afcce595c7adb51c 100644 --- a/lustre/include/obd_class.h +++ b/lustre/include/obd_class.h @@ -1408,15 +1408,34 @@ static inline int obd_quotactl(struct obd_export *exp, } static inline int obd_quota_adjust_qunit(struct obd_export *exp, - struct quota_adjust_qunit *oqaq) + struct quota_adjust_qunit *oqaq, + struct lustre_quota_ctxt *qctxt) { +#ifdef LPROCFS + struct timeval work_start; + struct timeval work_end; + long timediff; +#endif int rc; ENTRY; +#ifdef LPROCFS + if (qctxt) + do_gettimeofday(&work_start); +#endif EXP_CHECK_OP(exp, quota_adjust_qunit); EXP_COUNTER_INCREMENT(exp, quota_adjust_qunit); - rc = OBP(exp->exp_obd, quota_adjust_qunit)(exp, oqaq); + rc = OBP(exp->exp_obd, quota_adjust_qunit)(exp, oqaq, qctxt); + +#ifdef LPROCFS + if (qctxt) { + do_gettimeofday(&work_end); + timediff = cfs_timeval_sub(&work_end, &work_start, NULL); + lprocfs_counter_add(qctxt->lqc_stats, LQUOTA_ADJUST_QUNIT, + timediff); + } +#endif RETURN(rc); } diff --git a/lustre/mds/lproc_mds.c b/lustre/mds/lproc_mds.c index aee7e6ae07cd4f965e7e7a4614064cd5f218ca7f..9bbe76a0e13351c4ee0e4bfa8b3dc543d3d6d0cf 100644 --- a/lustre/mds/lproc_mds.c +++ b/lustre/mds/lproc_mds.c @@ -405,155 +405,6 @@ static int lprocfs_rd_nosquash_nid(char *page, char **start, off_t off, libcfs_nid2str(mds->mds_nosquash_nid)); } -#ifdef HAVE_QUOTA_SUPPORT -static int lprocfs_mds_rd_switch_qs(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, "changing qunit size is %s\n", - obd->u.obt.obt_qctxt.lqc_switch_qs ? - "enabled" : "disabled"); -} - -static int lprocfs_mds_rd_boundary_factor(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, "%lu\n", - obd->u.obt.obt_qctxt.lqc_cqs_boundary_factor); -} - -static int lprocfs_mds_rd_least_bunit(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, "%lu\n", - obd->u.obt.obt_qctxt.lqc_cqs_least_bunit); -} - -static int lprocfs_mds_rd_least_iunit(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, "%lu\n", - obd->u.obt.obt_qctxt.lqc_cqs_least_iunit); -} - -static int lprocfs_mds_rd_qs_factor(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, "%lu\n", - obd->u.obt.obt_qctxt.lqc_cqs_qs_factor); -} - -static int lprocfs_mds_wr_switch_qs(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) - obd->u.obt.obt_qctxt.lqc_switch_qs = 1; - else - obd->u.obt.obt_qctxt.lqc_switch_qs = 0; - - return count; -} - -static int lprocfs_mds_wr_boundary_factor(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 < 2) - return -EINVAL; - - obd->u.obt.obt_qctxt.lqc_cqs_boundary_factor = val; - return count; -} - -static int lprocfs_mds_wr_least_bunit(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 < PTLRPC_MAX_BRW_SIZE || - val >= obd->u.obt.obt_qctxt.lqc_bunit_sz) - return -EINVAL; - - obd->u.obt.obt_qctxt.lqc_cqs_least_bunit = val; - return count; -} - -static int lprocfs_mds_wr_least_iunit(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 < 1 || val >= obd->u.obt.obt_qctxt.lqc_iunit_sz) - return -EINVAL; - - obd->u.obt.obt_qctxt.lqc_cqs_least_iunit = val; - return count; -} - -static int lprocfs_mds_wr_qs_factor(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 < 2) - return -EINVAL; - - obd->u.obt.obt_qctxt.lqc_cqs_qs_factor = val; - return count; -} -#endif - struct lprocfs_vars lprocfs_mds_obd_vars[] = { { "uuid", lprocfs_rd_uuid, 0, 0 }, { "blocksize", lprocfs_rd_blksize, 0, 0 }, @@ -575,16 +426,16 @@ struct lprocfs_vars lprocfs_mds_obd_vars[] = { { "quota_iunit_sz", lprocfs_quota_rd_iunit, lprocfs_quota_wr_iunit, 0 }, { "quota_itune_sz", lprocfs_quota_rd_itune, lprocfs_quota_wr_itune, 0 }, { "quota_type", lprocfs_quota_rd_type, lprocfs_quota_wr_type, 0 }, - { "quota_switch_qs", lprocfs_mds_rd_switch_qs, - lprocfs_mds_wr_switch_qs, 0 }, - { "quota_boundary_factor", lprocfs_mds_rd_boundary_factor, - lprocfs_mds_wr_boundary_factor, 0 }, - { "quota_least_bunit", lprocfs_mds_rd_least_bunit, - lprocfs_mds_wr_least_bunit, 0 }, - { "quota_least_iunit", lprocfs_mds_rd_least_iunit, - lprocfs_mds_wr_least_iunit, 0 }, - { "quota_qs_factor", lprocfs_mds_rd_qs_factor, - lprocfs_mds_wr_qs_factor, 0 }, + { "quota_switch_qs", lprocfs_quota_rd_switch_qs, + lprocfs_quota_wr_switch_qs, 0 }, + { "quota_boundary_factor", lprocfs_quota_rd_boundary_factor, + lprocfs_quota_wr_boundary_factor, 0 }, + { "quota_least_bunit", lprocfs_quota_rd_least_bunit, + lprocfs_quota_wr_least_bunit, 0 }, + { "quota_least_iunit", lprocfs_quota_rd_least_iunit, + lprocfs_quota_wr_least_iunit, 0 }, + { "quota_qs_factor", lprocfs_quota_rd_qs_factor, + lprocfs_quota_wr_qs_factor, 0 }, { "quota_switch_seconds", lprocfs_quota_rd_switch_seconds, lprocfs_quota_wr_switch_seconds, 0 }, #endif diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c index 080adf6e894aa05e5dddedde5cbb6f7942debb68..5522d9d9e87aa057133367ce0ac73905b9b2f635 100644 --- a/lustre/obdclass/lprocfs_status.c +++ b/lustre/obdclass/lprocfs_status.c @@ -1773,163 +1773,6 @@ int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer, EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime); #endif /* CRAY_XT3 */ -#ifdef HAVE_QUOTA_SUPPORT -int lprocfs_quota_rd_bunit(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, "%lu\n", - obd->u.obt.obt_qctxt.lqc_bunit_sz); -} -EXPORT_SYMBOL(lprocfs_quota_rd_bunit); - -int lprocfs_quota_wr_bunit(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 % QUOTABLOCK_SIZE || - val <= obd->u.obt.obt_qctxt.lqc_btune_sz) - return -EINVAL; - - obd->u.obt.obt_qctxt.lqc_bunit_sz = val; - return count; -} -EXPORT_SYMBOL(lprocfs_quota_wr_bunit); - -int lprocfs_quota_rd_btune(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, "%lu\n", - obd->u.obt.obt_qctxt.lqc_btune_sz); -} -EXPORT_SYMBOL(lprocfs_quota_rd_btune); - -int lprocfs_quota_wr_btune(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 <= QUOTABLOCK_SIZE * MIN_QLIMIT || val % QUOTABLOCK_SIZE || - val >= obd->u.obt.obt_qctxt.lqc_bunit_sz) - return -EINVAL; - - obd->u.obt.obt_qctxt.lqc_btune_sz = val; - return count; -} -EXPORT_SYMBOL(lprocfs_quota_wr_btune); - -int lprocfs_quota_rd_iunit(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, "%lu\n", - obd->u.obt.obt_qctxt.lqc_iunit_sz); -} -EXPORT_SYMBOL(lprocfs_quota_rd_iunit); - -int lprocfs_quota_wr_iunit(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 <= obd->u.obt.obt_qctxt.lqc_itune_sz) - return -EINVAL; - - obd->u.obt.obt_qctxt.lqc_iunit_sz = val; - return count; -} -EXPORT_SYMBOL(lprocfs_quota_wr_iunit); - -int lprocfs_quota_rd_itune(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, "%lu\n", - obd->u.obt.obt_qctxt.lqc_itune_sz); -} -EXPORT_SYMBOL(lprocfs_quota_rd_itune); - -int lprocfs_quota_wr_itune(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 <= MIN_QLIMIT || - val >= obd->u.obt.obt_qctxt.lqc_iunit_sz) - return -EINVAL; - - obd->u.obt.obt_qctxt.lqc_itune_sz = val; - return count; -} -EXPORT_SYMBOL(lprocfs_quota_wr_itune); - -int lprocfs_quota_rd_switch_seconds(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_switch_seconds); -} -EXPORT_SYMBOL(lprocfs_quota_rd_switch_seconds); - -int lprocfs_quota_wr_switch_seconds(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 <= 10) - return -EINVAL; - - obd->u.obt.obt_qctxt.lqc_switch_seconds = val; - return count; -} -EXPORT_SYMBOL(lprocfs_quota_wr_switch_seconds); - -#endif - - EXPORT_SYMBOL(lprocfs_register); EXPORT_SYMBOL(lprocfs_srch); EXPORT_SYMBOL(lprocfs_remove); diff --git a/lustre/obdfilter/lproc_obdfilter.c b/lustre/obdfilter/lproc_obdfilter.c index 65bb6dab983dffe964af16ba2a8666426af39457..8fa00f1a14645e97f6a35c386e5b9098775cd6e7 100644 --- a/lustre/obdfilter/lproc_obdfilter.c +++ b/lustre/obdfilter/lproc_obdfilter.c @@ -225,8 +225,7 @@ static struct lprocfs_vars lprocfs_filter_obd_vars[] = { { "quota_type", lprocfs_quota_rd_type, lprocfs_quota_wr_type, 0}, { "quota_switch_seconds", lprocfs_quota_rd_switch_seconds, - lprocfs_quota_wr_switch_seconds, 0 }, - + lprocfs_quota_wr_switch_seconds, 0 }, #endif { "client_cache_count", lprocfs_filter_rd_fmd_max_num, lprocfs_filter_wr_fmd_max_num, 0 }, diff --git a/lustre/ost/ost_handler.c b/lustre/ost/ost_handler.c index 4ddb1eafd36cf23aecdfb01ce540b919e0044753..836bedf0688951ade9cd8ce32abc6172f8440610 100644 --- a/lustre/ost/ost_handler.c +++ b/lustre/ost/ost_handler.c @@ -1389,10 +1389,12 @@ static int ost_handle_quotacheck(struct ptlrpc_request *req) static int ost_handle_quota_adjust_qunit(struct ptlrpc_request *req) { struct quota_adjust_qunit *oqaq, *repoqa; + struct lustre_quota_ctxt *qctxt; int size[2] = { sizeof(struct ptlrpc_body), sizeof(*repoqa) }; int rc; ENTRY; + qctxt = &req->rq_export->exp_obd->u.obt.obt_qctxt; oqaq = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*oqaq), lustre_swab_quota_adjust_qunit); @@ -1402,7 +1404,7 @@ static int ost_handle_quota_adjust_qunit(struct ptlrpc_request *req) if (rc) GOTO(out, rc); repoqa = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*repoqa)); - req->rq_status = obd_quota_adjust_qunit(req->rq_export, oqaq); + req->rq_status = obd_quota_adjust_qunit(req->rq_export, oqaq, qctxt); *repoqa = *oqaq; out: RETURN(rc); diff --git a/lustre/quota/Makefile.in b/lustre/quota/Makefile.in index 2f1bfad372111ed6d135308d5f6409c86e54785b..112e82d05921bb194ff07f4567cbf729971706a6 100644 --- a/lustre/quota/Makefile.in +++ b/lustre/quota/Makefile.in @@ -2,7 +2,7 @@ MODULES := lquota MODULES += quotactl_test quotacheck_test lquota-objs := quota_check.o quota_context.o quota_ctl.o quota_interface.o -lquota-objs += quota_master.o quota_adjust_qunit.o +lquota-objs += quota_master.o quota_adjust_qunit.o lproc_quota.o quotactl-objs := quotactl_test.o quotaccheck-objs := quotacheck_test.o diff --git a/lustre/quota/lproc_quota.c b/lustre/quota/lproc_quota.c new file mode 100644 index 0000000000000000000000000000000000000000..244a22802a03edd4348e5d03215a5de33b264017 --- /dev/null +++ b/lustre/quota/lproc_quota.c @@ -0,0 +1,719 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * Copyright (C) 2002, 2003 Cluster File Systems, Inc. + * + * This file is part of the Lustre file system, http://www.lustre.org + * Lustre is a trademark of Cluster File Systems, Inc. + * + * You may have signed or agreed to another license before downloading + * this software. If so, you are bound by the terms and conditions + * of that agreement, and the following does not apply to you. See the + * LICENSE file included with this distribution for more information. + * + * If you did not agree to a different license, then this copy of Lustre + * is open source software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In either case, Lustre is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * license text for more details. + * + */ +#define DEBUG_SUBSYSTEM S_LQUOTA + +#include <linux/version.h> +#include <lprocfs_status.h> +#include <obd.h> +#include <linux/seq_file.h> +#include <lustre_fsfilt.h> + +#include "quota_internal.h" + +#ifdef LPROCFS +int lprocfs_quota_rd_bunit(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, "%lu\n", + obd->u.obt.obt_qctxt.lqc_bunit_sz); +} +EXPORT_SYMBOL(lprocfs_quota_rd_bunit); + +int lprocfs_quota_wr_bunit(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 % QUOTABLOCK_SIZE || + val <= obd->u.obt.obt_qctxt.lqc_btune_sz) + return -EINVAL; + + obd->u.obt.obt_qctxt.lqc_bunit_sz = val; + return count; +} +EXPORT_SYMBOL(lprocfs_quota_wr_bunit); + +int lprocfs_quota_rd_btune(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, "%lu\n", + obd->u.obt.obt_qctxt.lqc_btune_sz); +} +EXPORT_SYMBOL(lprocfs_quota_rd_btune); + +int lprocfs_quota_wr_btune(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 <= QUOTABLOCK_SIZE * MIN_QLIMIT || val % QUOTABLOCK_SIZE || + val >= obd->u.obt.obt_qctxt.lqc_bunit_sz) + return -EINVAL; + + obd->u.obt.obt_qctxt.lqc_btune_sz = val; + return count; +} +EXPORT_SYMBOL(lprocfs_quota_wr_btune); + +int lprocfs_quota_rd_iunit(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, "%lu\n", + obd->u.obt.obt_qctxt.lqc_iunit_sz); +} +EXPORT_SYMBOL(lprocfs_quota_rd_iunit); + +int lprocfs_quota_wr_iunit(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 <= obd->u.obt.obt_qctxt.lqc_itune_sz) + return -EINVAL; + + obd->u.obt.obt_qctxt.lqc_iunit_sz = val; + return count; +} +EXPORT_SYMBOL(lprocfs_quota_wr_iunit); + +int lprocfs_quota_rd_itune(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, "%lu\n", + obd->u.obt.obt_qctxt.lqc_itune_sz); +} +EXPORT_SYMBOL(lprocfs_quota_rd_itune); + +int lprocfs_quota_wr_itune(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 <= MIN_QLIMIT || + val >= obd->u.obt.obt_qctxt.lqc_iunit_sz) + return -EINVAL; + + obd->u.obt.obt_qctxt.lqc_itune_sz = val; + return count; +} +EXPORT_SYMBOL(lprocfs_quota_wr_itune); + +#define USER_QUOTA 1 +#define GROUP_QUOTA 2 + +#define MAX_STYPE_SIZE 5 + +/* The following information about CURRENT quotas is expected on the output: + * MDS: u for user quotas (administrative+operational) turned on, + * g for group quotas (administrative+operational) turned on, + * 1 for 32-bit operational quotas and 32-bit administrative quotas, + * 2 for 32-bit operational quotas and 64-bit administrative quotas, + * 3 for 64-bit operational quotas and 64-bit administrative quotas + * OST: u for user quotas (operational) turned on, + * g for group quotas (operational) turned on, + * 1 for 32-bit local operational quotas, + * 3 for 64-bit local operational quotas, + * Permanent parameters can be read with lctl (?) + */ +int lprocfs_quota_rd_type(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + struct obd_device *obd = (struct obd_device *)data; + char stype[MAX_STYPE_SIZE + 1] = ""; + int oq_type, rc, is_mds; + lustre_quota_version_t aq_version, oq_version; + struct obd_device_target *obt; + + LASSERT(obd != NULL); + + obt = &obd->u.obt; + is_mds = !strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME); + + /* Collect the needed information */ + oq_type = obd->u.obt.obt_qctxt.lqc_flags; + oq_version = obt->obt_qfmt; + if (is_mds) { + rc = mds_quota_get_version(obd, &aq_version); + if (rc) + return -EPROTO; + /* Here we can also assert that aq_type == oq_type + * except for quota startup/shutdown states */ + } + + /* Transform the collected data into a user-readable string */ + if (oq_type & LQC_USRQUOTA_FLAG) + strcat(stype, "u"); + if (oq_type & LQC_GRPQUOTA_FLAG) + strcat(stype, "g"); + + if ((!is_mds || aq_version == LUSTRE_QUOTA_V1) && + oq_version == LUSTRE_QUOTA_V1) + strcat(stype, "1"); +#ifdef HAVE_QUOTA64 + else if ((!is_mds || aq_version == LUSTRE_QUOTA_V2) && + oq_version == LUSTRE_QUOTA_V2) + strcat(stype, "3"); +#endif + else if (is_mds && aq_version == LUSTRE_QUOTA_V2 && + oq_version == LUSTRE_QUOTA_V1) + strcat(stype, "2"); + else + return -EPROTO; + + return snprintf(page, count, "%s\n", stype); +} +EXPORT_SYMBOL(lprocfs_quota_rd_type); + +static int auto_quota_on(struct obd_device *obd, int type, + struct super_block *sb, int is_master) +{ + struct obd_quotactl *oqctl; + struct lvfs_run_ctxt saved; + int rc = 0, id; + struct obd_device_target *obt; + ENTRY; + + LASSERT(type == USRQUOTA || type == GRPQUOTA || type == UGQUOTA); + + obt = &obd->u.obt; + + OBD_ALLOC_PTR(oqctl); + if (!oqctl) + RETURN(-ENOMEM); + + if (!atomic_dec_and_test(&obt->obt_quotachecking)) { + CDEBUG(D_INFO, "other people are doing quotacheck\n"); + atomic_inc(&obt->obt_quotachecking); + RETURN(-EBUSY); + } + + id = UGQUOTA2LQC(type); + /* quota already turned on */ + if ((obt->obt_qctxt.lqc_flags & id) == id) { + rc = 0; + goto out; + } + + oqctl->qc_type = type; + oqctl->qc_cmd = Q_QUOTAON; + oqctl->qc_id = obt->obt_qfmt; + + push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); + if (is_master) { + struct mds_obd *mds = &obd->u.mds; + + down(&mds->mds_qonoff_sem); + /* turn on cluster wide quota */ + rc = mds_admin_quota_on(obd, oqctl); + if (rc) + CDEBUG(rc == -ENOENT ? D_QUOTA : D_ERROR, + "auto-enable admin quota failed. rc=%d\n", rc); + up(&mds->mds_qonoff_sem); + + } + if (!rc) { + /* turn on local quota */ + rc = fsfilt_quotactl(obd, sb, oqctl); + if (rc) + CDEBUG(rc == -ENOENT ? D_QUOTA : D_ERROR, + "auto-enable local quota failed. rc=%d\n", rc); + else + obt->obt_qctxt.lqc_flags |= UGQUOTA2LQC(type); + } + + pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); + +out: + atomic_inc(&obt->obt_quotachecking); + + OBD_FREE_PTR(oqctl); + RETURN(rc); +} + +static int filter_quota_set_version(struct obd_device *obd, + lustre_quota_version_t version) +{ + struct obd_device_target *obt = &obd->u.obt; + + if (version != LUSTRE_QUOTA_V1) { +#ifdef HAVE_QUOTA64 + if (version != LUSTRE_QUOTA_V2) +#endif + return -EINVAL; + } + + if (!atomic_dec_and_test(&obt->obt_quotachecking)) { + CDEBUG(D_INFO, "other people are doing quotacheck\n"); + atomic_inc(&obt->obt_quotachecking); + return -EBUSY; + } + + if (obt->obt_qctxt.lqc_flags & (LQC_USRQUOTA_FLAG | LQC_GRPQUOTA_FLAG)) { + atomic_inc(&obt->obt_quotachecking); + return -EBUSY; + } + + obt->obt_qfmt = version; + + atomic_inc(&obt->obt_quotachecking); + + return 0; +} + +/* The following settings of CURRENT quotas is expected on the input: + * MDS: u for user quotas (administrative+operational) turned on, + * g for group quotas (administrative+operational) turned on, + * 1 for 32-bit operational quotas and 32-bit administrative quotas, + * 2 for 32-bit operational quotas and 64-bit administrative quotas, + * 3 for 64-bit operational quotas and 64-bit administrative quotas + * OST: u for user quotas (operational) turned on, + * g for group quotas (operational) turned on, + * 1 for 32-bit local operational quotas, + * 2 for 32-bit local operational quotas, + * 3 for 64-bit local operational quotas, + * Permanent parameters can be set with lctl/tunefs + */ +int lprocfs_quota_wr_type(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct obd_device *obd = (struct obd_device *)data; + struct obd_device_target *obt; + int type = 0, is_mds, idx; + unsigned long i; + char stype[MAX_STYPE_SIZE + 1] = ""; + static const lustre_quota_version_t s2av[3] = {LUSTRE_QUOTA_V1, + LUSTRE_QUOTA_V2, + LUSTRE_QUOTA_V2}, + s2ov[3] = {LUSTRE_QUOTA_V1, + LUSTRE_QUOTA_V1, + LUSTRE_QUOTA_V2}; + LASSERT(obd != NULL); + + obt = &obd->u.obt; + + is_mds = !strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME); + + if (count > MAX_STYPE_SIZE) + return -EINVAL; + + if (copy_from_user(stype, buffer, count)) + return -EFAULT; + + for (i = 0 ; i < count ; i++) { + int rc; + + switch (stype[i]) { + case 'u' : + type |= USER_QUOTA; + break; + case 'g' : + type |= GROUP_QUOTA; + break; + /* quota version specifiers */ + case '1' : + case '2' : + case '3' : + idx = stype[i] - '1'; +#ifndef HAVE_QUOTA64 + if (s2ov[idx] == LUSTRE_QUOTA_V2) + return -EINVAL; +#endif + if (is_mds) { + rc = mds_quota_set_version(obd, s2av[idx]); + if (rc) { + CDEBUG(D_QUOTA, "failed to set admin " + "quota to spec %c! %d\n", + stype[i], rc); + return rc; + } + } + rc = filter_quota_set_version(obd, s2ov[idx]); + if (rc) { + CDEBUG(D_QUOTA, "failed to set operational quota" + " to spec %c! %d\n", stype[i], rc); + return rc; + } + break; + default : /* just skip stray symbols like \n */ + break; + } + } + + if (type != 0) + auto_quota_on(obd, type - 1, obt->obt_sb, is_mds); + + return count; +} +EXPORT_SYMBOL(lprocfs_quota_wr_type); + +int lprocfs_quota_rd_switch_seconds(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_switch_seconds); +} +EXPORT_SYMBOL(lprocfs_quota_rd_switch_seconds); + +int lprocfs_quota_wr_switch_seconds(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 <= 10) + return -EINVAL; + + obd->u.obt.obt_qctxt.lqc_switch_seconds = val; + return count; +} +EXPORT_SYMBOL(lprocfs_quota_wr_switch_seconds); + +int lprocfs_quota_rd_switch_qs(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, "changing qunit size is %s\n", + obd->u.obt.obt_qctxt.lqc_switch_qs ? + "enabled" : "disabled"); +} +EXPORT_SYMBOL(lprocfs_quota_rd_switch_qs); + +int lprocfs_quota_wr_switch_qs(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) + obd->u.obt.obt_qctxt.lqc_switch_qs = 1; + else + obd->u.obt.obt_qctxt.lqc_switch_qs = 0; + + return count; +} +EXPORT_SYMBOL(lprocfs_quota_wr_switch_qs); + +int lprocfs_quota_rd_boundary_factor(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, "%lu\n", + obd->u.obt.obt_qctxt.lqc_cqs_boundary_factor); +} +EXPORT_SYMBOL(lprocfs_quota_rd_boundary_factor); + +int lprocfs_quota_wr_boundary_factor(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 < 2) + return -EINVAL; + + obd->u.obt.obt_qctxt.lqc_cqs_boundary_factor = val; + return count; +} +EXPORT_SYMBOL(lprocfs_quota_wr_boundary_factor); + +int lprocfs_quota_rd_least_bunit(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, "%lu\n", + obd->u.obt.obt_qctxt.lqc_cqs_least_bunit); +} +EXPORT_SYMBOL(lprocfs_quota_rd_least_bunit); + +int lprocfs_quota_wr_least_bunit(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 < PTLRPC_MAX_BRW_SIZE || + val >= obd->u.obt.obt_qctxt.lqc_bunit_sz) + return -EINVAL; + + obd->u.obt.obt_qctxt.lqc_cqs_least_bunit = val; + return count; +} +EXPORT_SYMBOL(lprocfs_quota_wr_least_bunit); + +int lprocfs_quota_rd_least_iunit(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, "%lu\n", + obd->u.obt.obt_qctxt.lqc_cqs_least_iunit); +} +EXPORT_SYMBOL(lprocfs_quota_rd_least_iunit); + +int lprocfs_quota_wr_least_iunit(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 < 1 || val >= obd->u.obt.obt_qctxt.lqc_iunit_sz) + return -EINVAL; + + obd->u.obt.obt_qctxt.lqc_cqs_least_iunit = val; + return count; +} +EXPORT_SYMBOL(lprocfs_quota_wr_least_iunit); + +int lprocfs_quota_rd_qs_factor(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, "%lu\n", + obd->u.obt.obt_qctxt.lqc_cqs_qs_factor); +} +EXPORT_SYMBOL(lprocfs_quota_rd_qs_factor); + +int lprocfs_quota_wr_qs_factor(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 < 2) + return -EINVAL; + + obd->u.obt.obt_qctxt.lqc_cqs_qs_factor = val; + return count; +} +EXPORT_SYMBOL(lprocfs_quota_wr_qs_factor); + +struct lprocfs_vars lprocfs_quota_common_vars[] = { + { "quota_bunit_sz", lprocfs_quota_rd_bunit, + lprocfs_quota_wr_bunit, 0}, + { "quota_btune_sz", lprocfs_quota_rd_btune, + lprocfs_quota_wr_btune, 0}, + { "quota_iunit_sz", lprocfs_quota_rd_iunit, + lprocfs_quota_wr_iunit, 0}, + { "quota_itune_sz", lprocfs_quota_rd_itune, + lprocfs_quota_wr_itune, 0}, + { "quota_type", lprocfs_quota_rd_type, + lprocfs_quota_wr_type, 0}, + { "quota_switch_seconds", lprocfs_quota_rd_switch_seconds, + lprocfs_quota_wr_switch_seconds, 0 }, +}; + +struct lprocfs_vars lprocfs_quota_master_vars[] = { + { "quota_switch_qs", lprocfs_quota_rd_switch_qs, + lprocfs_quota_wr_switch_qs, 0 }, + { "quota_boundary_factor", lprocfs_quota_rd_boundary_factor, + lprocfs_quota_wr_boundary_factor, 0 }, + { "quota_least_bunit", lprocfs_quota_rd_least_bunit, + lprocfs_quota_wr_least_bunit, 0 }, + { "quota_least_iunit", lprocfs_quota_rd_least_iunit, + lprocfs_quota_wr_least_iunit, 0 }, + { "quota_qs_factor", lprocfs_quota_rd_qs_factor, + lprocfs_quota_wr_qs_factor, 0 }, +}; + +int lquota_proc_setup(struct obd_device *obd, int is_master) +{ + struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt; + int rc = 0; + ENTRY; + + LASSERT(lquota_type_proc_dir && obd); + qctxt->lqc_proc_dir = lprocfs_register(obd->obd_name, + lquota_type_proc_dir, + lprocfs_quota_common_vars, obd); + if (IS_ERR(qctxt->lqc_proc_dir)) { + rc = PTR_ERR(qctxt->lqc_proc_dir); + CERROR("error %d setting up lprocfs for %s\n", rc, + obd->obd_name); + qctxt->lqc_proc_dir = NULL; + GOTO(out, rc); + } + + if (is_master) { + rc = lprocfs_add_vars(qctxt->lqc_proc_dir, + lprocfs_quota_master_vars, obd); + if (rc) { + CERROR("error %d setting up lprocfs for %s" + "(quota master)\n", rc, obd->obd_name); + GOTO(out_free_proc, rc); + } + } + + qctxt->lqc_stats = lprocfs_alloc_stats(LQUOTA_LAST_STAT - + LQUOTA_FIRST_STAT, 0); + if (!qctxt->lqc_stats) + GOTO(out_free_proc, rc = -ENOMEM); + + lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_SYNC_ACQ, + LPROCFS_CNTR_AVGMINMAX, "sync_acq_req", "us"); + lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_SYNC_REL, + LPROCFS_CNTR_AVGMINMAX, "sync_rel_req", "us"); + lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_ASYNC_ACQ, + LPROCFS_CNTR_AVGMINMAX, "async_acq_req", "us"); + lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_ASYNC_REL, + LPROCFS_CNTR_AVGMINMAX, "async_rel_req", "us"); + + lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_CHK_BLK, + LPROCFS_CNTR_AVGMINMAX, + "wait_for_blk_quota(lquota_chkquota)", "us"); + lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_CHK_INO, + LPROCFS_CNTR_AVGMINMAX, + "wait_for_ino_quota(lquota_chkquota)", "us"); + lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_COMMIT_BLK, + LPROCFS_CNTR_AVGMINMAX, + "wait_for_blk_quota(lquota_pending_commit)", + "us"); + lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_COMMIT_INO, + LPROCFS_CNTR_AVGMINMAX, + "wait_for_ino_quota(lquota_pending_commit)", + "us"); + + lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_PENDING_BLK_QUOTA, + LPROCFS_CNTR_AVGMINMAX, + "wait_for_pending_blk_quota_req" + "(qctxt_wait_pending_dqacq)", "us"); + lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_PENDING_INO_QUOTA, + LPROCFS_CNTR_AVGMINMAX, + "wait_for_pending_ino_quota_req" + "(qctxt_wait_pending_dqacq)", "us"); + lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_NOWAIT_PENDING_BLK_QUOTA, + LPROCFS_CNTR_AVGMINMAX, + "nowait_for_pending_blk_quota_req" + "(qctxt_wait_pending_dqacq)", "us"); + lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_NOWAIT_PENDING_INO_QUOTA, + LPROCFS_CNTR_AVGMINMAX, + "nowait_for_pending_ino_quota_req" + "(qctxt_wait_pending_dqacq)", "us"); + + lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_QUOTA_CTL, + LPROCFS_CNTR_AVGMINMAX, "quota_ctl", "us"); + lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_ADJUST_QUNIT, + LPROCFS_CNTR_AVGMINMAX, "adjust_qunit", "us"); + + lprocfs_register_stats(qctxt->lqc_proc_dir, "stats", qctxt->lqc_stats); + + RETURN(rc); + +out_free_proc: + lprocfs_remove(&qctxt->lqc_proc_dir); +out: + RETURN(rc); +} + +int lquota_proc_cleanup(struct lustre_quota_ctxt *qctxt) +{ + if (!qctxt || !qctxt->lqc_proc_dir) + return -EINVAL; + lprocfs_remove(&qctxt->lqc_proc_dir); + return 0; +} + +#endif /* LPROCFS */ diff --git a/lustre/quota/quota_adjust_qunit.c b/lustre/quota/quota_adjust_qunit.c index 8344fa8bda95f83884ac70b8943b90fc29236956..a894bc1d55d1bae9631ffdb63d1384ceaeb66dc1 100644 --- a/lustre/quota/quota_adjust_qunit.c +++ b/lustre/quota/quota_adjust_qunit.c @@ -36,7 +36,7 @@ #ifndef EXPORT_SYMTAB # define EXPORT_SYMTAB #endif -#define DEBUG_SUBSYSTEM S_MDS +#define DEBUG_SUBSYSTEM S_LQUOTA #ifdef __KERNEL__ # include <linux/version.h> @@ -321,10 +321,10 @@ search_lqs: } int filter_quota_adjust_qunit(struct obd_export *exp, - struct quota_adjust_qunit *oqaq) + struct quota_adjust_qunit *oqaq, + struct lustre_quota_ctxt *qctxt) { struct obd_device *obd = exp->exp_obd; - struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt; unsigned int uid = 0, gid = 0; int rc = 0; ENTRY; @@ -355,7 +355,8 @@ int filter_quota_adjust_qunit(struct obd_export *exp, #endif /* __KERNEL__ */ int client_quota_adjust_qunit(struct obd_export *exp, - struct quota_adjust_qunit *oqaq) + struct quota_adjust_qunit *oqaq, + struct lustre_quota_ctxt *qctxt) { struct ptlrpc_request *req; struct quota_adjust_qunit *oqa; @@ -395,7 +396,8 @@ out: } int lov_quota_adjust_qunit(struct obd_export *exp, - struct quota_adjust_qunit *oqaq) + struct quota_adjust_qunit *oqaq, + struct lustre_quota_ctxt *qctxt) { struct obd_device *obd = class_exp2obd(exp); struct lov_obd *lov = &obd->u.lov; @@ -415,7 +417,8 @@ int lov_quota_adjust_qunit(struct obd_export *exp, continue; } - err = obd_quota_adjust_qunit(lov->lov_tgts[i]->ltd_exp, oqaq); + err = obd_quota_adjust_qunit(lov->lov_tgts[i]->ltd_exp, oqaq, + NULL); if (err) { if (lov->lov_tgts[i]->ltd_active && !rc) rc = err; diff --git a/lustre/quota/quota_check.c b/lustre/quota/quota_check.c index 2789c011dc5bcd7a0f847d9c34b55faace844886..b91bee7ebab89959eadcab1b4d0f2d1b2e2e37cb 100644 --- a/lustre/quota/quota_check.c +++ b/lustre/quota/quota_check.c @@ -36,7 +36,7 @@ #ifndef EXPORT_SYMTAB # define EXPORT_SYMTAB #endif -#define DEBUG_SUBSYSTEM S_MDS +#define DEBUG_SUBSYSTEM S_LQUOTA #ifdef __KERNEL__ # include <linux/version.h> diff --git a/lustre/quota/quota_context.c b/lustre/quota/quota_context.c index 9fbf63126c4c2321a6690d14d7dc9d31dc1b6353..c1300a23bd0fa4a50237f34abc657134a491f08a 100644 --- a/lustre/quota/quota_context.c +++ b/lustre/quota/quota_context.c @@ -44,7 +44,7 @@ # define EXPORT_SYMTAB #endif -#define DEBUG_SUBSYSTEM S_MDS +#define DEBUG_SUBSYSTEM S_LQUOTA #include <linux/version.h> #include <linux/fs.h> @@ -58,6 +58,7 @@ #include <lustre_quota.h> #include <lustre_fsfilt.h> #include <class_hash.h> +#include <lprocfs_status.h> #include "quota_internal.h" extern struct lustre_hash_operations lqs_hash_operations; @@ -508,9 +509,14 @@ static int split_before_schedule_dqacq(struct obd_device *obd, int rc = 0; unsigned long factor; struct qunit_data tmp_qdata; + struct timeval work_start; + struct timeval work_end; + long timediff; ENTRY; LASSERT(qdata && qdata->qd_count); + LASSERT(opc == QUOTA_DQACQ || opc == QUOTA_DQREL); + do_gettimeofday(&work_start); QDATA_DEBUG(qdata, "%s quota split.\n", QDATA_IS_BLK(qdata) ? "block" : "inode"); if (QDATA_IS_BLK(qdata)) @@ -531,6 +537,16 @@ static int split_before_schedule_dqacq(struct obd_device *obd, QDATA_DEBUG(qdata, "don't be split.\n"); rc = schedule_dqacq(obd, qctxt, qdata, opc, wait); } + do_gettimeofday(&work_end); + timediff = cfs_timeval_sub(&work_end, &work_start, NULL); + if (opc == QUOTA_DQACQ) + lprocfs_counter_add(qctxt->lqc_stats, + wait ? LQUOTA_SYNC_ACQ : LQUOTA_ASYNC_ACQ, + timediff); + else + lprocfs_counter_add(qctxt->lqc_stats, + wait ? LQUOTA_SYNC_REL : LQUOTA_ASYNC_REL, + timediff); RETURN(rc); } @@ -976,9 +992,13 @@ qctxt_wait_pending_dqacq(struct lustre_quota_ctxt *qctxt, unsigned int id, { struct lustre_qunit *qunit = NULL; struct qunit_data qdata; + struct timeval work_start; + struct timeval work_end; + long timediff; struct l_wait_info lwi = { 0 }; ENTRY; + do_gettimeofday(&work_start); qdata.qd_id = id; qdata.qd_flags = type; if (isblk) @@ -1002,14 +1022,29 @@ qctxt_wait_pending_dqacq(struct lustre_quota_ctxt *qctxt, unsigned int id, CDEBUG(D_QUOTA, "qunit(%p) finishes waiting. (rc:%d)\n", qunit, qunit->lq_rc); qunit_put(qunit); + do_gettimeofday(&work_end); + timediff = cfs_timeval_sub(&work_end, &work_start, NULL); + lprocfs_counter_add(qctxt->lqc_stats, + isblk ? LQUOTA_WAIT_PENDING_BLK_QUOTA : + LQUOTA_WAIT_PENDING_INO_QUOTA, + timediff); + } else { + do_gettimeofday(&work_end); + timediff = cfs_timeval_sub(&work_end, &work_start, NULL); + lprocfs_counter_add(qctxt->lqc_stats, + isblk ? LQUOTA_NOWAIT_PENDING_BLK_QUOTA : + LQUOTA_NOWAIT_PENDING_INO_QUOTA, + timediff); } + RETURN(0); } int -qctxt_init(struct lustre_quota_ctxt *qctxt, struct super_block *sb, - dqacq_handler_t handler) +qctxt_init(struct obd_device *obd, dqacq_handler_t handler) { + struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt; + struct super_block *sb = obd->u.obt.obt_sb; int rc = 0; ENTRY; @@ -1040,11 +1075,17 @@ qctxt_init(struct lustre_quota_ctxt *qctxt, struct super_block *sb, rc = lustre_hash_init(&LQC_HASH_BODY(qctxt), "LQS_HASH",128, &lqs_hash_operations); if (rc) { - CDEBUG(D_ERROR, "initialize hash lqs on ost error!\n"); + CDEBUG(D_ERROR, "initialize hash lqs for %s error!\n", + obd->obd_name); lustre_hash_exit(&LQC_HASH_BODY(qctxt)); } spin_unlock(&qctxt->lqc_lock); +#ifdef LPROCFS + if (lquota_proc_setup(obd, is_master(obd, qctxt, 0, 0))) + CERROR("initialize proc for %s error!\n", obd->obd_name); +#endif + RETURN(rc); } @@ -1081,6 +1122,11 @@ void qctxt_cleanup(struct lustre_quota_ctxt *qctxt, int force) lustre_hash_exit(&LQC_HASH_BODY(qctxt)); ptlrpcd_decref(); +#ifdef LPROCFS + if (lquota_proc_cleanup(qctxt)) + CERROR("cleanup proc error!\n"); +#endif + EXIT; } diff --git a/lustre/quota/quota_ctl.c b/lustre/quota/quota_ctl.c index 31e5a49e59a675adab412506a007b052dda823d0..327287e2d31ce822771615aa8e7158db073db251 100644 --- a/lustre/quota/quota_ctl.c +++ b/lustre/quota/quota_ctl.c @@ -36,7 +36,7 @@ #ifndef EXPORT_SYMTAB # define EXPORT_SYMTAB #endif -#define DEBUG_SUBSYSTEM S_MDS +#define DEBUG_SUBSYSTEM S_LQUOTA #ifdef __KERNEL__ # include <linux/version.h> @@ -71,9 +71,14 @@ int mds_quota_ctl(struct obd_export *exp, struct obd_quotactl *oqctl) { struct obd_device *obd = exp->exp_obd; + struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt; + struct timeval work_start; + struct timeval work_end; + long timediff; int rc = 0; ENTRY; + do_gettimeofday(&work_start); switch (oqctl->qc_cmd) { case Q_QUOTAON: rc = mds_quota_on(obd, oqctl); @@ -113,6 +118,9 @@ int mds_quota_ctl(struct obd_export *exp, struct obd_quotactl *oqctl) CDEBUG(D_INFO, "mds_quotactl admin quota command %d, id %u, " "type %d, failed: rc = %d\n", oqctl->qc_cmd, oqctl->qc_id, oqctl->qc_type, rc); + do_gettimeofday(&work_end); + timediff = cfs_timeval_sub(&work_end, &work_start, NULL); + lprocfs_counter_add(qctxt->lqc_stats, LQUOTA_QUOTA_CTL, timediff); RETURN(rc); } @@ -122,9 +130,14 @@ int filter_quota_ctl(struct obd_export *exp, struct obd_quotactl *oqctl) struct obd_device *obd = exp->exp_obd; struct obd_device_target *obt = &obd->u.obt; struct lvfs_run_ctxt saved; + struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt; + struct timeval work_start; + struct timeval work_end; + long timediff; int rc = 0; ENTRY; + do_gettimeofday(&work_start); switch (oqctl->qc_cmd) { case Q_FINVALIDATE: case Q_QUOTAON: @@ -234,6 +247,9 @@ adjust: obd->obd_name, oqctl->qc_cmd); RETURN(-EFAULT); } + do_gettimeofday(&work_end); + timediff = cfs_timeval_sub(&work_end, &work_start, NULL); + lprocfs_counter_add(qctxt->lqc_stats, LQUOTA_QUOTA_CTL, timediff); RETURN(rc); } diff --git a/lustre/quota/quota_interface.c b/lustre/quota/quota_interface.c index e5b9f8134b2afd63cbe6ea1e710fcd72df9a4b55..eeee79e0c743a5f1c68f61adad6fe3cdfc5da1b8 100644 --- a/lustre/quota/quota_interface.c +++ b/lustre/quota/quota_interface.c @@ -37,7 +37,7 @@ #ifndef EXPORT_SYMTAB # define EXPORT_SYMTAB #endif -#define DEBUG_SUBSYSTEM S_MDS +#define DEBUG_SUBSYSTEM S_LQUOTA #ifdef __KERNEL__ # include <linux/version.h> @@ -69,260 +69,6 @@ #include "quota_internal.h" #ifdef __KERNEL__ - -/* quota proc file handling functions */ -#ifdef LPROCFS - -#define USER_QUOTA 1 -#define GROUP_QUOTA 2 - -#define MAX_STYPE_SIZE 5 - -/* The following information about CURRENT quotas is expected on the output: - * MDS: u for user quotas (administrative+operational) turned on, - * g for group quotas (administrative+operational) turned on, - * 1 for 32-bit operational quotas and 32-bit administrative quotas, - * 2 for 32-bit operational quotas and 64-bit administrative quotas, - * 3 for 64-bit operational quotas and 64-bit administrative quotas - * OST: u for user quotas (operational) turned on, - * g for group quotas (operational) turned on, - * 1 for 32-bit local operational quotas, - * 3 for 64-bit local operational quotas, - * Permanent parameters can be read with lctl (?) - */ -int lprocfs_quota_rd_type(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - struct obd_device *obd = (struct obd_device *)data; - char stype[MAX_STYPE_SIZE + 1] = ""; - int oq_type, rc, is_mds; - lustre_quota_version_t aq_version, oq_version; - struct obd_device_target *obt; - - LASSERT(obd != NULL); - - obt = &obd->u.obt; - is_mds = !strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME); - - /* Collect the needed information */ - oq_type = obd->u.obt.obt_qctxt.lqc_flags; - oq_version = obt->obt_qfmt; - if (is_mds) { - rc = mds_quota_get_version(obd, &aq_version); - if (rc) - return -EPROTO; - /* Here we can also assert that aq_type == oq_type - * except for quota startup/shutdown states */ - } - - /* Transform the collected data into a user-readable string */ - if (oq_type & LQC_USRQUOTA_FLAG) - strcat(stype, "u"); - if (oq_type & LQC_GRPQUOTA_FLAG) - strcat(stype, "g"); - - if ((!is_mds || aq_version == LUSTRE_QUOTA_V1) && - oq_version == LUSTRE_QUOTA_V1) - strcat(stype, "1"); -#ifdef HAVE_QUOTA64 - else if ((!is_mds || aq_version == LUSTRE_QUOTA_V2) && - oq_version == LUSTRE_QUOTA_V2) - strcat(stype, "3"); -#endif - else if (is_mds && aq_version == LUSTRE_QUOTA_V2 && - oq_version == LUSTRE_QUOTA_V1) - strcat(stype, "2"); - else - return -EPROTO; - - return snprintf(page, count, "%s\n", stype); -} -EXPORT_SYMBOL(lprocfs_quota_rd_type); - -static int auto_quota_on(struct obd_device *obd, int type, - struct super_block *sb, int is_master) -{ - struct obd_quotactl *oqctl; - struct lvfs_run_ctxt saved; - int rc = 0, id; - struct obd_device_target *obt; - ENTRY; - - LASSERT(type == USRQUOTA || type == GRPQUOTA || type == UGQUOTA); - - obt = &obd->u.obt; - - OBD_ALLOC_PTR(oqctl); - if (!oqctl) - RETURN(-ENOMEM); - - if (!atomic_dec_and_test(&obt->obt_quotachecking)) { - CDEBUG(D_INFO, "other people are doing quotacheck\n"); - atomic_inc(&obt->obt_quotachecking); - RETURN(-EBUSY); - } - - id = UGQUOTA2LQC(type); - /* quota already turned on */ - if ((obt->obt_qctxt.lqc_flags & id) == id) { - rc = 0; - goto out; - } - - oqctl->qc_type = type; - oqctl->qc_cmd = Q_QUOTAON; - oqctl->qc_id = obt->obt_qfmt; - - push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - if (is_master) { - struct mds_obd *mds = &obd->u.mds; - - down(&mds->mds_qonoff_sem); - /* turn on cluster wide quota */ - rc = mds_admin_quota_on(obd, oqctl); - if (rc) - CDEBUG(rc == -ENOENT ? D_QUOTA : D_ERROR, - "auto-enable admin quota failed. rc=%d\n", rc); - up(&mds->mds_qonoff_sem); - - } - if (!rc) { - /* turn on local quota */ - rc = fsfilt_quotactl(obd, sb, oqctl); - if (rc) - CDEBUG(rc == -ENOENT ? D_QUOTA : D_ERROR, - "auto-enable local quota failed. rc=%d\n", rc); - else - obt->obt_qctxt.lqc_flags |= UGQUOTA2LQC(type); - } - - pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - -out: - atomic_inc(&obt->obt_quotachecking); - - OBD_FREE_PTR(oqctl); - RETURN(rc); -} - -static int filter_quota_set_version(struct obd_device *obd, - lustre_quota_version_t version) -{ - struct obd_device_target *obt = &obd->u.obt; - - if (version != LUSTRE_QUOTA_V1) { -#ifdef HAVE_QUOTA64 - if (version != LUSTRE_QUOTA_V2) -#endif - return -EINVAL; - } - - if (!atomic_dec_and_test(&obt->obt_quotachecking)) { - CDEBUG(D_INFO, "other people are doing quotacheck\n"); - atomic_inc(&obt->obt_quotachecking); - return -EBUSY; - } - - if (obt->obt_qctxt.lqc_flags & (LQC_USRQUOTA_FLAG | LQC_GRPQUOTA_FLAG)) { - atomic_inc(&obt->obt_quotachecking); - return -EBUSY; - } - - obt->obt_qfmt = version; - - atomic_inc(&obt->obt_quotachecking); - - return 0; -} - -/* The following settings of CURRENT quotas is expected on the input: - * MDS: u for user quotas (administrative+operational) turned on, - * g for group quotas (administrative+operational) turned on, - * 1 for 32-bit operational quotas and 32-bit administrative quotas, - * 2 for 32-bit operational quotas and 64-bit administrative quotas, - * 3 for 64-bit operational quotas and 64-bit administrative quotas - * OST: u for user quotas (operational) turned on, - * g for group quotas (operational) turned on, - * 1 for 32-bit local operational quotas, - * 2 for 32-bit local operational quotas, - * 3 for 64-bit local operational quotas, - * Permanent parameters can be set with lctl/tunefs - */ -int lprocfs_quota_wr_type(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - struct obd_device *obd = (struct obd_device *)data; - struct obd_device_target *obt; - int type = 0, is_mds, idx; - unsigned long i; - char stype[MAX_STYPE_SIZE + 1] = ""; - static const lustre_quota_version_t s2av[3] = {LUSTRE_QUOTA_V1, - LUSTRE_QUOTA_V2, - LUSTRE_QUOTA_V2}, - s2ov[3] = {LUSTRE_QUOTA_V1, - LUSTRE_QUOTA_V1, - LUSTRE_QUOTA_V2}; - LASSERT(obd != NULL); - - obt = &obd->u.obt; - - is_mds = !strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME); - - if (count > MAX_STYPE_SIZE) - return -EINVAL; - - if (copy_from_user(stype, buffer, count)) - return -EFAULT; - - for (i = 0 ; i < count ; i++) { - int rc; - - switch (stype[i]) { - case 'u' : - type |= USER_QUOTA; - break; - case 'g' : - type |= GROUP_QUOTA; - break; - /* quota version specifiers */ - case '1' : - case '2' : - case '3' : - idx = stype[i] - '1'; -#ifndef HAVE_QUOTA64 - if (s2ov[idx] == LUSTRE_QUOTA_V2) - return -EINVAL; -#endif - if (is_mds) { - rc = mds_quota_set_version(obd, s2av[idx]); - if (rc) { - CDEBUG(D_QUOTA, "failed to set admin " - "quota to spec %c! %d\n", - stype[i], rc); - return rc; - } - } - rc = filter_quota_set_version(obd, s2ov[idx]); - if (rc) { - CDEBUG(D_QUOTA, "failed to set operational quota" - " to spec %c! %d\n", stype[i], rc); - return rc; - } - break; - default : /* just skip stray symbols like \n */ - break; - } - } - - if (type != 0) - auto_quota_on(obd, type - 1, obt->obt_sb, is_mds); - - return count; -} -EXPORT_SYMBOL(lprocfs_quota_wr_type); - -#endif /* LPROCFS */ - static int filter_quota_setup(struct obd_device *obd) { int rc = 0; @@ -335,7 +81,7 @@ static int filter_quota_setup(struct obd_device *obd) obt->obt_qfmt = LUSTRE_QUOTA_V1; #endif atomic_set(&obt->obt_quotachecking, 1); - rc = qctxt_init(&obt->obt_qctxt, obt->obt_sb, NULL); + rc = qctxt_init(obd, NULL); if (rc) CERROR("initialize quota context failed! (rc:%d)\n", rc); @@ -537,6 +283,10 @@ static int quota_chk_acq_common(struct obd_device *obd, unsigned int uid, unsigned int gid, int count, int *pending, int isblk, quota_acquire acquire) { + struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt; + struct timeval work_start; + struct timeval work_end; + long timediff; int rc = 0, cycle = 0, count_err = 0; ENTRY; @@ -544,6 +294,7 @@ static int quota_chk_acq_common(struct obd_device *obd, unsigned int uid, * pre-dqacq in time and quota hash on ost is used up, we * have to wait for the completion of in flight dqacq/dqrel, * in order to get enough quota for write b=12588 */ + do_gettimeofday(&work_start); while ((rc = quota_check_common(obd, uid, gid, count, cycle, isblk)) & QUOTA_RET_ACQUOTA) { @@ -591,10 +342,16 @@ static int quota_chk_acq_common(struct obd_device *obd, unsigned int uid, if (!cycle && rc & QUOTA_RET_INC_PENDING) *pending = 1; + do_gettimeofday(&work_end); + timediff = cfs_timeval_sub(&work_end, &work_start, NULL); + lprocfs_counter_add(qctxt->lqc_stats, + isblk ? LQUOTA_WAIT_FOR_CHK_BLK : + LQUOTA_WAIT_FOR_CHK_INO, + timediff); + RETURN(rc); } - static int filter_quota_check(struct obd_device *obd, unsigned int uid, unsigned int gid, int npage, int *flag, quota_acquire acquire) @@ -609,6 +366,9 @@ static int quota_pending_commit(struct obd_device *obd, unsigned int uid, unsigned int gid, int count, int isblk) { struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt; + struct timeval work_start; + struct timeval work_end; + long timediff; int i; __u32 id[MAXQUOTAS] = { uid, gid }; struct qunit_data qdata[MAXQUOTAS]; @@ -618,6 +378,7 @@ static int quota_pending_commit(struct obd_device *obd, unsigned int uid, if (!sb_any_quota_enabled(qctxt->lqc_sb)) RETURN(0); + do_gettimeofday(&work_start); for (i = 0; i < MAXQUOTAS; i++) { struct lustre_qunit_size *lqs = NULL; @@ -664,6 +425,12 @@ static int quota_pending_commit(struct obd_device *obd, unsigned int uid, lqs_putref(lqs); } } + do_gettimeofday(&work_end); + timediff = cfs_timeval_sub(&work_end, &work_start, NULL); + lprocfs_counter_add(qctxt->lqc_stats, + isblk ? LQUOTA_WAIT_FOR_COMMIT_BLK : + LQUOTA_WAIT_FOR_COMMIT_INO, + timediff); RETURN(0); } @@ -701,7 +468,7 @@ static int mds_quota_setup(struct obd_device *obd) atomic_set(&obt->obt_quotachecking, 1); /* initialize quota master and quota context */ sema_init(&mds->mds_qonoff_sem, 1); - rc = qctxt_init(&obt->obt_qctxt, obt->obt_sb, dqacq_handler); + rc = qctxt_init(obd, dqacq_handler); if (rc) { CERROR("initialize quota context failed! (rc:%d)\n", rc); RETURN(rc); @@ -1021,9 +788,23 @@ quota_interface_t lov_quota_interface = { }; #ifdef __KERNEL__ + +cfs_proc_dir_entry_t *lquota_type_proc_dir = NULL; + static int __init init_lustre_quota(void) { - int rc = qunit_cache_init(); + int rc = 0; + + lquota_type_proc_dir = lprocfs_register(OBD_LQUOTA_DEVICENAME, + proc_lustre_root, + NULL, NULL); + if (IS_ERR(lquota_type_proc_dir)) { + CERROR("LProcFS failed in lquota-init\n"); + rc = PTR_ERR(lquota_type_proc_dir); + return rc; + } + + rc = qunit_cache_init(); if (rc) return rc; PORTAL_SYMBOL_REGISTER(filter_quota_interface); @@ -1043,6 +824,9 @@ static void /*__exit*/ exit_lustre_quota(void) PORTAL_SYMBOL_UNREGISTER(lov_quota_interface); qunit_cache_cleanup(); + + if (lquota_type_proc_dir) + lprocfs_remove(&lquota_type_proc_dir); } MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>"); diff --git a/lustre/quota/quota_internal.h b/lustre/quota/quota_internal.h index c2250a212632e284aca28e56dd683285ae7e2c8b..03e6af13a8cca720c8571018a3db794f1fd813cc 100644 --- a/lustre/quota/quota_internal.h +++ b/lustre/quota/quota_internal.h @@ -45,6 +45,7 @@ /* This flag is set in qc_stat to distinguish if the current getquota * operation is for quota recovery */ #define QUOTA_RECOVERING 0x01 +#define OBD_LQUOTA_DEVICENAME "lquota" #ifdef __KERNEL__ @@ -101,8 +102,7 @@ int qctxt_adjust_qunit(struct obd_device *obd, struct lustre_quota_ctxt *qctxt, uid_t uid, gid_t gid, __u32 isblk, int wait); int qctxt_wait_pending_dqacq(struct lustre_quota_ctxt *qctxt, unsigned int id, unsigned short type, int isblk); -int qctxt_init(struct lustre_quota_ctxt *qctxt, struct super_block *sb, - dqacq_handler_t handler); +int qctxt_init(struct obd_device *obd, dqacq_handler_t handler); void qctxt_cleanup(struct lustre_quota_ctxt *qctxt, int force); void qslave_start_recovery(struct obd_device *obd, struct lustre_quota_ctxt *qctxt); @@ -167,10 +167,12 @@ static inline void lprocfs_quotacheck_test_init_vars #endif /* quota_adjust_qunit.c */ -int client_quota_adjust_qunit(struct obd_export *exp, struct - quota_adjust_qunit *oqaq); -int lov_quota_adjust_qunit(struct obd_export *exp, struct - quota_adjust_qunit *oqaq); +int client_quota_adjust_qunit(struct obd_export *exp, + struct quota_adjust_qunit *oqaq, + struct lustre_quota_ctxt *qctxt); +int lov_quota_adjust_qunit(struct obd_export *exp, + struct quota_adjust_qunit *oqaq, + struct lustre_quota_ctxt *qctxt); int quota_adjust_slave_lqs(struct quota_adjust_qunit *oqaq, struct lustre_quota_ctxt *qctxt); void qdata_to_oqaq(struct qunit_data *qdata, @@ -192,8 +194,13 @@ extern int quote_get_qdata(struct ptlrpc_request *req, struct qunit_data *qdata, int is_req, int is_exp); extern int quote_copy_qdata(struct ptlrpc_request *req, struct qunit_data *qdata, int is_req, int is_exp); -int filter_quota_adjust_qunit(struct obd_export *exp, struct - quota_adjust_qunit *oqaq); +int filter_quota_adjust_qunit(struct obd_export *exp, + struct quota_adjust_qunit *oqaq, + struct lustre_quota_ctxt *qctxt); +int lquota_proc_setup(struct obd_device *obd, int is_master); +int lquota_proc_cleanup(struct lustre_quota_ctxt *qctxt); + +extern cfs_proc_dir_entry_t *lquota_type_proc_dir; #endif #define LQS_BLK_DECREASE 1 diff --git a/lustre/quota/quota_master.c b/lustre/quota/quota_master.c index 8691c1b8779daa7e6a49e5f278285936a678e8a2..196fb818e0665f137a97f0f860b740897959bc48 100644 --- a/lustre/quota/quota_master.c +++ b/lustre/quota/quota_master.c @@ -44,7 +44,7 @@ # define EXPORT_SYMTAB #endif -#define DEBUG_SUBSYSTEM S_MDS +#define DEBUG_SUBSYSTEM S_LQUOTA #include <linux/version.h> #include <linux/fs.h> @@ -322,7 +322,7 @@ int dqacq_adjust_qunit_sz(struct obd_device *obd, qid_t id, int type, /* only when block qunit is reduced, boardcast to osts */ if ((adjust_res & LQS_BLK_DECREASE) && QAQ_IS_ADJBLK(oqaq)) - rc = obd_quota_adjust_qunit(mds->mds_osc_exp, oqaq); + rc = obd_quota_adjust_qunit(mds->mds_osc_exp, oqaq, qctxt); out: lustre_dqput(dquot); @@ -1227,7 +1227,7 @@ static int mds_init_slave_blimits(struct obd_device *obd, * this is will create a lqs for every ost, which will present * certain uid/gid is set quota or not */ QAQ_SET_ADJBLK(oqaq); - rc = obd_quota_adjust_qunit(mds->mds_osc_exp, oqaq); + rc = obd_quota_adjust_qunit(mds->mds_osc_exp, oqaq, qctxt); EXIT; out: diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index d2f042e59e2c613a29254383adfc5197bdcaef4c..224b03a419f17ef83e1f744f962624aa755079ba 100644 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -76,38 +76,38 @@ eval ONLY_99=true # set_blk_tunables(btune_sz) set_blk_tunesz() { - local btune=$(($1 * BLK_SZ)) + local btune=$(($1 * BLK_SZ)) # set btune size on all obdfilters - do_facet ost1 "lctl set_param obdfilter.*.quota_btune_sz=$btune" + do_facet ost1 "lctl set_param lquota.${FSNAME}-OST*.quota_btune_sz=$btune" # set btune size on mds - do_facet mds "lctl set_param mds.${FSNAME}-MDT*.quota_btune_sz=$btune" + do_facet mds "lctl set_param lquota.${FSNAME}-MDT*.quota_btune_sz=$btune" } # set_blk_unitsz(bunit_sz) set_blk_unitsz() { local bunit=$(($1 * BLK_SZ)) # set bunit size on all obdfilters - do_facet ost1 "lctl set_param obdfilter.*.quota_bunit_sz=$bunit" + do_facet ost1 "lctl set_param lquota.${FSNAME}-OST*.quota_bunit_sz=$bunit" # set bunit size on mds - do_facet mds "lctl set_param mds.${FSNAME}-MDT*.quota_bunit_sz=$bunit" + do_facet mds "lctl set_param lquota.${FSNAME}-MDT*.quota_bunit_sz=$bunit" } # set_file_tunesz(itune_sz) set_file_tunesz() { local itune=$1 # set itune size on all obdfilters - do_facet ost1 "lctl set_param obdfilter.*.quota_itune_sz=$itune" + do_facet ost1 "lctl set_param lquota.${FSNAME}-OST*.quota_itune_sz=$itune" # set itune size on mds - do_facet mds "lctl set_param mds.${FSNAME}-MDT*.quota_itune_sz=$itune" + do_facet mds "lctl set_param lquota.${FSNAME}-MDT*.quota_itune_sz=$itune" } # set_file_unitsz(iunit_sz) set_file_unitsz() { local iunit=$1 # set iunit size on all obdfilters - do_facet ost1 "lctl set_param obdfilter.*.quota_iunit_sz=$iunit" + do_facet ost1 "lctl set_param lquota.${FSNAME}-OST*.quota_iunit_sz=$iunit" # set iunit size on mds - do_facet mds "lctl set_param mds.${FSNAME}-MDT*.quota_iunit_sz=$iunit" + do_facet mds "lctl set_param lquota.${FSNAME}-MDT*.quota_iunit_sz=$iunit" } lustre_fail() { @@ -138,6 +138,24 @@ FAIL_ON_ERROR=true check_runas_id $TSTID2 $RUNAS2 FAIL_ON_ERROR=false +run_test_with_stat() { + (($# != 2)) && error "the number of arguments is wrong" + + do_facet mds "lctl set_param lquota.${FSNAME}-MDT*.stats=0" > /dev/null + for j in `seq $OSTCOUNT`; do + do_facet ost$j "lctl set_param lquota.${FSNAME}-OST*.stats=0" > /dev/null + done + run_test "$@" + if [ ${STAT:-"yes"} != "no" ]; then + echo "statistics info begin ***************************************" + do_facet mds "lctl get_param lquota.${FSNAME}-MDT*.stats" + for j in `seq $OSTCOUNT`; do + do_facet ost$j "lctl get_param lquota.${FSNAME}-OST*.stats" + done + echo "statistics info end ***************************************" + fi +} + # set quota test_0() { $LFS quotaoff -ug $DIR @@ -152,7 +170,7 @@ test_0() { do_facet ost$num "lctl set_param debug=+quota" done } -run_test 0 "Set quota =============================" +run_test_with_stat 0 "Set quota =============================" # test for specific quota limitation, qunit, qtune $1=block_quota_limit test_1_sub() { @@ -241,7 +259,7 @@ test_1() { set_blk_tunesz $((128 * 1024 / 2)) done } -run_test 1 "Block hard limit (normal use and out of quota) ===" +run_test_with_stat 1 "Block hard limit (normal use and out of quota) ===" # test for specific quota limitation, qunit, qtune $1=block_quota_limit test_2_sub() { @@ -331,7 +349,7 @@ test_2() { set_file_tunesz 2560 done } -run_test 2 "File hard limit (normal use and out of quota) ===" +run_test_with_stat 2 "File hard limit (normal use and out of quota) ===" test_block_soft() { TESTFILE=$1 @@ -428,7 +446,7 @@ test_3() { test_block_soft $TESTFILE $GRACE $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR } -run_test 3 "Block soft limit (start timer, timer goes off, stop timer) ===" +run_test_with_stat 3 "Block soft limit (start timer, timer goes off, stop timer) ===" test_file_soft() { TESTFILE=$1 @@ -514,7 +532,7 @@ test_4a() { # was test_4 $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace $MAX_IQ_TIME $DIR $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace $MAX_IQ_TIME $DIR } -run_test 4a "File soft limit (start timer, timer goes off, stop timer) ===" +run_test_with_stat 4a "File soft limit (start timer, timer goes off, stop timer) ===" test_4b() { # was test_4a GR_STR1="1w3d" @@ -542,7 +560,7 @@ test_4b() { # was test_4a $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace $MAX_IQ_TIME $DIR $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace $MAX_IQ_TIME $DIR } -run_test 4b "Grace time strings handling ===" +run_test_with_stat 4b "Grace time strings handling ===" # chown & chgrp (chown & chgrp successfully even out of block/file quota) test_5() { @@ -576,7 +594,7 @@ test_5() { $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR } -run_test 5 "Chown & chgrp successfully even out of block/file quota ===" +run_test_with_stat 5 "Chown & chgrp successfully even out of block/file quota ===" # block quota acquire & release test_6() { @@ -644,7 +662,7 @@ test_6() { $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR return 0 } -run_test 6 "Block quota acquire & release =========" +run_test_with_stat 6 "Block quota acquire & release =========" # quota recovery (block quota only by now) test_7() @@ -697,7 +715,7 @@ test_7() # cleanup $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR } -run_test 7 "Quota recovery (only block limit) ======" +run_test_with_stat 7 "Quota recovery (only block limit) ======" # run dbench with quota enabled test_8() { @@ -736,7 +754,7 @@ test_8() { cd $SAVE_PWD return $RC } -run_test 8 "Run dbench with quota enabled ===========" +run_test_with_stat 8 "Run dbench with quota enabled ===========" # run for fixing bug10707, it needs a big room. test for 64bit KB=1024 @@ -808,7 +826,7 @@ test_9() { return $RC } -run_test 9 "run for fixing bug10707(64bit) ===========" +run_test_with_stat 9 "run for fixing bug10707(64bit) ===========" # run for fixing bug10707, it need a big room. test for 32bit test_10() { @@ -866,7 +884,7 @@ test_10() { return $RC } -run_test 10 "run for fixing bug10707(32bit) ===========" +run_test_with_stat 10 "run for fixing bug10707(32bit) ===========" test_11() { wait_delete_completed @@ -935,7 +953,7 @@ test_11() { fi return $RV } -run_test 11 "run for fixing bug10912 ===========" +run_test_with_stat 11 "run for fixing bug10912 ===========" # test a deadlock between quota and journal b=11693 @@ -1007,7 +1025,7 @@ test_12() { $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR } -run_test 12 "test a deadlock between quota and journal ===" +run_test_with_stat 12 "test a deadlock between quota and journal ===" # test multiple clients write block quota b=11693 test_13() { @@ -1071,7 +1089,7 @@ test_13() { $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR } -run_test 13 "test multiple clients write block quota ===" +run_test_with_stat 13 "test multiple clients write block quota ===" check_if_quota_zero(){ line=`$LFS quota -v -$1 $2 $DIR | wc -l` @@ -1126,13 +1144,13 @@ test_14a() { # was test_14 b=12223 -- setting quota on root rm -f $TESTFILE sync; sleep 3; sync; } -run_test 14a "test setting quota on root ===" +run_test_with_stat 14a "test setting quota on root ===" # set quota version (both administrative and operational quotas) quota_set_version() { - do_facet mds "lctl set_param mds.${FSNAME}-MDT*.quota_type=$1" + do_facet mds "lctl set_param lquota.${FSNAME}-MDT*.quota_type=$1" for j in `seq $OSTCOUNT`; do - do_facet ost$j "lctl set_param obdfilter.*.quota_type=$1" + do_facet ost$j "lctl set_param lquota.${FSNAME}-OST*.quota_type=$1" done } @@ -1212,7 +1230,7 @@ test_14b(){ $LFS setquota -u quota15_$i -b 0 -B 0 -i 0 -I 0 $DIR || error "ifs setquota clear failed" done } -run_test 14b "setting 30 quota entries in quota v1 file before conversion ===" +run_test_with_stat 14b "setting 30 quota entries in quota v1 file before conversion ===" test_15(){ LIMIT=$((24 * 1024 * 1024 * 1024 * 1024)) # 24 TB @@ -1240,7 +1258,7 @@ test_15(){ echo "Testing that >4GB quota limits fail on volume with quota v1" ! $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR } -run_test 15 "set block quota more than 4T ===" +run_test_with_stat 15 "set block quota more than 4T ===" # $1=u/g $2=with qunit adjust or not test_16_tub() { @@ -1301,7 +1319,7 @@ test_16 () { set_blk_unitsz $((128 * 1024)) set_blk_tunesz $((128 * 1024 / 2)) } -run_test 16 "test without adjusting qunit" +run_test_with_stat 16 "test without adjusting qunit" # run for fixing bug14526, failed returned quota reqs shouldn't ruin lustre. test_17() { @@ -1358,7 +1376,7 @@ test_17() { return $RC } -run_test 17 "run for fixing bug14526 ===========" +run_test_with_stat 17 "run for fixing bug14526 ===========" # test when mds takes a long time to handle a quota req so that # the ost has dropped it, the ost still could work well b=14840 @@ -1415,7 +1433,7 @@ test_18() { set_blk_unitsz $((128 * 1024)) set_blk_tunesz $((128 * 1024 / 2)) } -run_test 18 "run for fixing bug14840 ===========" +run_test_with_stat 18 "run for fixing bug14840 ===========" # test when mds drops a quota req, the ost still could work well b=14840 test_18a() { @@ -1472,7 +1490,7 @@ test_18a() { set_blk_unitsz $((128 * 1024)) set_blk_tunesz $((128 * 1024 / 2)) } -run_test 18a "run for fixing bug14840 ===========" +run_test_with_stat 18a "run for fixing bug14840 ===========" test_19() { # 1 Mb bunit per each MDS/OSS @@ -1514,7 +1532,7 @@ test_19() { set_blk_tunesz $((128 * 1024 / 2)) } -run_test 19 "test if administrative limits updates do not zero operational limits (14790) ===" +run_test_with_stat 19 "test if administrative limits updates do not zero operational limits (14790) ===" test_20() { @@ -1537,7 +1555,7 @@ test_20() $MOUNT || error "could not reset quota limits" } -run_test 20 "test if setquota specifiers work properly (15754)" +run_test_with_stat 20 "test if setquota specifiers work properly (15754)" test_21_sub() { local testfile=$1 @@ -1615,7 +1633,7 @@ test_21() { return $RC } -run_test 21 "run for fixing bug16053 ===========" +run_test_with_stat 21 "run for fixing bug16053 ===========" test_22() { local SAVEREFORMAT @@ -1640,7 +1658,7 @@ test_22() { run_test 0 "reboot lustre" } -run_test 22 "test if quota_type saved as permanent parameter ====" +run_test_with_stat 22 "test if quota_type saved as permanent parameter ====" # turn off quota test_99() @@ -1650,7 +1668,7 @@ test_99() return 0 } -run_test 99 "Quota off ===============================" +run_test_with_stat 99 "Quota off ===============================" log "cleanup: ======================================================"