#define ARRAY_SIZE(a) ((sizeof (a)) / (sizeof ((a)[0])))
#endif
+#if !defined(swap)
+#define swap(x,y) do { typeof(x) z = x; x = y; y = z; } while (0)
+#endif
+
#if !defined(container_of)
/* given a pointer @ptr to the field @member embedded into type (usually
* struct) @type, return pointer to the embedding instance of @type. */
# Quota support. The kernel must support CONFIG_QUOTA.
#
AC_DEFUN([LC_QUOTA_CONFIG],
-[LB_LINUX_CONFIG_IM([QUOTA],[AC_DEFINE(HAVE_QUOTA_SUPPORT, 1, [support quota])],[
- AC_MSG_ERROR([Lustre quota requires that CONFIG_QUOTA is enabled in your kernel.])
-])
+[LB_LINUX_CONFIG_IM([QUOTA],[],[
+ AC_MSG_ERROR([Lustre quota requires that CONFIG_QUOTA is enabled in your kernel.])
+ ])
])
# truncate_complete_page() was exported from RHEL5/SLES10, but not in SLES11 SP0 (2.6.27)
#include <lustre_ver.h>
#include "cmm_internal.h"
#include "mdc_internal.h"
-#ifdef HAVE_QUOTA_SUPPORT
-# include <lustre_quota.h>
-#endif
struct obd_ops cmm_obd_device_ops = {
.o_owner = THIS_MODULE
RETURN(rc);
}
-#ifdef HAVE_QUOTA_SUPPORT
-/**
- * \name Quota functions
- * @{
- */
-static int cmm_quota_notify(const struct lu_env *env, struct md_device *m)
-{
- struct cmm_device *cmm_dev = md2cmm_dev(m);
- int rc;
- ENTRY;
-
- rc = cmm_child_ops(cmm_dev)->mdo_quota.mqo_notify(env,
- cmm_dev->cmm_child);
- RETURN(rc);
-}
-
-static int cmm_quota_setup(const struct lu_env *env, struct md_device *m,
- void *data)
-{
- struct cmm_device *cmm_dev = md2cmm_dev(m);
- int rc;
- ENTRY;
-
- rc = cmm_child_ops(cmm_dev)->mdo_quota.mqo_setup(env,
- cmm_dev->cmm_child,
- data);
- RETURN(rc);
-}
-
-static int cmm_quota_cleanup(const struct lu_env *env, struct md_device *m)
-{
- struct cmm_device *cmm_dev = md2cmm_dev(m);
- int rc;
- ENTRY;
-
- rc = cmm_child_ops(cmm_dev)->mdo_quota.mqo_cleanup(env,
- cmm_dev->cmm_child);
- RETURN(rc);
-}
-
-static int cmm_quota_recovery(const struct lu_env *env, struct md_device *m)
-{
- struct cmm_device *cmm_dev = md2cmm_dev(m);
- int rc;
- ENTRY;
-
- rc = cmm_child_ops(cmm_dev)->mdo_quota.mqo_recovery(env,
- cmm_dev->cmm_child);
- RETURN(rc);
-}
-
-static int cmm_quota_check(const struct lu_env *env, struct md_device *m,
- __u32 type)
-{
- struct cmm_device *cmm_dev = md2cmm_dev(m);
- int rc;
- ENTRY;
-
- /* disable quota for CMD case temporary. */
- if (cmm_dev->cmm_tgt_count)
- RETURN(-EOPNOTSUPP);
-
- rc = cmm_child_ops(cmm_dev)->mdo_quota.mqo_check(env,
- cmm_dev->cmm_child,
- type);
- RETURN(rc);
-}
-
-static int cmm_quota_on(const struct lu_env *env, struct md_device *m,
- __u32 type)
-{
- struct cmm_device *cmm_dev = md2cmm_dev(m);
- int rc;
- ENTRY;
-
- /* disable quota for CMD case temporary. */
- if (cmm_dev->cmm_tgt_count)
- RETURN(-EOPNOTSUPP);
-
- rc = cmm_child_ops(cmm_dev)->mdo_quota.mqo_on(env,
- cmm_dev->cmm_child,
- type);
- RETURN(rc);
-}
-
-static int cmm_quota_off(const struct lu_env *env, struct md_device *m,
- __u32 type)
-{
- struct cmm_device *cmm_dev = md2cmm_dev(m);
- int rc;
- ENTRY;
-
- rc = cmm_child_ops(cmm_dev)->mdo_quota.mqo_off(env,
- cmm_dev->cmm_child,
- type);
- RETURN(rc);
-}
-
-static int cmm_quota_setinfo(const struct lu_env *env, struct md_device *m,
- __u32 type, __u32 id, struct obd_dqinfo *dqinfo)
-{
- struct cmm_device *cmm_dev = md2cmm_dev(m);
- int rc;
- ENTRY;
-
- /* disable quota for CMD case temporary. */
- if (cmm_dev->cmm_tgt_count)
- RETURN(-EOPNOTSUPP);
-
- rc = cmm_child_ops(cmm_dev)->mdo_quota.mqo_setinfo(env,
- cmm_dev->cmm_child,
- type, id, dqinfo);
- RETURN(rc);
-}
-
-static int cmm_quota_getinfo(const struct lu_env *env,
- const struct md_device *m,
- __u32 type, __u32 id, struct obd_dqinfo *dqinfo)
-{
- struct cmm_device *cmm_dev = md2cmm_dev((struct md_device *)m);
- int rc;
- ENTRY;
-
- /* disable quota for CMD case temporary. */
- if (cmm_dev->cmm_tgt_count)
- RETURN(-EOPNOTSUPP);
-
- rc = cmm_child_ops(cmm_dev)->mdo_quota.mqo_getinfo(env,
- cmm_dev->cmm_child,
- type, id, dqinfo);
- RETURN(rc);
-}
-
-static int cmm_quota_setquota(const struct lu_env *env, struct md_device *m,
- __u32 type, __u32 id, struct obd_dqblk *dqblk)
-{
- struct cmm_device *cmm_dev = md2cmm_dev(m);
- int rc;
- ENTRY;
-
- /* disable quota for CMD case temporary. */
- if (cmm_dev->cmm_tgt_count)
- RETURN(-EOPNOTSUPP);
-
- rc = cmm_child_ops(cmm_dev)->mdo_quota.mqo_setquota(env,
- cmm_dev->cmm_child,
- type, id, dqblk);
- RETURN(rc);
-}
-
-static int cmm_quota_getquota(const struct lu_env *env,
- const struct md_device *m,
- __u32 type, __u32 id, struct obd_dqblk *dqblk)
-{
- struct cmm_device *cmm_dev = md2cmm_dev((struct md_device *)m);
- int rc;
- ENTRY;
-
- /* disable quota for CMD case temporary. */
- if (cmm_dev->cmm_tgt_count)
- RETURN(-EOPNOTSUPP);
-
- rc = cmm_child_ops(cmm_dev)->mdo_quota.mqo_getquota(env,
- cmm_dev->cmm_child,
- type, id, dqblk);
- RETURN(rc);
-}
-
-static int cmm_quota_getoinfo(const struct lu_env *env,
- const struct md_device *m,
- __u32 type, __u32 id, struct obd_dqinfo *dqinfo)
-{
- struct cmm_device *cmm_dev = md2cmm_dev((struct md_device *)m);
- int rc;
- ENTRY;
-
- /* disable quota for CMD case temporary. */
- if (cmm_dev->cmm_tgt_count)
- RETURN(-EOPNOTSUPP);
-
- rc = cmm_child_ops(cmm_dev)->mdo_quota.mqo_getoinfo(env,
- cmm_dev->cmm_child,
- type, id, dqinfo);
- RETURN(rc);
-}
-
-static int cmm_quota_getoquota(const struct lu_env *env,
- const struct md_device *m,
- __u32 type, __u32 id, struct obd_dqblk *dqblk)
-{
- struct cmm_device *cmm_dev = md2cmm_dev((struct md_device *)m);
- int rc;
- ENTRY;
-
- /* disable quota for CMD case temporary. */
- if (cmm_dev->cmm_tgt_count)
- RETURN(-EOPNOTSUPP);
-
- rc = cmm_child_ops(cmm_dev)->mdo_quota.mqo_getoquota(env,
- cmm_dev->cmm_child,
- type, id, dqblk);
- RETURN(rc);
-}
-
-static int cmm_quota_invalidate(const struct lu_env *env, struct md_device *m,
- __u32 type)
-{
- struct cmm_device *cmm_dev = md2cmm_dev(m);
- int rc;
- ENTRY;
-
- /* disable quota for CMD case temporary. */
- if (cmm_dev->cmm_tgt_count)
- RETURN(-EOPNOTSUPP);
-
- rc = cmm_child_ops(cmm_dev)->mdo_quota.mqo_invalidate(env,
- cmm_dev->cmm_child,
- type);
- RETURN(rc);
-}
-
-static int cmm_quota_finvalidate(const struct lu_env *env, struct md_device *m,
- __u32 type)
-{
- struct cmm_device *cmm_dev = md2cmm_dev(m);
- int rc;
- ENTRY;
-
- /* disable quota for CMD case temporary. */
- if (cmm_dev->cmm_tgt_count)
- RETURN(-EOPNOTSUPP);
-
- rc = cmm_child_ops(cmm_dev)->mdo_quota.mqo_finvalidate(env,
- cmm_dev->cmm_child,
- type);
- RETURN(rc);
-}
-/** @} */
-#endif
-
int cmm_iocontrol(const struct lu_env *env, struct md_device *m,
unsigned int cmd, int len, void *data)
{
.mdo_update_capa_key = cmm_update_capa_key,
.mdo_llog_ctxt_get = cmm_llog_ctxt_get,
.mdo_iocontrol = cmm_iocontrol,
-#ifdef HAVE_QUOTA_SUPPORT
- .mdo_quota = {
- .mqo_notify = cmm_quota_notify,
- .mqo_setup = cmm_quota_setup,
- .mqo_cleanup = cmm_quota_cleanup,
- .mqo_recovery = cmm_quota_recovery,
- .mqo_check = cmm_quota_check,
- .mqo_on = cmm_quota_on,
- .mqo_off = cmm_quota_off,
- .mqo_setinfo = cmm_quota_setinfo,
- .mqo_getinfo = cmm_quota_getinfo,
- .mqo_setquota = cmm_quota_setquota,
- .mqo_getquota = cmm_quota_getquota,
- .mqo_getoinfo = cmm_quota_getoinfo,
- .mqo_getoquota = cmm_quota_getoquota,
- .mqo_invalidate = cmm_quota_invalidate,
- .mqo_finvalidate = cmm_quota_finvalidate
- }
-#endif
};
extern struct lu_device_type mdc_device_type;
mdsno_t mdc_num;
struct lu_site *site = cmm2lu_dev(cm)->ld_site;
int rc;
-#ifdef HAVE_QUOTA_SUPPORT
- int first;
-#endif
ENTRY;
/* find out that there is no such mdc */
mc = lu2mdc_dev(ld);
cfs_list_add_tail(&mc->mc_linkage, &cm->cmm_targets);
cm->cmm_tgt_count++;
-#ifdef HAVE_QUOTA_SUPPORT
- first = cm->cmm_tgt_count;
-#endif
cfs_spin_unlock(&cm->cmm_tgt_guard);
lu_device_get(cmm_lu);
lu_site2md(site)->ms_server_fld->lsf_control_exp =
mc->mc_desc.cl_exp;
}
-#ifdef HAVE_QUOTA_SUPPORT
- /* XXX: Disable quota for CMD case temporary. */
- if (first == 1) {
- CWARN("Disable quota for CMD case temporary!\n");
- cmm_child_ops(cm)->mdo_quota.mqo_off(env, cm->cmm_child, UGQUOTA);
- }
-#endif
/* Set max md size for the mdc. */
rc = cmm_post_init_mdc(env, cm);
RETURN(rc);
#ifndef __KERNEL__
# define NEED_QUOTA_DEFS
-# ifdef HAVE_QUOTA_SUPPORT
-# include <sys/quota.h>
-# endif
+# include <sys/quota.h>
#else
# include <linux/version.h>
-# ifdef HAVE_QUOTA_SUPPORT
-# include <linux/quota.h>
-# endif
+# include <linux/quota.h>
#endif
/*
struct lquota_trans *trans)
{
}
-
-#ifdef LPROCFS
-/* dumb procfs handler which always report success, for backward compatibility
- * purpose */
-int lprocfs_quota_rd_type_dumb(char *, char **, off_t, int, int *, void *);
-int lprocfs_quota_wr_type_dumb(struct file *, const char *, unsigned long,
- void *);
-#endif /* LPROCFS */
#endif /* _LUSTRE_LQUOTA_H */
obd_count vallen, void *val,
struct ptlrpc_request_set *set);
-/* quotacheck callback, dqacq/dqrel callback handler */
-int target_handle_qc_callback(struct ptlrpc_request *req);
-#ifdef HAVE_QUOTA_SUPPORT
-int target_handle_dqacq_callback(struct ptlrpc_request *req);
-#else
-#define target_handle_dqacq_callback(req) ldlm_callback_reply(req, -ENOTSUPP)
-#endif
-
#define OBD_RECOVERY_MAX_TIME (obd_timeout * 18) /* b13079 */
void target_send_reply(struct ptlrpc_request *req, int rc, int fail_id);
#define toqb(x) (((x) + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS)
#endif
-#ifdef HAVE_QUOTA_SUPPORT
-
#ifndef MAX_IQ_TIME
#define MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */
#endif
#endif /* !__KERNEL__ */
-#else
-
-#define LL_DQUOT_OFF(sb) do {} while(0)
-
-struct lustre_quota_info {
-};
-
-struct lustre_quota_ctxt {
-};
-
-#endif /* !HAVE_QUOTA_SUPPORT */
-
/* If the (quota limit < qunit * slave count), the slave which can't
* acquire qunit should set it's local limit as MIN_QLIMIT */
#define MIN_QLIMIT 1
int (*mdo_iocontrol)(const struct lu_env *env, struct md_device *m,
unsigned int cmd, int len, void *data);
-
-#ifdef HAVE_QUOTA_SUPPORT
- struct md_quota_operations {
- int (*mqo_notify)(const struct lu_env *env,
- struct md_device *m);
-
- int (*mqo_setup)(const struct lu_env *env,
- struct md_device *m,
- void *data);
-
- int (*mqo_cleanup)(const struct lu_env *env,
- struct md_device *m);
-
- int (*mqo_recovery)(const struct lu_env *env,
- struct md_device *m);
-
- int (*mqo_check)(const struct lu_env *env,
- struct md_device *m,
- __u32 type);
-
- int (*mqo_on)(const struct lu_env *env,
- struct md_device *m,
- __u32 type);
-
- int (*mqo_off)(const struct lu_env *env,
- struct md_device *m,
- __u32 type);
-
- int (*mqo_setinfo)(const struct lu_env *env,
- struct md_device *m,
- __u32 type,
- __u32 id,
- struct obd_dqinfo *dqinfo);
-
- int (*mqo_getinfo)(const struct lu_env *env,
- const struct md_device *m,
- __u32 type,
- __u32 id,
- struct obd_dqinfo *dqinfo);
-
- int (*mqo_setquota)(const struct lu_env *env,
- struct md_device *m,
- __u32 type,
- __u32 id,
- struct obd_dqblk *dqblk);
-
- int (*mqo_getquota)(const struct lu_env *env,
- const struct md_device *m,
- __u32 type,
- __u32 id,
- struct obd_dqblk *dqblk);
-
- int (*mqo_getoinfo)(const struct lu_env *env,
- const struct md_device *m,
- __u32 type,
- __u32 id,
- struct obd_dqinfo *dqinfo);
-
- int (*mqo_getoquota)(const struct lu_env *env,
- const struct md_device *m,
- __u32 type,
- __u32 id,
- struct obd_dqblk *dqblk);
-
- int (*mqo_invalidate)(const struct lu_env *env,
- struct md_device *m,
- __u32 type);
-
- int (*mqo_finvalidate)(const struct lu_env *env,
- struct md_device *m,
- __u32 type);
- } mdo_quota;
-#endif
};
enum md_upcall_event {
OBD_NOTIFY_SYNC,
/* Configuration event */
OBD_NOTIFY_CONFIG,
- /* Trigger quota recovery */
- OBD_NOTIFY_QUOTA,
/* Administratively deactivate/activate event */
OBD_NOTIFY_DEACTIVATE,
OBD_NOTIFY_ACTIVATE
struct obd_quotactl *);
int (*o_quotactl)(struct obd_device *, struct obd_export *,
struct obd_quotactl *);
- int (*o_quota_adjust_qunit)(struct obd_export *exp,
- struct quota_adjust_qunit *oqaq,
- struct lustre_quota_ctxt *qctxt,
- struct ptlrpc_request_set *rqset);
-
int (*o_ping)(const struct lu_env *, struct obd_export *exp);
obd->obd_last_committed = transno;
}
-static inline void init_obd_quota_ops(quota_interface_t *interface,
- struct obd_ops *obd_ops)
-{
- if (!interface)
- return;
-
- LASSERT(obd_ops);
- obd_ops->o_quotacheck = QUOTA_OP(interface, check);
- obd_ops->o_quotactl = QUOTA_OP(interface, ctl);
- obd_ops->o_quota_adjust_qunit = QUOTA_OP(interface, adjust_qunit);
-}
-
static inline struct lustre_capa *oinfo_capa(struct obd_info *oinfo)
{
return oinfo->oi_capa;
RETURN(rc);
}
-static inline int obd_quota_adjust_qunit(struct obd_export *exp,
- struct quota_adjust_qunit *oqaq,
- struct lustre_quota_ctxt *qctxt,
- struct ptlrpc_request_set *set)
-{
-#if defined(LPROCFS) && defined(HAVE_QUOTA_SUPPORT)
- struct timeval work_start;
- struct timeval work_end;
- long timediff;
-#endif
- int rc;
- ENTRY;
-
-#if defined(LPROCFS) && defined(HAVE_QUOTA_SUPPORT)
- if (qctxt)
- cfs_gettimeofday(&work_start);
-#endif
- EXP_CHECK_DT_OP(exp, quota_adjust_qunit);
- EXP_COUNTER_INCREMENT(exp, quota_adjust_qunit);
-
- rc = OBP(exp->exp_obd, quota_adjust_qunit)(exp, oqaq, qctxt, set);
-
-#if defined(LPROCFS) && defined(HAVE_QUOTA_SUPPORT)
- if (qctxt) {
- cfs_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);
-}
-
static inline int obd_health_check(const struct lu_env *env,
struct obd_device *obd)
{
EXIT;
}
-int target_handle_qc_callback(struct ptlrpc_request *req)
-{
- struct obd_quotactl *oqctl;
- struct client_obd *cli = &req->rq_export->exp_obd->u.cli;
-
- oqctl = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
- if (oqctl == NULL) {
- CERROR("Can't unpack obd_quotactl\n");
- RETURN(-EPROTO);
- }
-
- cli->cl_qchk_stat = oqctl->qc_stat;
-
- return 0;
-}
-
-#ifdef HAVE_QUOTA_SUPPORT
-int target_handle_dqacq_callback(struct ptlrpc_request *req)
-{
-#ifdef __KERNEL__
- struct obd_device *obd = req->rq_export->exp_obd;
- struct obd_device *master_obd = NULL, *lov_obd = NULL;
- struct obd_device_target *obt;
- struct lustre_quota_ctxt *qctxt;
- struct qunit_data *qdata = NULL;
- int rc = 0;
- ENTRY;
-
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_DROP_QUOTA_REQ))
- RETURN(rc);
-
- rc = req_capsule_server_pack(&req->rq_pill);
- if (rc) {
- CERROR("packing reply failed!: rc = %d\n", rc);
- RETURN(rc);
- }
-
- LASSERT(req->rq_export);
-
- qdata = quota_get_qdata(req, QUOTA_REQUEST, QUOTA_EXPORT);
- if (IS_ERR(qdata)) {
- rc = PTR_ERR(qdata);
- CDEBUG(D_ERROR, "Can't unpack qunit_data(rc: %d)\n", rc);
- req->rq_status = rc;
- GOTO(out, rc);
- }
-
- /* we use the observer */
- if (obd_pin_observer(obd, &lov_obd) ||
- obd_pin_observer(lov_obd, &master_obd)) {
- CERROR("Can't find the observer, it is recovering\n");
- req->rq_status = -EAGAIN;
- GOTO(out, rc);
- }
-
- obt = &master_obd->u.obt;
- qctxt = &obt->obt_qctxt;
-
- if (!qctxt->lqc_setup || !qctxt->lqc_valid) {
- /* quota_type has not been processed yet, return EAGAIN
- * until we know whether or not quotas are supposed to
- * be enabled */
- CDEBUG(D_QUOTA, "quota_type not processed yet, return "
- "-EAGAIN\n");
- req->rq_status = -EAGAIN;
- GOTO(out, rc);
- }
-
- cfs_down_read(&obt->obt_rwsem);
- if (qctxt->lqc_lqs_hash == NULL) {
- cfs_up_read(&obt->obt_rwsem);
- /* quota_type has not been processed yet, return EAGAIN
- * until we know whether or not quotas are supposed to
- * be enabled */
- CDEBUG(D_QUOTA, "quota_ctxt is not ready yet, return "
- "-EAGAIN\n");
- req->rq_status = -EAGAIN;
- GOTO(out, rc);
- }
-
- LASSERT(qctxt->lqc_handler);
- rc = qctxt->lqc_handler(master_obd, qdata,
- lustre_msg_get_opc(req->rq_reqmsg));
- cfs_up_read(&obt->obt_rwsem);
- if (rc && rc != -EDQUOT)
- CDEBUG(rc == -EBUSY ? D_QUOTA : D_ERROR,
- "dqacq/dqrel failed! (rc:%d)\n", rc);
- req->rq_status = rc;
-
- rc = quota_copy_qdata(req, qdata, QUOTA_REPLY, QUOTA_EXPORT);
- if (rc < 0) {
- CERROR("Can't pack qunit_data(rc: %d)\n", rc);
- GOTO(out, rc);
- }
-
- /* Block the quota req. b=14840 */
- OBD_FAIL_TIMEOUT(OBD_FAIL_MDS_BLOCK_QUOTA_REQ, obd_timeout);
- EXIT;
-
-out:
- if (master_obd)
- obd_unpin_observer(lov_obd);
- if (lov_obd)
- obd_unpin_observer(obd);
-
- rc = ptlrpc_reply(req);
- return rc;
-#else
- return 0;
-#endif /* !__KERNEL__ */
-}
-#endif /* HAVE_QUOTA_SUPPORT */
-
ldlm_mode_t lck_compat_array[] = {
[LCK_EX] LCK_COMPAT_EX,
[LCK_PW] LCK_COMPAT_PW,
RETURN(0);
ldlm_callback_reply(req, rc);
RETURN(0);
- case OBD_QC_CALLBACK:
- req_capsule_set(&req->rq_pill, &RQF_QC_CALLBACK);
- if (OBD_FAIL_CHECK(OBD_FAIL_OBD_QC_CALLBACK_NET))
- RETURN(0);
- rc = target_handle_qc_callback(req);
- ldlm_callback_reply(req, rc);
- RETURN(0);
- case QUOTA_DQACQ:
- case QUOTA_DQREL:
- /* reply in handler */
- req_capsule_set(&req->rq_pill, &RQF_MDS_QUOTA_DQACQ);
- rc = target_handle_dqacq_callback(req);
- RETURN(0);
case LLOG_ORIGIN_HANDLE_CREATE:
req_capsule_set(&req->rq_pill, &RQF_LLOG_ORIGIN_HANDLE_CREATE);
if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOGD_NET))
RETURN(rc);
}
-int lov_quota_adjust_qunit(struct obd_export *exp,
- struct quota_adjust_qunit *oqaq,
- struct lustre_quota_ctxt *qctxt,
- struct ptlrpc_request_set *rqset)
-{
- struct obd_device *obd = class_exp2obd(exp);
- struct lov_obd *lov = &obd->u.lov;
- int i, err, rc = 0;
- unsigned no_set = 0;
- ENTRY;
-
- if (!QAQ_IS_ADJBLK(oqaq)) {
- CERROR("bad qaq_flags %x for lov obd.\n", oqaq->qaq_flags);
- RETURN(-EFAULT);
- }
-
- if (rqset == NULL) {
- rqset = ptlrpc_prep_set();
- if (!rqset)
- RETURN(-ENOMEM);
- no_set = 1;
- }
-
- obd_getref(obd);
- for (i = 0; i < lov->desc.ld_tgt_count; i++) {
-
- if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active) {
- CDEBUG(D_HA, "ost %d is inactive\n", i);
- continue;
- }
-
- err = obd_quota_adjust_qunit(lov->lov_tgts[i]->ltd_exp, oqaq,
- NULL, rqset);
- if (err) {
- if (lov->lov_tgts[i]->ltd_active && !rc)
- rc = err;
- continue;
- }
- }
-
- err = ptlrpc_set_wait(rqset);
- if (!rc)
- rc = err;
-
- /* Destroy the set if none was provided by the caller */
- if (no_set)
- ptlrpc_set_destroy(rqset);
-
- obd_putref(obd);
- RETURN(rc);
-}
-
struct obd_ops lov_obd_ops = {
.o_owner = THIS_MODULE,
.o_setup = lov_setup,
.o_putref = lov_putref,
.o_quotactl = lov_quotactl,
.o_quotacheck = lov_quotacheck,
- .o_quota_adjust_qunit = lov_quota_adjust_qunit,
};
-static quota_interface_t *quota_interface;
-extern quota_interface_t lov_quota_interface;
-
cfs_mem_cache_t *lov_oinfo_slab;
extern struct lu_kmem_descr lov_caches[];
}
lprocfs_lov_init_vars(&lvars);
- cfs_request_module("lquota");
- quota_interface = PORTAL_SYMBOL_GET(lov_quota_interface);
- init_obd_quota_ops(quota_interface, &lov_obd_ops);
-
rc = class_register_type(&lov_obd_ops, NULL, lvars.module_vars,
LUSTRE_LOV_NAME, &lov_device_type);
if (rc) {
- if (quota_interface)
- PORTAL_SYMBOL_PUT(lov_quota_interface);
rc2 = cfs_mem_cache_destroy(lov_oinfo_slab);
LASSERT(rc2 == 0);
lu_kmem_fini(lov_caches);
{
int rc;
- if (quota_interface)
- PORTAL_SYMBOL_PUT(lov_quota_interface);
-
class_unregister_type(LUSTRE_LOV_NAME);
rc = cfs_mem_cache_destroy(lov_oinfo_slab);
LASSERT(rc == 0);
static int fsfilt_ext3_setup(struct super_block *sb)
{
-#if defined(HAVE_QUOTA_SUPPORT) || defined(S_PDIROPS)
- struct ext3_sb_info *sbi = EXT3_SB(sb);
-#if 0
- sbi->dx_lock = fsfilt_ext3_dx_lock;
- sbi->dx_unlock = fsfilt_ext3_dx_unlock;
-#endif
-#endif
if (!EXT3_HAS_COMPAT_FEATURE(sb,
EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
CERROR("ext3 mounted without journal\n");
#ifdef S_PDIROPS
CWARN("Enabling PDIROPS\n");
- set_opt(sbi->s_mount_opt, PDIROPS);
+ set_opt(EXT3_SB(sb)->s_mount_opt, PDIROPS);
sb->s_flags |= S_PDIROPS;
#endif
if (!EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX))
CWARN("filesystem doesn't have dir_index feature enabled\n");
-#ifdef HAVE_QUOTA_SUPPORT
- /* enable journaled quota support */
- /* kfreed in ext3_put_super() */
- sbi->s_qf_names[USRQUOTA] = kstrdup("lquota.user.reserved", GFP_KERNEL);
- if (!sbi->s_qf_names[USRQUOTA])
- return -ENOMEM;
- sbi->s_qf_names[GRPQUOTA] = kstrdup("lquota.group.reserved", GFP_KERNEL);
- if (!sbi->s_qf_names[GRPQUOTA]) {
- kfree(sbi->s_qf_names[USRQUOTA]);
- sbi->s_qf_names[USRQUOTA] = NULL;
- return -ENOMEM;
- }
- sbi->s_jquota_fmt = QFMT_LUSTRE;
- set_opt(sbi->s_mount_opt, QUOTA);
-#endif
return 0;
}
return 0;
}
-#ifdef HAVE_QUOTA_SUPPORT
#define DQINFO_COPY(out, in) \
do { \
Q_COPY(out, in, dqi_bgrace); \
/* read old quota limits from old quota file. (only for the user
* has limits but hasn't file) */
-#ifdef HAVE_QUOTA_SUPPORT
for (i = 0; i < MAXQUOTAS; i++) {
cfs_list_t id_list;
struct dquot_id *dqid, *tmp;
OBD_FREE_PTR(dqid);
}
}
-#endif
/* turn off quota cause we are to dump chk_dqblk to files */
quota_onoff(sb, Q_QUOTAOFF, oqc->qc_type, oqc->qc_id);
return 0;
}
-#endif
-
lvfs_sbdev_type fsfilt_ext3_journal_sbdev(struct super_block *sb)
{
return (EXT3_SB(sb)->journal_bdev);
.fs_get_version = fsfilt_ext3_get_version,
.fs_set_version = fsfilt_ext3_set_version,
#endif
-#ifdef HAVE_QUOTA_SUPPORT
.fs_quotactl = fsfilt_ext3_quotactl,
.fs_quotacheck = fsfilt_ext3_quotacheck,
.fs_quotainfo = fsfilt_ext3_quotainfo,
.fs_qids = fsfilt_ext3_qids,
.fs_dquot = fsfilt_ext3_dquot,
.fs_get_mblk = fsfilt_ext3_get_mblk,
-#endif
.fs_journal_sbdev = fsfilt_ext3_journal_sbdev,
.fs_fid2dentry = fsfilt_ext3_fid2dentry,
};
#include <obd_support.h>
#include "lustre_quota_fmt.h"
-#ifdef HAVE_QUOTA_SUPPORT
-
static const uint lustre_initqversions[][MAXQUOTAS] = {
[LUSTRE_QUOTA_V2] = LUSTRE_INITQVERSIONS_V2
};
RETURN(rc);
}
EXPORT_SYMBOL(lustre_get_qids);
-#endif
#ifndef _LUSTRE_QUOTA_FMT_H
#define _LUSTRE_QUOTA_FMT_H
-#ifdef HAVE_QUOTA_SUPPORT
-
#include <linux/types.h>
#include <linux/quota.h>
#define LUSTRE_OPQFILES_NAMES_V2 { "lquota_v2.user", "lquota_v2.group" }
#endif /* lustre_quota_fmt.h */
-#endif
#include "lustre_quota_fmt.h"
-#ifdef HAVE_QUOTA_SUPPORT
-
char *test_quotafile[2] = { "usrquota_test", "grpquota_test" };
static int quotfmt_initialize(struct lustre_quota_info *lqi,
module_init(quotfmt_test_init);
module_exit(quotfmt_test_exit);
-
-#endif /* HAVE_QUOTA_SUPPORT */
MODULES := mdd
mdd-objs := mdd_object.o mdd_lov.o mdd_orphans.o mdd_lproc.o mdd_dir.o
-mdd-objs += mdd_device.o mdd_trans.o mdd_permission.o mdd_lock.o mdd_quota.o
+mdd-objs += mdd_device.o mdd_trans.o mdd_permission.o mdd_lock.o
mdd-objs += mdd_lfsck.o
EXTRA_PRE_CFLAGS := -I@LINUX@/fs -I@LDISKFS_DIR@ -I@LDISKFS_DIR@/ldiskfs
}
EXPORT_SYMBOL(md_capainfo);
-/*
- * context key constructor/destructor:
- * mdd_quota_key_init, mdd_quota_key_fini
- */
-LU_KEY_INIT_FINI(mdd_quota, struct md_quota);
-
-struct lu_context_key mdd_quota_key = {
- .lct_tags = LCT_SESSION,
- .lct_init = mdd_quota_key_init,
- .lct_fini = mdd_quota_key_fini
-};
-
-struct md_quota *md_quota(const struct lu_env *env)
-{
- LASSERT(env->le_ses != NULL);
- return lu_context_key_get(env->le_ses, &mdd_quota_key);
-}
-EXPORT_SYMBOL(md_quota);
-
static int mdd_changelog_user_register(struct mdd_device *mdd, int *id)
{
struct llog_ctxt *ctxt;
}
/* type constructor/destructor: mdd_type_init, mdd_type_fini */
-LU_TYPE_INIT_FINI(mdd, &mdd_thread_key, &mdd_ucred_key, &mdd_capainfo_key,
- &mdd_quota_key);
+LU_TYPE_INIT_FINI(mdd, &mdd_thread_key, &mdd_ucred_key, &mdd_capainfo_key);
const struct md_device_operations mdd_ops = {
.mdo_statfs = mdd_statfs,
.mdo_update_capa_key= mdd_update_capa_key,
.mdo_llog_ctxt_get = mdd_llog_ctxt_get,
.mdo_iocontrol = mdd_iocontrol,
-#ifdef HAVE_QUOTA_SUPPORT
- .mdo_quota = {
- .mqo_notify = mdd_quota_notify,
- .mqo_setup = mdd_quota_setup,
- .mqo_cleanup = mdd_quota_cleanup,
- .mqo_recovery = mdd_quota_recovery,
- .mqo_check = mdd_quota_check,
- .mqo_on = mdd_quota_on,
- .mqo_off = mdd_quota_off,
- .mqo_setinfo = mdd_quota_setinfo,
- .mqo_getinfo = mdd_quota_getinfo,
- .mqo_setquota = mdd_quota_setquota,
- .mqo_getquota = mdd_quota_getquota,
- .mqo_getoinfo = mdd_quota_getoinfo,
- .mqo_getoquota = mdd_quota_getoquota,
- .mqo_invalidate = mdd_quota_invalidate,
- .mqo_finvalidate = mdd_quota_finvalidate
- }
-#endif
};
static struct lu_device_type_operations mdd_device_type_ops = {
struct mdd_device *mdd = mdo2mdd(src_obj);
struct dynlock_handle *dlh;
struct thandle *handle;
-#ifdef HAVE_QUOTA_SUPPORT
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct obd_export *exp = md_quota(env)->mq_exp;
- struct mds_obd *mds = &obd->u.mds;
- unsigned int qids[MAXQUOTAS] = { 0, 0 };
- int quota_opc = 0, rec_pending[MAXQUOTAS] = { 0, 0 };
-#endif
int rc;
ENTRY;
-#ifdef HAVE_QUOTA_SUPPORT
- if (mds->mds_quota) {
- struct lu_attr *la_tmp = &mdd_env_info(env)->mti_la;
-
- rc = mdd_la_get(env, mdd_tobj, la_tmp, BYPASS_CAPA);
- if (!rc) {
- void *data = NULL;
- mdd_data_get(env, mdd_tobj, &data);
- quota_opc = FSFILT_OP_LINK;
- mdd_quota_wrapper(la_tmp, qids);
- /* get block quota for parent */
- lquota_chkquota(mds_quota_interface_ref, obd, exp,
- qids, rec_pending, 1, NULL,
- LQUOTA_FLAGS_BLK, data, 1);
- }
- }
-#endif
-
handle = mdd_trans_create(env, mdd);
if (IS_ERR(handle))
GOTO(out_pending, rc = PTR_ERR(handle));
stop:
mdd_trans_stop(env, mdd, rc, handle);
out_pending:
-#ifdef HAVE_QUOTA_SUPPORT
- if (quota_opc) {
- lquota_pending_commit(mds_quota_interface_ref, obd,
- qids, rec_pending, 1);
- /* Trigger dqacq for the parent owner. If failed,
- * the next call for lquota_chkquota will process it. */
- lquota_adjust(mds_quota_interface_ref, obd, 0, qids, rc,
- quota_opc);
- }
-#endif
return rc;
}
struct mdd_device *mdd = mdo2mdd(pobj);
struct dynlock_handle *dlh;
struct thandle *handle;
-#ifdef HAVE_QUOTA_SUPPORT
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct mds_obd *mds = &obd->u.mds;
- unsigned int qcids[MAXQUOTAS] = { 0, 0 };
- unsigned int qpids[MAXQUOTAS] = { 0, 0 };
- int quota_opc = 0;
-#endif
int rc, is_dir;
ENTRY;
rc = mdd_la_get(env, mdd_cobj, cattr,
mdd_object_capa(env, mdd_cobj));
-#ifdef HAVE_QUOTA_SUPPORT
- if (mds->mds_quota && ma->ma_valid & MA_INODE &&
- ma->ma_attr.la_nlink == 0) {
- struct lu_attr *la_tmp = &mdd_env_info(env)->mti_la;
-
- rc = mdd_la_get(env, mdd_pobj, la_tmp, BYPASS_CAPA);
- if (!rc) {
- mdd_quota_wrapper(la_tmp, qpids);
- if (mdd_cobj->mod_count == 0) {
- quota_opc = FSFILT_OP_UNLINK;
- mdd_quota_wrapper(&ma->ma_attr, qcids);
- } else {
- quota_opc = FSFILT_OP_UNLINK_PARTIAL_PARENT;
- }
- }
- }
-#endif
if (!is_dir)
/* old files may not have link ea; ignore errors */
mdd_links_rename(env, mdd_cobj, mdo2fid(mdd_pobj),
#warning "please remove this after 2.4 (LOD/OSP)."
#endif
-#ifdef HAVE_QUOTA_SUPPORT
- if (quota_opc)
- /* Trigger dqrel on the owner of child and parent. If failed,
- * the next call for lquota_chkquota will process it. */
- lquota_adjust(mds_quota_interface_ref, obd, qcids, qpids, rc,
- quota_opc);
-#endif
return rc;
}
const char *name = lname->ln_name;
int rc, created = 0, initialized = 0, inserted = 0, lmm_size = 0;
int got_def_acl = 0;
-#ifdef HAVE_QUOTA_SUPPORT
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct obd_export *exp = md_quota(env)->mq_exp;
- struct mds_obd *mds = &obd->u.mds;
- unsigned int qcids[MAXQUOTAS] = { 0, 0 };
- unsigned int qpids[MAXQUOTAS] = { 0, 0 };
- int quota_opc = 0, block_count = 0;
- int inode_pending[MAXQUOTAS] = { 0, 0 };
- int block_pending[MAXQUOTAS] = { 0, 0 };
- int parent_pending[MAXQUOTAS] = { 0, 0 };
-#endif
ENTRY;
/*
if (rc)
RETURN(rc);
-#ifdef HAVE_QUOTA_SUPPORT
- if (mds->mds_quota) {
- int same = 0;
-
- quota_opc = FSFILT_OP_CREATE;
- mdd_quota_wrapper(attr, qcids);
- mdd_quota_wrapper(pattr, qpids);
- /* get file quota for child */
- lquota_chkquota(mds_quota_interface_ref, obd, exp,
- qcids, inode_pending, 1, NULL, 0, NULL,
- 0);
- switch (attr->la_mode & S_IFMT) {
- case S_IFLNK:
- case S_IFDIR:
- block_count = 2;
- break;
- case S_IFREG:
- block_count = 1;
- break;
- }
- if (qcids[USRQUOTA] == qpids[USRQUOTA] &&
- qcids[GRPQUOTA] == qpids[GRPQUOTA]) {
- block_count += 1;
- same = 1;
- }
- /* get block quota for child and parent */
- if (block_count)
- lquota_chkquota(mds_quota_interface_ref, obd,
- exp, qcids, block_pending,
- block_count, NULL,
- LQUOTA_FLAGS_BLK, NULL, 0);
- if (!same)
- lquota_chkquota(mds_quota_interface_ref, obd,
- exp, qpids, parent_pending, 1,
- NULL, LQUOTA_FLAGS_BLK, NULL,
- 0);
- }
-#endif
-
if (OBD_FAIL_CHECK(OBD_FAIL_MDS_DQACQ_NET))
GOTO(out_pending, rc = -EINPROGRESS);
/* finish lov_create stuff, free all temporary data */
mdd_lov_create_finish(env, mdd, lmm, lmm_size, spec);
out_pending:
-#ifdef HAVE_QUOTA_SUPPORT
- if (quota_opc) {
- lquota_pending_commit(mds_quota_interface_ref, obd, qcids,
- inode_pending, 0);
- lquota_pending_commit(mds_quota_interface_ref, obd, qcids,
- block_pending, 1);
- lquota_pending_commit(mds_quota_interface_ref, obd, qpids,
- parent_pending, 1);
- /* Trigger dqacq on the owner of child and parent. If failed,
- * the next call for lquota_chkquota will process it. */
- lquota_adjust(mds_quota_interface_ref, obd, qcids, qpids, rc,
- quota_opc);
- }
-#endif
/* The child object shouldn't be cached anymore */
if (rc)
cfs_set_bit(LU_OBJECT_HEARD_BANSHEE,
int is_dir;
unsigned cl_flags = 0;
int rc, rc2;
-
-#ifdef HAVE_QUOTA_SUPPORT
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct obd_export *exp = md_quota(env)->mq_exp;
- struct mds_obd *mds = &obd->u.mds;
- unsigned int qspids[MAXQUOTAS] = { 0, 0 };
- unsigned int qtcids[MAXQUOTAS] = { 0, 0 };
- unsigned int qtpids[MAXQUOTAS] = { 0, 0 };
- int quota_copc = 0, quota_popc = 0;
- int rec_pending[MAXQUOTAS] = { 0, 0 };
-#endif
ENTRY;
if (tobj)
mdd_tobj = md2mdd_obj(tobj);
-#ifdef HAVE_QUOTA_SUPPORT
- if (mds->mds_quota) {
- struct lu_attr *la_tmp = &mdd_env_info(env)->mti_la;
-
- rc = mdd_la_get(env, mdd_spobj, la_tmp, BYPASS_CAPA);
- if (!rc) {
- mdd_quota_wrapper(la_tmp, qspids);
- if (!tobj) {
- rc = mdd_la_get(env, mdd_tpobj, la_tmp,
- BYPASS_CAPA);
- if (!rc) {
- void *data = NULL;
- mdd_data_get(env, mdd_tpobj, &data);
- quota_popc = FSFILT_OP_LINK;
- mdd_quota_wrapper(la_tmp, qtpids);
- /* get block quota for target parent */
- lquota_chkquota(mds_quota_interface_ref,
- obd, exp, qtpids,
- rec_pending, 1, NULL,
- LQUOTA_FLAGS_BLK,
- data, 1);
- }
- }
- }
- }
-#endif
mdd_sobj = mdd_object_find(env, mdd, lf);
handle = mdd_trans_create(env, mdd);
ma->ma_attr = *tg_attr;
ma->ma_valid |= MA_INODE;
- if (so_attr->la_nlink == 0) {
+ if (so_attr->la_nlink == 0)
cl_flags |= CLF_RENAME_LAST;
-#ifdef HAVE_QUOTA_SUPPORT
- if (mds->mds_quota && mdd_tobj->mod_count == 0) {
- quota_copc = FSFILT_OP_UNLINK_PARTIAL_CHILD;
- mdd_quota_wrapper(&ma->ma_attr, qtcids);
- }
-#endif
- }
}
la->la_valid = LA_CTIME | LA_MTIME;
if (mdd_sobj)
mdd_object_put(env, mdd_sobj);
out_pending:
-#ifdef HAVE_QUOTA_SUPPORT
- if (mds->mds_quota) {
- if (quota_popc)
- lquota_pending_commit(mds_quota_interface_ref, obd,
- qtpids, rec_pending, 1);
-
- if (quota_copc) {
- /* Trigger dqrel on the source owner of parent.
- * If failed, the next call for lquota_chkquota will
- * process it. */
- lquota_adjust(mds_quota_interface_ref, obd, 0, qspids, rc,
- FSFILT_OP_UNLINK_PARTIAL_PARENT);
-
- /* Trigger dqrel on the target owner of child.
- * If failed, the next call for lquota_chkquota
- * will process it. */
- lquota_adjust(mds_quota_interface_ref, obd, qtcids,
- qtpids, rc, quota_copc);
- }
- }
-#endif
return rc;
}
#include <lustre_eacl.h>
#include <md_object.h>
#include <dt_object.h>
-#ifdef HAVE_QUOTA_SUPPORT
-# include <lustre_quota.h>
-#endif
#include <lustre_fsfilt.h>
#include <lustre/lustre_lfsck_user.h>
#include <lustre_fid.h>
#include <lprocfs_status.h>
#include <lustre_log.h>
-#ifdef HAVE_QUOTA_SUPPORT
-/* quota stuff */
-extern quota_interface_t *mds_quota_interface_ref;
-
-static inline void mdd_quota_wrapper(struct lu_attr *la, unsigned int *qids)
-{
- qids[USRQUOTA] = la->la_uid;
- qids[GRPQUOTA] = la->la_gid;
-}
-#endif
-
/* PDO lock is unnecessary for current MDT stack because operations
* are already protected by ldlm lock */
#define MDD_DISABLE_PDO_LOCK 1
struct lu_attr *attr,
struct thandle *handle,
const struct md_op_spec *spec);
-/* mdd_quota.c*/
-#ifdef HAVE_QUOTA_SUPPORT
-int mdd_quota_notify(const struct lu_env *env, struct md_device *m);
-int mdd_quota_setup(const struct lu_env *env, struct md_device *m,
- void *data);
-int mdd_quota_cleanup(const struct lu_env *env, struct md_device *m);
-int mdd_quota_recovery(const struct lu_env *env, struct md_device *m);
-int mdd_quota_check(const struct lu_env *env, struct md_device *m,
- __u32 type);
-int mdd_quota_on(const struct lu_env *env, struct md_device *m,
- __u32 type);
-int mdd_quota_off(const struct lu_env *env, struct md_device *m,
- __u32 type);
-int mdd_quota_setinfo(const struct lu_env *env, struct md_device *m,
- __u32 type, __u32 id, struct obd_dqinfo *dqinfo);
-int mdd_quota_getinfo(const struct lu_env *env, const struct md_device *m,
- __u32 type, __u32 id, struct obd_dqinfo *dqinfo);
-int mdd_quota_setquota(const struct lu_env *env, struct md_device *m,
- __u32 type, __u32 id, struct obd_dqblk *dqblk);
-int mdd_quota_getquota(const struct lu_env *env, const struct md_device *m,
- __u32 type, __u32 id, struct obd_dqblk *dqblk);
-int mdd_quota_getoinfo(const struct lu_env *env, const struct md_device *m,
- __u32 type, __u32 id, struct obd_dqinfo *dqinfo);
-int mdd_quota_getoquota(const struct lu_env *env, const struct md_device *m,
- __u32 type, __u32 id, struct obd_dqblk *dqblk);
-int mdd_quota_invalidate(const struct lu_env *env, struct md_device *m,
- __u32 type);
-int mdd_quota_finvalidate(const struct lu_env *env, struct md_device *m,
- __u32 type);
-#endif
/* mdd_trans.c */
int mdd_lov_destroy(const struct lu_env *env, struct mdd_device *mdd,
rc = md_do_upcall(NULL, &mdd->mdd_md_dev,
MD_LOV_CONFIG, data);
break;
-#ifdef HAVE_QUOTA_SUPPORT
- case OBD_NOTIFY_QUOTA:
- rc = md_do_upcall(NULL, &mdd->mdd_md_dev,
- MD_LOV_QUOTA, data);
- break;
-#endif
default:
CDEBUG(D_INFO, "Unhandled notification %#x\n", ev);
}
/*
* Add here for obd notify mechanism, when adding a new ost, the mds
- * will notify this mdd. The mds will be used for quota also.
+ * will notify this mdd.
*/
obd->obd_upcall.onu_upcall = mdd_notify;
obd->obd_upcall.onu_owner = mdd;
return cucb.idx;
}
-#ifdef HAVE_QUOTA_SUPPORT
-static int mdd_lprocfs_quota_rd_type(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct mdd_device *mdd = data;
- return lprocfs_quota_rd_type(page, start, off, count, eof,
- mdd->mdd_obd_dev);
-}
-
-static int mdd_lprocfs_quota_wr_type(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- struct mdd_device *mdd = data;
- return lprocfs_quota_wr_type(file, buffer, count, mdd->mdd_obd_dev);
-}
-#endif
-
static int lprocfs_rd_sync_perm(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
{ "changelog_mask", lprocfs_rd_changelog_mask,
lprocfs_wr_changelog_mask, 0 },
{ "changelog_users", lprocfs_rd_changelog_users, 0, 0},
-#ifdef HAVE_QUOTA_SUPPORT
- { "quota_type", mdd_lprocfs_quota_rd_type,
- mdd_lprocfs_quota_wr_type, 0 },
-#endif
{ "sync_permission", lprocfs_rd_sync_perm, lprocfs_wr_sync_perm, 0 },
{ "lfsck_speed_limit", lprocfs_rd_lfsck_speed_limit,
lprocfs_wr_lfsck_speed_limit, 0 },
int rc, lmm_size = 0, cookie_size = 0;
struct lu_attr *la_copy = &mdd_env_info(env)->mti_la_for_fix;
const struct lu_attr *la = &ma->ma_attr;
-#ifdef HAVE_QUOTA_SUPPORT
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct mds_obd *mds = &obd->u.mds;
- unsigned int qnids[MAXQUOTAS] = { 0, 0 };
- unsigned int qoids[MAXQUOTAS] = { 0, 0 };
- int quota_opc = 0, block_count = 0;
- int inode_pending[MAXQUOTAS] = { 0, 0 };
- int block_pending[MAXQUOTAS] = { 0, 0 };
-#endif
ENTRY;
*la_copy = ma->ma_attr;
CDEBUG(D_INODE, "setting mtime "LPU64", ctime "LPU64"\n",
la->la_mtime, la->la_ctime);
-#ifdef HAVE_QUOTA_SUPPORT
- if (mds->mds_quota && la_copy->la_valid & (LA_UID | LA_GID)) {
- struct obd_export *exp = md_quota(env)->mq_exp;
- struct lu_attr *la_tmp = &mdd_env_info(env)->mti_la;
-
- rc = mdd_la_get(env, mdd_obj, la_tmp, BYPASS_CAPA);
- if (!rc) {
- quota_opc = FSFILT_OP_SETATTR;
- mdd_quota_wrapper(la_copy, qnids);
- mdd_quota_wrapper(la_tmp, qoids);
- /* get file quota for new owner */
- lquota_chkquota(mds_quota_interface_ref, obd, exp,
- qnids, inode_pending, 1, NULL, 0,
- NULL, 0);
- block_count = (la_tmp->la_blocks + 7) >> 3;
- if (block_count) {
- void *data = NULL;
- mdd_data_get(env, mdd_obj, &data);
- /* get block quota for new owner */
- lquota_chkquota(mds_quota_interface_ref, obd,
- exp, qnids, block_pending,
- block_count, NULL,
- LQUOTA_FLAGS_BLK, data, 1);
- }
- }
- }
-#endif
-
if (la_copy->la_valid & LA_FLAGS) {
rc = mdd_attr_set_internal(env, mdd_obj, la_copy, handle, 1);
if (rc == 0)
rc = mdd_lov_setattr_async(env, mdd_obj, lmm, lmm_size,
logcookies);
}
-#ifdef HAVE_QUOTA_SUPPORT
- if (quota_opc) {
- lquota_pending_commit(mds_quota_interface_ref, obd, qnids,
- inode_pending, 0);
- lquota_pending_commit(mds_quota_interface_ref, obd, qnids,
- block_pending, 1);
- /* Trigger dqrel/dqacq for original owner and new owner.
- * If failed, the next call for lquota_chkquota will
- * process it. */
- lquota_adjust(mds_quota_interface_ref, obd, qnids, qoids, rc,
- quota_opc);
- }
-#endif
RETURN(rc);
}
struct thandle *handle = NULL;
int rc;
int is_orphan = 0, reset = 1;
-
-#ifdef HAVE_QUOTA_SUPPORT
- struct obd_device *obd = mdo2mdd(obj)->mdd_obd_dev;
- struct mds_obd *mds = &obd->u.mds;
- unsigned int qids[MAXQUOTAS] = { 0, 0 };
- int quota_opc = 0;
-#endif
ENTRY;
if (ma->ma_valid & MA_FLAGS && ma->ma_attr_flags & MDS_KEEP_ORPHAN) {
/* Object maybe not in orphan list originally, it is rare case for
* mdd_finish_unlink() failure. */
if (rc == 0 && (ma->ma_attr.la_nlink == 0 || is_orphan)) {
-#ifdef HAVE_QUOTA_SUPPORT
- if (mds->mds_quota) {
- quota_opc = FSFILT_OP_UNLINK_PARTIAL_CHILD;
- mdd_quota_wrapper(&ma->ma_attr, qids);
- }
-#endif
/* MDS_CLOSE_CLEANUP means destroy OSS objects by MDS. */
if (ma->ma_valid & MA_FLAGS &&
ma->ma_attr_flags & MDS_CLOSE_CLEANUP) {
stop:
if (handle != NULL)
mdd_trans_stop(env, mdd, rc, handle);
-#ifdef HAVE_QUOTA_SUPPORT
- if (quota_opc)
- /* Trigger dqrel on the owner of child. If failed,
- * the next call for lquota_chkquota will process it */
- lquota_adjust(mds_quota_interface_ref, obd, qids, 0, rc,
- quota_opc);
-#endif
return rc;
}
+++ /dev/null
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/mdd/mdd_quota.c
- *
- * Lustre Metadata Server (mdd) routines
- *
- * Author: Fan Yong <Yong.Fan@Sun.Com>
- */
-
-#ifdef HAVE_QUOTA_SUPPORT
-
-#include "mdd_internal.h"
-
-int mdd_quota_notify(const struct lu_env *env, struct md_device *m)
-{
- struct mdd_device *mdd = lu2mdd_dev(&m->md_lu_dev);
- struct obd_device *obd = mdd->mdd_obd_dev;
- ENTRY;
-
- lquota_setinfo(mds_quota_interface_ref, obd, (void *)1);
- RETURN(0);
-}
-
-int mdd_quota_setup(const struct lu_env *env, struct md_device *m,
- void *data)
-{
- struct mdd_device *mdd = lu2mdd_dev(&m->md_lu_dev);
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct dt_device *dt = mdd->mdd_child;
- int rc;
- ENTRY;
-
- LASSERT(obd->obd_fsops != NULL);
- dt->dd_ops->dt_init_quota_ctxt(env, dt, (void *)obd, data);
- rc = lquota_setup(mds_quota_interface_ref, obd);
- RETURN(rc);
-}
-
-int mdd_quota_cleanup(const struct lu_env *env, struct md_device *m)
-{
- struct mdd_device *mdd = lu2mdd_dev(&m->md_lu_dev);
- struct obd_device *obd = mdd->mdd_obd_dev;
- int rc1, rc2;
- ENTRY;
-
- rc1 = lquota_cleanup(mds_quota_interface_ref, obd);
- rc2 = lquota_fs_cleanup(mds_quota_interface_ref, obd);
- RETURN(rc1 ? : rc2);
-}
-
-int mdd_quota_recovery(const struct lu_env *env, struct md_device *m)
-{
- struct mdd_device *mdd = lu2mdd_dev(&m->md_lu_dev);
- struct obd_device *obd = mdd->mdd_obd_dev;
- int rc;
- ENTRY;
-
- rc = lquota_recovery(mds_quota_interface_ref, obd);
- RETURN(rc);
-}
-
-int mdd_quota_check(const struct lu_env *env, struct md_device *m,
- __u32 type)
-{
- struct mdd_device *mdd = lu2mdd_dev(&m->md_lu_dev);
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct obd_export *exp = md_quota(env)->mq_exp;
- struct obd_quotactl *oqctl = &mdd_env_info(env)->mti_oqctl;
- int rc;
- ENTRY;
-
- oqctl->qc_type = type;
- rc = lquota_check(mds_quota_interface_ref, obd, exp, oqctl);
- RETURN(rc);
-}
-
-int mdd_quota_on(const struct lu_env *env, struct md_device *m,
- __u32 type)
-{
- struct mdd_device *mdd = lu2mdd_dev(&m->md_lu_dev);
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct obd_quotactl *oqctl = &mdd_env_info(env)->mti_oqctl;
- int rc;
- ENTRY;
-
- oqctl->qc_cmd = Q_QUOTAON;
- oqctl->qc_type = type;
- rc = lquota_ctl(mds_quota_interface_ref, obd, oqctl);
- RETURN(rc);
-}
-
-int mdd_quota_off(const struct lu_env *env, struct md_device *m,
- __u32 type)
-{
- struct mdd_device *mdd = lu2mdd_dev(&m->md_lu_dev);
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct obd_quotactl *oqctl = &mdd_env_info(env)->mti_oqctl;
- int rc;
- ENTRY;
-
- oqctl->qc_cmd = Q_QUOTAOFF;
- oqctl->qc_type = type;
- rc = lquota_ctl(mds_quota_interface_ref, obd, oqctl);
- RETURN(rc);
-}
-
-int mdd_quota_setinfo(const struct lu_env *env, struct md_device *m,
- __u32 type, __u32 id, struct obd_dqinfo *dqinfo)
-{
- struct mdd_device *mdd = lu2mdd_dev(&m->md_lu_dev);
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct obd_quotactl *oqctl = &mdd_env_info(env)->mti_oqctl;
- int rc;
- ENTRY;
-
- oqctl->qc_cmd = Q_SETINFO;
- oqctl->qc_type = type;
- oqctl->qc_id = id;
- oqctl->qc_dqinfo = *dqinfo;
- rc = lquota_ctl(mds_quota_interface_ref, obd, oqctl);
- RETURN(rc);
-}
-
-int mdd_quota_getinfo(const struct lu_env *env, const struct md_device *m,
- __u32 type, __u32 id, struct obd_dqinfo *dqinfo)
-{
- struct mdd_device *mdd = lu2mdd_dev(
- &((struct md_device *)m)->md_lu_dev);
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct obd_quotactl *oqctl = &mdd_env_info(env)->mti_oqctl;
- int rc;
- ENTRY;
-
- oqctl->qc_cmd = Q_GETINFO;
- oqctl->qc_type = type;
- oqctl->qc_id = id;
- rc = lquota_ctl(mds_quota_interface_ref, obd, oqctl);
- *dqinfo = oqctl->qc_dqinfo;
- RETURN(rc);
-}
-
-int mdd_quota_setquota(const struct lu_env *env, struct md_device *m,
- __u32 type, __u32 id, struct obd_dqblk *dqblk)
-{
- struct mdd_device *mdd = lu2mdd_dev(&m->md_lu_dev);
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct obd_quotactl *oqctl = &mdd_env_info(env)->mti_oqctl;
- int rc;
- ENTRY;
-
- oqctl->qc_cmd = Q_SETQUOTA;
- oqctl->qc_type = type;
- oqctl->qc_id = id;
- oqctl->qc_dqblk = *dqblk;
- rc = lquota_ctl(mds_quota_interface_ref, obd, oqctl);
- RETURN(rc);
-}
-
-int mdd_quota_getquota(const struct lu_env *env, const struct md_device *m,
- __u32 type, __u32 id, struct obd_dqblk *dqblk)
-{
- struct mdd_device *mdd = lu2mdd_dev(
- &((struct md_device *)m)->md_lu_dev);
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct obd_quotactl *oqctl = &mdd_env_info(env)->mti_oqctl;
- int rc;
- ENTRY;
-
- oqctl->qc_cmd = Q_GETQUOTA;
- oqctl->qc_type = type;
- oqctl->qc_id = id;
- rc = lquota_ctl(mds_quota_interface_ref, obd, oqctl);
- *dqblk = oqctl->qc_dqblk;
- RETURN(rc);
-}
-
-int mdd_quota_getoinfo(const struct lu_env *env, const struct md_device *m,
- __u32 type, __u32 id, struct obd_dqinfo *dqinfo)
-{
- struct mdd_device *mdd = lu2mdd_dev(
- &((struct md_device *)m)->md_lu_dev);
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct obd_quotactl *oqctl = &mdd_env_info(env)->mti_oqctl;
- int rc;
- ENTRY;
-
- oqctl->qc_cmd = Q_GETOINFO;
- oqctl->qc_type = type;
- oqctl->qc_id = id;
- rc = lquota_ctl(mds_quota_interface_ref, obd, oqctl);
- *dqinfo = oqctl->qc_dqinfo;
- RETURN(rc);
-}
-
-int mdd_quota_getoquota(const struct lu_env *env, const struct md_device *m,
- __u32 type, __u32 id, struct obd_dqblk *dqblk)
-{
- struct mdd_device *mdd = lu2mdd_dev(
- &((struct md_device *)m)->md_lu_dev);
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct obd_quotactl *oqctl = &mdd_env_info(env)->mti_oqctl;
- int rc;
- ENTRY;
-
- oqctl->qc_cmd = Q_GETOQUOTA;
- oqctl->qc_type = type;
- oqctl->qc_id = id;
- rc = lquota_ctl(mds_quota_interface_ref, obd, oqctl);
- *dqblk = oqctl->qc_dqblk;
- RETURN(rc);
-}
-
-int mdd_quota_invalidate(const struct lu_env *env, struct md_device *m,
- __u32 type)
-{
- struct mdd_device *mdd = lu2mdd_dev(&m->md_lu_dev);
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct obd_quotactl *oqctl = &mdd_env_info(env)->mti_oqctl;
- int rc;
- ENTRY;
-
- oqctl->qc_cmd = LUSTRE_Q_INVALIDATE;
- oqctl->qc_type = type;
- rc = lquota_ctl(mds_quota_interface_ref, obd, oqctl);
- RETURN(rc);
-}
-
-int mdd_quota_finvalidate(const struct lu_env *env, struct md_device *m,
- __u32 type)
-{
- struct mdd_device *mdd = lu2mdd_dev(&m->md_lu_dev);
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct obd_quotactl *oqctl = &mdd_env_info(env)->mti_oqctl;
- int rc;
- ENTRY;
-
- oqctl->qc_cmd = LUSTRE_Q_FINVALIDATE;
- oqctl->qc_type = type;
- rc = lquota_ctl(mds_quota_interface_ref, obd, oqctl);
- RETURN(rc);
-}
-#endif
// .o_health_check = mds_cmd_health_check,
};
-quota_interface_t *mds_quota_interface_ref;
-extern quota_interface_t mds_quota_interface;
-
static int __init mds_cmd_init(void)
{
struct lprocfs_static_vars lvars;
- int rc;
-
- cfs_request_module("%s", "lquota");
- mds_quota_interface_ref = PORTAL_SYMBOL_GET(mds_quota_interface);
- rc = lquota_init(mds_quota_interface_ref);
- if (rc) {
- if (mds_quota_interface_ref)
- PORTAL_SYMBOL_PUT(mds_quota_interface);
- return rc;
- }
- init_obd_quota_ops(mds_quota_interface_ref, &mds_cmd_obd_ops);
lprocfs_mds_init_vars(&lvars);
class_register_type(&mds_cmd_obd_ops, NULL, lvars.module_vars,
static void /*__exit*/ mds_cmd_exit(void)
{
- lquota_exit(mds_quota_interface_ref);
- if (mds_quota_interface_ref)
- PORTAL_SYMBOL_PUT(mds_quota_interface);
-
class_unregister_type(LUSTRE_MDS_NAME);
}
-EXPORT_SYMBOL(mds_quota_interface_ref);
MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("Lustre Metadata Server (MDS)");
MODULE_LICENSE("GPL");
GOTO(out, rc);
}
-#ifdef HAVE_QUOTA_SUPPORT
- if (obd->obd_upcall.onu_owner) {
- /*
- * This is a hack for mds_notify->mdd_notify. When the mds obd
- * in mdd is removed, This hack should be removed.
- */
- LASSERT(obd->obd_upcall.onu_upcall != NULL);
- rc = obd->obd_upcall.onu_upcall(obd, NULL, OBD_NOTIFY_QUOTA,
- obd->obd_upcall.onu_owner,NULL);
- }
-#endif
EXIT;
out:
if (rc) {
#include <lustre_mdt.h>
#include <lustre_log.h>
#include "mdt_internal.h"
-#ifdef HAVE_QUOTA_SUPPORT
-# include <lustre_quota.h>
-#endif
#include <lustre_acl.h>
#include <lustre_param.h>
+#include <lquota.h>
mdl_mode_t mdt_mdl_lock_modes[] = {
[LCK_MINMODE] = MDL_MINMODE,
__u32 op)
{
struct req_capsule *pill = info->mti_pill;
- struct md_quota *mq = md_quota(info->mti_env);
struct mdt_body *repbody;
int rc = 0, rc2;
ENTRY;
rc = lustre_msg_get_status(mdt_info_req(info)->rq_repmsg);
GOTO(out_ucred, rc);
}
- mq->mq_exp = info->mti_exp;
rc = mdt_reint_rec(info, lhc);
EXIT;
out_ucred:
RETURN(rc);
}
-#ifdef HAVE_QUOTA_SUPPORT
-static int mdt_quotacheck_handle(struct mdt_thread_info *info)
+/*
+ * Quotacheck handler.
+ * in-kernel quotacheck isn't supported any more.
+ */
+static int mdt_quotacheck(struct mdt_thread_info *info)
{
- struct obd_quotactl *oqctl;
- struct req_capsule *pill = info->mti_pill;
- struct obd_export *exp = info->mti_exp;
- struct md_quota *mq = md_quota(info->mti_env);
- struct md_device *next = info->mti_mdt->mdt_child;
- int rc;
- ENTRY;
-
- oqctl = req_capsule_client_get(pill, &RMF_OBD_QUOTACTL);
- if (oqctl == NULL)
- RETURN(-EPROTO);
+ struct obd_quotactl *oqctl;
+ int rc;
+ ENTRY;
- /* remote client has no permission for quotacheck */
- if (unlikely(exp_connect_rmtclient(exp)))
- RETURN(-EPERM);
+ oqctl = req_capsule_client_get(info->mti_pill, &RMF_OBD_QUOTACTL);
+ if (oqctl == NULL)
+ RETURN(err_serious(-EPROTO));
- rc = req_capsule_server_pack(pill);
- if (rc)
- RETURN(rc);
+ rc = req_capsule_server_pack(info->mti_pill);
+ if (rc)
+ RETURN(err_serious(rc));
- mq->mq_exp = exp;
- rc = next->md_ops->mdo_quota.mqo_check(info->mti_env, next,
- oqctl->qc_type);
- RETURN(rc);
+ /* deprecated, not used any more */
+ RETURN(-EOPNOTSUPP);
}
-static int mdt_quotactl_handle(struct mdt_thread_info *info)
+/*
+ * Handle quota control requests to consult current usage/limit, but also
+ * to configure quota enforcement
+ */
+static int mdt_quotactl(struct mdt_thread_info *info)
{
- struct obd_quotactl *oqctl, *repoqc;
- struct req_capsule *pill = info->mti_pill;
- struct obd_export *exp = info->mti_exp;
- struct md_quota *mq = md_quota(info->mti_env);
- struct md_device *next = info->mti_mdt->mdt_child;
- const struct md_quota_operations *mqo = &next->md_ops->mdo_quota;
- int id, rc;
- ENTRY;
+ struct obd_export *exp = info->mti_exp;
+ struct req_capsule *pill = info->mti_pill;
+ struct obd_quotactl *oqctl, *repoqc;
+ int id, rc;
+ ENTRY;
- oqctl = req_capsule_client_get(pill, &RMF_OBD_QUOTACTL);
- if (oqctl == NULL)
- RETURN(-EPROTO);
+ oqctl = req_capsule_client_get(pill, &RMF_OBD_QUOTACTL);
+ if (oqctl == NULL)
+ RETURN(err_serious(-EPROTO));
- id = oqctl->qc_id;
- if (exp_connect_rmtclient(exp)) {
- struct ptlrpc_request *req = mdt_info_req(info);
- struct mdt_export_data *med = mdt_req2med(req);
- struct lustre_idmap_table *idmap = med->med_idmap;
+ rc = req_capsule_server_pack(pill);
+ if (rc)
+ RETURN(err_serious(rc));
- if (unlikely(oqctl->qc_cmd != Q_GETQUOTA &&
- oqctl->qc_cmd != Q_GETINFO))
- RETURN(-EPERM);
+ switch (oqctl->qc_cmd) {
+ case Q_QUOTACHECK:
+ case LUSTRE_Q_INVALIDATE:
+ case LUSTRE_Q_FINVALIDATE:
+ case Q_QUOTAON:
+ case Q_QUOTAOFF:
+ case Q_INITQUOTA:
+ /* deprecated, not used any more */
+ RETURN(-EOPNOTSUPP);
+ /* master quotactl */
+ case Q_GETINFO:
+ case Q_SETINFO:
+ case Q_SETQUOTA:
+ case Q_GETQUOTA:
+ /* slave quotactl */
+ case Q_GETOINFO:
+ case Q_GETOQUOTA:
+ break;
+ default:
+ CERROR("Unsupported quotactl command: %d\n", oqctl->qc_cmd);
+ RETURN(-EFAULT);
+ }
+ /* map uid/gid for remote client */
+ id = oqctl->qc_id;
+ if (exp_connect_rmtclient(exp)) {
+ struct lustre_idmap_table *idmap;
+
+ idmap = mdt_req2med(mdt_info_req(info))->med_idmap;
+
+ if (unlikely(oqctl->qc_cmd != Q_GETQUOTA &&
+ oqctl->qc_cmd != Q_GETINFO))
+ RETURN(-EPERM);
+
+ if (oqctl->qc_type == USRQUOTA)
+ id = lustre_idmap_lookup_uid(NULL, idmap, 0,
+ oqctl->qc_id);
+ else if (oqctl->qc_type == GRPQUOTA)
+ id = lustre_idmap_lookup_gid(NULL, idmap, 0,
+ oqctl->qc_id);
+ else
+ RETURN(-EINVAL);
+
+ if (id == CFS_IDMAP_NOTFOUND) {
+ CDEBUG(D_QUOTA, "no mapping for id %u\n", oqctl->qc_id);
+ RETURN(-EACCES);
+ }
+ }
- if (oqctl->qc_type == USRQUOTA)
- id = lustre_idmap_lookup_uid(NULL, idmap, 0,
- oqctl->qc_id);
- else if (oqctl->qc_type == GRPQUOTA)
- id = lustre_idmap_lookup_gid(NULL, idmap, 0,
- oqctl->qc_id);
- else
- RETURN(-EINVAL);
+ repoqc = req_capsule_server_get(pill, &RMF_OBD_QUOTACTL);
+ if (repoqc == NULL)
+ RETURN(err_serious(-EFAULT));
- if (id == CFS_IDMAP_NOTFOUND) {
- CDEBUG(D_QUOTA, "no mapping for id %u\n",
- oqctl->qc_id);
- RETURN(-EACCES);
- }
- }
+ if (oqctl->qc_id != id)
+ swap(oqctl->qc_id, id);
+
+ switch (oqctl->qc_cmd) {
+
+ /* master quotactl */
+ case Q_GETINFO:
+ case Q_SETINFO:
+ case Q_SETQUOTA:
+ /* XXX: not implemented yet. Will be when qmt support is
+ * added */
+ CERROR("quotactl operation %d not implemented yet\n",
+ oqctl->qc_cmd);
+ RETURN(-EOPNOTSUPP);
+ case Q_GETQUOTA:
+ /* XXX: return no limit for now, just for testing purpose */
+ memset(&oqctl->qc_dqblk, 0, sizeof(struct obd_dqblk));
+ oqctl->qc_dqblk.dqb_valid = QIF_LIMITS;
+ rc = 0;
+ break;
- rc = req_capsule_server_pack(pill);
- if (rc)
- RETURN(rc);
+ /* slave quotactl */
+ case Q_GETOINFO:
+ case Q_GETOQUOTA:
+ rc = lquotactl_slv(info->mti_env, info->mti_mdt->mdt_bottom,
+ oqctl);
+ break;
- repoqc = req_capsule_server_get(pill, &RMF_OBD_QUOTACTL);
- LASSERT(repoqc != NULL);
+ default:
+ CERROR("Unsupported quotactl command: %d\n", oqctl->qc_cmd);
+ RETURN(-EFAULT);
+ }
- mq->mq_exp = exp;
- switch (oqctl->qc_cmd) {
- case Q_QUOTAON:
- rc = mqo->mqo_on(info->mti_env, next, oqctl->qc_type);
- break;
- case Q_QUOTAOFF:
- rc = mqo->mqo_off(info->mti_env, next, oqctl->qc_type);
- break;
- case Q_SETINFO:
- rc = mqo->mqo_setinfo(info->mti_env, next, oqctl->qc_type, id,
- &oqctl->qc_dqinfo);
- break;
- case Q_GETINFO:
- rc = mqo->mqo_getinfo(info->mti_env, next, oqctl->qc_type, id,
- &oqctl->qc_dqinfo);
- break;
- case Q_SETQUOTA:
- rc = mqo->mqo_setquota(info->mti_env, next, oqctl->qc_type, id,
- &oqctl->qc_dqblk);
- break;
- case Q_GETQUOTA:
- rc = mqo->mqo_getquota(info->mti_env, next, oqctl->qc_type, id,
- &oqctl->qc_dqblk);
- break;
- case Q_GETOINFO:
- rc = mqo->mqo_getoinfo(info->mti_env, next, oqctl->qc_type, id,
- &oqctl->qc_dqinfo);
- break;
- case Q_GETOQUOTA:
- rc = mqo->mqo_getoquota(info->mti_env, next, oqctl->qc_type, id,
- &oqctl->qc_dqblk);
- break;
- case LUSTRE_Q_INVALIDATE:
- rc = mqo->mqo_invalidate(info->mti_env, next, oqctl->qc_type);
- break;
- case LUSTRE_Q_FINVALIDATE:
- rc = mqo->mqo_finvalidate(info->mti_env, next, oqctl->qc_type);
- break;
- default:
- CERROR("unsupported mdt_quotactl command: %d\n",
- oqctl->qc_cmd);
- RETURN(-EFAULT);
- }
+ if (oqctl->qc_id != id)
+ swap(oqctl->qc_id, id);
- *repoqc = *oqctl;
- RETURN(rc);
+ *repoqc = *oqctl;
+ RETURN(rc);
}
-#endif
-
/*
* OBD PING and other handlers.
mdt_procfs_fini(m);
-#ifdef HAVE_QUOTA_SUPPORT
- next->md_ops->mdo_quota.mqo_cleanup(env, next);
-#endif
lut_fini(env, &m->mdt_lut);
mdt_fs_cleanup(env, m);
upcall_cache_cleanup(m->mdt_identity_cache);
mdt_adapt_sptlrpc_conf(obd, 1);
next = m->mdt_child;
-#ifdef HAVE_QUOTA_SUPPORT
- rc = next->md_ops->mdo_quota.mqo_setup(env, next, lmi->lmi_mnt);
- if (rc)
- GOTO(err_llog_cleanup, rc);
-#endif
rc = next->md_ops->mdo_iocontrol(env, next, OBD_IOC_GET_MNTOPT, 0,
&mntopts);
if (rc)
- GOTO(err_quota, rc);
+ GOTO(err_llog_cleanup, rc);
if (mntopts & MNTOPT_USERXATTR)
m->mdt_opts.mo_user_xattr = 1;
if (IS_ERR(m->mdt_identity_cache)) {
rc = PTR_ERR(m->mdt_identity_cache);
m->mdt_identity_cache = NULL;
- GOTO(err_quota, rc);
+ GOTO(err_llog_cleanup, rc);
}
target_recovery_init(&m->mdt_lut, mdt_recovery_handle);
target_recovery_fini(obd);
upcall_cache_cleanup(m->mdt_identity_cache);
m->mdt_identity_cache = NULL;
-err_quota:
-#ifdef HAVE_QUOTA_SUPPORT
- next->md_ops->mdo_quota.mqo_cleanup(env, next);
-#endif
err_llog_cleanup:
mdt_llog_ctxt_unclone(env, m, LLOG_CHANGELOG_ORIG_CTXT);
mdt_obd_llog_cleanup(obd);
/* Check that MDT is not yet configured */
LASSERT(!cfs_test_bit(MDT_FL_CFGLOG, &m->mdt_state));
break;
-#ifdef HAVE_QUOTA_SUPPORT
- case MD_LOV_QUOTA:
- if (md->md_lu_dev.ld_obd->obd_recovering == 0 &&
- likely(md->md_lu_dev.ld_obd->obd_stopping == 0))
- next->md_ops->mdo_quota.mqo_recovery(env, next);
- break;
-#endif
default:
CERROR("invalid event\n");
rc = -EINVAL;
enum obd_notify_event ev, void *data)
{
struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-#ifdef HAVE_QUOTA_SUPPORT
- struct md_device *next = mdt->mdt_child;
-#endif
ENTRY;
switch (ev) {
case OBD_NOTIFY_CONFIG:
mdt_allow_cli(mdt, (unsigned long)data);
-
-#ifdef HAVE_QUOTA_SUPPORT
- /* quota_type has been processed, we can now handle
- * incoming quota requests */
- next->md_ops->mdo_quota.mqo_notify(NULL, next);
-#endif
break;
default:
CDEBUG(D_INFO, "Unhandled notification %#x\n", ev);
int mdt_postrecov(const struct lu_env *env, struct mdt_device *mdt)
{
struct lu_device *ld = md2lu_dev(mdt->mdt_child);
-#ifdef HAVE_QUOTA_SUPPORT
- struct obd_device *obd = mdt2obd_dev(mdt);
- struct md_device *next = mdt->mdt_child;
-#endif
int rc;
ENTRY;
rc = ld->ld_ops->ldo_recovery_complete(env, ld);
-#ifdef HAVE_QUOTA_SUPPORT
- if (likely(obd->obd_stopping == 0))
- next->md_ops->mdo_quota.mqo_recovery(env, next);
-#endif
RETURN(rc);
}
DEF_MDT_HNDL_F(0 |HABEO_REFERO, PIN, mdt_pin),
DEF_MDT_HNDL_0(0, SYNC, mdt_sync),
DEF_MDT_HNDL_F(HABEO_CORPUS|HABEO_REFERO, IS_SUBDIR, mdt_is_subdir),
-#ifdef HAVE_QUOTA_SUPPORT
-DEF_MDT_HNDL_F(0, QUOTACHECK, mdt_quotacheck_handle),
-DEF_MDT_HNDL_F(0, QUOTACTL, mdt_quotactl_handle)
-#endif
+DEF_MDT_HNDL_F(0, QUOTACHECK, mdt_quotacheck),
+DEF_MDT_HNDL_F(0, QUOTACTL, mdt_quotactl)
};
#define DEF_OBD_HNDL(flags, name, fn) \
LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
- LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
-#ifdef HAVE_QUOTA_SUPPORT
- if (obd->u.obt.obt_qctxt.lqc_lqs_hash)
- c += cfs_hash_debug_str(obd->u.obt.obt_qctxt.lqc_lqs_hash,
- page + c, count - c);
-#endif
return c;
}
#include <lustre_log.h>
#include <libcfs/list.h>
#include <lustre_disk.h>
-#include <lustre_quota.h>
#include <linux/slab.h>
#include <lustre_param.h>
#include <lustre/ll_fiemap.h>
/* do this after llog being initialized */
filter_adapt_sptlrpc_conf(obd, 1);
- rc = lquota_setup(filter_quota_interface_ref, obd);
- if (rc)
- GOTO(err_post, rc);
-
q = bdev_get_queue(mnt->mnt_sb->s_bdev);
if (queue_max_sectors(q) < queue_max_hw_sectors(q) &&
queue_max_sectors(q) < PTLRPC_MAX_BRW_SIZE >> 9)
lprocfs_free_per_client_stats(obd);
lprocfs_obd_cleanup(obd);
lprocfs_free_obd_stats(obd);
- lquota_cleanup(filter_quota_interface_ref, obd);
break;
}
RETURN(rc);
exp->exp_obd->obd_name, exp->exp_client_uuid.uuid,
exp, fed->fed_pending);
- lquota_clearinfo(filter_quota_interface_ref, exp, exp->exp_obd);
-
target_destroy_export(exp);
if (unlikely(obd_uuid_equals(&exp->exp_obd->obd_uuid,
/* Flush any remaining cancel messages out to the target */
filter_sync_llogs(obd, exp);
- lquota_clearinfo(filter_quota_interface_ref, exp, exp->exp_obd);
-
rc = server_disconnect_export(exp);
/* Do not erase record for recoverable client. */
int filter_setattr_internal(struct obd_export *exp, struct dentry *dentry,
struct obdo *oa, struct obd_trans_info *oti)
{
- unsigned int orig_ids[MAXQUOTAS] = {0, 0};
struct llog_cookie *fcc = NULL;
struct filter_obd *filter;
int rc, err, sync = 0;
iattr.ia_mode &= ~S_ISGID;
}
- orig_ids[USRQUOTA] = inode->i_uid;
- orig_ids[GRPQUOTA] = inode->i_gid;
handle = fsfilt_start_log(exp->exp_obd, inode,
FSFILT_OP_SETATTR, oti, 1);
if (IS_ERR(handle))
up_write(&inode->i_alloc_sem);
if (fcc)
OBD_FREE(fcc, sizeof(*fcc));
-
- /* trigger quota release */
- if (ia_valid & (ATTR_SIZE | ATTR_UID | ATTR_GID)) {
- unsigned int cur_ids[MAXQUOTAS] = {oa->o_uid, oa->o_gid};
- int rc2 = lquota_adjust(filter_quota_interface_ref,
- exp->exp_obd, cur_ids,
- orig_ids, rc, FSFILT_OP_SETATTR);
- CDEBUG(rc2 ? D_ERROR : D_QUOTA,
- "filter adjust qunit. (rc:%d)\n", rc2);
- }
return rc;
}
struct obd_trans_info *oti, struct obd_export *md_exp,
void *capa)
{
- unsigned int qcids[MAXQUOTAS] = {0, 0};
struct obd_device *obd;
struct filter_obd *filter;
struct dentry *dchild = NULL, *dparent = NULL;
LBUG();
}
- /* trigger quota release */
- qcids[USRQUOTA] = oa->o_uid;
- qcids[GRPQUOTA] = oa->o_gid;
- rc2 = lquota_adjust(filter_quota_interface_ref, obd, qcids, NULL, rc,
- FSFILT_OP_UNLINK);
- if (rc2)
- CERROR("filter adjust qunit! (rc:%d)\n", rc2);
return rc;
}
/* setup llog group 1 for interop */
filter_setup_llog_group(exp, obd, FID_SEQ_LLOG);
}
-
- lquota_setinfo(filter_quota_interface_ref, obd, exp);
out:
RETURN(rc);
}
if (KEY_IS(KEY_REVIMP_UPD)) {
filter_revimp_update(exp);
- lquota_clearinfo(filter_quota_interface_ref, exp, exp->exp_obd);
RETURN(0);
}
.o_notify = filter_notify,
};
-quota_interface_t *filter_quota_interface_ref;
-extern quota_interface_t filter_quota_interface;
-
static int __init obdfilter_init(void)
{
struct lprocfs_static_vars lvars;
lprocfs_filter_init_vars(&lvars);
- cfs_request_module("%s", "lquota");
OBD_ALLOC(obdfilter_created_scratchpad,
OBDFILTER_CREATED_SCRATCHPAD_ENTRIES *
sizeof(*obdfilter_created_scratchpad));
if (!ll_fmd_cachep)
GOTO(out, rc = -ENOMEM);
- filter_quota_interface_ref = PORTAL_SYMBOL_GET(filter_quota_interface);
- init_obd_quota_ops(filter_quota_interface_ref, &filter_obd_ops);
-
rc = class_register_type(&filter_obd_ops, NULL, lvars.module_vars,
LUSTRE_OST_NAME, NULL);
if (rc) {
LASSERTF(err == 0, "Cannot destroy ll_fmd_cachep: rc %d\n",err);
ll_fmd_cachep = NULL;
out:
- if (filter_quota_interface_ref)
- PORTAL_SYMBOL_PUT(filter_quota_interface);
-
OBD_FREE(obdfilter_created_scratchpad,
OBDFILTER_CREATED_SCRATCHPAD_ENTRIES *
sizeof(*obdfilter_created_scratchpad));
static void __exit obdfilter_exit(void)
{
- if (filter_quota_interface_ref)
- PORTAL_SYMBOL_PUT(filter_quota_interface);
-
if (ll_fmd_cachep) {
int rc = cfs_mem_cache_destroy(ll_fmd_cachep);
LASSERTF(rc == 0, "Cannot destroy ll_fmd_cachep: rc %d\n", rc);
static inline void filter_stats_counter_init(struct lprocfs_stats *stats) {}
#endif
-/* Quota stuff */
-extern quota_interface_t *filter_quota_interface_ref;
-
int filter_update_capa_key(struct obd_device *obd, struct lustre_capa_key *key);
int filter_auth_capa(struct obd_export *exp, struct lu_fid *fid, obd_seq seq,
struct lustre_capa *capa, __u64 opc);
#include <obd_class.h>
#include <lustre_fsfilt.h>
-#include <lustre_quota.h>
#include "filter_internal.h"
/* 512byte block min */
LASSERT(iobuf->dr_npages > 0);
create = 1;
mutex = &obd->u.filter.fo_alloc_lock;
-
- lquota_enforce(filter_quota_interface_ref, obd,
- iobuf->dr_ignore_quota);
}
if (rw == OBD_BRW_WRITE &&
struct filter_obd *fo = &obd->u.filter;
void *wait_handle = NULL;
int total_size = 0;
- unsigned int qcids[MAXQUOTAS] = { oa->o_uid, oa->o_gid };
- int rec_pending[MAXQUOTAS] = { 0, 0 }, quota_pages = 0;
int sync_journal_commit = obd->u.filter.fo_syncjournal;
int retries = 0;
ENTRY;
* we don't need a grant */
if (!(flags & OBD_BRW_GRANTED) && lnb->rc == -ENOSPC)
lnb->rc = 0;
- } else {
- quota_pages++;
}
if (lnb->rc) { /* ENOSPC, network RPC error, etc. */
}
}
- /* we try to get enough quota to write here, and let ldiskfs
- * decide if it is out of quota or not b=14783 */
- rc = lquota_chkquota(filter_quota_interface_ref, obd, exp, qcids,
- rec_pending, quota_pages, oti, LQUOTA_FLAGS_BLK,
- (void *)inode, obj->ioo_bufcnt);
- if (rc == -ENOTCONN)
- GOTO(cleanup, rc);
-
if (OBD_FAIL_CHECK(OBD_FAIL_OST_DQACQ_NET))
GOTO(cleanup, rc = -EINPROGRESS);
push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
cleanup_phase = 2;
- fsfilt_check_slow(obd, now, "quota init");
-
retry:
mutex_lock(&inode->i_mutex);
fsfilt_check_slow(obd, now, "i_mutex");
oa->o_id, (__u32)oa->o_seq, (__u32)oa->o_seq,
oa->o_size, oa->o_mtime, oa->o_atime, oa->o_ctime,
oa->o_blocks);
- lquota_getflag(filter_quota_interface_ref, obd, oa);
fsfilt_check_slow(obd, now, "direct_io");
fsfilt_check_slow(obd, now, "commitrw commit");
cleanup:
- lquota_pending_commit(filter_quota_interface_ref, obd, qcids,
- rec_pending, 1);
-
filter_grant_commit(exp, niocount, res);
switch (cleanup_phase) {
break;
}
- /* trigger quota pre-acquire */
- 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[USRQUOTA], qcids[GRPQUOTA]);
- if (qcids[USRQUOTA] != oa->o_uid || qcids[GRPQUOTA] != oa->o_gid) {
- 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, uid:%u, gid:%u)\n",
- err, qcids[USRQUOTA], qcids[GRPQUOTA]);
- }
-
for (i = 0, lnb = res; i < niocount; i++, lnb++) {
if (lnb->page == NULL)
continue;
{ "readcache_max_filesize",
lprocfs_filter_rd_readcache,
lprocfs_filter_wr_readcache, 0 },
-#ifdef HAVE_QUOTA_SUPPORT
- { "quota_type", lprocfs_quota_rd_type,
- lprocfs_quota_wr_type, 0},
-#endif
{ "client_cache_count", lprocfs_filter_rd_fmd_max_num,
lprocfs_filter_wr_fmd_max_num, 0 },
{ "client_cache_seconds", lprocfs_filter_rd_fmd_max_age,
{ "capa", lprocfs_ofd_rd_capa,
lprocfs_ofd_wr_capa, 0 },
{ "capa_count", lprocfs_ofd_rd_capa_count, 0, 0 },
- /* we still register a fake quota type file for backward compatibility*/
- { "quota_type", lprocfs_quota_rd_type_dumb,
- lprocfs_quota_wr_type_dumb, 0},
{ 0 }
};
}
/*
- * Handle quotacheck requests.
- * Although in-kernel quotacheck isn't supported any more, we still emulate it
- * in order to interoperate with current MDT stack which needs proper
- * quotacheck support, even for space accounting.
- *
- * \param obd - is the obd device associated with the ofd
- * \param exp - is the client's export
- * \param oqctl - is the obd_quotactl request to be processed
- */
-static int ofd_quotacheck(struct obd_device *obd, struct obd_export *exp,
- struct obd_quotactl *oqctl)
-{
- struct ptlrpc_request *req;
- struct obd_quotactl *body;
- ENTRY;
-
- req = ptlrpc_request_alloc_pack(exp->exp_imp_reverse, &RQF_QC_CALLBACK,
- LUSTRE_OBD_VERSION, OBD_QC_CALLBACK);
- if (req == NULL)
- RETURN(-ENOMEM);
-
- body = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
- oqctl->qc_stat = 0;
- memcpy(body, oqctl, sizeof(*body));
-
- ptlrpc_request_set_replen(req);
- ptlrpcd_add_req(req, PDL_POLICY_ROUND, -1);
-
- RETURN(0);
-}
-
-/*
- * Handle quota control requests to consult current usage/limit, but also
- * to configure quota enforcement
+ * Handle quota control requests to consult current usage/limit.
*
* \param obd - is the obd device associated with the ofd
* \param exp - is the client's export
.o_health_check = ofd_health_check,
.o_notify = ofd_obd_notify,
.o_quotactl = ofd_quotactl,
- .o_quotacheck = ofd_quotacheck,
};
int osc_quotacheck(struct obd_device *unused, struct obd_export *exp,
struct obd_quotactl *oqctl);
int osc_quota_poll_check(struct obd_export *exp, struct if_quotacheck *qchk);
-int osc_quota_adjust_qunit(struct obd_export *exp,
- struct quota_adjust_qunit *oqaq,
- struct lustre_quota_ctxt *qctxt,
- struct ptlrpc_request_set *rqset);
#endif /* OSC_INTERNAL_H */
rc = -EINTR;
RETURN(rc);
}
-
-int osc_quota_adjust_qunit(struct obd_export *exp,
- struct quota_adjust_qunit *oqaq,
- struct lustre_quota_ctxt *qctxt,
- struct ptlrpc_request_set *rqset)
-{
- struct ptlrpc_request *req;
- struct quota_adjust_qunit *oqa;
- int rc = 0;
- ENTRY;
-
- /* client don't support this kind of operation, abort it */
- if (!(exp->exp_connect_flags & OBD_CONNECT_CHANGE_QS)) {
- CDEBUG(D_QUOTA, "osc: %s don't support change qunit size\n",
- exp->exp_obd->obd_name);
- RETURN(rc);
- }
- if (strcmp(exp->exp_obd->obd_type->typ_name, LUSTRE_OSC_NAME))
- RETURN(-EINVAL);
-
- LASSERT(rqset);
-
- req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
- &RQF_OST_QUOTA_ADJUST_QUNIT,
- LUSTRE_OST_VERSION,
- OST_QUOTA_ADJUST_QUNIT);
- if (req == NULL)
- RETURN(-ENOMEM);
-
- oqa = req_capsule_client_get(&req->rq_pill, &RMF_QUOTA_ADJUST_QUNIT);
- *oqa = *oqaq;
-
- ptlrpc_request_set_replen(req);
-
- ptlrpc_set_add_req(rqset, req);
- RETURN(rc);
-}
.o_process_config = osc_process_config,
.o_quotactl = osc_quotactl,
.o_quotacheck = osc_quotacheck,
- .o_quota_adjust_qunit = osc_quota_adjust_qunit,
};
extern struct lu_kmem_descr osc_caches[];
return osd_invariant(osd_obj(l));
}
-#ifdef HAVE_QUOTA_SUPPORT
-static inline void
-osd_push_ctxt(const struct lu_env *env, struct osd_ctxt *save, bool is_md)
-{
- struct md_ucred *uc;
- struct cred *tc;
-
- if (!is_md)
- /* OFD support */
- return;
-
- uc = md_ucred(env);
-
- LASSERT(uc != NULL);
-
- save->oc_uid = current_fsuid();
- save->oc_gid = current_fsgid();
- save->oc_cap = current_cap();
- if ((tc = prepare_creds())) {
- tc->fsuid = uc->mu_fsuid;
- tc->fsgid = uc->mu_fsgid;
- commit_creds(tc);
- }
- /* XXX not suboptimal */
- cfs_curproc_cap_unpack(uc->mu_cap);
-}
-
-static inline void
-osd_pop_ctxt(struct osd_ctxt *save, bool is_md)
-{
- struct cred *tc;
-
- if (!is_md)
- /* OFD support */
- return;
-
- if ((tc = prepare_creds())) {
- tc->fsuid = save->oc_uid;
- tc->fsgid = save->oc_gid;
- tc->cap_effective = save->oc_cap;
- commit_creds(tc);
- }
-}
-#endif
-
/*
* Concurrency: doesn't matter
*/
OSD_EXEC_OP(handle, attr_set);
inode = obj->oo_inode;
- if (!osd_dt_dev(handle->th_dev)->od_is_md) {
- /* OFD support */
- rc = osd_quota_transfer(inode, attr);
- if (rc)
- return rc;
- } else {
-#ifdef HAVE_QUOTA_SUPPORT
- if ((attr->la_valid & LA_UID && attr->la_uid != inode->i_uid) ||
- (attr->la_valid & LA_GID && attr->la_gid != inode->i_gid)) {
- struct osd_ctxt *save = &osd_oti_get(env)->oti_ctxt;
- struct iattr iattr;
- int rc;
-
- iattr.ia_valid = 0;
- if (attr->la_valid & LA_UID)
- iattr.ia_valid |= ATTR_UID;
- if (attr->la_valid & LA_GID)
- iattr.ia_valid |= ATTR_GID;
- iattr.ia_uid = attr->la_uid;
- iattr.ia_gid = attr->la_gid;
- osd_push_ctxt(env, save, 1);
- rc = ll_vfs_dq_transfer(inode, &iattr) ? -EDQUOT : 0;
- osd_pop_ctxt(save, 1);
- if (rc != 0)
- return rc;
- }
-#endif
- }
+
+ rc = osd_quota_transfer(inode, attr);
+ if (rc)
+ return rc;
+
cfs_spin_lock(&obj->oo_guard);
rc = osd_inode_setattr(env, inode, attr);
cfs_spin_unlock(&obj->oo_guard);
struct osd_thandle *oth;
struct dt_object *parent = NULL;
struct inode *inode;
-#ifdef HAVE_QUOTA_SUPPORT
- struct osd_ctxt *save = &info->oti_ctxt;
-#endif
LINVRNT(osd_invariant(obj));
LASSERT(obj->oo_inode == NULL);
if (hint && hint->dah_parent)
parent = hint->dah_parent;
-#ifdef HAVE_QUOTA_SUPPORT
- osd_push_ctxt(info->oti_env, save, osd_dt_dev(th->th_dev)->od_is_md);
-#endif
inode = ldiskfs_create_inode(oth->ot_handle,
parent ? osd_dt_obj(parent)->oo_inode :
osd_sb(osd)->s_root->d_inode,
mode);
-#ifdef HAVE_QUOTA_SUPPORT
- osd_pop_ctxt(save, osd_dt_dev(th->th_dev)->od_is_md);
-#endif
if (!IS_ERR(inode)) {
/* Do not update file c/mtime in ldiskfs.
* NB: don't need any lock because no contention at this
if ((valid & LA_MTIME) && (attr->la_mtime == LTIME_S(inode->i_mtime)))
attr->la_valid &= ~LA_MTIME;
- if (!osd_obj2dev(obj)->od_is_md) {
- /* OFD support */
- result = osd_quota_transfer(inode, attr);
- if (result)
- return;
- } else {
-#ifdef HAVE_QUOTA_SUPPORT
- attr->la_valid &= ~(LA_UID | LA_GID);
-#endif
- }
+ result = osd_quota_transfer(inode, attr);
+ if (result)
+ return;
if (attr->la_valid != 0) {
result = osd_inode_setattr(info->oti_env, inode, attr);
LASSERT(obj->oo_inode != NULL);
- if (osd->od_is_md) {
- struct md_ucred *uc = md_ucred(env);
- LASSERT(uc != NULL);
- }
-
osd_id_gen(id, obj->oo_inode->i_ino, obj->oo_inode->i_generation);
return osd_oi_insert(info, osd, fid, id, th);
}
struct iam_path_descr *ipd;
struct osd_thandle *oh;
struct iam_container *bag = &obj->oo_dir->od_container;
-#ifdef HAVE_QUOTA_SUPPORT
- cfs_cap_t save = cfs_curproc_cap_pack();
-#endif
struct osd_thread_info *oti = osd_oti_get(env);
struct iam_rec *iam_rec;
int rc;
oh = container_of0(th, struct osd_thandle, ot_super);
LASSERT(oh->ot_handle != NULL);
LASSERT(oh->ot_handle->h_transaction != NULL);
-#ifdef HAVE_QUOTA_SUPPORT
- if (ignore_quota)
- cfs_cap_raise(CFS_CAP_SYS_RESOURCE);
- else
- cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
-#endif
if (S_ISDIR(obj->oo_inode->i_mode)) {
iam_rec = (struct iam_rec *)oti->oti_ldp;
osd_fid_pack((struct osd_fid_pack *)iam_rec, rec, &oti->oti_fid);
rc = iam_insert(oh->ot_handle, bag, (const struct iam_key *)key,
iam_rec, ipd);
-#ifdef HAVE_QUOTA_SUPPORT
- cfs_curproc_cap_unpack(save);
-#endif
osd_ipd_put(env, bag, ipd);
LINVRNT(osd_invariant(obj));
RETURN(rc);
struct lu_fid *fid = (struct lu_fid *) rec;
const char *name = (const char *)key;
struct osd_object *child;
-#ifdef HAVE_QUOTA_SUPPORT
- cfs_cap_t save = cfs_curproc_cap_pack();
-#endif
int rc;
ENTRY;
child = osd_object_find(env, dt, fid);
if (!IS_ERR(child)) {
-#ifdef HAVE_QUOTA_SUPPORT
- if (ignore_quota)
- cfs_cap_raise(CFS_CAP_SYS_RESOURCE);
- else
- cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
-#endif
rc = osd_ea_add_rec(env, obj, child->oo_inode, name, rec, th);
-#ifdef HAVE_QUOTA_SUPPORT
- cfs_curproc_cap_unpack(save);
-#endif
osd_object_put(env, child);
} else {
rc = PTR_ERR(child);
/** Enable thandle usage statistics */
#define OSD_THANDLE_STATS (0)
-#ifdef HAVE_QUOTA_SUPPORT
-struct osd_ctxt {
- __u32 oc_uid;
- __u32 oc_gid;
- cfs_kernel_cap_t oc_cap;
-};
-#endif
-
struct osd_directory {
struct iam_container od_container;
struct iam_descr od_descr;
struct osd_iobuf oti_iobuf;
struct inode oti_inode;
int oti_created[PTLRPC_MAX_BRW_PAGES];
-#ifdef HAVE_QUOTA_SUPPORT
- struct osd_ctxt oti_ctxt;
-#endif
struct lu_env oti_obj_delete_tx_env;
#define OSD_FID_REC_SZ 32
char oti_ldp[OSD_FID_REC_SZ];
struct inode *inode = osd_dt_obj(dt)->oo_inode;
struct osd_thandle *oh;
ssize_t result;
-#ifdef HAVE_QUOTA_SUPPORT
- cfs_cap_t save = cfs_curproc_cap_pack();
-#endif
int is_link;
LASSERT(dt_object_exists(dt));
oh = container_of(handle, struct osd_thandle, ot_super);
LASSERT(oh->ot_handle->h_transaction != NULL);
-#ifdef HAVE_QUOTA_SUPPORT
- if (ignore_quota)
- cfs_cap_raise(CFS_CAP_SYS_RESOURCE);
- else
- cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
-#endif
/* Write small symlink to inode body as we need to maintain correct
* on-disk symlinks for ldiskfs.
* Note: the buf->lb_buf contains a NUL terminator while buf->lb_len
result = osd_ldiskfs_write_record(inode, buf->lb_buf,
buf->lb_len, is_link, pos,
oh->ot_handle);
-#ifdef HAVE_QUOTA_SUPPORT
- cfs_curproc_cap_unpack(save);
-#endif
if (result == 0)
result = buf->lb_len;
return result;
struct iam_path_descr *ipd;
struct osd_thandle *oh;
int rc;
-#ifdef HAVE_QUOTA_SUPPORT
- cfs_cap_t save = cfs_curproc_cap_pack();
-#endif
ENTRY;
LASSERT(oi);
oh = container_of0(th, struct osd_thandle, ot_super);
LASSERT(oh->ot_handle != NULL);
LASSERT(oh->ot_handle->h_transaction != NULL);
-#ifdef HAVE_QUOTA_SUPPORT
- cfs_cap_raise(CFS_CAP_SYS_RESOURCE);
-#endif
if (S_ISDIR(oi->oi_inode->i_mode))
osd_fid_pack((struct osd_fid_pack *)iam_rec, rec,
&oti->oti_fid);
iam_rec = (struct iam_rec *) rec;
rc = iam_insert(oh->ot_handle, bag, (const struct iam_key *)key,
iam_rec, ipd);
-#ifdef HAVE_QUOTA_SUPPORT
- cfs_curproc_cap_unpack(save);
-#endif
osd_ipd_put(oti->oti_env, bag, ipd);
LINVRNT(osd_invariant(obj));
RETURN(rc);
RETURN(rc);
}
-#ifdef HAVE_QUOTA_SUPPORT
static int ost_handle_quotactl(struct ptlrpc_request *req)
{
struct obd_quotactl *oqctl, *repoqc;
if (rc)
RETURN(-ENOMEM);
- req->rq_status = obd_quotacheck(req->rq_export, oqctl);
- RETURN(0);
+ /* deprecated, not used any more */
+ req->rq_status = -EOPNOTSUPP;
+ RETURN(-EOPNOTSUPP);
}
-static int ost_handle_quota_adjust_qunit(struct ptlrpc_request *req)
-{
- struct quota_adjust_qunit *oqaq, *repoqa;
- struct lustre_quota_ctxt *qctxt;
- int rc;
- ENTRY;
-
- qctxt = &req->rq_export->exp_obd->u.obt.obt_qctxt;
- oqaq = req_capsule_client_get(&req->rq_pill, &RMF_QUOTA_ADJUST_QUNIT);
- if (oqaq == NULL)
- GOTO(out, rc = -EPROTO);
-
- rc = req_capsule_server_pack(&req->rq_pill);
- if (rc)
- GOTO(out, rc);
-
- repoqa = req_capsule_server_get(&req->rq_pill, &RMF_QUOTA_ADJUST_QUNIT);
- req->rq_status = obd_quota_adjust_qunit(req->rq_export, oqaq, qctxt, NULL);
- *repoqa = *oqaq;
-
- out:
- RETURN(rc);
-}
-#endif
-
static int ost_llog_handle_connect(struct obd_export *exp,
struct ptlrpc_request *req)
{
case OST_SYNC:
case OST_SET_INFO:
case OST_GET_INFO:
-#ifdef HAVE_QUOTA_SUPPORT
case OST_QUOTACHECK:
case OST_QUOTACTL:
case OST_QUOTA_ADJUST_QUNIT:
-#endif
rc = lustre_msg_check_version(msg, LUSTRE_OST_VERSION);
if (rc)
CERROR("bad opc %u version %08x, expecting %08x\n",
req_capsule_set(&req->rq_pill, &RQF_OST_GET_INFO_GENERIC);
rc = ost_get_info(req->rq_export, req);
break;
-#ifdef HAVE_QUOTA_SUPPORT
case OST_QUOTACHECK:
CDEBUG(D_INODE, "quotacheck\n");
req_capsule_set(&req->rq_pill, &RQF_OST_QUOTACHECK);
RETURN(0);
rc = ost_handle_quotactl(req);
break;
- case OST_QUOTA_ADJUST_QUNIT:
- CDEBUG(D_INODE, "quota_adjust_qunit\n");
- req_capsule_set(&req->rq_pill, &RQF_OST_QUOTA_ADJUST_QUNIT);
- rc = ost_handle_quota_adjust_qunit(req);
- break;
-#endif
case OBD_PING:
DEBUG_REQ(D_INODE, req, "ping");
req_capsule_set(&req->rq_pill, &RQF_OBD_PING);
MODULES := lquota
-quota-objs := lquota_lib.o lquota_disk.o lproc_quota.o
-quota-objs += quota_check.o quota_context.o quota_ctl.o quota_interface.o
-quota-objs += quota_master.o quota_adjust_qunit.o
+quota-objs := lproc_quota.o lquota_lib.o lquota_disk.o
qsd-objs := qsd_lib.o
lquota-objs := $(quota-objs) $(qsd-objs)
EXTRA_DIST := $(lquota-objs:%.o=%.c) lquota_internal.h qsd_internal.h
-EXTRA_DIST += quota_internal.h
@INCLUDE_RULES@
#include <lustre_fsfilt.h>
#include "lquota_internal.h"
-#include "quota_internal.h"
#ifdef LPROCFS
/* structure allocated at seq_open time and release when seq_release is called.
.llseek = seq_lseek,
.release = lprocfs_quota_seq_release,
};
-
-int lprocfs_quota_rd_type_dumb(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- return 0;
-}
-EXPORT_SYMBOL(lprocfs_quota_rd_type_dumb);
-
-int lprocfs_quota_wr_type_dumb(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- return count;
-}
-EXPORT_SYMBOL(lprocfs_quota_wr_type_dumb);
-
-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
-
-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;
-
- LASSERT(obd != NULL);
-
- /* Collect the needed information */
- oq_type = obd->u.obt.obt_qctxt.lqc_flags;
-
- /* 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");
-
- strcat(stype, "3");
-
- return snprintf(page, count, "%s\n", stype);
-}
-EXPORT_SYMBOL(lprocfs_quota_rd_type);
-
-/*
- * generic_quota_on is very lazy and tolerant about current quota settings
- * @global means to turn on quotas on each OST additionally to local quotas;
- * should not be called from filter_quota_ctl on MDS nodes (as it starts
- * admin quotas on MDS nodes).
- */
-int generic_quota_on(struct obd_device *obd, struct obd_quotactl *oqctl, int global)
-{
- struct obd_device_target *obt = &obd->u.obt;
- struct lvfs_run_ctxt saved;
- int id, is_master, rc = 0, local; /* means we need a local quotaon */
-
- cfs_down(&obt->obt_quotachecking);
- push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- id = UGQUOTA2LQC(oqctl->qc_type);
- local = (obt->obt_qctxt.lqc_flags & id) != id;
-
- oqctl->qc_cmd = Q_QUOTAON;
- oqctl->qc_id = obt->obt_qfmt;
-
- is_master = !strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME);
- if (is_master) {
- cfs_down_write(&obd->u.mds.mds_qonoff_sem);
- if (local) {
- /* turn on cluster wide quota */
- rc = mds_admin_quota_on(obd, oqctl);
- if (rc && rc != -ENOENT)
- CERROR("%s: %s admin quotaon failed. rc=%d\n",
- obd->obd_name, global ? "global":"local",
- rc);
- }
- }
-
- if (rc == 0) {
- if (local) {
- rc = fsfilt_quotactl(obd, obt->obt_sb, oqctl);
- if (rc) {
- if (rc != -ENOENT)
- CERROR("%s: %s quotaon failed with"
- " rc=%d\n", obd->obd_name,
- global ? "global" : "local", rc);
- } else {
- obt->obt_qctxt.lqc_flags |= UGQUOTA2LQC(oqctl->qc_type);
- build_lqs(obd);
- }
- }
-
- if (rc == 0 && global && is_master)
- rc = obd_quotactl(obd->u.mds.mds_lov_exp, oqctl);
- }
-
- if (is_master)
- cfs_up_write(&obd->u.mds.mds_qonoff_sem);
-
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- cfs_up(&obt->obt_quotachecking);
-
- CDEBUG(D_QUOTA, "%s: quotaon type:master:global:local:flags:rc "
- "%u:%d:%d:%d:%lu:%d\n",
- obd->obd_name, oqctl->qc_type, is_master, global, local,
- obt->obt_qctxt.lqc_flags, rc);
-
- return rc;
-}
-
-static int auto_quota_on(struct obd_device *obd, int type)
-{
- struct obd_quotactl *oqctl;
- int rc;
- ENTRY;
-
- LASSERT(type == USRQUOTA || type == GRPQUOTA || type == UGQUOTA);
-
- OBD_ALLOC_PTR(oqctl);
- if (!oqctl)
- RETURN(-ENOMEM);
-
- oqctl->qc_type = type;
-
- rc = generic_quota_on(obd, oqctl, 0);
-
- OBD_FREE_PTR(oqctl);
- RETURN(rc);
-}
-
-int lprocfs_quota_wr_type(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- struct obd_device *obd = (struct obd_device *)data;
- int type = 0;
- unsigned long i;
- char stype[MAX_STYPE_SIZE + 1] = "";
-
- LASSERT(obd != NULL);
-
- if (count > MAX_STYPE_SIZE)
- return -EINVAL;
-
- if (cfs_copy_from_user(stype, buffer, count))
- return -EFAULT;
-
- for (i = 0 ; i < count ; i++) {
- switch (stype[i]) {
- case 'u' :
- type |= USER_QUOTA;
- break;
- case 'g' :
- type |= GROUP_QUOTA;
- break;
- case '1' :
- case '2' :
- CWARN("quota_type options 1 and 2 are obsolete, "
- "they will be ignored\n");
- break;
- case '3' : /* the only valid version spec, do nothing */
- default : /* just skip stray symbols like \n */
- break;
- }
- }
-
- if (type != 0) {
- int rc = auto_quota_on(obd, type - 1);
-
- if (rc && rc != -EALREADY && rc != -ENOENT)
- return rc;
- }
-
- 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_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)
-{
- 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 },
- { "quota_sync_blk", lprocfs_quota_rd_sync_blk,
- lprocfs_quota_wr_sync_blk, 0},
- { NULL }
-};
-
-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 },
- { NULL }
-};
-
-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("%s: error %d setting up lprocfs\n",
- obd->obd_name, rc);
- 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("%s: error %d setting up lprocfs for "
- "quota master\n", obd->obd_name, rc);
- 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;
-
- if (qctxt->lqc_stats != NULL)
- lprocfs_free_stats(&qctxt->lqc_stats);
-
- lprocfs_remove(&qctxt->lqc_proc_dir);
- return 0;
-}
-
#endif /* LPROCFS */
/* lproc_quota.c */
extern struct file_operations lprocfs_quota_seq_fops;
-
-/* quota_interface.c
- * old quota module initialization routines, to be removed */
-int init_lustre_quota(void);
-void exit_lustre_quota(void);
-
#endif /* _LQUOTA_INTERNAL_H */
#include "lquota_internal.h"
+static int hash_lqs_cur_bits = HASH_LQS_CUR_BITS;
+CFS_MODULE_PARM(hash_lqs_cur_bits, "i", int, 0444,
+ "the current bits of lqs hash");
+
/* register lquota key */
LU_KEY_INIT_FINI(lquota, struct lquota_thread_info);
LU_CONTEXT_KEY_DEFINE(lquota, LCT_MD_THREAD | LCT_DT_THREAD | LCT_LOCAL);
static int __init init_lquota(void)
{
- int rc;
-
- /* call old quota module init function */
- rc = init_lustre_quota();
- if (rc)
- return rc;
-
/* new quota initialization */
lquota_key_init_generic(&lquota_thread_key, NULL);
lu_context_key_register(&lquota_thread_key);
static void exit_lquota(void)
{
- /* call old quota module exit function */
- exit_lustre_quota();
-
lu_context_key_degister(&lquota_thread_key);
}
+++ /dev/null
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Whamcloud, Inc.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-#define DEBUG_SUBSYSTEM S_LQUOTA
-
-#ifdef __KERNEL__
-# include <linux/version.h>
-# include <linux/module.h>
-# include <linux/init.h>
-# include <linux/fs.h>
-# include <linux/jbd.h>
-# include <linux/quota.h>
-# include <linux/buffer_head.h>
-# include <linux/workqueue.h>
-# include <linux/mount.h>
-#else /* __KERNEL__ */
-# include <liblustre.h>
-#endif
-
-#include <obd_class.h>
-#include <lustre_mds.h>
-#include <lustre_dlm.h>
-#include <lustre_cfg.h>
-#include <obd_ost.h>
-#include <lustre_fsfilt.h>
-#include <linux/lustre_quota.h>
-#include "quota_internal.h"
-
-#ifdef __KERNEL__
-/**
- * This function is charge of recording lqs_ino_rec and
- * lqs_blk_rec. when a lquota slave checks a quota
- * request(check_cur_qunit) and finishes a quota
- * request(dqacq_completion), it will be called.
- * is_chk: whether it is checking quota; otherwise, it is finishing
- * is_acq: whether it is acquiring; otherwise, it is releasing
- */
-void quota_compute_lqs(struct qunit_data *qdata, struct lustre_qunit_size *lqs,
- int is_chk, int is_acq)
-{
- long long *rec;
-
- LASSERT(qdata && lqs);
- LASSERT_SPIN_LOCKED(&lqs->lqs_lock);
-
- rec = QDATA_IS_BLK(qdata) ? &lqs->lqs_blk_rec : &lqs->lqs_ino_rec;
-
- if (!!is_chk + !!is_acq == 1)
- *rec -= qdata->qd_count;
- else
- *rec += qdata->qd_count;
-
-}
-
-struct lustre_qunit_size *quota_search_lqs(unsigned long long lqs_key,
- struct lustre_quota_ctxt *qctxt,
- int create)
-{
- struct lustre_qunit_size *lqs;
- struct lustre_qunit_size *lqs2;
- cfs_hash_t *hs = NULL;
- int rc = 0;
-
- cfs_spin_lock(&qctxt->lqc_lock);
- if (qctxt->lqc_valid) {
- LASSERT(qctxt->lqc_lqs_hash != NULL);
- hs = cfs_hash_getref(qctxt->lqc_lqs_hash);
- }
- cfs_spin_unlock(&qctxt->lqc_lock);
-
- if (hs == NULL) {
- rc = -EBUSY;
- goto out;
- }
-
- /* cfs_hash_lookup will +1 refcount for caller */
- lqs = cfs_hash_lookup(qctxt->lqc_lqs_hash, &lqs_key);
- if (lqs != NULL) /* found */
- goto out_put;
-
- if (!create)
- goto out_put;
-
- OBD_ALLOC_PTR(lqs);
- if (!lqs) {
- rc = -ENOMEM;
- goto out_put;
- }
-
- lqs->lqs_key = lqs_key;
-
- cfs_spin_lock_init(&lqs->lqs_lock);
-
- lqs->lqs_bwrite_pending = 0;
- lqs->lqs_iwrite_pending = 0;
- lqs->lqs_ino_rec = 0;
- lqs->lqs_blk_rec = 0;
- lqs->lqs_id = LQS_KEY_ID(lqs->lqs_key);
- lqs->lqs_flags = LQS_KEY_GRP(lqs->lqs_key) ? LQUOTA_FLAGS_GRP : 0;
- lqs->lqs_bunit_sz = qctxt->lqc_bunit_sz;
- lqs->lqs_iunit_sz = qctxt->lqc_iunit_sz;
- lqs->lqs_btune_sz = qctxt->lqc_btune_sz;
- lqs->lqs_itune_sz = qctxt->lqc_itune_sz;
- if (qctxt->lqc_handler) {
- lqs->lqs_last_bshrink = 0;
- lqs->lqs_last_ishrink = 0;
- }
-
- lqs->lqs_ctxt = qctxt; /* must be called before lqs_initref */
- cfs_atomic_set(&lqs->lqs_refcount, 1); /* 1 for caller */
- cfs_atomic_inc(&lqs->lqs_ctxt->lqc_lqs);
-
- /* lqc_lqs_hash will take +1 refcount on lqs on adding */
- lqs2 = cfs_hash_findadd_unique(qctxt->lqc_lqs_hash,
- &lqs->lqs_key, &lqs->lqs_hash);
- if (lqs2 == lqs) /* added to hash */
- goto out_put;
-
- create = 0;
- lqs_putref(lqs);
- lqs = lqs2;
-
- out_put:
- cfs_hash_putref(hs);
- out:
- if (rc != 0) { /* error */
- CERROR("get lqs error(rc: %d)\n", rc);
- return ERR_PTR(rc);
- }
-
- if (lqs != NULL) {
- LQS_DEBUG(lqs, "%s\n",
- (create == 1 ? "create lqs" : "search lqs"));
- }
- return lqs;
-}
-
-int quota_adjust_slave_lqs(struct quota_adjust_qunit *oqaq,
- struct lustre_quota_ctxt *qctxt)
-{
- struct lustre_qunit_size *lqs = NULL;
- unsigned long *unit, *tune;
- signed long tmp = 0;
- cfs_time_t time_limit = 0, *shrink;
- int i, rc = 0;
- ENTRY;
-
- LASSERT(qctxt);
- lqs = quota_search_lqs(LQS_KEY(QAQ_IS_GRP(oqaq), oqaq->qaq_id),
- qctxt, QAQ_IS_CREATE_LQS(oqaq) ? 1 : 0);
- if (lqs == NULL || IS_ERR(lqs)){
- CERROR("fail to find a lqs for %sid %u!\n",
- QAQ_IS_GRP(oqaq) ? "g" : "u", oqaq->qaq_id);
- RETURN(PTR_ERR(lqs));
- }
-
- CDEBUG(D_QUOTA, "before: bunit: %lu, iunit: %lu.\n",
- lqs->lqs_bunit_sz, lqs->lqs_iunit_sz);
- cfs_spin_lock(&lqs->lqs_lock);
- for (i = 0; i < 2; i++) {
- if (i == 0 && !QAQ_IS_ADJBLK(oqaq))
- continue;
-
- if (i == 1 && !QAQ_IS_ADJINO(oqaq))
- continue;
-
- tmp = i ? (lqs->lqs_iunit_sz - oqaq->qaq_iunit_sz) :
- (lqs->lqs_bunit_sz - oqaq->qaq_bunit_sz);
- shrink = i ? &lqs->lqs_last_ishrink :
- &lqs->lqs_last_bshrink;
- time_limit = cfs_time_add(i ? lqs->lqs_last_ishrink :
- lqs->lqs_last_bshrink,
- cfs_time_seconds(qctxt->lqc_switch_seconds));
- unit = i ? &lqs->lqs_iunit_sz : &lqs->lqs_bunit_sz;
- tune = i ? &lqs->lqs_itune_sz : &lqs->lqs_btune_sz;
-
- /* quota master shrinks */
- if (qctxt->lqc_handler && tmp > 0)
- *shrink = cfs_time_current();
-
- /* quota master enlarges */
- if (qctxt->lqc_handler && tmp < 0) {
- /* in case of ping-pong effect, don't enlarge lqs
- * in a short time */
- if (*shrink &&
- cfs_time_before(cfs_time_current(), time_limit))
- tmp = 0;
- }
-
- /* when setquota, don't enlarge lqs b=18616 */
- if (QAQ_IS_CREATE_LQS(oqaq) && tmp < 0)
- tmp = 0;
-
- if (tmp != 0) {
- *unit = i ? oqaq->qaq_iunit_sz : oqaq->qaq_bunit_sz;
- *tune = (*unit) / 2;
- }
-
-
- if (tmp > 0)
- rc |= i ? LQS_INO_DECREASE : LQS_BLK_DECREASE;
- if (tmp < 0)
- rc |= i ? LQS_INO_INCREASE : LQS_BLK_INCREASE;
- }
- cfs_spin_unlock(&lqs->lqs_lock);
- CDEBUG(D_QUOTA, "after: bunit: %lu, iunit: %lu.\n",
- lqs->lqs_bunit_sz, lqs->lqs_iunit_sz);
-
- lqs_putref(lqs);
-
- RETURN(rc);
-}
-
-int filter_quota_adjust_qunit(struct obd_export *exp,
- struct quota_adjust_qunit *oqaq,
- struct lustre_quota_ctxt *qctxt,
- struct ptlrpc_request_set *rqset)
-{
- struct obd_device *obd = exp->exp_obd;
- unsigned int id[MAXQUOTAS] = { 0, 0 };
- int rc = 0;
- ENTRY;
-
- LASSERT(oqaq);
- LASSERT(QAQ_IS_ADJBLK(oqaq));
- rc = quota_adjust_slave_lqs(oqaq, qctxt);
- if (rc < 0) {
- CERROR("adjust mds slave's qunit size failed!(rc:%d)\n", rc);
- RETURN(rc);
- }
- if (QAQ_IS_GRP(oqaq))
- id[GRPQUOTA] = oqaq->qaq_id;
- else
- id[USRQUOTA] = oqaq->qaq_id;
-
- if (rc > 0) {
- rc = qctxt_adjust_qunit(obd, qctxt, id, 1, 0, NULL);
- if (rc == -EDQUOT || rc == -EBUSY ||
- rc == QUOTA_REQ_RETURNED || rc == -EAGAIN) {
- CDEBUG(D_QUOTA, "rc: %d.\n", rc);
- rc = 0;
- }
- if (rc)
- CERROR("slave adjust block quota failed!(rc:%d)\n", rc);
- }
- RETURN(rc);
-}
-#endif /* __KERNEL__ */
+++ /dev/null
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Whamcloud, Inc.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-#define DEBUG_SUBSYSTEM S_LQUOTA
-
-#ifdef __KERNEL__
-# include <linux/version.h>
-# include <linux/module.h>
-# include <linux/init.h>
-# include <linux/fs.h>
-# include <linux/jbd.h>
-# include <linux/ext3_fs.h>
-# include <linux/buffer_head.h>
-# include <linux/workqueue.h>
-# include <linux/mount.h>
-#else /* __KERNEL__ */
-# include <liblustre.h>
-#endif
-
-#include <obd_class.h>
-#include <lustre_mds.h>
-#include <lustre_dlm.h>
-#include <lustre_cfg.h>
-#include <obd_ost.h>
-#include <lustre_fsfilt.h>
-#include <lustre_quota.h>
-#include "quota_internal.h"
-
-#ifdef __KERNEL__
-static int target_quotacheck_callback(struct obd_export *exp,
- struct obd_quotactl *oqctl)
-{
- struct ptlrpc_request *req;
- struct obd_quotactl *body;
- int rc;
- ENTRY;
-
- req = ptlrpc_request_alloc_pack(exp->exp_imp_reverse, &RQF_QC_CALLBACK,
- LUSTRE_OBD_VERSION, OBD_QC_CALLBACK);
- if (req == NULL)
- RETURN(-ENOMEM);
-
- body = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
- *body = *oqctl;
-
- ptlrpc_request_set_replen(req);
-
- rc = ptlrpc_queue_wait(req);
- ptlrpc_req_finished(req);
-
- RETURN(rc);
-}
-
-static int target_quotacheck_thread(void *data)
-{
- struct quotacheck_thread_args *qta = data;
- struct obd_export *exp;
- struct obd_device *obd;
- struct obd_quotactl *oqctl;
- struct lvfs_run_ctxt saved;
- int rc;
-
- cfs_daemonize_ctxt("quotacheck");
-
- exp = qta->qta_exp;
- obd = qta->qta_obd;
- oqctl = &qta->qta_oqctl;
-
- push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
-
- rc = fsfilt_quotacheck(obd, qta->qta_sb, oqctl);
- if (rc)
- CERROR("%s: fsfilt_quotacheck: %d\n", obd->obd_name, rc);
-
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
-
- rc = target_quotacheck_callback(exp, oqctl);
- class_export_put(exp);
- cfs_up(qta->qta_sem);
- OBD_FREE_PTR(qta);
- return rc;
-}
-
-int target_quota_check(struct obd_device *obd, struct obd_export *exp,
- struct obd_quotactl *oqctl)
-{
- struct obd_device_target *obt = &obd->u.obt;
- struct quotacheck_thread_args *qta;
- int rc = 0;
- ENTRY;
-
- OBD_ALLOC_PTR(qta);
- if (!qta)
- RETURN(ENOMEM);
-
- cfs_down(&obt->obt_quotachecking);
-
- qta->qta_exp = exp;
- qta->qta_obd = obd;
- qta->qta_oqctl = *oqctl;
- qta->qta_oqctl.qc_id = obt->obt_qfmt; /* override qfmt version */
- qta->qta_sb = obt->obt_sb;
- qta->qta_sem = &obt->obt_quotachecking;
-
- /* quotaoff firstly */
- oqctl->qc_cmd = Q_QUOTAOFF;
- if (!strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME)) {
- rc = do_mds_quota_off(obd, oqctl);
- if (rc && rc != -EALREADY) {
- CERROR("off quota on MDS failed: %d\n", rc);
- GOTO(out, rc);
- }
-
- /* quota master */
- rc = init_admin_quotafiles(obd, &qta->qta_oqctl);
- if (rc) {
- CERROR("init_admin_quotafiles failed: %d\n", rc);
- GOTO(out, rc);
- }
- } else {
- struct lvfs_run_ctxt saved;
- struct lustre_quota_ctxt *qctxt = &obt->obt_qctxt;
-
- push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- rc = fsfilt_quotactl(obd, obt->obt_sb, oqctl);
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- if (!rc) {
- qctxt->lqc_flags &= ~UGQUOTA2LQC(oqctl->qc_type);
- } else if (!quota_is_off(qctxt, oqctl)) {
- CERROR("off quota on OSS failed: %d\n", rc);
- GOTO(out, rc);
- }
- }
-
- /* we get ref for exp because target_quotacheck_callback() will use this
- * export later b=18126 */
- class_export_get(exp);
- rc = cfs_create_thread(target_quotacheck_thread, qta,
- CFS_DAEMON_FLAGS);
- if (rc >= 0) {
- /* target_quotacheck_thread will drop the ref on exp and release
- * obt_quotachecking */
- CDEBUG(D_INFO, "%s: target_quotacheck_thread: %d\n",
- obd->obd_name, rc);
- RETURN(0);
- } else {
- CERROR("%s: error starting quotacheck_thread: %d\n",
- obd->obd_name, rc);
- class_export_put(exp);
- EXIT;
- }
-
-out:
- cfs_up(&obt->obt_quotachecking);
- OBD_FREE_PTR(qta);
- return rc;
-}
-
-#endif /* __KERNEL__ */
+++ /dev/null
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Whamcloud, Inc.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/quota/quota_context.c
- *
- * Lustre Quota Context
- *
- * Author: Niu YaWei <niu@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_LQUOTA
-
-#include <linux/version.h>
-#include <linux/fs.h>
-#include <asm/unistd.h>
-#include <linux/slab.h>
-#include <linux/quotaops.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include <obd_class.h>
-#include <lustre_quota.h>
-#include <lustre_fsfilt.h>
-#include <lprocfs_status.h>
-#include "quota_internal.h"
-
-static int hash_lqs_cur_bits = HASH_LQS_CUR_BITS;
-CFS_MODULE_PARM(hash_lqs_cur_bits, "i", int, 0444,
- "the current bits of lqs hash");
-
-static cfs_hash_ops_t lqs_hash_ops;
-
-unsigned long default_bunit_sz = 128 * 1024 * 1024; /* 128M bytes */
-unsigned long default_btune_ratio = 50; /* 50 percentage */
-unsigned long default_iunit_sz = 5120; /* 5120 inodes */
-unsigned long default_itune_ratio = 50; /* 50 percentage */
-
-cfs_mem_cache_t *qunit_cachep = NULL;
-cfs_list_t qunit_hash[NR_DQHASH];
-DEFINE_SPINLOCK(qunit_hash_lock);
-
-/* please sync qunit_state with qunit_state_names */
-enum qunit_state {
- /**
- * a qunit is created
- */
- QUNIT_CREATED = 0,
- /**
- * a qunit is added into qunit hash, that means
- * a quota req will be sent or is flying
- */
- QUNIT_IN_HASH = 1,
- /**
- * a qunit is removed from qunit hash, that
- * means a quota req is handled and comes back
- */
- QUNIT_RM_FROM_HASH = 2,
- /**
- * qunit can wake up all threads waiting for it
- */
- QUNIT_FINISHED = 3,
-};
-
-static const char *qunit_state_names[] = {
- [QUNIT_CREATED] = "CREATED",
- [QUNIT_IN_HASH] = "IN_HASH",
- [QUNIT_RM_FROM_HASH] = "RM_FROM_HASH",
- [QUNIT_FINISHED] = "FINISHED",
-};
-
-struct lustre_qunit {
- cfs_list_t lq_hash; /** Hash list in memory */
- cfs_atomic_t lq_refcnt; /** Use count */
- struct lustre_quota_ctxt *lq_ctxt; /** Quota context this applies to */
- struct qunit_data lq_data; /** See qunit_data */
- unsigned int lq_opc; /** QUOTA_DQACQ, QUOTA_DQREL */
- cfs_waitq_t lq_waitq; /** Threads waiting for this qunit */
- cfs_spinlock_t lq_lock; /** Protect the whole structure */
- enum qunit_state lq_state; /** Present the status of qunit */
- int lq_rc; /** The rc of lq_data */
- pid_t lq_owner;
-};
-
-#define QUNIT_SET_STATE(qunit, state) \
-do { \
- cfs_spin_lock(&qunit->lq_lock); \
- QDATA_DEBUG((&qunit->lq_data), "qunit(%p) lq_state(%s->%s), " \
- "lq_rc(%d), lq_owner(%d)\n", \
- qunit, qunit_state_names[qunit->lq_state], \
- qunit_state_names[state], qunit->lq_rc, \
- qunit->lq_owner); \
- qunit->lq_state = state; \
- cfs_spin_unlock(&qunit->lq_lock); \
-} while(0)
-
-#define QUNIT_SET_STATE_AND_RC(qunit, state, rc) \
-do { \
- cfs_spin_lock(&qunit->lq_lock); \
- qunit->lq_rc = rc; \
- QDATA_DEBUG((&qunit->lq_data), "qunit(%p) lq_state(%s->%s), " \
- "lq_rc(%d), lq_owner(%d)\n", \
- qunit, qunit_state_names[qunit->lq_state], \
- qunit_state_names[state], qunit->lq_rc, \
- qunit->lq_owner); \
- qunit->lq_state = state; \
- cfs_spin_unlock(&qunit->lq_lock); \
-} while(0)
-
-int should_translate_quota (struct obd_import *imp)
-{
- ENTRY;
-
- LASSERT(imp);
- if (imp->imp_connect_data.ocd_connect_flags & OBD_CONNECT_QUOTA64)
- RETURN(0);
- else
- RETURN(1);
-}
-
-void qunit_cache_cleanup(void)
-{
- int i;
- ENTRY;
-
- cfs_spin_lock(&qunit_hash_lock);
- for (i = 0; i < NR_DQHASH; i++)
- LASSERT(cfs_list_empty(qunit_hash + i));
- cfs_spin_unlock(&qunit_hash_lock);
-
- if (qunit_cachep) {
- int rc;
- rc = cfs_mem_cache_destroy(qunit_cachep);
- LASSERTF(rc == 0, "couldn't destroy qunit_cache slab\n");
- qunit_cachep = NULL;
- }
- EXIT;
-}
-
-int qunit_cache_init(void)
-{
- int i;
- ENTRY;
-
- LASSERT(qunit_cachep == NULL);
- qunit_cachep = cfs_mem_cache_create("ll_qunit_cache",
- sizeof(struct lustre_qunit),
- 0, 0);
- if (!qunit_cachep)
- RETURN(-ENOMEM);
-
- cfs_spin_lock(&qunit_hash_lock);
- for (i = 0; i < NR_DQHASH; i++)
- CFS_INIT_LIST_HEAD(qunit_hash + i);
- cfs_spin_unlock(&qunit_hash_lock);
- RETURN(0);
-}
-
-static inline int
-qunit_hashfn(struct lustre_quota_ctxt *qctxt, struct qunit_data *qdata)
- __attribute__((__const__));
-
-static inline int
-qunit_hashfn(struct lustre_quota_ctxt *qctxt, struct qunit_data *qdata)
-{
- unsigned int id = qdata->qd_id;
- unsigned int type = QDATA_IS_GRP(qdata);
-
- unsigned long tmp = ((unsigned long)qctxt >> L1_CACHE_SHIFT) ^ id;
- tmp = (tmp * (MAXQUOTAS - type)) % NR_DQHASH;
- return tmp;
-}
-
-/* caller must hold qunit_hash_lock */
-static inline struct lustre_qunit *find_qunit(unsigned int hashent,
- struct lustre_quota_ctxt *qctxt,
- struct qunit_data *qdata)
-{
- struct lustre_qunit *qunit = NULL;
- struct qunit_data *tmp;
-
- LASSERT_SPIN_LOCKED(&qunit_hash_lock);
- cfs_list_for_each_entry(qunit, qunit_hash + hashent, lq_hash) {
- tmp = &qunit->lq_data;
- if (qunit->lq_ctxt == qctxt &&
- qdata->qd_id == tmp->qd_id &&
- (qdata->qd_flags & LQUOTA_QUNIT_FLAGS) ==
- (tmp->qd_flags & LQUOTA_QUNIT_FLAGS))
- return qunit;
- }
- return NULL;
-}
-
-/* check_cur_qunit - check the current usage of qunit.
- * @qctxt: quota context
- * @qdata: the type of quota unit to be checked
- *
- * return: 1 - need acquire qunit;
- * 2 - need release qunit;
- * 0 - need do nothing.
- * < 0 - error.
- */
-static int
-check_cur_qunit(struct obd_device *obd,
- struct lustre_quota_ctxt *qctxt, struct qunit_data *qdata)
-{
- struct super_block *sb = qctxt->lqc_sb;
- unsigned long qunit_sz, tune_sz;
- __u64 usage, limit, limit_org, pending_write = 0;
- long long record = 0;
- struct obd_quotactl *qctl;
- struct lustre_qunit_size *lqs = NULL;
- int ret = 0;
- ENTRY;
-
- if (!sb_has_quota_active(sb, QDATA_IS_GRP(qdata)))
- RETURN(0);
-
- cfs_spin_lock(&qctxt->lqc_lock);
- if (!qctxt->lqc_valid){
- cfs_spin_unlock(&qctxt->lqc_lock);
- RETURN(0);
- }
- cfs_spin_unlock(&qctxt->lqc_lock);
-
- OBD_ALLOC_PTR(qctl);
- if (qctl == NULL)
- RETURN(-ENOMEM);
-
- /* get fs quota usage & limit */
- qctl->qc_cmd = Q_GETQUOTA;
- qctl->qc_id = qdata->qd_id;
- qctl->qc_type = QDATA_IS_GRP(qdata);
- ret = fsfilt_quotactl(obd, sb, qctl);
- if (ret) {
- if (ret == -ESRCH) /* no limit */
- ret = 0;
- else
- CERROR("can't get fs quota usage! (rc:%d)\n", ret);
- GOTO(out, ret);
- }
-
- if (QDATA_IS_BLK(qdata)) {
- usage = qctl->qc_dqblk.dqb_curspace;
- limit = qctl->qc_dqblk.dqb_bhardlimit << QUOTABLOCK_BITS;
- } else {
- usage = qctl->qc_dqblk.dqb_curinodes;
- limit = qctl->qc_dqblk.dqb_ihardlimit;
- }
-
- /* ignore the no quota limit case; and it can avoid creating
- * unnecessary lqs for uid/gid */
- if (!limit)
- GOTO(out, ret = 0);
-
- lqs = quota_search_lqs(LQS_KEY(QDATA_IS_GRP(qdata), qdata->qd_id),
- qctxt, 0);
- if (IS_ERR(lqs) || lqs == NULL) {
- CERROR("fail to find a lqs for %sid: %u)!\n",
- QDATA_IS_GRP(qdata) ? "g" : "u", qdata->qd_id);
- GOTO (out, ret = 0);
- }
- cfs_spin_lock(&lqs->lqs_lock);
-
- if (QDATA_IS_BLK(qdata)) {
- qunit_sz = lqs->lqs_bunit_sz;
- tune_sz = lqs->lqs_btune_sz;
- pending_write = lqs->lqs_bwrite_pending;
- record = lqs->lqs_blk_rec;
- LASSERT(!(qunit_sz % QUOTABLOCK_SIZE));
- } else {
- /* we didn't need change inode qunit size now */
- qunit_sz = lqs->lqs_iunit_sz;
- tune_sz = lqs->lqs_itune_sz;
- pending_write = lqs->lqs_iwrite_pending;
- record = lqs->lqs_ino_rec;
- }
-
- /* we don't count the MIN_QLIMIT */
- if ((limit == MIN_QLIMIT && !QDATA_IS_BLK(qdata)) ||
- (toqb(limit) == MIN_QLIMIT && QDATA_IS_BLK(qdata)))
- limit = 0;
-
- usage += pending_write;
- limit_org = limit;
- /* when a releasing quota req is sent, before it returned
- limit is assigned a small value. limit will overflow */
- if (record < 0)
- usage -= record;
- else
- limit += record;
-
- LASSERT(qdata->qd_count == 0);
- if (limit <= usage + tune_sz) {
- while (qdata->qd_count + limit <=
- usage + tune_sz)
- qdata->qd_count += qunit_sz;
- ret = 1;
- } else if (limit > usage + qunit_sz + tune_sz &&
- limit_org > qdata->qd_count + qunit_sz) {
- while (limit - qdata->qd_count > usage + qunit_sz + tune_sz &&
- limit_org > qdata->qd_count + qunit_sz)
- qdata->qd_count += qunit_sz;
- ret = 2;
- /* if there are other pending writes for this uid/gid, releasing
- * quota is put off until the last pending write b=16645 */
- /* if there is an ongoing quota request, a releasing request is aborted.
- * That ongoing quota request will call this function again when
- * it returned b=18630 */
- if (pending_write || record) {
- CDEBUG(D_QUOTA, "delay quota release\n");
- ret = 0;
- }
- }
- if (ret > 0)
- quota_compute_lqs(qdata, lqs, 1, (ret == 1) ? 1 : 0);
-
- CDEBUG(D_QUOTA, "type: %c, limit: "LPU64", usage: "LPU64
- ", pending_write: "LPU64", record: %lld"
- ", qunit_sz: %lu, tune_sz: %lu, ret: %d.\n",
- QDATA_IS_BLK(qdata) ? 'b' : 'i', limit, usage, pending_write,
- record, qunit_sz, tune_sz, ret);
- LASSERT(ret == 0 || qdata->qd_count);
-
- cfs_spin_unlock(&lqs->lqs_lock);
- lqs_putref(lqs);
-
- EXIT;
- out:
- OBD_FREE_PTR(qctl);
- return ret;
-}
-
-/**
- * Compute the remaining quota for certain gid or uid b=11693
- */
-int compute_remquota(struct obd_device *obd, struct lustre_quota_ctxt *qctxt,
- struct qunit_data *qdata, int isblk)
-{
- struct super_block *sb = qctxt->lqc_sb;
- __u64 usage, limit;
- struct obd_quotactl *qctl;
- int ret = QUOTA_RET_OK;
- ENTRY;
-
- /* ignore root user */
- if (qdata->qd_id == 0 && QDATA_IS_GRP(qdata) == USRQUOTA)
- RETURN(QUOTA_RET_NOLIMIT);
-
- OBD_ALLOC_PTR(qctl);
- if (qctl == NULL)
- RETURN(-ENOMEM);
-
- /* get fs quota usage & limit */
- qctl->qc_cmd = Q_GETQUOTA;
- qctl->qc_id = qdata->qd_id;
- qctl->qc_type = QDATA_IS_GRP(qdata);
- ret = fsfilt_quotactl(obd, sb, qctl);
- if (ret) {
- if (ret == -ESRCH) /* no limit */
- ret = QUOTA_RET_NOLIMIT;
- else
- CDEBUG(D_QUOTA, "can't get fs quota usage! (rc:%d)",
- ret);
- GOTO(out, ret);
- }
-
- usage = isblk ? qctl->qc_dqblk.dqb_curspace :
- qctl->qc_dqblk.dqb_curinodes;
- limit = isblk ? qctl->qc_dqblk.dqb_bhardlimit << QUOTABLOCK_BITS :
- qctl->qc_dqblk.dqb_ihardlimit;
- if (!limit){ /* no limit */
- ret = QUOTA_RET_NOLIMIT;
- GOTO(out, ret);
- }
-
- if (limit >= usage)
- qdata->qd_count = limit - usage;
- else
- qdata->qd_count = 0;
- EXIT;
-out:
- OBD_FREE_PTR(qctl);
- return ret;
-}
-
-static struct lustre_qunit *alloc_qunit(struct lustre_quota_ctxt *qctxt,
- struct qunit_data *qdata, int opc)
-{
- struct lustre_qunit *qunit = NULL;
- ENTRY;
-
- OBD_SLAB_ALLOC_PTR_GFP(qunit, qunit_cachep, CFS_ALLOC_IO);
- if (qunit == NULL)
- RETURN(NULL);
-
- CFS_INIT_LIST_HEAD(&qunit->lq_hash);
- cfs_waitq_init(&qunit->lq_waitq);
- cfs_atomic_set(&qunit->lq_refcnt, 1);
- qunit->lq_ctxt = qctxt;
- memcpy(&qunit->lq_data, qdata, sizeof(*qdata));
- qunit->lq_opc = opc;
- cfs_spin_lock_init(&qunit->lq_lock);
- QUNIT_SET_STATE_AND_RC(qunit, QUNIT_CREATED, 0);
- qunit->lq_owner = cfs_curproc_pid();
- RETURN(qunit);
-}
-
-static inline void free_qunit(struct lustre_qunit *qunit)
-{
- OBD_SLAB_FREE(qunit, qunit_cachep, sizeof(*qunit));
-}
-
-static inline void qunit_get(struct lustre_qunit *qunit)
-{
- cfs_atomic_inc(&qunit->lq_refcnt);
-}
-
-static void qunit_put(struct lustre_qunit *qunit)
-{
- LASSERT(cfs_atomic_read(&qunit->lq_refcnt));
- if (cfs_atomic_dec_and_test(&qunit->lq_refcnt))
- free_qunit(qunit);
-}
-
-/* caller must hold qunit_hash_lock and release ref of qunit after using it */
-static struct lustre_qunit *dqacq_in_flight(struct lustre_quota_ctxt *qctxt,
- struct qunit_data *qdata)
-{
- unsigned int hashent = qunit_hashfn(qctxt, qdata);
- struct lustre_qunit *qunit;
- ENTRY;
-
- LASSERT_SPIN_LOCKED(&qunit_hash_lock);
- qunit = find_qunit(hashent, qctxt, qdata);
- if (qunit)
- qunit_get(qunit);
- RETURN(qunit);
-}
-
-static void
-insert_qunit_nolock(struct lustre_quota_ctxt *qctxt, struct lustre_qunit *qunit)
-{
- cfs_list_t *head;
-
- LASSERT(cfs_list_empty(&qunit->lq_hash));
- qunit_get(qunit);
- head = qunit_hash + qunit_hashfn(qctxt, &qunit->lq_data);
- cfs_list_add(&qunit->lq_hash, head);
- QUNIT_SET_STATE(qunit, QUNIT_IN_HASH);
-}
-
-static void compute_lqs_after_removing_qunit(struct lustre_qunit *qunit)
-{
- struct lustre_qunit_size *lqs;
-
- lqs = quota_search_lqs(LQS_KEY(QDATA_IS_GRP(&qunit->lq_data),
- qunit->lq_data.qd_id),
- qunit->lq_ctxt, 0);
- if (lqs && !IS_ERR(lqs)) {
- cfs_spin_lock(&lqs->lqs_lock);
- if (qunit->lq_opc == QUOTA_DQACQ)
- quota_compute_lqs(&qunit->lq_data, lqs, 0, 1);
- if (qunit->lq_opc == QUOTA_DQREL)
- quota_compute_lqs(&qunit->lq_data, lqs, 0, 0);
- cfs_spin_unlock(&lqs->lqs_lock);
- /* this is for quota_search_lqs */
- lqs_putref(lqs);
- /* this is for schedule_dqacq */
- lqs_putref(lqs);
- }
-}
-
-static void remove_qunit_nolock(struct lustre_qunit *qunit)
-{
- LASSERT(!cfs_list_empty(&qunit->lq_hash));
- LASSERT_SPIN_LOCKED(&qunit_hash_lock);
-
- cfs_list_del_init(&qunit->lq_hash);
- QUNIT_SET_STATE(qunit, QUNIT_RM_FROM_HASH);
- qunit_put(qunit);
-}
-
-void* quota_barrier(struct lustre_quota_ctxt *qctxt,
- struct obd_quotactl *oqctl, int isblk)
-{
- struct lustre_qunit *qunit, *find_qunit;
- int cycle = 1;
-
- OBD_SLAB_ALLOC_PTR(qunit, qunit_cachep);
- if (qunit == NULL) {
- CERROR("locating %sunit failed for %sid %u\n",
- isblk ? "b" : "i", oqctl->qc_type ? "g" : "u",
- oqctl->qc_id);
- qctxt_wait_pending_dqacq(qctxt, oqctl->qc_id,
- oqctl->qc_type, isblk);
- return NULL;
- }
-
- CFS_INIT_LIST_HEAD(&qunit->lq_hash);
- cfs_spin_lock_init(&qunit->lq_lock);
- cfs_waitq_init(&qunit->lq_waitq);
- cfs_atomic_set(&qunit->lq_refcnt, 1);
- qunit->lq_ctxt = qctxt;
- qunit->lq_data.qd_id = oqctl->qc_id;
- qunit->lq_data.qd_flags = oqctl->qc_type;
- if (isblk)
- QDATA_SET_BLK(&qunit->lq_data);
- QUNIT_SET_STATE_AND_RC(qunit, QUNIT_CREATED, 0);
- /* it means it is only an invalid qunit for barrier */
- qunit->lq_opc = QUOTA_LAST_OPC;
-
- while (1) {
- cfs_spin_lock(&qunit_hash_lock);
- find_qunit = dqacq_in_flight(qctxt, &qunit->lq_data);
- if (find_qunit) {
- cfs_spin_unlock(&qunit_hash_lock);
- qunit_put(find_qunit);
- qctxt_wait_pending_dqacq(qctxt, oqctl->qc_id,
- oqctl->qc_type, isblk);
- CDEBUG(D_QUOTA, "cycle=%d\n", cycle++);
- continue;
- }
- break;
- }
- insert_qunit_nolock(qctxt, qunit);
- cfs_spin_unlock(&qunit_hash_lock);
- return qunit;
-}
-
-void quota_unbarrier(void *handle)
-{
- struct lustre_qunit *qunit = (struct lustre_qunit *)handle;
-
- if (qunit == NULL) {
- CERROR("handle is NULL\n");
- return;
- }
-
- LASSERT(qunit->lq_opc == QUOTA_LAST_OPC);
- cfs_spin_lock(&qunit_hash_lock);
- remove_qunit_nolock(qunit);
- cfs_spin_unlock(&qunit_hash_lock);
- QUNIT_SET_STATE_AND_RC(qunit, QUNIT_FINISHED, QUOTA_REQ_RETURNED);
- cfs_waitq_signal(&qunit->lq_waitq);
- qunit_put(qunit);
-}
-
-#define INC_QLIMIT(limit, count) (limit == MIN_QLIMIT) ? \
- (limit = count) : (limit += count)
-
-
-static inline int is_master(struct lustre_quota_ctxt *qctxt)
-{
- return qctxt->lqc_handler ? 1 : 0;
-}
-
-static int
-schedule_dqacq(struct obd_device *obd, struct lustre_quota_ctxt *qctxt,
- struct qunit_data *qdata, int opc, int wait,
- struct obd_trans_info *oti);
-
-static inline void qdata_to_oqaq(struct qunit_data *qdata,
- struct quota_adjust_qunit *oqaq)
-{
- LASSERT(qdata);
- LASSERT(oqaq);
-
- oqaq->qaq_flags = qdata->qd_flags;
- oqaq->qaq_id = qdata->qd_id;
- if (QDATA_IS_ADJBLK(qdata))
- oqaq->qaq_bunit_sz = qdata->qd_qunit;
- if (QDATA_IS_ADJINO(qdata))
- oqaq->qaq_iunit_sz = qdata->qd_qunit;
-}
-
-static int
-dqacq_completion(struct obd_device *obd, struct lustre_quota_ctxt *qctxt,
- struct qunit_data *qdata, int rc, int opc)
-{
- struct lustre_qunit *qunit = NULL;
- struct super_block *sb = qctxt->lqc_sb;
- int err = 0;
- struct quota_adjust_qunit *oqaq = NULL;
- int rc1 = 0;
- ENTRY;
-
- LASSERT(qdata);
- QDATA_DEBUG(qdata, "obd(%s): complete %s quota req\n",
- obd->obd_name, (opc == QUOTA_DQACQ) ? "acq" : "rel");
-
- /* do it only when a releasing quota req more than 5MB b=18491 */
- if (opc == QUOTA_DQREL && qdata->qd_count >= 5242880)
- OBD_FAIL_TIMEOUT(OBD_FAIL_QUOTA_DELAY_REL, 5);
-
- /* update local operational quota file */
- if (rc == 0) {
- __u64 count = QUSG(qdata->qd_count, QDATA_IS_BLK(qdata));
- struct obd_quotactl *qctl;
- __u64 *hardlimit;
-
- OBD_ALLOC_PTR(qctl);
- if (qctl == NULL)
- GOTO(out, err = -ENOMEM);
-
- /* acq/rel qunit for specified uid/gid is serialized,
- * so there is no race between get fs quota limit and
- * set fs quota limit */
- qctl->qc_cmd = Q_GETQUOTA;
- qctl->qc_id = qdata->qd_id;
- qctl->qc_type = QDATA_IS_GRP(qdata);
- err = fsfilt_quotactl(obd, sb, qctl);
- if (err) {
- CERROR("error get quota fs limit! (rc:%d)\n", err);
- GOTO(out_mem, err);
- }
-
- if (QDATA_IS_BLK(qdata)) {
- qctl->qc_dqblk.dqb_valid = QIF_BLIMITS;
- hardlimit = &qctl->qc_dqblk.dqb_bhardlimit;
- } else {
- qctl->qc_dqblk.dqb_valid = QIF_ILIMITS;
- hardlimit = &qctl->qc_dqblk.dqb_ihardlimit;
- }
-
- CDEBUG(D_QUOTA, "hardlimt: "LPU64"\n", *hardlimit);
-
- if (*hardlimit == 0)
- goto out_mem;
-
- switch (opc) {
- case QUOTA_DQACQ:
- INC_QLIMIT(*hardlimit, count);
- break;
- case QUOTA_DQREL:
- LASSERTF(count < *hardlimit,
- "id(%u) flag(%u) type(%c) isblk(%c) "
- "count("LPU64") qd_qunit("LPU64") "
- "hardlimit("LPU64").\n",
- qdata->qd_id, qdata->qd_flags,
- QDATA_IS_GRP(qdata) ? 'g' : 'u',
- QDATA_IS_BLK(qdata) ? 'b': 'i',
- qdata->qd_count, qdata->qd_qunit, *hardlimit);
- *hardlimit -= count;
- break;
- default:
- LBUG();
- }
-
- /* clear quota limit */
- if (count == 0)
- *hardlimit = 0;
-
- qctl->qc_cmd = Q_SETQUOTA;
- err = fsfilt_quotactl(obd, sb, qctl);
- if (err)
- CERROR("error set quota fs limit! (rc:%d)\n", err);
-
- QDATA_DEBUG(qdata, "%s completion\n",
- opc == QUOTA_DQACQ ? "DQACQ" : "DQREL");
-out_mem:
- OBD_FREE_PTR(qctl);
- } else if (rc == -EDQUOT) {
- QDATA_DEBUG(qdata, "acquire qunit got EDQUOT.\n");
- } else if (rc == -EBUSY) {
- QDATA_DEBUG(qdata, "it's is recovering, got EBUSY.\n");
- } else {
- CERROR("acquire qunit got error! (rc:%d)\n", rc);
- }
-out:
- /* remove the qunit from hash */
- cfs_spin_lock(&qunit_hash_lock);
-
- qunit = dqacq_in_flight(qctxt, qdata);
- /* this qunit has been removed by qctxt_cleanup() */
- if (!qunit) {
- cfs_spin_unlock(&qunit_hash_lock);
- QDATA_DEBUG(qdata, "%s is discarded because qunit isn't found\n",
- opc == QUOTA_DQACQ ? "DQACQ" : "DQREL");
- RETURN(err);
- }
-
- LASSERT(opc == qunit->lq_opc);
- /* remove this qunit from lq_hash so that new processes cannot be added
- * to qunit->lq_waiters */
- remove_qunit_nolock(qunit);
- cfs_spin_unlock(&qunit_hash_lock);
-
- compute_lqs_after_removing_qunit(qunit);
-
- if (rc == 0)
- rc = QUOTA_REQ_RETURNED;
- QUNIT_SET_STATE_AND_RC(qunit, QUNIT_FINISHED, rc);
- /* wake up all waiters */
- cfs_waitq_broadcast(&qunit->lq_waitq);
-
- /* this is for dqacq_in_flight() */
- qunit_put(qunit);
- if (rc < 0 && rc != -EDQUOT)
- GOTO(out1, err);
-
- /* don't reschedule in such cases:
- * - acq/rel failure and qunit isn't changed,
- * but not for quota recovery.
- * - local dqacq/dqrel.
- * - local disk io failure.
- */
- OBD_ALLOC_PTR(oqaq);
- if (!oqaq)
- GOTO(out1, err = -ENOMEM);
- qdata_to_oqaq(qdata, oqaq);
- /* adjust the qunit size in slaves */
- rc1 = quota_adjust_slave_lqs(oqaq, qctxt);
- OBD_FREE_PTR(oqaq);
- if (rc1 < 0) {
- CERROR("adjust slave's qunit size failed!(rc:%d)\n", rc1);
- GOTO(out1, err = rc1);
- }
- if (err || (rc < 0 && rc != -EBUSY && rc1 == 0) || is_master(qctxt))
- GOTO(out1, err);
-
- if (opc == QUOTA_DQREL && qdata->qd_count >= 5242880 &&
- OBD_FAIL_CHECK(OBD_FAIL_QUOTA_DELAY_REL))
- GOTO(out1, err);
-
- /* reschedule another dqacq/dqrel if needed */
- qdata->qd_count = 0;
- qdata->qd_flags &= LQUOTA_QUNIT_FLAGS;
- rc1 = check_cur_qunit(obd, qctxt, qdata);
- if (rc1 > 0) {
- int opc;
- opc = rc1 == 1 ? QUOTA_DQACQ : QUOTA_DQREL;
- rc1 = schedule_dqacq(obd, qctxt, qdata, opc, 0, NULL);
- QDATA_DEBUG(qdata, "reschedudle opc(%d) rc(%d)\n", opc, rc1);
- }
- out1:
- /* this is for alloc_qunit() */
- qunit_put(qunit);
- RETURN(err);
-}
-
-struct dqacq_async_args {
- struct lustre_quota_ctxt *aa_ctxt;
- struct lustre_qunit *aa_qunit;
-};
-
-static int dqacq_interpret(const struct lu_env *env,
- struct ptlrpc_request *req, void *data, int rc)
-{
- struct dqacq_async_args *aa = (struct dqacq_async_args *)data;
- struct lustre_quota_ctxt *qctxt = aa->aa_ctxt;
- struct obd_device_target *obt = qctxt->lqc_obt;
- struct lustre_qunit *qunit = aa->aa_qunit;
- struct obd_device *obd = req->rq_import->imp_obd;
- struct qunit_data *qdata = NULL;
- ENTRY;
-
- LASSERT(req);
- LASSERT(req->rq_import);
-
- cfs_down_read(&obt->obt_rwsem);
- /* if a quota req timeouts or is dropped, we should update quota
- * statistics which will be handled in dqacq_completion. And in
- * this situation we should get qdata from request instead of
- * reply */
- qdata = quota_get_qdata(req, (rc != 0) ? QUOTA_REQUEST : QUOTA_REPLY,
- QUOTA_IMPORT);
- if (IS_ERR(qdata)) {
- rc = PTR_ERR(qdata);
- DEBUG_REQ(D_ERROR, req,
- "error unpacking qunit_data(rc: %ld)\n",
- PTR_ERR(qdata));
- qdata = &qunit->lq_data;
- }
-
- QDATA_DEBUG(qdata, "qdata: interpret rc(%d).\n", rc);
- QDATA_DEBUG((&qunit->lq_data), "lq_data: \n");
-
- if (qdata->qd_id != qunit->lq_data.qd_id ||
- OBD_FAIL_CHECK(OBD_FAIL_QUOTA_RET_QDATA)) {
- CERROR("the returned qd_id isn't expected!"
- "(qdata: %u, lq_data: %u)\n", qdata->qd_id,
- qunit->lq_data.qd_id);
- qdata->qd_id = qunit->lq_data.qd_id;
- rc = -EPROTO;
- }
- if (QDATA_IS_GRP(qdata) != QDATA_IS_GRP(&qunit->lq_data)) {
- CERROR("the returned grp/usr isn't expected!"
- "(qdata: %u, lq_data: %u)\n", qdata->qd_flags,
- qunit->lq_data.qd_flags);
- if (QDATA_IS_GRP(&qunit->lq_data))
- QDATA_SET_GRP(qdata);
- else
- QDATA_CLR_GRP(qdata);
- rc = -EPROTO;
- }
- if (qdata->qd_count > qunit->lq_data.qd_count) {
- CERROR("the returned qd_count isn't expected!"
- "(qdata: "LPU64", lq_data: "LPU64")\n", qdata->qd_count,
- qunit->lq_data.qd_count);
- rc = -EPROTO;
- }
-
- if (unlikely(rc == -ESRCH))
- CERROR("quota for %s has been enabled by master, but disabled "
- "by slave.\n", QDATA_IS_GRP(qdata) ? "group" : "user");
-
- rc = dqacq_completion(obd, qctxt, qdata, rc,
- lustre_msg_get_opc(req->rq_reqmsg));
-
- cfs_up_read(&obt->obt_rwsem);
- RETURN(rc);
-}
-
-/**
- * check if quota master is online
- */
-int check_qm(struct lustre_quota_ctxt *qctxt)
-{
- int rc;
- ENTRY;
-
- cfs_spin_lock(&qctxt->lqc_lock);
- /* quit waiting when mds is back or qctxt is cleaned up */
- rc = qctxt->lqc_import || !qctxt->lqc_valid;
- cfs_spin_unlock(&qctxt->lqc_lock);
-
- RETURN(rc);
-}
-
-/* wake up all waiting threads when lqc_import is NULL */
-void dqacq_interrupt(struct lustre_quota_ctxt *qctxt)
-{
- struct lustre_qunit *qunit, *tmp;
- int i;
- ENTRY;
-
- cfs_spin_lock(&qunit_hash_lock);
- for (i = 0; i < NR_DQHASH; i++) {
- cfs_list_for_each_entry_safe(qunit, tmp, &qunit_hash[i],
- lq_hash) {
- if (qunit->lq_ctxt != qctxt)
- continue;
-
- /* Wake up all waiters. Do not change lq_state.
- * The waiters will check lq_rc which is kept as 0
- * if no others change it, then the waiters will return
- * -EAGAIN to caller who can perform related quota
- * acq/rel if necessary. */
- cfs_waitq_broadcast(&qunit->lq_waitq);
- }
- }
- cfs_spin_unlock(&qunit_hash_lock);
- EXIT;
-}
-
-static int got_qunit(struct lustre_qunit *qunit, int is_master)
-{
- struct lustre_quota_ctxt *qctxt = qunit->lq_ctxt;
- int rc = 0;
- ENTRY;
-
- cfs_spin_lock(&qunit->lq_lock);
- switch (qunit->lq_state) {
- case QUNIT_IN_HASH:
- case QUNIT_RM_FROM_HASH:
- break;
- case QUNIT_FINISHED:
- rc = 1;
- break;
- default:
- CERROR("invalid qunit state %d\n", qunit->lq_state);
- }
- cfs_spin_unlock(&qunit->lq_lock);
-
- if (!rc) {
- cfs_spin_lock(&qctxt->lqc_lock);
- rc = !qctxt->lqc_valid;
- if (!is_master)
- rc |= !qctxt->lqc_import;
- cfs_spin_unlock(&qctxt->lqc_lock);
- }
-
- RETURN(rc);
-}
-
-static inline void
-revoke_lqs_rec(struct lustre_qunit_size *lqs, struct qunit_data *qdata, int opc)
-{
- /* revoke lqs_xxx_rec which is computed in check_cur_qunit
- * b=18630 */
- cfs_spin_lock(&lqs->lqs_lock);
- quota_compute_lqs(qdata, lqs, 0, (opc == QUOTA_DQACQ) ? 1 : 0);
- cfs_spin_unlock(&lqs->lqs_lock);
-}
-
-static int verify_cur_qunit(struct obd_device *obd,
- struct lustre_quota_ctxt *qctxt,
- struct qunit_data *qdata, int opc)
-{
- struct obd_quotactl *qctl;
- __u64 limit;
- int ret = 0;
- ENTRY;
-
- /* extra quota acquire can be tolerated. */
- if (opc == QUOTA_DQACQ)
- RETURN(ret);
-
- OBD_ALLOC_PTR(qctl);
- if (qctl == NULL) {
- CERROR("Fail to allocate mem!\n");
- RETURN(-ENOMEM);
- }
-
- qctl->qc_cmd = Q_GETQUOTA;
- qctl->qc_id = qdata->qd_id;
- qctl->qc_type = QDATA_IS_GRP(qdata);
- ret = fsfilt_quotactl(obd, qctxt->lqc_sb, qctl);
- if (ret) {
- /* -ESRCH means no limit */
- CDEBUG(ret == -ESRCH ? D_QUOTA : D_ERROR,
- "Can't get quota usage! rc:%d\n", ret);
- GOTO(out, ret);
- }
-
- if (QDATA_IS_BLK(qdata))
- limit = qctl->qc_dqblk.dqb_bhardlimit << QUOTABLOCK_BITS;
- else
- limit = qctl->qc_dqblk.dqb_ihardlimit;
-
- if (limit <= qdata->qd_count) {
- CDEBUG(D_QUOTA, "drop extra release. id(%u), flag(%u), "
- "type(%c), isblk(%c), count("LPU64"), "
- "qd_qunit("LPU64"), hardlimit("LPU64").\n",
- qdata->qd_id, qdata->qd_flags,
- QDATA_IS_GRP(qdata) ? 'g' : 'u',
- QDATA_IS_BLK(qdata) ? 'b' : 'i',
- qdata->qd_count, qdata->qd_qunit, limit);
- ret = -EAGAIN;
- }
-out:
- OBD_FREE_PTR(qctl);
- RETURN(ret);
-}
-
-static int
-schedule_dqacq(struct obd_device *obd, struct lustre_quota_ctxt *qctxt,
- struct qunit_data *qdata, int opc, int wait,
- struct obd_trans_info *oti)
-{
- struct lustre_qunit *qunit, *empty;
- struct l_wait_info lwi = { 0 };
- struct ptlrpc_request *req;
- struct dqacq_async_args *aa;
- struct obd_import *imp = NULL;
- struct lustre_qunit_size *lqs = NULL;
- struct timeval work_start;
- struct timeval work_end;
- long timediff;
- int rc = 0;
- ENTRY;
-
- LASSERT(opc == QUOTA_DQACQ || opc == QUOTA_DQREL);
- cfs_gettimeofday(&work_start);
-
- lqs = quota_search_lqs(LQS_KEY(QDATA_IS_GRP(qdata), qdata->qd_id),
- qctxt, 0);
- if (lqs == NULL || IS_ERR(lqs)) {
- CERROR("Can't find the lustre qunit size!\n");
- RETURN(-EPERM);
- }
-
- if ((empty = alloc_qunit(qctxt, qdata, opc)) == NULL) {
- revoke_lqs_rec(lqs, qdata, opc);
- /* this is for quota_search_lqs */
- lqs_putref(lqs);
- RETURN(-ENOMEM);
- }
-
- OBD_FAIL_TIMEOUT(OBD_FAIL_QUOTA_DELAY_SD, 5);
-
- cfs_spin_lock(&qunit_hash_lock);
- qunit = dqacq_in_flight(qctxt, qdata);
- if (qunit) {
- cfs_spin_unlock(&qunit_hash_lock);
- qunit_put(empty);
-
- revoke_lqs_rec(lqs, qdata, opc);
- /* this is for quota_search_lqs */
- lqs_putref(lqs);
- goto wait_completion;
- }
- qunit = empty;
- qunit_get(qunit);
- insert_qunit_nolock(qctxt, qunit);
- cfs_spin_unlock(&qunit_hash_lock);
-
- /* From here, the quota request will be sent anyway.
- * When this qdata request returned or is cancelled,
- * lqs_putref will be called at that time */
- lqs_getref(lqs);
- /* this is for quota_search_lqs */
- lqs_putref(lqs);
-
- /* LU-1493
- *
- * There is a race between the check_cur_qunit() and the
- * dqacq_completion(): check_cur_qunit() read hardlimit
- * and calculate how much quota need be acquired/released
- * based on the hardlimit, however, the hardlimit can be
- * changed by the dqacq_completion() at anytime. So that
- * could result in extra quota acquire/release when there
- * is inflight dqacq.
- *
- * In general, such extra dqacq dosen't bring fatal error,
- * unless an extra release is going to release more than
- * 'hardlimit' quota.
- *
- * To minimize the code changes (anyway, it'll be totally
- * rewritten in the new quota design), we just do one more
- * check here to avoid the extra release which could bring
- * fatal error. A better solution could be calculating the
- * qd_count here and removing the lqs_blk/ino_rec stuff.
- */
- rc = verify_cur_qunit(obd, qctxt, qdata, opc);
- if (rc) {
- cfs_spin_lock(&qunit_hash_lock);
- remove_qunit_nolock(qunit);
- cfs_spin_unlock(&qunit_hash_lock);
-
- compute_lqs_after_removing_qunit(qunit);
- /* this is for qunit_get() */
- qunit_put(qunit);
- /* this for alloc_qunit() */
- qunit_put(qunit);
- /* drop this extra release silently */
- RETURN(0);
- }
-
- QDATA_DEBUG(qdata, "obd(%s): send %s quota req\n",
- obd->obd_name, (opc == QUOTA_DQACQ) ? "acq" : "rel");
- /* master is going to dqacq/dqrel from itself */
- if (is_master(qctxt)) {
- int rc2;
- QDATA_DEBUG(qdata, "local %s.\n",
- opc == QUOTA_DQACQ ? "DQACQ" : "DQREL");
- QDATA_SET_CHANGE_QS(qdata);
- rc = qctxt->lqc_handler(obd, qdata, opc);
- rc2 = dqacq_completion(obd, qctxt, qdata, rc, opc);
- /* this is for qunit_get() */
- qunit_put(qunit);
-
- cfs_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 ? rc : rc2);
- }
-
- cfs_spin_lock(&qctxt->lqc_lock);
- if (!qctxt->lqc_import) {
- cfs_spin_unlock(&qctxt->lqc_lock);
- QDATA_DEBUG(qdata, "lqc_import is invalid.\n");
-
- cfs_spin_lock(&qunit_hash_lock);
- remove_qunit_nolock(qunit);
- cfs_spin_unlock(&qunit_hash_lock);
-
- compute_lqs_after_removing_qunit(qunit);
-
- QUNIT_SET_STATE_AND_RC(qunit, QUNIT_FINISHED, -EAGAIN);
- cfs_waitq_broadcast(&qunit->lq_waitq);
-
- /* this is for qunit_get() */
- qunit_put(qunit);
- /* this for alloc_qunit() */
- qunit_put(qunit);
- cfs_spin_lock(&qctxt->lqc_lock);
- if (wait && !qctxt->lqc_import) {
- cfs_spin_unlock(&qctxt->lqc_lock);
- LASSERT(oti && oti->oti_thread);
- /* The recovery thread doesn't have watchdog
- * attached. LU-369 */
- if (oti->oti_thread->t_watchdog)
- lc_watchdog_disable(oti->oti_thread->\
- t_watchdog);
- CDEBUG(D_QUOTA, "sleep for quota master\n");
- l_wait_event(qctxt->lqc_wait_for_qmaster,
- check_qm(qctxt), &lwi);
- CDEBUG(D_QUOTA, "wake up when quota master is back\n");
- if (oti->oti_thread->t_watchdog)
- lc_watchdog_touch(oti->oti_thread->t_watchdog,
- ptlrpc_server_get_timeout(\
- oti->oti_thread->t_svcpt));
- } else {
- cfs_spin_unlock(&qctxt->lqc_lock);
- }
-
- RETURN(-EAGAIN);
- }
- imp = class_import_get(qctxt->lqc_import);
- cfs_spin_unlock(&qctxt->lqc_lock);
-
- /* build dqacq/dqrel request */
- LASSERT(imp);
-
- req = ptlrpc_request_alloc_pack(imp, &RQF_MDS_QUOTA_DQACQ,
- LUSTRE_MDS_VERSION, opc);
- class_import_put(imp);
- if (req == NULL) {
- CERROR("Can't alloc request\n");
- dqacq_completion(obd, qctxt, qdata, -ENOMEM, opc);
- /* this is for qunit_get() */
- qunit_put(qunit);
- RETURN(-ENOMEM);
- }
-
- ptlrpc_request_set_replen(req);
- req->rq_no_resend = req->rq_no_delay = 1;
- rc = quota_copy_qdata(req, qdata, QUOTA_REQUEST, QUOTA_IMPORT);
- if (rc < 0) {
- CERROR("Can't pack qunit_data(rc: %d)\n", rc);
- ptlrpc_req_finished(req);
- dqacq_completion(obd, qctxt, qdata, -EPROTO, opc);
- /* this is for qunit_get() */
- qunit_put(qunit);
- RETURN(rc);
- }
-
- CLASSERT(sizeof(*aa) <= sizeof(req->rq_async_args));
- aa = ptlrpc_req_async_args(req);
- aa->aa_ctxt = qctxt;
- aa->aa_qunit = qunit;
-
- req->rq_interpret_reply = dqacq_interpret;
- ptlrpcd_add_req(req, PDL_POLICY_LOCAL, -1);
-
- QDATA_DEBUG(qdata, "%s scheduled.\n",
- opc == QUOTA_DQACQ ? "DQACQ" : "DQREL");
-wait_completion:
- if (wait && qunit) {
- struct qunit_data *p = &qunit->lq_data;
-
- QDATA_DEBUG(p, "qunit(%p) is waiting for dqacq.\n", qunit);
- l_wait_event(qunit->lq_waitq, got_qunit(qunit, is_master(qctxt)),
- &lwi);
- /* rc = -EAGAIN, it means the quota master isn't ready yet
- * rc = QUOTA_REQ_RETURNED, it means a quota req is finished;
- * rc = -EDQUOT, it means out of quota
- * rc = -EBUSY, it means recovery is happening
- * other rc < 0, it means real errors, functions who call
- * schedule_dqacq should take care of this */
- cfs_spin_lock(&qunit->lq_lock);
- rc = qunit->lq_rc;
- cfs_spin_unlock(&qunit->lq_lock);
- CDEBUG(D_QUOTA, "qunit(%p) finishes waiting: id(%u) flag(%u) "
- "rc(%d) owner(%d)\n", qunit, qunit->lq_data.qd_id,
- qunit->lq_data.qd_flags, rc, qunit->lq_owner);
- }
-
- qunit_put(qunit);
- cfs_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);
-}
-
-int
-qctxt_adjust_qunit(struct obd_device *obd, struct lustre_quota_ctxt *qctxt,
- const unsigned int id[], __u32 isblk, int wait,
- struct obd_trans_info *oti)
-{
- int rc = 0, i = USRQUOTA;
- struct qunit_data qdata[MAXQUOTAS];
- ENTRY;
-
- /* XXX In quota_chk_acq_common(), we do something like:
- *
- * while (quota_check_common() & QUOTA_RET_ACQUOTA) {
- * rc = qctxt_adjust_qunit();
- * }
- *
- * to make sure the slave acquired enough quota from master.
- *
- * Unfortunately, qctxt_adjust_qunit() checks QB/QI_SET to
- * decide if do real DQACQ or not, but quota_check_common()
- * doesn't check QB/QI_SET flags. This inconsistence could
- * lead into an infinite loop.
- *
- * We can't fix it by simply adding QB/QI_SET checking in the
- * quota_check_common(), since we must guarantee that the
- * paried quota_pending_commit() has same QB/QI_SET, but the
- * flags can be actually cleared at any time...
- *
- * A quick non-intrusive solution is to just skip the
- * QB/QI_SET checking here when the @wait is non-zero.
- * (If the @wait is non-zero, the caller must have already
- * checked the QB/QI_SET).
- */
- if (!wait && quota_is_set(obd, id, isblk ? QB_SET : QI_SET) == 0)
- RETURN(0);
-
- for (i = 0; i < MAXQUOTAS; i++) {
- qdata[i].qd_id = id[i];
- qdata[i].qd_flags = i;
- if (isblk)
- QDATA_SET_BLK(&qdata[i]);
- qdata[i].qd_count = 0;
-
- rc = check_cur_qunit(obd, qctxt, &qdata[i]);
- if (rc > 0) {
- int opc;
- /* need acquire or release */
- opc = rc == 1 ? QUOTA_DQACQ : QUOTA_DQREL;
- rc = schedule_dqacq(obd, qctxt, &qdata[i], opc,
- wait,oti);
- if (rc < 0)
- RETURN(rc);
- } else if (wait == 1) {
- /* when wait equates 1, that means mds_quota_acquire
- * or filter_quota_acquire is calling it. */
- rc = qctxt_wait_pending_dqacq(qctxt, id[i], i, isblk);
- if (rc < 0)
- RETURN(rc);
- }
- }
-
- RETURN(rc);
-}
-
-int
-qctxt_wait_pending_dqacq(struct lustre_quota_ctxt *qctxt, unsigned int id,
- unsigned short type, int isblk)
-{
- 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 };
- int rc = 0;
- ENTRY;
-
- cfs_gettimeofday(&work_start);
- qdata.qd_id = id;
- qdata.qd_flags = type;
- if (isblk)
- QDATA_SET_BLK(&qdata);
- qdata.qd_count = 0;
-
- cfs_spin_lock(&qunit_hash_lock);
- qunit = dqacq_in_flight(qctxt, &qdata);
- cfs_spin_unlock(&qunit_hash_lock);
-
- if (qunit) {
- struct qunit_data *p = &qunit->lq_data;
-
- QDATA_DEBUG(p, "qunit(%p) is waiting for dqacq.\n", qunit);
- l_wait_event(qunit->lq_waitq, got_qunit(qunit, is_master(qctxt)),
- &lwi);
- CDEBUG(D_QUOTA, "qunit(%p) finishes waiting: rc(%d) "
- "owner(%d)\n", qunit, qunit->lq_rc, qunit->lq_owner);
- /* keep same as schedule_dqacq() b=17030 */
- cfs_spin_lock(&qunit->lq_lock);
- rc = qunit->lq_rc;
- cfs_spin_unlock(&qunit->lq_lock);
- /* this is for dqacq_in_flight() */
- qunit_put(qunit);
- cfs_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 {
- cfs_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(rc);
-}
-
-int
-qctxt_init(struct obd_device *obd, dqacq_handler_t handler)
-{
- struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
- struct obd_device_target *obt = &obd->u.obt;
- struct super_block *sb = obt->obt_sb;
- int rc = 0;
- ENTRY;
-
- LASSERT(qctxt);
-
- rc = ptlrpcd_addref();
- if (rc)
- RETURN(rc);
-
- cfs_waitq_init(&qctxt->lqc_wait_for_qmaster);
- cfs_waitq_init(&qctxt->lqc_lqs_waitq);
- cfs_atomic_set(&qctxt->lqc_lqs, 0);
- cfs_spin_lock_init(&qctxt->lqc_lock);
- cfs_spin_lock(&qctxt->lqc_lock);
- qctxt->lqc_handler = handler;
- qctxt->lqc_sb = sb;
- qctxt->lqc_obt = obt;
- qctxt->lqc_import = NULL;
- qctxt->lqc_recovery = 0;
- qctxt->lqc_switch_qs = 1; /* Change qunit size in default setting */
- qctxt->lqc_valid = 1;
- qctxt->lqc_cqs_boundary_factor = 4;
- qctxt->lqc_cqs_least_bunit = PTLRPC_MAX_BRW_SIZE;
- qctxt->lqc_cqs_least_iunit = 2;
- qctxt->lqc_cqs_qs_factor = 2;
- qctxt->lqc_flags = 0;
- QUOTA_MASTER_UNREADY(qctxt);
- qctxt->lqc_bunit_sz = default_bunit_sz;
- qctxt->lqc_btune_sz = default_bunit_sz / 100 * default_btune_ratio;
- qctxt->lqc_iunit_sz = default_iunit_sz;
- 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;
- cfs_spin_unlock(&qctxt->lqc_lock);
-
- qctxt->lqc_lqs_hash = cfs_hash_create("LQS_HASH",
- hash_lqs_cur_bits,
- HASH_LQS_MAX_BITS,
- min(hash_lqs_cur_bits,
- HASH_LQS_BKT_BITS),
- 0, CFS_HASH_MIN_THETA,
- CFS_HASH_MAX_THETA,
- &lqs_hash_ops, CFS_HASH_DEFAULT);
- if (!qctxt->lqc_lqs_hash) {
- CERROR("initialize hash lqs for %s error!\n", obd->obd_name);
- RETURN(-ENOMEM);
- }
-
-#ifdef LPROCFS
- rc = lquota_proc_setup(obd, is_master(qctxt));
- if (rc)
- CERROR("initialize proc for %s error!\n", obd->obd_name);
-#endif
-
- RETURN(rc);
-}
-
-static int check_lqs(struct lustre_quota_ctxt *qctxt)
-{
- int rc;
- ENTRY;
-
- rc = !cfs_atomic_read(&qctxt->lqc_lqs);
-
- RETURN(rc);
-}
-
-int qctxt_del_lqs(cfs_hash_t *hs, cfs_hash_bd_t *bd,
- cfs_hlist_node_t *hnode, void *data)
-{
- /* remove from hash and -1 refcount */
- cfs_hash_bd_del_locked(hs, bd, hnode);
- return 0;
-}
-
-void qctxt_cleanup(struct lustre_quota_ctxt *qctxt, int force)
-{
- struct lustre_qunit *qunit, *tmp;
- cfs_list_t tmp_list;
- struct l_wait_info lwi = { 0 };
- struct obd_device_target *obt = qctxt->lqc_obt;
- int i;
- ENTRY;
-
- CFS_INIT_LIST_HEAD(&tmp_list);
-
- cfs_spin_lock(&qctxt->lqc_lock);
- qctxt->lqc_valid = 0;
- cfs_spin_unlock(&qctxt->lqc_lock);
-
- cfs_spin_lock(&qunit_hash_lock);
- for (i = 0; i < NR_DQHASH; i++) {
- cfs_list_for_each_entry_safe(qunit, tmp, &qunit_hash[i],
- lq_hash) {
- if (qunit->lq_ctxt != qctxt)
- continue;
- remove_qunit_nolock(qunit);
- cfs_list_add(&qunit->lq_hash, &tmp_list);
- }
- }
- cfs_spin_unlock(&qunit_hash_lock);
-
- cfs_list_for_each_entry_safe(qunit, tmp, &tmp_list, lq_hash) {
- cfs_list_del_init(&qunit->lq_hash);
- compute_lqs_after_removing_qunit(qunit);
-
- /* wake up all waiters */
- QUNIT_SET_STATE_AND_RC(qunit, QUNIT_FINISHED, 0);
- cfs_waitq_broadcast(&qunit->lq_waitq);
- qunit_put(qunit);
- }
-
- /* after qctxt_cleanup, qctxt might be freed, then check_qm() is
- * unpredicted. So we must wait until lqc_wait_for_qmaster is empty */
- while (cfs_waitq_active(&qctxt->lqc_wait_for_qmaster)) {
- cfs_waitq_signal(&qctxt->lqc_wait_for_qmaster);
- cfs_schedule_timeout_and_set_state(CFS_TASK_INTERRUPTIBLE,
- cfs_time_seconds(1));
- }
-
- /* release refcount on lustre_qunit_size holding by lqs_hash */
- cfs_hash_for_each_safe(qctxt->lqc_lqs_hash, qctxt_del_lqs, NULL);
-
- l_wait_event(qctxt->lqc_lqs_waitq, check_lqs(qctxt), &lwi);
- cfs_down_write(&obt->obt_rwsem);
- cfs_hash_putref(qctxt->lqc_lqs_hash);
- qctxt->lqc_lqs_hash = NULL;
- cfs_up_write(&obt->obt_rwsem);
-
- ptlrpcd_decref();
-
-#ifdef LPROCFS
- if (lquota_proc_cleanup(qctxt))
- CERROR("cleanup proc error!\n");
-#endif
-
- EXIT;
-}
-
-struct qslave_recov_thread_data {
- struct obd_device *obd;
- struct lustre_quota_ctxt *qctxt;
- cfs_completion_t comp;
-};
-
-/* FIXME only recovery block quota by now */
-static int qslave_recovery_main(void *arg)
-{
- struct qslave_recov_thread_data *data = arg;
- struct obd_device *obd = data->obd;
- struct lustre_quota_ctxt *qctxt = data->qctxt;
- unsigned int type;
- int rc = 0;
- ENTRY;
-
- cfs_daemonize_ctxt("qslave_recovd");
-
- /* for obdfilter */
- class_incref(obd, "qslave_recovd_filter", obd);
-
- cfs_complete(&data->comp);
-
- cfs_spin_lock(&qctxt->lqc_lock);
- if (qctxt->lqc_recovery) {
- cfs_spin_unlock(&qctxt->lqc_lock);
- class_decref(obd, "qslave_recovd_filter", obd);
- RETURN(0);
- } else {
- qctxt->lqc_recovery = 1;
- cfs_spin_unlock(&qctxt->lqc_lock);
- }
-
- for (type = USRQUOTA; type < MAXQUOTAS; type++) {
- struct qunit_data qdata;
- struct quota_info *dqopt = sb_dqopt(qctxt->lqc_sb);
- cfs_list_t id_list;
- struct dquot_id *dqid, *tmp;
- int ret;
-
- mutex_lock(&dqopt->dqonoff_mutex);
- if (!sb_has_quota_active(qctxt->lqc_sb, type)) {
- mutex_unlock(&dqopt->dqonoff_mutex);
- break;
- }
-
- LASSERT(dqopt->files[type] != NULL);
- CFS_INIT_LIST_HEAD(&id_list);
- rc = fsfilt_qids(obd, NULL, dqopt->files[type], type, &id_list);
- mutex_unlock(&dqopt->dqonoff_mutex);
- if (rc)
- CERROR("Get ids from quota file failed. (rc:%d)\n", rc);
-
- cfs_list_for_each_entry_safe(dqid, tmp, &id_list, di_link) {
- cfs_list_del_init(&dqid->di_link);
- /* skip slave recovery on itself */
- if (is_master(qctxt))
- goto free;
- if (rc && rc != -EBUSY)
- goto free;
-
- qdata.qd_id = dqid->di_id;
- qdata.qd_flags = type;
- QDATA_SET_BLK(&qdata);
- qdata.qd_count = 0;
-
- ret = check_cur_qunit(obd, qctxt, &qdata);
- if (ret > 0) {
- int opc;
- opc = ret == 1 ? QUOTA_DQACQ : QUOTA_DQREL;
- rc = schedule_dqacq(obd, qctxt, &qdata, opc,
- 0, NULL);
- if (rc == -EDQUOT)
- rc = 0;
- } else {
- rc = 0;
- }
-
- if (rc && rc != -EBUSY)
- CERROR("qslave recovery failed! (id:%d type:%d "
- " rc:%d)\n", dqid->di_id, type, rc);
-free:
- OBD_FREE_PTR(dqid);
- }
- }
-
- cfs_spin_lock(&qctxt->lqc_lock);
- qctxt->lqc_recovery = 0;
- cfs_spin_unlock(&qctxt->lqc_lock);
- class_decref(obd, "qslave_recovd_filter", obd);
- RETURN(rc);
-}
-
-void
-qslave_start_recovery(struct obd_device *obd, struct lustre_quota_ctxt *qctxt)
-{
- struct qslave_recov_thread_data data;
- int rc;
- ENTRY;
-
- if (!sb_any_quota_loaded(qctxt->lqc_sb))
- goto exit;
-
- data.obd = obd;
- data.qctxt = qctxt;
- cfs_init_completion(&data.comp);
-
- rc = cfs_create_thread(qslave_recovery_main, &data,
- CFS_DAEMON_FLAGS);
- if (rc < 0) {
- CERROR("Cannot start quota recovery thread: rc %d\n", rc);
- goto exit;
- }
- cfs_wait_for_completion(&data.comp);
-exit:
- EXIT;
-}
-
-inline int quota_is_on(struct lustre_quota_ctxt *qctxt,
- struct obd_quotactl *oqctl)
-{
- return ((qctxt->lqc_flags & UGQUOTA2LQC(oqctl->qc_type)) ==
- UGQUOTA2LQC(oqctl->qc_type));
-}
-
-inline int quota_is_off(struct lustre_quota_ctxt *qctxt,
- struct obd_quotactl *oqctl)
-{
- return !(qctxt->lqc_flags & UGQUOTA2LQC(oqctl->qc_type));
-}
-
-/*
- * When quotaon, build a lqs for every uid/gid who has been set limitation
- * for quota. After quota_search_lqs, it will hold one ref for the lqs.
- * It will be released when qctxt_cleanup() is executed b=18574
- *
- * Should be called with obt->obt_quotachecking held. b=20152
- */
-void build_lqs(struct obd_device *obd)
-{
- struct obd_device_target *obt = &obd->u.obt;
- struct lustre_quota_ctxt *qctxt = &obt->obt_qctxt;
- cfs_list_t id_list;
- int i, rc;
-
- LASSERT_SEM_LOCKED(&obt->obt_quotachecking);
- CFS_INIT_LIST_HEAD(&id_list);
- for (i = 0; i < MAXQUOTAS; i++) {
- struct dquot_id *dqid, *tmp;
-
- if (sb_dqopt(qctxt->lqc_sb)->files[i] == NULL)
- continue;
-
- rc = fsfilt_qids(obd, NULL, sb_dqopt(qctxt->lqc_sb)->files[i],
- i, &id_list);
- if (rc) {
- CERROR("%s: failed to get %s qids!\n", obd->obd_name,
- i ? "group" : "user");
- continue;
- }
-
- cfs_list_for_each_entry_safe(dqid, tmp, &id_list,
- di_link) {
- struct lustre_qunit_size *lqs;
-
- cfs_list_del_init(&dqid->di_link);
- lqs = quota_search_lqs(LQS_KEY(i, dqid->di_id),
- qctxt, 1);
- if (lqs && !IS_ERR(lqs)) {
- lqs->lqs_flags |= dqid->di_flag;
- lqs_putref(lqs);
- } else {
- CERROR("%s: failed to create a lqs for %sid %u"
- "\n", obd->obd_name, i ? "g" : "u",
- dqid->di_id);
- }
-
- OBD_FREE_PTR(dqid);
- }
- }
-}
-
-/**
- * lqs<->qctxt hash operations
- */
-
-/**
- * string hashing using djb2 hash algorithm
- */
-static unsigned
-lqs_hash(cfs_hash_t *hs, const void *key, unsigned mask)
-{
- unsigned long long id;
- unsigned hash;
- ENTRY;
-
- LASSERT(key);
- id = *((unsigned long long *)key);
- hash = (LQS_KEY_GRP(id) ? 5381 : 5387) * (unsigned)LQS_KEY_ID(id);
-
- RETURN(hash & mask);
-}
-
-static void *
-lqs_key(cfs_hlist_node_t *hnode)
-{
- struct lustre_qunit_size *lqs;
- ENTRY;
-
- lqs = cfs_hlist_entry(hnode, struct lustre_qunit_size, lqs_hash);
- RETURN(&lqs->lqs_key);
-}
-
-static int
-lqs_keycmp(const void *key, cfs_hlist_node_t *hnode)
-{
- struct lustre_qunit_size *q =
- cfs_hlist_entry(hnode, struct lustre_qunit_size, lqs_hash);
-
- RETURN(q->lqs_key == *((unsigned long long *)key));
-}
-
-static void *
-lqs_object(cfs_hlist_node_t *hnode)
-{
- return cfs_hlist_entry(hnode, struct lustre_qunit_size, lqs_hash);
-}
-
-static void
-lqs_get(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
-{
- struct lustre_qunit_size *q =
- cfs_hlist_entry(hnode, struct lustre_qunit_size, lqs_hash);
-
- lqs_getref(q);
-}
-
-static void
-lqs_put_locked(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
-{
- struct lustre_qunit_size *q =
- cfs_hlist_entry(hnode, struct lustre_qunit_size, lqs_hash);
-
- lqs_putref(q);
-}
-
-static void
-lqs_exit(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
-{
- CERROR("It should not have any item left to be handled by this!");
-}
-
-static cfs_hash_ops_t lqs_hash_ops = {
- .hs_hash = lqs_hash,
- .hs_key = lqs_key,
- .hs_keycmp = lqs_keycmp,
- .hs_object = lqs_object,
- .hs_get = lqs_get,
- .hs_put_locked = lqs_put_locked,
- .hs_exit = lqs_exit
-};
+++ /dev/null
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Whamcloud, Inc.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-#define DEBUG_SUBSYSTEM S_LQUOTA
-
-#ifdef __KERNEL__
-# include <linux/version.h>
-# include <linux/module.h>
-# include <linux/init.h>
-# include <linux/fs.h>
-# include <linux/jbd.h>
-# include <linux/quota.h>
-# include <linux/buffer_head.h>
-# include <linux/workqueue.h>
-# include <linux/mount.h>
-#else /* __KERNEL__ */
-# include <liblustre.h>
-#endif
-
-#include <obd_class.h>
-#include <lustre_mds.h>
-#include <lustre_dlm.h>
-#include <lustre_cfg.h>
-#include <obd_ost.h>
-#include <lustre_fsfilt.h>
-#include <lustre_quota.h>
-#include "quota_internal.h"
-
-#ifdef __KERNEL__
-
-int mds_quota_ctl(struct obd_device *obd, struct obd_export *unused,
- struct obd_quotactl *oqctl)
-{
- struct obd_device_target *obt = &obd->u.obt;
- struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
- struct timeval work_start;
- struct timeval work_end;
- long timediff;
- int rc = 0;
- ENTRY;
-
- cfs_gettimeofday(&work_start);
- switch (oqctl->qc_cmd) {
- case Q_QUOTAON:
- oqctl->qc_id = obt->obt_qfmt; /* override qfmt version */
- rc = mds_quota_on(obd, oqctl);
- break;
- case Q_QUOTAOFF:
- oqctl->qc_id = obt->obt_qfmt; /* override qfmt version */
- rc = mds_quota_off(obd, oqctl);
- break;
- case Q_SETINFO:
- rc = mds_set_dqinfo(obd, oqctl);
- break;
- case Q_GETINFO:
- rc = mds_get_dqinfo(obd, oqctl);
- break;
- case Q_SETQUOTA:
- rc = mds_set_dqblk(obd, oqctl);
- break;
- case Q_GETQUOTA:
- rc = mds_get_dqblk(obd, oqctl);
- break;
- case Q_GETOINFO:
- case Q_GETOQUOTA:
- rc = mds_get_obd_quota(obd, oqctl);
- break;
- case LUSTRE_Q_INVALIDATE:
- rc = mds_quota_invalidate(obd, oqctl);
- break;
- case LUSTRE_Q_FINVALIDATE:
- oqctl->qc_id = obt->obt_qfmt; /* override qfmt version */
- rc = mds_quota_finvalidate(obd, oqctl);
- break;
- default:
- CERROR("%s: unsupported mds_quotactl command: %d\n",
- obd->obd_name, oqctl->qc_cmd);
- RETURN(-EFAULT);
- }
-
- if (rc)
- 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);
- cfs_gettimeofday(&work_end);
- timediff = cfs_timeval_sub(&work_end, &work_start, NULL);
- lprocfs_counter_add(qctxt->lqc_stats, LQUOTA_QUOTA_CTL, timediff);
-
- RETURN(rc);
-}
-
-int filter_quota_ctl(struct obd_device *unused, 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 = &obt->obt_qctxt;
- struct lustre_qunit_size *lqs;
- void *handle = NULL;
- struct timeval work_start;
- struct timeval work_end;
- long timediff;
- int rc = 0;
- ENTRY;
-
- cfs_gettimeofday(&work_start);
- switch (oqctl->qc_cmd) {
- case Q_QUOTAON:
- oqctl->qc_id = obt->obt_qfmt;
- rc = generic_quota_on(obd, oqctl, 0);
- break;
- case Q_FINVALIDATE:
- case Q_QUOTAOFF:
- cfs_down(&obt->obt_quotachecking);
- if (oqctl->qc_cmd == Q_FINVALIDATE &&
- (obt->obt_qctxt.lqc_flags & UGQUOTA2LQC(oqctl->qc_type))) {
- CWARN("quota[%u] is on yet\n", oqctl->qc_type);
- cfs_up(&obt->obt_quotachecking);
- rc = -EBUSY;
- break;
- }
- oqctl->qc_id = obt->obt_qfmt; /* override qfmt version */
- case Q_GETOINFO:
- case Q_GETOQUOTA:
- case Q_GETQUOTA:
- /* In recovery scenario, this pending dqacq/dqrel might have
- * been processed by master successfully before it's dquot
- * on master enter recovery mode. We must wait for this
- * dqacq/dqrel done then return the correct limits to master */
- if (oqctl->qc_stat == QUOTA_RECOVERING)
- handle = quota_barrier(&obd->u.obt.obt_qctxt, oqctl, 1);
-
- push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- rc = fsfilt_quotactl(obd, obt->obt_sb, oqctl);
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
-
- if (oqctl->qc_stat == QUOTA_RECOVERING)
- quota_unbarrier(handle);
-
- if (oqctl->qc_cmd == Q_QUOTAOFF ||
- oqctl->qc_cmd == Q_FINVALIDATE) {
- if (oqctl->qc_cmd == Q_QUOTAOFF) {
- if (!rc)
- obt->obt_qctxt.lqc_flags &=
- ~UGQUOTA2LQC(oqctl->qc_type);
- else if (quota_is_off(qctxt, oqctl))
- rc = -EALREADY;
- CDEBUG(D_QUOTA, "%s: quotaoff type:flags:rc "
- "%u:%lu:%d\n", obd->obd_name,
- oqctl->qc_type, qctxt->lqc_flags, rc);
- }
- cfs_up(&obt->obt_quotachecking);
- }
-
- break;
- case Q_SETQUOTA:
- /* currently, it is only used for nullifying the quota */
- handle = quota_barrier(&obd->u.obt.obt_qctxt, oqctl, 1);
-
- push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- rc = fsfilt_quotactl(obd, obd->u.obt.obt_sb, oqctl);
-
- if (!rc) {
- oqctl->qc_cmd = Q_SYNC;
- fsfilt_quotactl(obd, obd->u.obt.obt_sb, oqctl);
- oqctl->qc_cmd = Q_SETQUOTA;
- }
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- quota_unbarrier(handle);
-
- lqs = quota_search_lqs(LQS_KEY(oqctl->qc_type, oqctl->qc_id),
- qctxt, 0);
- if (lqs == NULL || IS_ERR(lqs)){
- CERROR("fail to create lqs during setquota operation "
- "for %sid %u\n", oqctl->qc_type ? "g" : "u",
- oqctl->qc_id);
- } else {
- lqs->lqs_flags &= ~QB_SET;
- lqs_putref(lqs);
- }
-
- break;
- case Q_INITQUOTA:
- {
- unsigned int id[MAXQUOTAS] = { 0, 0 };
-
- /* Initialize quota limit to MIN_QLIMIT */
- LASSERT(oqctl->qc_dqblk.dqb_valid == QIF_BLIMITS);
- LASSERT(oqctl->qc_dqblk.dqb_bsoftlimit == 0);
-
- if (!oqctl->qc_dqblk.dqb_bhardlimit)
- goto adjust;
-
- /* There might be a pending dqacq/dqrel (which is going to
- * clear stale limits on slave). we should wait for it's
- * completion then initialize limits */
- handle = quota_barrier(&obd->u.obt.obt_qctxt, oqctl, 1);
- LASSERT(oqctl->qc_dqblk.dqb_bhardlimit == MIN_QLIMIT);
- push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- rc = fsfilt_quotactl(obd, obd->u.obt.obt_sb, oqctl);
-
- /* Update on-disk quota, in case of lose the changed limits
- * (MIN_QLIMIT) on crash, which cannot be recovered.*/
- if (!rc) {
- oqctl->qc_cmd = Q_SYNC;
- fsfilt_quotactl(obd, obd->u.obt.obt_sb, oqctl);
- oqctl->qc_cmd = Q_INITQUOTA;
- }
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- quota_unbarrier(handle);
-
- if (rc)
- RETURN(rc);
-adjust:
- lqs = quota_search_lqs(LQS_KEY(oqctl->qc_type, oqctl->qc_id),
- qctxt, 1);
- if (lqs == NULL || IS_ERR(lqs)){
- CERROR("fail to create lqs during setquota operation "
- "for %sid %u\n", oqctl->qc_type ? "g" : "u",
- oqctl->qc_id);
- break;
- } else {
- lqs->lqs_flags |= QB_SET;
- lqs_putref(lqs);
- }
-
- /* Trigger qunit pre-acquire */
- if (oqctl->qc_type == USRQUOTA)
- id[USRQUOTA] = oqctl->qc_id;
- else
- id[GRPQUOTA] = oqctl->qc_id;
-
- rc = qctxt_adjust_qunit(obd, &obd->u.obt.obt_qctxt,
- id, 1, 0, NULL);
- if (rc == -EDQUOT || rc == -EBUSY) {
- CDEBUG(D_QUOTA, "rc: %d.\n", rc);
- rc = 0;
- }
-
- break;
- }
- default:
- CERROR("%s: unsupported filter_quotactl command: %d\n",
- obd->obd_name, oqctl->qc_cmd);
- RETURN(-EFAULT);
- }
- cfs_gettimeofday(&work_end);
- timediff = cfs_timeval_sub(&work_end, &work_start, NULL);
- lprocfs_counter_add(qctxt->lqc_stats, LQUOTA_QUOTA_CTL, timediff);
-
- RETURN(rc);
-}
-#endif /* __KERNEL__ */
+++ /dev/null
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Whamcloud, Inc.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-#define DEBUG_SUBSYSTEM S_LQUOTA
-
-#ifdef __KERNEL__
-# include <linux/version.h>
-# include <linux/module.h>
-# include <linux/init.h>
-# include <linux/fs.h>
-# include <linux/jbd.h>
-# include <linux/buffer_head.h>
-# include <linux/workqueue.h>
-# include <linux/mount.h>
-#else /* __KERNEL__ */
-# include <liblustre.h>
-#endif
-
-#include <obd_class.h>
-#include <lustre_mds.h>
-#include <lustre_dlm.h>
-#include <lustre_cfg.h>
-#include <obd_ost.h>
-#include <lustre_fsfilt.h>
-#include <lustre_quota.h>
-#include <lprocfs_status.h>
-#include "quota_internal.h"
-
-#ifdef __KERNEL__
-
-static cfs_time_t last_print = 0;
-static DEFINE_SPINLOCK(last_print_lock);
-
-static int filter_quota_setup(struct obd_device *obd)
-{
- int rc = 0;
- struct obd_device_target *obt = &obd->u.obt;
- ENTRY;
-
- cfs_init_rwsem(&obt->obt_rwsem);
- obt->obt_qfmt = LUSTRE_QUOTA_V2;
- cfs_sema_init(&obt->obt_quotachecking, 1);
- rc = qctxt_init(obd, NULL);
- if (rc)
- CERROR("initialize quota context failed! (rc:%d)\n", rc);
-
- RETURN(rc);
-}
-
-static int filter_quota_cleanup(struct obd_device *obd)
-{
- ENTRY;
- qctxt_cleanup(&obd->u.obt.obt_qctxt, 0);
- RETURN(0);
-}
-
-static int filter_quota_setinfo(struct obd_device *obd, void *data)
-{
- struct obd_export *exp = data;
- struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
- struct obd_import *imp = exp->exp_imp_reverse;
- ENTRY;
-
- LASSERT(imp != NULL);
-
- /* setup the quota context import */
- cfs_spin_lock(&qctxt->lqc_lock);
- if (qctxt->lqc_import != NULL) {
- cfs_spin_unlock(&qctxt->lqc_lock);
- if (qctxt->lqc_import == imp)
- CDEBUG(D_WARNING, "%s: lqc_import(%p) of obd(%p) was "
- "activated already.\n", obd->obd_name, imp, obd);
- else
- CERROR("%s: lqc_import(%p:%p) of obd(%p) was "
- "activated by others.\n", obd->obd_name,
- qctxt->lqc_import, imp, obd);
- } else {
- qctxt->lqc_import = imp;
- /* make imp's connect flags equal relative exp's connect flags
- * adding it to avoid the scan export list */
- imp->imp_connect_data.ocd_connect_flags |=
- (exp->exp_connect_flags &
- (OBD_CONNECT_QUOTA64 | OBD_CONNECT_CHANGE_QS));
- cfs_spin_unlock(&qctxt->lqc_lock);
- CDEBUG(D_QUOTA, "%s: lqc_import(%p) of obd(%p) is reactivated "
- "now.\n", obd->obd_name, imp, obd);
-
- cfs_waitq_signal(&qctxt->lqc_wait_for_qmaster);
- /* start quota slave recovery thread. (release high limits) */
- qslave_start_recovery(obd, qctxt);
- }
- RETURN(0);
-}
-
-static int filter_quota_clearinfo(struct obd_export *exp, struct obd_device *obd)
-{
- struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
- struct obd_import *imp = exp->exp_imp_reverse;
- ENTRY;
-
- /* lquota may be not set up before destroying export, b=14896 */
- if (!obd->obd_set_up)
- RETURN(0);
-
- if (unlikely(imp == NULL))
- RETURN(0);
-
- /* when exp->exp_imp_reverse is destroyed, the corresponding lqc_import
- * should be invalid b=12374 */
- cfs_spin_lock(&qctxt->lqc_lock);
- if (qctxt->lqc_import == imp) {
- qctxt->lqc_import = NULL;
- cfs_spin_unlock(&qctxt->lqc_lock);
- CDEBUG(D_QUOTA, "%s: lqc_import(%p) of obd(%p) is invalid now.\n",
- obd->obd_name, imp, obd);
- ptlrpc_cleanup_imp(imp);
- dqacq_interrupt(qctxt);
- } else {
- cfs_spin_unlock(&qctxt->lqc_lock);
- }
- RETURN(0);
-}
-
-static int filter_quota_enforce(struct obd_device *obd, unsigned int ignore)
-{
- ENTRY;
-
- if (!sb_any_quota_loaded(obd->u.obt.obt_sb))
- RETURN(0);
-
- if (ignore) {
- CDEBUG(D_QUOTA, "blocks will be written with ignoring quota.\n");
- cfs_cap_raise(CFS_CAP_SYS_RESOURCE);
- } else {
- cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
- }
-
- RETURN(0);
-}
-
-#define GET_OA_ID(flag, oa) (flag == USRQUOTA ? oa->o_uid : oa->o_gid)
-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;
-
- if (!sb_any_quota_loaded(obt->obt_sb))
- RETURN(0);
-
- OBD_ALLOC_PTR(oqctl);
- if (!oqctl)
- 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 lustre_qunit_size *lqs = NULL;
-
- /* check if quota is enabled */
- if (!sb_has_quota_active(obt->obt_sb, cnt))
- continue;
-
- lqs = quota_search_lqs(LQS_KEY(cnt, GET_OA_ID(cnt, oa)),
- qctxt, 0);
- if (IS_ERR(lqs)) {
- rc = PTR_ERR(lqs);
- CDEBUG(D_QUOTA, "search lqs for %s %d failed, "
- "(rc = %d)\n",
- cnt == USRQUOTA ? "user" : "group",
- GET_OA_ID(cnt, oa), rc);
- break;
- } else if (lqs == NULL) {
- /* continue to check group quota if the file's owner
- * doesn't have quota limit. LU-530 */
- continue;
- } else {
- cfs_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;
- cfs_spin_unlock(&lqs->lqs_lock);
- CDEBUG(D_QUOTA, "set sync flag: bunit(%lu), "
- "sync_blk(%d)\n", lqs->lqs_bunit_sz,
- qctxt->lqc_sync_blk);
- /* this is for quota_search_lqs */
- lqs_putref(lqs);
- continue;
- }
- cfs_spin_unlock(&lqs->lqs_lock);
- /* this is for quota_search_lqs */
- lqs_putref(lqs);
- }
-
- memset(oqctl, 0, sizeof(*oqctl));
-
- oqctl->qc_cmd = Q_GETQUOTA;
- oqctl->qc_type = cnt;
- oqctl->qc_id = (cnt == USRQUOTA) ? oa->o_uid : oa->o_gid;
- err = fsfilt_quotactl(obd, obt->obt_sb, oqctl);
- if (err) {
- if (!rc)
- rc = err;
- oa->o_valid &= ~((cnt == USRQUOTA) ? OBD_MD_FLUSRQUOTA :
- OBD_MD_FLGRPQUOTA);
- CDEBUG(D_QUOTA, "fsfilt getquota for %s %d failed, "
- "(rc = %d)\n",
- cnt == USRQUOTA ? "user" : "group",
- cnt == USRQUOTA ? oa->o_uid : oa->o_gid, err);
- continue;
- }
-
- if (oqctl->qc_dqblk.dqb_bhardlimit &&
- (toqb(oqctl->qc_dqblk.dqb_curspace) >=
- oqctl->qc_dqblk.dqb_bhardlimit)) {
- oa->o_flags |= (cnt == USRQUOTA) ?
- OBD_FL_NO_USRQUOTA : OBD_FL_NO_GRPQUOTA;
- CDEBUG(D_QUOTA, "out of quota for %s %d\n",
- cnt == USRQUOTA ? "user" : "group",
- cnt == USRQUOTA ? oa->o_uid : oa->o_gid);
- }
- }
- OBD_FREE_PTR(oqctl);
- RETURN(rc);
-}
-
-/**
- * check whether the left quota of certain uid and gid can satisfy a block_write
- * or inode_create rpc. When need to acquire quota, return QUOTA_RET_ACQUOTA
- */
-static int quota_check_common(struct obd_device *obd, const unsigned int id[],
- int pending[], int count, int cycle, int isblk,
- struct inode *inode, int frags)
-{
- struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
- int i;
- struct qunit_data qdata[MAXQUOTAS];
- int mb = 0;
- int rc = 0, rc2[2] = { 0, 0 };
- ENTRY;
-
- cfs_spin_lock(&qctxt->lqc_lock);
- if (!qctxt->lqc_valid){
- cfs_spin_unlock(&qctxt->lqc_lock);
- RETURN(rc);
- }
- cfs_spin_unlock(&qctxt->lqc_lock);
-
- for (i = 0; i < MAXQUOTAS; i++) {
- struct lustre_qunit_size *lqs = NULL;
-
- qdata[i].qd_id = id[i];
- qdata[i].qd_flags = i;
- if (isblk)
- QDATA_SET_BLK(&qdata[i]);
- qdata[i].qd_count = 0;
-
- /* check if quota is enabled */
- if (!sb_has_quota_active(qctxt->lqc_sb, i))
- continue;
-
- /* ignore root user */
- if (qdata[i].qd_id == 0 && !QDATA_IS_GRP(&qdata[i]))
- continue;
-
- lqs = quota_search_lqs(LQS_KEY(i, id[i]), qctxt, 0);
- if (lqs == NULL || IS_ERR(lqs))
- continue;
-
- if (IS_ERR(lqs)) {
- CERROR("can not find lqs for check_common: "
- "[id %u] [%c] [isblk %d] [count %d] [rc %ld]\n",
- id[i], i % 2 ? 'g': 'u', isblk, count,
- PTR_ERR(lqs));
- RETURN(PTR_ERR(lqs));
- }
-
- rc2[i] = compute_remquota(obd, qctxt, &qdata[i], isblk);
- cfs_spin_lock(&lqs->lqs_lock);
- if (!cycle) {
- if (isblk) {
- pending[i] = count * CFS_PAGE_SIZE;
- /* in order to complete this write, we need extra
- * meta blocks. This function can get it through
- * data needed to be written b=16542 */
- if (inode) {
- mb = pending[i];
- rc = fsfilt_get_mblk(obd, qctxt->lqc_sb,
- &mb, inode,
- frags);
- if (rc)
- CERROR("%s: can't get extra "
- "meta blocks\n",
- obd->obd_name);
- else
- pending[i] += mb;
- }
- LASSERTF(pending[i] >= 0, "pending is not valid"
- ", count=%d, mb=%d\n", count, mb);
- lqs->lqs_bwrite_pending += pending[i];
- } else {
- pending[i] = count;
- lqs->lqs_iwrite_pending += pending[i];
- }
- }
-
- /* if xx_rec < 0, that means quota are releasing,
- * and it may return before we use quota. So if
- * we find this situation, we assuming it has
- * returned b=18491 */
- if (isblk && lqs->lqs_blk_rec < 0) {
- if (qdata[i].qd_count < -lqs->lqs_blk_rec)
- qdata[i].qd_count = 0;
- else
- qdata[i].qd_count += lqs->lqs_blk_rec;
- }
- if (!isblk && lqs->lqs_ino_rec < 0) {
- if (qdata[i].qd_count < -lqs->lqs_ino_rec)
- qdata[i].qd_count = 0;
- else
- qdata[i].qd_count += lqs->lqs_ino_rec;
- }
-
- CDEBUG(D_QUOTA, "[id %u] [%c] [isblk %d] [count %d]"
- " [lqs pending: %lu] [qd_count: "LPU64"] [metablocks: %d]"
- " [pending: %d]\n", id[i], i % 2 ? 'g': 'u', isblk, count,
- isblk ? lqs->lqs_bwrite_pending : lqs->lqs_iwrite_pending,
- qdata[i].qd_count, mb, pending[i]);
- if (rc2[i] == QUOTA_RET_OK) {
- if (isblk && qdata[i].qd_count < lqs->lqs_bwrite_pending)
- rc2[i] = QUOTA_RET_ACQUOTA;
- if (!isblk && qdata[i].qd_count <
- lqs->lqs_iwrite_pending)
- rc2[i] = QUOTA_RET_ACQUOTA;
- }
-
- cfs_spin_unlock(&lqs->lqs_lock);
-
- if (lqs->lqs_blk_rec < 0 &&
- qdata[i].qd_count <
- lqs->lqs_bwrite_pending - lqs->lqs_blk_rec - mb)
- OBD_FAIL_TIMEOUT(OBD_FAIL_QUOTA_DELAY_REL, 5);
-
- /* When cycle is zero, lqs_*_pending will be changed. We will
- * get reference of the lqs here and put reference of lqs in
- * quota_pending_commit b=14784 */
- if (!cycle)
- lqs_getref(lqs);
-
- /* this is for quota_search_lqs */
- lqs_putref(lqs);
- }
-
- if (rc2[0] == QUOTA_RET_ACQUOTA || rc2[1] == QUOTA_RET_ACQUOTA)
- RETURN(QUOTA_RET_ACQUOTA);
- else
- RETURN(rc);
-}
-
-int quota_is_set(struct obd_device *obd, const unsigned int id[], int flag)
-{
- struct lustre_qunit_size *lqs;
- int i, q_set = 0;
-
- if (!sb_any_quota_loaded(obd->u.obt.obt_qctxt.lqc_sb))
- RETURN(0);
-
- for (i = 0; i < MAXQUOTAS; i++) {
- /* check if quota is enabled */
- if (!sb_has_quota_active(obd->u.obt.obt_qctxt.lqc_sb, i))
- continue;
- lqs = quota_search_lqs(LQS_KEY(i, id[i]),
- &obd->u.obt.obt_qctxt, 0);
- if (lqs && !IS_ERR(lqs)) {
- if (lqs->lqs_flags & flag)
- q_set = 1;
- lqs_putref(lqs);
- }
- }
-
- return q_set;
-}
-
-static int quota_chk_acq_common(struct obd_device *obd, struct obd_export *exp,
- const unsigned int id[], int pending[],
- int count, quota_acquire acquire,
- struct obd_trans_info *oti, int isblk,
- struct inode *inode, int frags)
-{
- struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
- struct timeval work_start;
- struct timeval work_end;
- long timediff;
- struct l_wait_info lwi = { 0 };
- int rc = 0, cycle = 0, count_err = 1;
- ENTRY;
-
- if (!quota_is_set(obd, id, isblk ? QB_SET : QI_SET))
- RETURN(0);
-
- if (isblk && (exp->exp_failed || exp->exp_abort_active_req))
- /* If the client has been evicted or if it
- * timed out and tried to reconnect already,
- * abort the request immediately */
- RETURN(-ENOTCONN);
-
- CDEBUG(D_QUOTA, "check quota for %s\n", obd->obd_name);
- pending[USRQUOTA] = pending[GRPQUOTA] = 0;
- /* Unfortunately, if quota master is too busy to handle the
- * 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 */
- cfs_gettimeofday(&work_start);
- while ((rc = quota_check_common(obd, id, pending, count, cycle, isblk,
- inode, frags)) &
- QUOTA_RET_ACQUOTA) {
- struct ptlrpc_thread *thr = oti != NULL ?
- oti->oti_thread : NULL;
-
- cfs_spin_lock(&qctxt->lqc_lock);
- if (!qctxt->lqc_import && oti != NULL) {
- cfs_spin_unlock(&qctxt->lqc_lock);
-
- LASSERT(thr != NULL);
- /* The recovery thread doesn't have watchdog
- * attached. LU-369 */
- if (thr->t_watchdog != NULL)
- lc_watchdog_disable(thr->t_watchdog);
- CDEBUG(D_QUOTA, "sleep for quota master\n");
- l_wait_event(qctxt->lqc_wait_for_qmaster,
- check_qm(qctxt), &lwi);
-
- CDEBUG(D_QUOTA, "wake up when quota master is back\n");
- if (thr->t_watchdog != NULL) {
- lc_watchdog_touch(thr->t_watchdog,
- ptlrpc_server_get_timeout(thr->t_svcpt));
- }
- } else {
- cfs_spin_unlock(&qctxt->lqc_lock);
- }
-
- cycle++;
- if (isblk)
- OBD_FAIL_TIMEOUT(OBD_FAIL_OST_HOLD_WRITE_RPC, 90);
- /* after acquire(), we should run quota_check_common again
- * so that we confirm there are enough quota to finish write */
- rc = acquire(obd, id, oti, isblk);
-
- /* please reference to dqacq_completion for the below */
- /* a new request is finished, try again */
- if (rc == QUOTA_REQ_RETURNED) {
- CDEBUG(D_QUOTA, "finish a quota req, try again\n");
- continue;
- }
-
- /* it is out of quota already */
- if (rc == -EDQUOT) {
- CDEBUG(D_QUOTA, "out of quota, return -EDQUOT\n");
- break;
- }
-
- /* Related quota has been disabled by master, but enabled by
- * slave, do not try again. */
- if (unlikely(rc == -ESRCH)) {
- CERROR("mismatched quota configuration, stop try.\n");
- break;
- }
-
- if (isblk && (exp->exp_failed || exp->exp_abort_active_req))
- /* The client has been evicted or tried to
- * to reconnect already, abort the request */
- RETURN(-ENOTCONN);
-
- /* -EBUSY and others, wait a second and try again */
- if (rc < 0) {
- cfs_waitq_t waitq;
- struct l_wait_info lwi;
-
- if (thr != NULL && thr->t_watchdog != NULL)
- lc_watchdog_touch(thr->t_watchdog,
- ptlrpc_server_get_timeout(thr->t_svcpt));
- CDEBUG(D_QUOTA, "rc: %d, count_err: %d\n", rc,
- count_err++);
-
- cfs_waitq_init(&waitq);
- lwi = LWI_TIMEOUT(cfs_time_seconds(min(cycle, 10)), NULL,
- NULL);
- l_wait_event(waitq, 0, &lwi);
- }
-
- if (rc < 0 || cycle % 10 == 0) {
- cfs_spin_lock(&last_print_lock);
- if (last_print == 0 ||
- cfs_time_before((last_print + cfs_time_seconds(30)),
- cfs_time_current())) {
- last_print = cfs_time_current();
- cfs_spin_unlock(&last_print_lock);
- CWARN("still haven't managed to acquire quota "
- "space from the quota master after %d "
- "retries (err=%d, rc=%d)\n",
- cycle, count_err - 1, rc);
- } else {
- cfs_spin_unlock(&last_print_lock);
- }
- }
-
- CDEBUG(D_QUOTA, "recheck quota with rc: %d, cycle: %d\n", rc,
- cycle);
- }
- cfs_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);
-
- if (rc > 0)
- rc = 0;
- RETURN(rc);
-}
-
-/**
- * when a block_write or inode_create rpc is finished, adjust the record for
- * pending blocks and inodes
- */
-static int quota_pending_commit(struct obd_device *obd, const unsigned int id[],
- int pending[], int isblk)
-{
- struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
- struct timeval work_start;
- struct timeval work_end;
- long timediff;
- int i;
- struct qunit_data qdata[MAXQUOTAS];
- ENTRY;
-
- CDEBUG(D_QUOTA, "commit pending quota for %s\n", obd->obd_name);
- CLASSERT(MAXQUOTAS < 4);
- if (!sb_any_quota_loaded(qctxt->lqc_sb))
- RETURN(0);
-
- cfs_gettimeofday(&work_start);
- for (i = 0; i < MAXQUOTAS; i++) {
- struct lustre_qunit_size *lqs = NULL;
-
- LASSERT(pending[i] >= 0);
- if (pending[i] == 0)
- continue;
-
- qdata[i].qd_id = id[i];
- qdata[i].qd_flags = i;
- if (isblk)
- QDATA_SET_BLK(&qdata[i]);
- qdata[i].qd_count = 0;
-
- if (qdata[i].qd_id == 0 && !QDATA_IS_GRP(&qdata[i]))
- continue;
-
- lqs = quota_search_lqs(LQS_KEY(i, qdata[i].qd_id), qctxt, 0);
- if (lqs == NULL || IS_ERR(lqs)) {
- CERROR("can not find lqs for pending_commit: "
- "[id %u] [%c] [pending %u] [isblk %d] (rc %ld), "
- "maybe cause unexpected lqs refcount error!\n",
- id[i], i ? 'g': 'u', pending[i], isblk,
- lqs ? PTR_ERR(lqs) : -1);
- continue;
- }
-
- cfs_spin_lock(&lqs->lqs_lock);
- if (isblk) {
- LASSERTF(lqs->lqs_bwrite_pending >= pending[i],
- "there are too many blocks! [id %u] [%c] "
- "[bwrite_pending %lu] [pending %u]\n",
- id[i], i % 2 ? 'g' : 'u',
- lqs->lqs_bwrite_pending, pending[i]);
-
- lqs->lqs_bwrite_pending -= pending[i];
- } else {
- LASSERTF(lqs->lqs_iwrite_pending >= pending[i],
- "there are too many files! [id %u] [%c] "
- "[iwrite_pending %lu] [pending %u]\n",
- id[i], i % 2 ? 'g' : 'u',
- lqs->lqs_iwrite_pending, pending[i]);
-
- lqs->lqs_iwrite_pending -= pending[i];
- }
- CDEBUG(D_QUOTA, "%s: lqs_pending=%lu pending[%d]=%d isblk=%d\n",
- obd->obd_name,
- isblk ? lqs->lqs_bwrite_pending : lqs->lqs_iwrite_pending,
- i, pending[i], isblk);
- cfs_spin_unlock(&lqs->lqs_lock);
-
- /* for quota_search_lqs in pending_commit */
- lqs_putref(lqs);
- /* for quota_search_lqs in quota_check */
- lqs_putref(lqs);
- }
- cfs_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);
-}
-
-static int mds_quota_init(void)
-{
- return lustre_dquot_init();
-}
-
-static int mds_quota_exit(void)
-{
- lustre_dquot_exit();
- return 0;
-}
-
-static int mds_quota_setup(struct obd_device *obd)
-{
- struct obd_device_target *obt = &obd->u.obt;
- struct mds_obd *mds = &obd->u.mds;
- int rc;
- ENTRY;
-
- if (unlikely(mds->mds_quota)) {
- CWARN("try to reinitialize quota context!\n");
- RETURN(0);
- }
-
- cfs_init_rwsem(&obt->obt_rwsem);
- obt->obt_qfmt = LUSTRE_QUOTA_V2;
- mds->mds_quota_info.qi_version = LUSTRE_QUOTA_V2;
- cfs_sema_init(&obt->obt_quotachecking, 1);
- /* initialize quota master and quota context */
- cfs_init_rwsem(&mds->mds_qonoff_sem);
- rc = qctxt_init(obd, dqacq_handler);
- if (rc) {
- CERROR("%s: initialize quota context failed! (rc:%d)\n",
- obd->obd_name, rc);
- RETURN(rc);
- }
- mds->mds_quota = 1;
- RETURN(rc);
-}
-
-static int mds_quota_cleanup(struct obd_device *obd)
-{
- ENTRY;
- if (unlikely(!obd->u.mds.mds_quota))
- RETURN(0);
-
- qctxt_cleanup(&obd->u.obt.obt_qctxt, 0);
- RETURN(0);
-}
-
-static int mds_quota_setinfo(struct obd_device *obd, void *data)
-{
- struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
- ENTRY;
-
- if (unlikely(!obd->u.mds.mds_quota))
- RETURN(0);
-
- if (data != NULL)
- QUOTA_MASTER_READY(qctxt);
- else
- QUOTA_MASTER_UNREADY(qctxt);
- RETURN(0);
-}
-
-static int mds_quota_fs_cleanup(struct obd_device *obd)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct obd_quotactl oqctl;
- ENTRY;
-
- if (unlikely(!mds->mds_quota))
- RETURN(0);
-
- mds->mds_quota = 0;
- memset(&oqctl, 0, sizeof(oqctl));
- oqctl.qc_type = UGQUOTA;
-
- cfs_down_write(&mds->mds_qonoff_sem);
- mds_admin_quota_off(obd, &oqctl);
- cfs_up_write(&mds->mds_qonoff_sem);
- RETURN(0);
-}
-
-static int quota_acquire_common(struct obd_device *obd, const unsigned int id[],
- struct obd_trans_info *oti, int isblk)
-{
- struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
- int rc;
- ENTRY;
-
- rc = qctxt_adjust_qunit(obd, qctxt, id, isblk, 1, oti);
- RETURN(rc);
-}
-
-quota_interface_t mds_quota_interface = {
- .quota_init = mds_quota_init,
- .quota_exit = mds_quota_exit,
- .quota_setup = mds_quota_setup,
- .quota_cleanup = mds_quota_cleanup,
- .quota_check = target_quota_check,
- .quota_ctl = mds_quota_ctl,
- .quota_setinfo = mds_quota_setinfo,
- .quota_fs_cleanup = mds_quota_fs_cleanup,
- .quota_recovery = mds_quota_recovery,
- .quota_adjust = mds_quota_adjust,
- .quota_chkquota = quota_chk_acq_common,
- .quota_acquire = quota_acquire_common,
- .quota_pending_commit = quota_pending_commit,
-};
-
-quota_interface_t filter_quota_interface = {
- .quota_setup = filter_quota_setup,
- .quota_cleanup = filter_quota_cleanup,
- .quota_check = target_quota_check,
- .quota_ctl = filter_quota_ctl,
- .quota_setinfo = filter_quota_setinfo,
- .quota_clearinfo = filter_quota_clearinfo,
- .quota_enforce = filter_quota_enforce,
- .quota_getflag = filter_quota_getflag,
- .quota_acquire = quota_acquire_common,
- .quota_adjust = filter_quota_adjust,
- .quota_chkquota = quota_chk_acq_common,
- .quota_adjust_qunit = filter_quota_adjust_qunit,
- .quota_pending_commit = quota_pending_commit,
-};
-
-cfs_proc_dir_entry_t *lquota_type_proc_dir = NULL;
-
-int init_lustre_quota(void)
-{
- 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);
- PORTAL_SYMBOL_REGISTER(mds_quota_interface);
-
- return 0;
-}
-
-void exit_lustre_quota(void)
-{
- PORTAL_SYMBOL_UNREGISTER(filter_quota_interface);
- PORTAL_SYMBOL_UNREGISTER(mds_quota_interface);
-
- qunit_cache_cleanup();
-
- if (lquota_type_proc_dir)
- lprocfs_remove(&lquota_type_proc_dir);
-}
-
-EXPORT_SYMBOL(mds_quota_interface);
-EXPORT_SYMBOL(filter_quota_interface);
-#endif /* __KERNEL */
+++ /dev/null
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-#ifndef __QUOTA_INTERNAL_H
-#define __QUOTA_INTERNAL_H
-
-#include <lustre_quota.h>
-
-/* QUSG covnert bytes to blocks when counting block quota */
-#define QUSG(count, isblk) (isblk ? toqb(count) : count)
-
-/* 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__
-
-#define DQUOT_DEBUG(dquot, fmt, arg...) \
- CDEBUG(D_QUOTA, "refcnt(%u) id(%u) type(%u) off(%llu) flags(%lu) " \
- "bhardlimit("LPU64") curspace("LPU64") ihardlimit("LPU64") " \
- "curinodes("LPU64"): " fmt, cfs_atomic_read(&dquot->dq_refcnt),\
- dquot->dq_id, dquot->dq_type, dquot->dq_off, dquot->dq_flags, \
- dquot->dq_dqb.dqb_bhardlimit, dquot->dq_dqb.dqb_curspace, \
- dquot->dq_dqb.dqb_ihardlimit, dquot->dq_dqb.dqb_curinodes, \
- ## arg); \
-
-#define QINFO_DEBUG(qinfo, fmt, arg...) \
- CDEBUG(D_QUOTA, "files (%p/%p) flags(%lu/%lu) blocks(%u/%u) " \
- "free_blk(/%u/%u) free_entry(%u/%u): " fmt, \
- qinfo->qi_files[0], qinfo->qi_files[1], \
- qinfo->qi_info[0].dqi_flags, qinfo->qi_info[1].dqi_flags, \
- qinfo->qi_info[0].dqi_blocks, qinfo->qi_info[1].dqi_blocks, \
- qinfo->qi_info[0].dqi_free_blk, qinfo->qi_info[1].dqi_free_blk,\
- qinfo->qi_info[0].dqi_free_entry, \
- qinfo->qi_info[1].dqi_free_entry, ## arg);
-
-#define QDATA_DEBUG(qd, fmt, arg...) \
- CDEBUG(D_QUOTA, "id(%u) flag(%u) type(%c) isblk(%c) count("LPU64") " \
- "qd_qunit("LPU64"): " fmt, qd->qd_id, qd->qd_flags, \
- QDATA_IS_GRP(qd) ? 'g' : 'u', QDATA_IS_BLK(qd) ? 'b': 'i', \
- qd->qd_count, \
- (QDATA_IS_ADJBLK(qd) | QDATA_IS_ADJINO(qd)) ? qd->qd_qunit : 0,\
- ## arg);
-
-#define QAQ_DEBUG(qaq, fmt, arg...) \
- CDEBUG(D_QUOTA, "id(%u) flag(%u) type(%c) bunit("LPU64") " \
- "iunit("LPU64"): " fmt, qaq->qaq_id, qaq->qaq_flags, \
- QAQ_IS_GRP(qaq) ? 'g': 'u', qaq->qaq_bunit_sz, \
- qaq->qaq_iunit_sz, ## arg);
-
-#define LQS_DEBUG(lqs, fmt, arg...) \
- CDEBUG(D_QUOTA, "lqs(%p) id(%u) flag(%lu) type(%c) bunit(%lu) " \
- "btune(%lu) iunit(%lu) itune(%lu) lqs_bwrite_pending(%lu) " \
- "lqs_iwrite_pending(%lu) ino_rec(%lld) blk_rec(%lld) " \
- "refcount(%d): " \
- fmt, lqs, lqs->lqs_id, lqs->lqs_flags, \
- LQS_IS_GRP(lqs) ? 'g' : 'u', \
- lqs->lqs_bunit_sz, lqs->lqs_btune_sz, lqs->lqs_iunit_sz, \
- lqs->lqs_itune_sz, lqs->lqs_bwrite_pending, \
- lqs->lqs_iwrite_pending, lqs->lqs_ino_rec, \
- lqs->lqs_blk_rec, cfs_atomic_read(&lqs->lqs_refcount), ## arg);
-
-
-/* quota_context.c */
-void qunit_cache_cleanup(void);
-int qunit_cache_init(void);
-int qctxt_adjust_qunit(struct obd_device *obd, struct lustre_quota_ctxt *qctxt,
- const unsigned int id[], __u32 isblk, int wait,
- struct obd_trans_info *oti);
-int qctxt_wait_pending_dqacq(struct lustre_quota_ctxt *qctxt, unsigned int id,
- unsigned short type, int isblk);
-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);
-int compute_remquota(struct obd_device *obd,
- struct lustre_quota_ctxt *qctxt, struct qunit_data *qdata,
- int isblk);
-int check_qm(struct lustre_quota_ctxt *qctxt);
-void dqacq_interrupt(struct lustre_quota_ctxt *qctxt);
-int quota_is_on(struct lustre_quota_ctxt *qctxt, struct obd_quotactl *oqctl);
-int quota_is_off(struct lustre_quota_ctxt *qctxt, struct obd_quotactl *oqctl);
-void* quota_barrier(struct lustre_quota_ctxt *qctxt,
- struct obd_quotactl *oqctl, int isblk);
-void quota_unbarrier(void *handle);
-/* quota_master.c */
-int lustre_dquot_init(void);
-void lustre_dquot_exit(void);
-int dqacq_handler(struct obd_device *obd, struct qunit_data *qdata, int opc);
-int mds_quota_adjust(struct obd_device *obd, const unsigned int qcids[],
- const unsigned int qpids[], int rc, int opc);
-int filter_quota_adjust(struct obd_device *obd, const unsigned int qcids[],
- const unsigned int qpids[], int rc, int opc);
-int init_admin_quotafiles(struct obd_device *obd, struct obd_quotactl *oqctl);
-int mds_quota_get_version(struct obd_device *obd, lustre_quota_version_t *ver);
-int mds_quota_invalidate(struct obd_device *obd, struct obd_quotactl *oqctl);
-int mds_quota_finvalidate(struct obd_device *obd, struct obd_quotactl *oqctl);
-
-int mds_admin_quota_on(struct obd_device *obd, struct obd_quotactl *oqctl);
-int mds_quota_on(struct obd_device *obd, struct obd_quotactl *oqctl);
-int mds_quota_off(struct obd_device *obd, struct obd_quotactl *oqctl);
-int do_mds_quota_off(struct obd_device *obd, struct obd_quotactl *oqctl);
-int mds_admin_quota_off(struct obd_device *obd, struct obd_quotactl *oqctl);
-int mds_set_dqinfo(struct obd_device *obd, struct obd_quotactl *oqctl);
-int mds_get_dqinfo(struct obd_device *obd, struct obd_quotactl *oqctl);
-int mds_set_dqblk(struct obd_device *obd, struct obd_quotactl *oqctl);
-int mds_get_dqblk(struct obd_device *obd, struct obd_quotactl *oqctl);
-int mds_quota_recovery(struct obd_device *obd);
-int mds_get_obd_quota(struct obd_device *obd, struct obd_quotactl *oqctl);
-int dquot_create_oqaq(struct lustre_quota_ctxt *qctxt, struct lustre_dquot
- *dquot, __u32 ost_num, __u32 mdt_num, int type,
- struct quota_adjust_qunit *oqaq);
-int generic_quota_on(struct obd_device *, struct obd_quotactl *, int);
-#endif
-
-/* quota_ctl.c */
-int mds_quota_ctl(struct obd_device *obd, struct obd_export *exp,
- struct obd_quotactl *oqctl);
-int filter_quota_ctl(struct obd_device *unused, struct obd_export *exp,
- struct obd_quotactl *oqctl);
-
-/* quota_chk.c */
-int target_quota_check(struct obd_device *obd, struct obd_export *exp,
- struct obd_quotactl *oqctl);
-
-int quota_adjust_slave_lqs(struct quota_adjust_qunit *oqaq, struct
- lustre_quota_ctxt *qctxt);
-#ifdef __KERNEL__
-int quota_is_set(struct obd_device *obd, const unsigned int id[], int flag);
-struct lustre_qunit_size *quota_search_lqs(unsigned long long lqs_key,
- struct lustre_quota_ctxt *qctxt,
- int create);
-void quota_compute_lqs(struct qunit_data *qdata, struct lustre_qunit_size *lqs,
- int is_chk, int is_acq);
-
-
-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,
- struct lustre_quota_ctxt *qctxt,
- struct ptlrpc_request_set *rqset);
-int lquota_proc_setup(struct obd_device *obd, int is_master);
-int lquota_proc_cleanup(struct lustre_quota_ctxt *qctxt);
-void build_lqs(struct obd_device *obd);
-
-extern cfs_proc_dir_entry_t *lquota_type_proc_dir;
-#endif
-
-#define LQS_BLK_DECREASE 1
-#define LQS_BLK_INCREASE 2
-#define LQS_INO_DECREASE 4
-#define LQS_INO_INCREASE 8
-
-/* the return status of quota operation */
-#define QUOTA_REQ_RETURNED 1
-
-#endif
+++ /dev/null
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Whamcloud, Inc.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/quota/quota_master.c
- *
- * Lustre Quota Master request handler
- *
- * Author: Niu YaWei <niu@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_LQUOTA
-
-#include <linux/version.h>
-#include <linux/fs.h>
-#include <asm/unistd.h>
-#include <linux/slab.h>
-#include <linux/quotaops.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/quota.h>
-
-#include <obd_class.h>
-#include <lustre_quota.h>
-#include <lustre_fsfilt.h>
-#include <lustre_mds.h>
-
-#include "quota_internal.h"
-
-/* lock ordering: mds->mds_qonoff_sem > dquot->dq_mutex > lqs->lqs_lock */
-static cfs_list_t lustre_dquot_hash[NR_DQHASH];
-static DEFINE_RWLOCK(dquot_hash_lock);
-
-cfs_mem_cache_t *lustre_dquot_cachep;
-
-int lustre_dquot_init(void)
-{
- int i;
- ENTRY;
-
- LASSERT(lustre_dquot_cachep == NULL);
- lustre_dquot_cachep = cfs_mem_cache_create("lustre_dquot_cache",
- sizeof(struct lustre_dquot),
- 0, 0);
- if (!lustre_dquot_cachep)
- return (-ENOMEM);
-
- for (i = 0; i < NR_DQHASH; i++) {
- CFS_INIT_LIST_HEAD(lustre_dquot_hash + i);
- }
- RETURN(0);
-}
-
-void lustre_dquot_exit(void)
-{
- int i;
- ENTRY;
- /* FIXME cleanup work ?? */
-
- for (i = 0; i < NR_DQHASH; i++) {
- LASSERT(cfs_list_empty(lustre_dquot_hash + i));
- }
- if (lustre_dquot_cachep) {
- int rc;
- rc = cfs_mem_cache_destroy(lustre_dquot_cachep);
- LASSERTF(rc == 0,"couldn't destroy lustre_dquot_cachep slab\n");
- lustre_dquot_cachep = NULL;
- }
- EXIT;
-}
-
-static inline int
-dquot_hashfn(struct lustre_quota_info *info, unsigned int id, int type)
- __attribute__((__const__));
-
-static inline int
-dquot_hashfn(struct lustre_quota_info *info, unsigned int id, int type)
-{
- unsigned long tmp = ((unsigned long)info >> L1_CACHE_SHIFT) ^ id;
- tmp = (tmp * (MAXQUOTAS - type)) % NR_DQHASH;
- return tmp;
-}
-
-/* caller must hold dquot_hash_lock */
-static struct lustre_dquot *find_dquot(int hashent,
- struct lustre_quota_info *lqi, qid_t id,
- int type)
-{
- struct lustre_dquot *dquot;
- ENTRY;
-
- cfs_list_for_each_entry(dquot, &lustre_dquot_hash[hashent], dq_hash) {
- if (dquot->dq_info == lqi &&
- dquot->dq_id == id && dquot->dq_type == type)
- RETURN(dquot);
- }
- RETURN(NULL);
-}
-
-static struct lustre_dquot *alloc_dquot(struct lustre_quota_info *lqi,
- qid_t id, int type)
-{
- struct lustre_dquot *dquot = NULL;
- ENTRY;
-
- OBD_SLAB_ALLOC_PTR_GFP(dquot, lustre_dquot_cachep, CFS_ALLOC_IO);
- if (dquot == NULL)
- RETURN(NULL);
-
- CFS_INIT_LIST_HEAD(&dquot->dq_hash);
- cfs_mutex_init(&dquot->dq_mutex);
- cfs_mutex_lock(&dquot->dq_mutex);
- cfs_atomic_set(&dquot->dq_refcnt, 1);
- dquot->dq_info = lqi;
- dquot->dq_id = id;
- dquot->dq_type = type;
-
- RETURN(dquot);
-}
-
-static void free_dquot(struct lustre_dquot *dquot)
-{
- OBD_SLAB_FREE(dquot, lustre_dquot_cachep, sizeof(*dquot));
-}
-
-static void insert_dquot_nolock(struct lustre_dquot *dquot)
-{
- cfs_list_t *head = lustre_dquot_hash +
- dquot_hashfn(dquot->dq_info, dquot->dq_id, dquot->dq_type);
- LASSERT(cfs_list_empty(&dquot->dq_hash));
- cfs_list_add(&dquot->dq_hash, head);
-}
-
-static void remove_dquot_nolock(struct lustre_dquot *dquot)
-{
- LASSERT(!cfs_list_empty(&dquot->dq_hash));
- cfs_list_del_init(&dquot->dq_hash);
-}
-
-static void lustre_dqput(struct lustre_dquot *dquot)
-{
- ENTRY;
- cfs_write_lock(&dquot_hash_lock);
- LASSERT(cfs_atomic_read(&dquot->dq_refcnt));
- cfs_atomic_dec(&dquot->dq_refcnt);
- if (cfs_atomic_read(&dquot->dq_refcnt) == 0) {
- remove_dquot_nolock(dquot);
- free_dquot(dquot);
- }
- cfs_write_unlock(&dquot_hash_lock);
- EXIT;
-}
-
-static struct lustre_dquot *lustre_dqget(struct obd_device *obd,
- struct lustre_quota_info *lqi,
- qid_t id, int type, int can_fake)
-{
- unsigned int hashent = dquot_hashfn(lqi, id, type);
- struct lustre_dquot *dquot, *empty;
- int free_dq = 0;
- ENTRY;
-
- if ((empty = alloc_dquot(lqi, id, type)) == NULL)
- RETURN(ERR_PTR(-ENOMEM));
-
- cfs_read_lock(&dquot_hash_lock);
- if ((dquot = find_dquot(hashent, lqi, id, type)) != NULL) {
- cfs_atomic_inc(&dquot->dq_refcnt);
- cfs_read_unlock(&dquot_hash_lock);
- cfs_mutex_unlock(&empty->dq_mutex);
- free_dq = 1;
- } else {
- int rc;
-
- cfs_read_unlock(&dquot_hash_lock);
-
- dquot = empty;
- rc = fsfilt_dquot(obd, dquot, QFILE_RD_DQUOT);
- cfs_mutex_unlock(&dquot->dq_mutex);
- if (rc) {
- CERROR("can't read dquot from admin quotafile! "
- "(rc:%d)\n", rc);
- free_dquot(dquot);
- RETURN(ERR_PTR(rc));
- } else {
- cfs_write_lock(&dquot_hash_lock);
- if ((dquot = find_dquot(hashent, lqi, id, type)) != NULL) {
- cfs_atomic_inc(&dquot->dq_refcnt);
- free_dq = 1;
- } else {
- dquot = empty;
- insert_dquot_nolock(dquot);
- }
- cfs_write_unlock(&dquot_hash_lock);
- }
-
- }
-
- LASSERT(dquot);
- if (!can_fake && cfs_test_bit(DQ_FAKE_B, &dquot->dq_flags)) {
- DQUOT_DEBUG(dquot, "It is a fake dquot: unexpected!\n");
- lustre_dqput(dquot);
- dquot = ERR_PTR(-ENOENT);
- }
-
- if (free_dq)
- free_dquot(empty);
-
-
- RETURN(dquot);
-}
-
-static void init_oqaq(struct quota_adjust_qunit *oqaq,
- struct lustre_quota_ctxt *qctxt,
- qid_t id, int type)
-{
- struct lustre_qunit_size *lqs = NULL;
-
- oqaq->qaq_id = id;
- oqaq->qaq_flags = type;
- lqs = quota_search_lqs(LQS_KEY(type, id), qctxt, 0);
- if (lqs && !IS_ERR(lqs)) {
- cfs_spin_lock(&lqs->lqs_lock);
- oqaq->qaq_bunit_sz = lqs->lqs_bunit_sz;
- oqaq->qaq_iunit_sz = lqs->lqs_iunit_sz;
- oqaq->qaq_flags = lqs->lqs_flags;
- cfs_spin_unlock(&lqs->lqs_lock);
- lqs_putref(lqs);
- } else {
- CDEBUG(D_QUOTA, "Can't find the lustre qunit size!\n");
- oqaq->qaq_bunit_sz = qctxt->lqc_bunit_sz;
- oqaq->qaq_iunit_sz = qctxt->lqc_iunit_sz;
- }
-}
-
-int dqacq_adjust_qunit_sz(struct obd_device *obd, qid_t id, int type,
- __u32 is_blk)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct lustre_quota_ctxt *qctxt = &mds->mds_obt.obt_qctxt;
- __u32 ost_num = mds->mds_lov_objid_count, mdt_num = 1;
- struct quota_adjust_qunit *oqaq = NULL;
- unsigned int qid[MAXQUOTAS] = { 0, 0 };
- struct lustre_quota_info *info = &mds->mds_quota_info;
- struct lustre_dquot *dquot = NULL;
- int adjust_res = 0;
- int rc = 0;
- ENTRY;
-
- LASSERT(mds);
- cfs_down_read(&mds->mds_qonoff_sem);
- dquot = lustre_dqget(obd, info, id, type, 0);
- if (IS_ERR(dquot))
- RETURN(PTR_ERR(dquot));
-
- cfs_up_read(&mds->mds_qonoff_sem);
- OBD_ALLOC_PTR(oqaq);
- if (!oqaq)
- GOTO(out, rc = -ENOMEM);
-
- cfs_mutex_lock(&dquot->dq_mutex);
- init_oqaq(oqaq, qctxt, id, type);
-
- rc = dquot_create_oqaq(qctxt, dquot, ost_num, mdt_num,
- is_blk ? LQUOTA_FLAGS_ADJBLK :
- LQUOTA_FLAGS_ADJINO, oqaq);
-
- if (rc < 0) {
- CERROR("create oqaq failed! (rc:%d)\n", rc);
- GOTO(out_sem, rc);
- }
- QAQ_DEBUG(oqaq, "show oqaq.\n")
-
- if (!QAQ_IS_ADJBLK(oqaq) && !QAQ_IS_ADJINO(oqaq))
- GOTO(out_sem, rc);
-
- /* adjust the mds slave qunit size */
- adjust_res = quota_adjust_slave_lqs(oqaq, qctxt);
- if (adjust_res <= 0) {
- if (adjust_res < 0) {
- rc = adjust_res;
- CERROR("adjust mds slave's qunit size failed! "
- "(rc:%d)\n", rc);
- } else {
- CDEBUG(D_QUOTA, "qunit doesn't need to be adjusted.\n");
- }
- GOTO(out_sem, rc);
- }
-
- if (type)
- qid[GRPQUOTA] = dquot->dq_id;
- else
- qid[USRQUOTA] = dquot->dq_id;
-
- cfs_mutex_unlock(&dquot->dq_mutex);
-
- rc = qctxt_adjust_qunit(obd, qctxt, qid, is_blk, 0, NULL);
- if (rc == -EDQUOT || rc == -EBUSY) {
- CDEBUG(D_QUOTA, "rc: %d.\n", rc);
- rc = 0;
- }
- if (rc) {
- CERROR("%s: mds fail to adjust file quota! (rc:%d)\n",
- obd->obd_name, rc);
- GOTO(out, rc);
- }
-
- /* 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_lov_exp, oqaq, qctxt, NULL);
-
-out:
- lustre_dqput(dquot);
- if (oqaq)
- OBD_FREE_PTR(oqaq);
-
- RETURN(rc);
-out_sem:
- cfs_mutex_unlock(&dquot->dq_mutex);
- goto out;
-}
-
-int dqacq_handler(struct obd_device *obd, struct qunit_data *qdata, int opc)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct lustre_quota_ctxt *qctxt = &mds->mds_obt.obt_qctxt;
- struct lustre_quota_info *info = &mds->mds_quota_info;
- struct lustre_dquot *dquot = NULL;
- __u64 *usage = NULL;
- __u64 hlimit = 0, slimit = 0;
- time_t *time = NULL;
- unsigned int grace = 0;
- struct lustre_qunit_size *lqs = NULL;
- int rc = 0;
- ENTRY;
-
- if (OBD_FAIL_CHECK(OBD_FAIL_OBD_DQACQ))
- RETURN(-EIO);
-
- if (!sb_has_quota_active(qctxt->lqc_sb,
- QDATA_IS_GRP(qdata) ? GRPQUOTA : USRQUOTA))
- RETURN(-EIO);
-
- lqs = quota_search_lqs(LQS_KEY(QDATA_IS_GRP(qdata), qdata->qd_id),
- qctxt, 0);
- if (lqs == NULL)
- rc = -ENOENT;
- if (IS_ERR(lqs))
- rc = PTR_ERR(lqs);
- if (rc)
- RETURN(rc);
-
- cfs_spin_lock(&lqs->lqs_lock);
- if (LQS_IS_RECOVERY(lqs)) {
- cfs_spin_unlock(&lqs->lqs_lock);
- LQS_DEBUG(lqs, "this lqs is under recovery\n");
- GOTO(skip, rc = -EBUSY);
- }
- cfs_spin_unlock(&lqs->lqs_lock);
-
- cfs_down_write(&mds->mds_qonoff_sem);
- dquot = lustre_dqget(obd, info, qdata->qd_id, QDATA_IS_GRP(qdata), 0);
- if (IS_ERR(dquot)) {
- cfs_up_write(&mds->mds_qonoff_sem);
- GOTO(skip, rc = PTR_ERR(dquot));
- }
-
- DQUOT_DEBUG(dquot, "get dquot in dqacq_handler\n");
- QINFO_DEBUG(dquot->dq_info, "get dquot in dqadq_handler\n");
-
- cfs_mutex_lock(&dquot->dq_mutex);
-
- if (QDATA_IS_BLK(qdata)) {
- grace = info->qi_info[QDATA_IS_GRP(qdata)].dqi_bgrace;
- usage = &dquot->dq_dqb.dqb_curspace;
- hlimit = dquot->dq_dqb.dqb_bhardlimit;
- slimit = dquot->dq_dqb.dqb_bsoftlimit;
- time = &dquot->dq_dqb.dqb_btime;
- } else {
- grace = info->qi_info[QDATA_IS_GRP(qdata)].dqi_igrace;
- usage = (__u64 *) & dquot->dq_dqb.dqb_curinodes;
- hlimit = dquot->dq_dqb.dqb_ihardlimit;
- slimit = dquot->dq_dqb.dqb_isoftlimit;
- time = &dquot->dq_dqb.dqb_itime;
- }
-
- /* if the quota limit in admin quotafile is zero, we just inform
- * slave to clear quota limit with zero qd_count */
- if (hlimit == 0 && slimit == 0) {
- qdata->qd_count = 0;
- GOTO(out, rc);
- }
-
- switch (opc) {
- case QUOTA_DQACQ:
- if (hlimit &&
- QUSG(*usage + qdata->qd_count, QDATA_IS_BLK(qdata)) > hlimit)
- {
- if (QDATA_IS_CHANGE_QS(qdata) &&
- QUSG(*usage, QDATA_IS_BLK(qdata)) < hlimit)
- qdata->qd_count = (hlimit -
- QUSG(*usage, QDATA_IS_BLK(qdata)))
- * (QDATA_IS_BLK(qdata) ?
- QUOTABLOCK_SIZE : 1);
- else
- GOTO(out, rc = -EDQUOT);
- }
-
- if (slimit &&
- QUSG(*usage + qdata->qd_count, QDATA_IS_BLK(qdata)) > slimit) {
- if (*time && cfs_time_current_sec() >= *time)
- GOTO(out, rc = -EDQUOT);
- else if (!*time)
- *time = cfs_time_current_sec() + grace;
- }
-
- *usage += qdata->qd_count;
- break;
- case QUOTA_DQREL:
- /* The usage in administrative file might be incorrect before
- * recovery done */
- if (*usage < qdata->qd_count)
- *usage = 0;
- else
- *usage -= qdata->qd_count;
-
- /* (usage <= soft limit) but not (usage < soft limit) */
- if (!slimit || QUSG(*usage, QDATA_IS_BLK(qdata)) <= slimit)
- *time = 0;
- break;
- default:
- LBUG();
- }
-
- rc = fsfilt_dquot(obd, dquot, QFILE_WR_DQUOT);
- EXIT;
-out:
- cfs_mutex_unlock(&dquot->dq_mutex);
- cfs_up_write(&mds->mds_qonoff_sem);
- lustre_dqput(dquot);
- if (rc != -EDQUOT)
- dqacq_adjust_qunit_sz(obd, qdata->qd_id, QDATA_IS_GRP(qdata),
- QDATA_IS_BLK(qdata));
-
- cfs_spin_lock(&lqs->lqs_lock);
- qdata->qd_qunit = QDATA_IS_BLK(qdata) ? lqs->lqs_bunit_sz :
- lqs->lqs_iunit_sz;
- cfs_spin_unlock(&lqs->lqs_lock);
-
- if (QDATA_IS_BLK(qdata))
- QDATA_SET_ADJBLK(qdata);
- else
- QDATA_SET_ADJINO(qdata);
-
- QDATA_DEBUG(qdata, "alloc/release qunit in dqacq_handler\n");
-skip:
- lqs_putref(lqs);
-
- return rc;
-}
-
-int mds_quota_adjust(struct obd_device *obd, const unsigned int qcids[],
- const unsigned int qpids[], int rc, int opc)
-{
- struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
- int rc2 = 0;
- ENTRY;
-
- if (rc && rc != -EDQUOT && rc != ENOLCK)
- RETURN(0);
-
- switch (opc) {
- case FSFILT_OP_SETATTR:
- /* release file quota on original owner */
- rc2 |= qctxt_adjust_qunit(obd, qctxt, qpids, 0, 0, NULL);
- /* release block quota on original owner */
- rc2 |= qctxt_adjust_qunit(obd, qctxt, qpids, 1, 0, NULL);
- /* acquire file quota on current owner */
- rc2 |= qctxt_adjust_qunit(obd, qctxt, qcids, 0, 0, NULL);
- /* acquire block quota on current owner */
- rc2 |= qctxt_adjust_qunit(obd, qctxt, qcids, 1, 0, NULL);
- break;
- case FSFILT_OP_UNLINK_PARTIAL_CHILD:
- /* release file quota on child */
- rc2 |= qctxt_adjust_qunit(obd, qctxt, qcids, 0, 0, NULL);
- /* rlease block quota on child */
- rc2 |= qctxt_adjust_qunit(obd, qctxt, qcids, 1, 0, NULL);
- break;
- case FSFILT_OP_CREATE_PARTIAL_CHILD:
- /* acquire file quota on child */
- rc2 |= qctxt_adjust_qunit(obd, qctxt, qcids, 0, 0, NULL);
- /* acquire block quota on child */
- rc2 |= qctxt_adjust_qunit(obd, qctxt, qcids, 1, 0, NULL);
- break;
- case FSFILT_OP_LINK:
- /* acquire block quota on parent */
- rc2 |= qctxt_adjust_qunit(obd, qctxt, qpids, 1, 0, NULL);
- break;
- case FSFILT_OP_UNLINK:
- /* release block quota on parent */
- rc2 |= qctxt_adjust_qunit(obd, qctxt, qpids, 1, 0, NULL);
- /* release file quota on child */
- rc2 |= qctxt_adjust_qunit(obd, qctxt, qcids, 0, 0, NULL);
- if (qpids[0] != qcids[0] || qpids[1] != qcids[1])
- /* release block quota on child */
- rc2 |= qctxt_adjust_qunit(obd, qctxt, qcids, 1, 0,
- NULL);
- break;
- case FSFILT_OP_UNLINK_PARTIAL_PARENT:
- /* release block quota on parent */
- rc2 |= qctxt_adjust_qunit(obd, qctxt, qpids, 1, 0, NULL);
- break;
- case FSFILT_OP_CREATE:
- /* acquire block quota on parent */
- rc2 |= qctxt_adjust_qunit(obd, qctxt, qpids, 1, 0, NULL);
- /* acquire file quota on child */
- rc2 |= qctxt_adjust_qunit(obd, qctxt, qcids, 0, 0, NULL);
- if (qpids[0] != qcids[0] || qpids[1] != qcids[1])
- /* acquire block quota on child */
- rc2 |= qctxt_adjust_qunit(obd, qctxt, qcids, 1, 0,
- NULL);
- break;
- default:
- LBUG();
- break;
- }
-
- if (rc2)
- CDEBUG(D_QUOTA,
- "mds adjust qunit %ssuccessfully! (opc:%d rc:%d)\n",
- rc2 == QUOTA_REQ_RETURNED ? "" : "un", opc, rc2);
- RETURN(0);
-}
-
-int filter_quota_adjust(struct obd_device *obd, const unsigned int qcids[],
- const unsigned int qpids[], int rc, int opc)
-{
- struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
- int rc2 = 0;
- ENTRY;
-
- if (rc && rc != -EDQUOT)
- RETURN(0);
-
- switch (opc) {
- case FSFILT_OP_SETATTR:
- /* acquire/release block quota on original & current owner */
- rc = qctxt_adjust_qunit(obd, qctxt, qcids, 1, 0, NULL);
- rc2 = qctxt_adjust_qunit(obd, qctxt, qpids, 1, 0, NULL);
- break;
- case FSFILT_OP_UNLINK:
- /* release block quota on this owner */
- case FSFILT_OP_CREATE: /* XXX for write operation on obdfilter */
- /* acquire block quota on this owner */
- rc = qctxt_adjust_qunit(obd, qctxt, qcids, 1, 0, NULL);
- break;
- default:
- LBUG();
- break;
- }
-
- if (rc || rc2) {
- if (!rc)
- rc = rc2;
- CDEBUG(D_QUOTA,
- "filter adjust qunit %ssuccessfully! (opc:%d rc%d)\n",
- rc == QUOTA_REQ_RETURNED ? "" : "un", opc, rc);
- }
-
- RETURN(0);
-}
-
-static const char prefix[] = "OBJECTS/";
-
-int mds_quota_invalidate(struct obd_device *obd, struct obd_quotactl *oqctl)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct lustre_quota_info *qinfo = &mds->mds_quota_info;
- struct obd_device_target *obt = &obd->u.obt;
- int rc = 0, i, rc1 = 0;
- char *quotafile[] = LUSTRE_ADMIN_QUOTAFILES_V2;
- char name[64];
- struct lvfs_run_ctxt saved;
- ENTRY;
-
- LASSERT(qinfo->qi_version == LUSTRE_QUOTA_V2);
-
- if (oqctl->qc_type != USRQUOTA &&
- oqctl->qc_type != GRPQUOTA &&
- oqctl->qc_type != UGQUOTA)
- RETURN(-EINVAL);
-
- cfs_down(&obt->obt_quotachecking);
- push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- cfs_down_write(&mds->mds_qonoff_sem);
-
- for (i = 0; i < MAXQUOTAS; i++) {
- struct file *fp;
-
- if (!Q_TYPESET(oqctl, i))
- continue;
-
- /* quota file has been opened ? */
- if (qinfo->qi_files[i]) {
- CWARN("quota[%d] is on yet\n", i);
- rc1 = -EBUSY;
- continue;
- }
-
- LASSERT(strlen(quotafile[i]) + sizeof(prefix) <= sizeof(name));
- sprintf(name, "%s%s", prefix, quotafile[i]);
-
- fp = filp_open(name, O_CREAT | O_TRUNC | O_RDWR, 0644);
- if (IS_ERR(fp)) {
- rc = PTR_ERR(fp);
- CERROR("%s: error invalidating admin quotafile %s (rc:%d)\n",
- obd->obd_name, name, rc);
- }
- else
- filp_close(fp, 0);
- }
-
- cfs_up_write(&mds->mds_qonoff_sem);
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- cfs_up(&obt->obt_quotachecking);
- RETURN(rc ? : rc1);
-}
-
-int mds_quota_finvalidate(struct obd_device *obd, struct obd_quotactl *oqctl)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct obd_device_target *obt = &obd->u.obt;
- int rc;
- struct lvfs_run_ctxt saved;
- ENTRY;
-
- if (oqctl->qc_type != USRQUOTA &&
- oqctl->qc_type != GRPQUOTA &&
- oqctl->qc_type != UGQUOTA)
- RETURN(-EINVAL);
-
- cfs_down(&obt->obt_quotachecking);
- if (obt->obt_qctxt.lqc_flags & UGQUOTA2LQC(oqctl->qc_type))
- GOTO(out, rc = -EBUSY);
- push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- cfs_down_write(&mds->mds_qonoff_sem);
-
- oqctl->qc_cmd = Q_FINVALIDATE;
- rc = fsfilt_quotactl(obd, obd->u.obt.obt_sb, oqctl);
- if (!rc)
- rc = obd_quotactl(mds->mds_lov_exp, oqctl);
-
- cfs_up_write(&mds->mds_qonoff_sem);
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
-out:
- cfs_up(&obt->obt_quotachecking);
- RETURN(rc);
-}
-
-int init_admin_quotafiles(struct obd_device *obd, struct obd_quotactl *oqctl)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct lustre_quota_info *qinfo = &mds->mds_quota_info;
- const char *quotafile[] = LUSTRE_ADMIN_QUOTAFILES_V2;
- struct lvfs_run_ctxt saved;
- char name[64];
- int i, rc = 0;
- ENTRY;
-
- LASSERT(qinfo->qi_version == LUSTRE_QUOTA_V2);
-
- push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- cfs_down_write(&mds->mds_qonoff_sem);
-
- for (i = 0; i < MAXQUOTAS && !rc; i++) {
- struct file *fp;
-
- if (!Q_TYPESET(oqctl, i))
- continue;
-
- /* quota file has been opened ? */
- if (qinfo->qi_files[i]) {
- CWARN("init %s admin quotafile while quota on.\n",
- i == USRQUOTA ? "user" : "group");
- continue;
- }
-
- LASSERT(strlen(quotafile[i]) + sizeof(prefix) <= sizeof(name));
- sprintf(name, "%s%s", prefix, quotafile[i]);
-
- /* check if quota file exists and is correct */
- fp = filp_open(name, O_RDONLY, 0);
- if (!IS_ERR(fp)) {
- /* irregular file is not the right place for quota */
- if (!S_ISREG(fp->f_dentry->d_inode->i_mode)) {
- CERROR("admin quota file %s is not "
- "regular!", name);
- filp_close(fp, 0);
- rc = -EINVAL;
- break;
- }
- qinfo->qi_files[i] = fp;
- rc = fsfilt_quotainfo(obd, qinfo, i, QFILE_CHK);
- qinfo->qi_files[i] = NULL;
- filp_close(fp, 0);
- }
- else
- rc = PTR_ERR(fp);
-
- if (!rc)
- continue;
-
- /* -EINVAL may be returned by quotainfo for bad quota file */
- if (rc != -ENOENT && rc != -EINVAL) {
- CERROR("%s: error opening old quota file %s (%d)\n",
- obd->obd_name, name, rc);
- break;
- }
-
- CDEBUG(D_INFO, "%s new quota file %s\n", name,
- rc == -ENOENT ? "creating" : "overwriting");
-
- /* create quota file overwriting old if needed */
- fp = filp_open(name, O_CREAT | O_TRUNC | O_RDWR, 0644);
- if (IS_ERR(fp)) {
- rc = PTR_ERR(fp);
- CERROR("%s: error creating admin quotafile %s (rc:%d)\n",
- obd->obd_name, name, rc);
- break;
- }
-
- qinfo->qi_files[i] = fp;
-
- rc = fsfilt_quotainfo(obd, qinfo, i, QFILE_INIT_INFO);
- if (rc)
- CERROR("error init %s admin quotafile! (rc:%d)\n",
- i == USRQUOTA ? "user" : "group", rc);
-
- filp_close(fp, 0);
- qinfo->qi_files[i] = NULL;
- }
-
- cfs_up_write(&mds->mds_qonoff_sem);
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- RETURN(rc);
-}
-
-static int close_quota_files(struct obd_quotactl *oqctl,
- struct lustre_quota_info *qinfo)
-{
- int i, rc = 0;
- ENTRY;
-
- for (i = 0; i < MAXQUOTAS; i++) {
- if (!Q_TYPESET(oqctl, i))
- continue;
- if (qinfo->qi_files[i] == NULL) {
- CDEBUG(D_QUOTA, "quota[%d] is off already\n", i);
- rc = -EALREADY;
- continue;
- }
- filp_close(qinfo->qi_files[i], 0);
- qinfo->qi_files[i] = NULL;
- }
- RETURN(rc);
-}
-
-int mds_admin_quota_on(struct obd_device *obd, struct obd_quotactl *oqctl)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct lustre_quota_info *qinfo = &mds->mds_quota_info;
- const char *quotafile[] = LUSTRE_ADMIN_QUOTAFILES_V2;
- char name[64];
- int i, rc = 0, rc1 = 0;
- ENTRY;
-
- LASSERT(qinfo->qi_version == LUSTRE_QUOTA_V2);
-
- /* open admin quota files and read quotafile info */
- for (i = 0; i < MAXQUOTAS; i++) {
- struct file *fp;
-
- if (!Q_TYPESET(oqctl, i) || qinfo->qi_files[i] != NULL)
- continue;
-
- LASSERT(strlen(quotafile[i])
- + sizeof(prefix) <= sizeof(name));
- sprintf(name, "%s%s", prefix, quotafile[i]);
- fp = filp_open(name, O_RDWR, 0);
- if (IS_ERR(fp) || !S_ISREG(fp->f_dentry->d_inode->i_mode)) {
- rc = IS_ERR(fp) ? PTR_ERR(fp) : -EINVAL;
- CERROR("error open/create %s! (rc:%d)\n", name, rc);
- break;
- }
- qinfo->qi_files[i] = fp;
-
- rc = fsfilt_quotainfo(obd, qinfo, i, QFILE_CHK);
- if (rc) {
- CERROR("invalid quota file %s! (rc:%d)\n", name, rc);
- break;
- }
-
- rc = fsfilt_quotainfo(obd, qinfo, i, QFILE_RD_INFO);
- if (rc) {
- CERROR("error read quotainfo of %s! (rc:%d)\n", name,
- rc);
- break;
- }
- }
-
- if (rc && rc1 != -EALREADY)
- close_quota_files(oqctl, qinfo);
-
- RETURN(rc ? : rc1);
-}
-
-int mds_quota_on(struct obd_device *obd, struct obd_quotactl *oqctl)
-{
- int rc;
- ENTRY;
-
- if (oqctl->qc_type != USRQUOTA &&
- oqctl->qc_type != GRPQUOTA &&
- oqctl->qc_type != UGQUOTA)
- RETURN(-EINVAL);
-
- rc = generic_quota_on(obd, oqctl, 1);
-
- RETURN(rc);
-}
-
-
-int mds_admin_quota_off(struct obd_device *obd,
- struct obd_quotactl *oqctl)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct lustre_quota_info *qinfo = &mds->mds_quota_info;
- int rc;
- ENTRY;
-
- /* close admin quota files */
- rc = close_quota_files(oqctl, qinfo);
- RETURN(rc);
-}
-
-
-/* with obt->obt_quotachecking held */
-int do_mds_quota_off(struct obd_device *obd, struct obd_quotactl *oqctl)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct obd_device_target *obt = &obd->u.obt;
- struct lustre_quota_ctxt *qctxt = &obt->obt_qctxt;
- struct lvfs_run_ctxt saved;
- int rc = 0, rc1 = 0, rc2 = 0;
- ENTRY;
-
- LASSERT_SEM_LOCKED(&obt->obt_quotachecking);
-
- if (oqctl->qc_type != USRQUOTA &&
- oqctl->qc_type != GRPQUOTA &&
- oqctl->qc_type != UGQUOTA)
- RETURN(-EINVAL);
-
- push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- cfs_down_write(&mds->mds_qonoff_sem);
- /* close admin quota files */
- rc2 = mds_admin_quota_off(obd, oqctl);
- if (rc2 && rc2 != -EALREADY) {
- CWARN("mds quota[%d] is failed to be off for %d\n", oqctl->qc_type, rc2);
- GOTO(out, rc2);
- }
-
- rc1 = fsfilt_quotactl(obd, obd->u.obt.obt_sb, oqctl);
- if (!rc1) {
- obt->obt_qctxt.lqc_flags &= ~UGQUOTA2LQC(oqctl->qc_type);
- } else if (quota_is_off(qctxt, oqctl)) {
- CWARN("mds local quota[%d] is off already\n", oqctl->qc_type);
- rc1 = -EALREADY;
- } else {
- if (rc2 != -EALREADY) {
- CWARN("mds local quota[%d] is failed to be off for %d\n",
- oqctl->qc_type, rc1);
- oqctl->qc_cmd = Q_QUOTAON;
- mds_admin_quota_on(obd, oqctl);
- oqctl->qc_cmd = Q_QUOTAOFF;
- }
- GOTO(out, rc1);
- }
-
- rc = obd_quotactl(mds->mds_lov_exp, oqctl);
- if (rc && rc != -EALREADY) {
- CWARN("mds remote quota[%d] is failed to be off for %d\n",
- oqctl->qc_type, rc);
- oqctl->qc_cmd = Q_QUOTAON;
- if (rc2 != -EALREADY)
- mds_admin_quota_on(obd, oqctl);
- if (rc1 != -EALREADY) {
- fsfilt_quotactl(obd, obd->u.obt.obt_sb, oqctl);
- qctxt->lqc_flags |= UGQUOTA2LQC(oqctl->qc_type);
- }
- oqctl->qc_cmd = Q_QUOTAOFF;
- }
- EXIT;
-
-out:
- CDEBUG(D_QUOTA, "%s: quotaoff type:flags:rc %u:%lu:%d\n",
- obd->obd_name, oqctl->qc_type, qctxt->lqc_flags, rc);
- cfs_up_write(&mds->mds_qonoff_sem);
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- return rc ? : (rc1 ? : rc2);
-}
-
-int mds_quota_off(struct obd_device *obd, struct obd_quotactl *oqctl)
-{
- struct obd_device_target *obt = &obd->u.obt;
- int rc;
- ENTRY;
-
- cfs_down(&obt->obt_quotachecking);
- rc = do_mds_quota_off(obd, oqctl);
- cfs_up(&obt->obt_quotachecking);
- RETURN(rc);
-}
-
-int mds_set_dqinfo(struct obd_device *obd, struct obd_quotactl *oqctl)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct lustre_quota_info *qinfo = &mds->mds_quota_info;
- struct obd_dqinfo *dqinfo = &oqctl->qc_dqinfo;
- int rc;
- ENTRY;
-
- if (oqctl->qc_type != USRQUOTA &&
- oqctl->qc_type != GRPQUOTA)
- RETURN(-EINVAL);
-
- cfs_down_write(&mds->mds_qonoff_sem);
- if (qinfo->qi_files[oqctl->qc_type] == NULL) {
- CWARN("quota[%u] is off\n", oqctl->qc_type);
- GOTO(out, rc = -ESRCH);
- }
-
- qinfo->qi_info[oqctl->qc_type].dqi_bgrace = dqinfo->dqi_bgrace;
- qinfo->qi_info[oqctl->qc_type].dqi_igrace = dqinfo->dqi_igrace;
- qinfo->qi_info[oqctl->qc_type].dqi_flags = dqinfo->dqi_flags;
-
- rc = fsfilt_quotainfo(obd, qinfo, oqctl->qc_type, QFILE_WR_INFO);
- EXIT;
-
-out:
- cfs_up_write(&mds->mds_qonoff_sem);
- return rc;
-}
-
-int mds_get_dqinfo(struct obd_device *obd, struct obd_quotactl *oqctl)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct lustre_quota_info *qinfo = &mds->mds_quota_info;
- struct obd_dqinfo *dqinfo = &oqctl->qc_dqinfo;
- int rc = 0;
- ENTRY;
-
- if (oqctl->qc_type != USRQUOTA &&
- oqctl->qc_type != GRPQUOTA)
- RETURN(-EINVAL);
-
- cfs_down_read(&mds->mds_qonoff_sem);
- if (qinfo->qi_files[oqctl->qc_type] == NULL) {
- CWARN("quota[%u] is off\n", oqctl->qc_type);
- GOTO(out, rc = -ESRCH);
- }
-
- dqinfo->dqi_bgrace = qinfo->qi_info[oqctl->qc_type].dqi_bgrace;
- dqinfo->dqi_igrace = qinfo->qi_info[oqctl->qc_type].dqi_igrace;
- dqinfo->dqi_flags = qinfo->qi_info[oqctl->qc_type].dqi_flags;
- EXIT;
-
-out:
- cfs_up_read(&mds->mds_qonoff_sem);
- return rc;
-}
-
-int dquot_create_oqaq(struct lustre_quota_ctxt *qctxt,
- struct lustre_dquot *dquot, __u32 ost_num, __u32 mdt_num,
- int type, struct quota_adjust_qunit *oqaq)
-{
- __u64 bunit_curr_o, iunit_curr_o;
- unsigned long shrink_qunit_limit = qctxt->lqc_cqs_boundary_factor;
- unsigned long cqs_factor = qctxt->lqc_cqs_qs_factor;
- __u64 blimit = dquot->dq_dqb.dqb_bhardlimit ?
- dquot->dq_dqb.dqb_bhardlimit : dquot->dq_dqb.dqb_bsoftlimit;
- __u64 ilimit = dquot->dq_dqb.dqb_ihardlimit ?
- dquot->dq_dqb.dqb_ihardlimit : dquot->dq_dqb.dqb_isoftlimit;
- int rc = 0;
- ENTRY;
-
- if (!dquot || !oqaq)
- RETURN(-EINVAL);
- LASSERT_MUTEX_LOCKED(&dquot->dq_mutex);
- LASSERT(oqaq->qaq_iunit_sz);
- LASSERT(oqaq->qaq_bunit_sz);
-
- /* don't change qunit size */
- if (!qctxt->lqc_switch_qs)
- RETURN(rc);
-
- bunit_curr_o = oqaq->qaq_bunit_sz;
- iunit_curr_o = oqaq->qaq_iunit_sz;
-
- if (dquot->dq_type == GRPQUOTA)
- QAQ_SET_GRP(oqaq);
-
- if ((type & LQUOTA_FLAGS_ADJBLK) && blimit) {
- __u64 b_limitation =
- oqaq->qaq_bunit_sz * (ost_num + 1) * shrink_qunit_limit;
- /* enlarge block qunit size */
- while (blimit >
- QUSG(dquot->dq_dqb.dqb_curspace + 2 * b_limitation, 1)) {
- oqaq->qaq_bunit_sz =
- QUSG(oqaq->qaq_bunit_sz * cqs_factor, 1)
- << QUOTABLOCK_BITS;
- if (oqaq->qaq_bunit_sz >= qctxt->lqc_bunit_sz)
- break;
- b_limitation = oqaq->qaq_bunit_sz * (ost_num + 1) *
- shrink_qunit_limit;
- }
-
- if (oqaq->qaq_bunit_sz > qctxt->lqc_bunit_sz)
- oqaq->qaq_bunit_sz = qctxt->lqc_bunit_sz;
-
- /* shrink block qunit size */
- while (blimit <
- QUSG(dquot->dq_dqb.dqb_curspace + b_limitation, 1)) {
- do_div(oqaq->qaq_bunit_sz , cqs_factor);
- oqaq->qaq_bunit_sz = QUSG(oqaq->qaq_bunit_sz, 1) <<
- QUOTABLOCK_BITS;
- b_limitation = oqaq->qaq_bunit_sz * (ost_num + 1) *
- shrink_qunit_limit;
- if (oqaq->qaq_bunit_sz < qctxt->lqc_cqs_least_bunit)
- break;
- }
-
- if (oqaq->qaq_bunit_sz < qctxt->lqc_cqs_least_bunit)
- oqaq->qaq_bunit_sz = qctxt->lqc_cqs_least_bunit;
-
- if (bunit_curr_o != oqaq->qaq_bunit_sz)
- QAQ_SET_ADJBLK(oqaq);
-
- }
-
- if ((type & LQUOTA_FLAGS_ADJINO) && ilimit) {
- __u64 i_limitation =
- oqaq->qaq_iunit_sz * mdt_num * shrink_qunit_limit;
- /* enlarge file qunit size */
- while (ilimit > dquot->dq_dqb.dqb_curinodes
- + 2 * i_limitation) {
- oqaq->qaq_iunit_sz = oqaq->qaq_iunit_sz * cqs_factor;
- if (oqaq->qaq_iunit_sz >= qctxt->lqc_iunit_sz)
- break;
- i_limitation = oqaq->qaq_iunit_sz * mdt_num *
- shrink_qunit_limit;
- }
-
- if (oqaq->qaq_iunit_sz > qctxt->lqc_iunit_sz)
- oqaq->qaq_iunit_sz = qctxt->lqc_iunit_sz;
-
- /* shrink file qunit size */
- while (ilimit < dquot->dq_dqb.dqb_curinodes
- + i_limitation) {
- do_div(oqaq->qaq_iunit_sz, cqs_factor);
- i_limitation = oqaq->qaq_iunit_sz * mdt_num *
- shrink_qunit_limit;
- if (oqaq->qaq_iunit_sz < qctxt->lqc_cqs_least_iunit)
- break;
- }
-
- if (oqaq->qaq_iunit_sz < qctxt->lqc_cqs_least_iunit)
- oqaq->qaq_iunit_sz = qctxt->lqc_cqs_least_iunit;
-
- if (iunit_curr_o != oqaq->qaq_iunit_sz)
- QAQ_SET_ADJINO(oqaq);
-
- }
-
- QAQ_DEBUG(oqaq, "the oqaq computed\n");
-
- RETURN(rc);
-}
-
-static int mds_init_slave_ilimits(struct obd_device *obd,
- struct obd_quotactl *oqctl, int set)
-{
- /* XXX: for file limits only adjust local now */
- struct obd_device_target *obt = &obd->u.obt;
- struct lustre_quota_ctxt *qctxt = &obt->obt_qctxt;
- unsigned int id[MAXQUOTAS] = { 0, 0 };
- struct obd_quotactl *ioqc = NULL;
- struct lustre_qunit_size *lqs;
- int flag;
- int rc;
- ENTRY;
-
- /* if we are going to set zero limit, needn't init slaves */
- if (!oqctl->qc_dqblk.dqb_ihardlimit && !oqctl->qc_dqblk.dqb_isoftlimit &&
- !set)
- RETURN(0);
-
- OBD_ALLOC_PTR(ioqc);
- if (!ioqc)
- RETURN(-ENOMEM);
-
- flag = oqctl->qc_dqblk.dqb_ihardlimit ||
- oqctl->qc_dqblk.dqb_isoftlimit || !set;
- ioqc->qc_cmd = flag ? Q_INITQUOTA : Q_SETQUOTA;
- ioqc->qc_id = oqctl->qc_id;
- ioqc->qc_type = oqctl->qc_type;
- ioqc->qc_dqblk.dqb_valid = QIF_ILIMITS;
- ioqc->qc_dqblk.dqb_ihardlimit = flag ? MIN_QLIMIT : 0;
-
- /* build lqs for mds */
- lqs = quota_search_lqs(LQS_KEY(oqctl->qc_type, oqctl->qc_id),
- qctxt, flag ? 1 : 0);
- if (lqs && !IS_ERR(lqs)) {
- if (flag)
- lqs->lqs_flags |= QI_SET;
- else
- lqs->lqs_flags &= ~QI_SET;
- lqs_putref(lqs);
- } else {
- CERROR("fail to %s lqs for inode(%s id: %u)!\n",
- flag ? "create" : "search",
- oqctl->qc_type ? "group" : "user",
- oqctl->qc_id);
- GOTO(out, rc = PTR_ERR(lqs));
- }
-
- /* set local limit to MIN_QLIMIT */
- rc = fsfilt_quotactl(obd, obd->u.obt.obt_sb, ioqc);
- if (rc)
- GOTO(out, rc);
-
- /* trigger local qunit pre-acquire */
- if (oqctl->qc_type == USRQUOTA)
- id[USRQUOTA] = oqctl->qc_id;
- else
- id[GRPQUOTA] = oqctl->qc_id;
-
- rc = qctxt_adjust_qunit(obd, &obd->u.obt.obt_qctxt, id, 0, 0, NULL);
- if (rc == -EDQUOT || rc == -EBUSY) {
- CDEBUG(D_QUOTA, "rc: %d.\n", rc);
- rc = 0;
- }
- if (rc) {
- CDEBUG(D_QUOTA,"error mds adjust local file quota! (rc:%d)\n",
- rc);
- GOTO(out, rc);
- }
- /* FIXME initialize all slaves in CMD */
- EXIT;
-out:
- if (ioqc)
- OBD_FREE_PTR(ioqc);
- return rc;
-}
-
-static int mds_init_slave_blimits(struct obd_device *obd,
- struct obd_quotactl *oqctl, int set)
-{
- struct obd_device_target *obt = &obd->u.obt;
- struct lustre_quota_ctxt *qctxt = &obt->obt_qctxt;
- struct mds_obd *mds = &obd->u.mds;
- struct obd_quotactl *ioqc;
- struct lustre_qunit_size *lqs;
- unsigned int id[MAXQUOTAS] = { 0, 0 };
- int rc;
- int flag;
- ENTRY;
-
- /* if we are going to set zero limit, needn't init slaves */
- if (!oqctl->qc_dqblk.dqb_bhardlimit && !oqctl->qc_dqblk.dqb_bsoftlimit &&
- !set)
- RETURN(0);
-
- OBD_ALLOC_PTR(ioqc);
- if (!ioqc)
- RETURN(-ENOMEM);
-
- flag = oqctl->qc_dqblk.dqb_bhardlimit ||
- oqctl->qc_dqblk.dqb_bsoftlimit || !set;
- ioqc->qc_cmd = flag ? Q_INITQUOTA : Q_SETQUOTA;
- ioqc->qc_id = oqctl->qc_id;
- ioqc->qc_type = oqctl->qc_type;
- ioqc->qc_dqblk.dqb_valid = QIF_BLIMITS;
- ioqc->qc_dqblk.dqb_bhardlimit = flag ? MIN_QLIMIT : 0;
-
- /* build lqs for mds */
- lqs = quota_search_lqs(LQS_KEY(oqctl->qc_type, oqctl->qc_id),
- qctxt, flag ? 1 : 0);
- if (lqs && !IS_ERR(lqs)) {
- if (flag)
- lqs->lqs_flags |= QB_SET;
- else
- lqs->lqs_flags &= ~QB_SET;
- lqs_putref(lqs);
- } else {
- CERROR("fail to %s lqs for block(%s id: %u)!\n",
- flag ? "create" : "search",
- oqctl->qc_type ? "group" : "user",
- oqctl->qc_id);
- GOTO(out, rc = PTR_ERR(lqs));
- }
-
- rc = fsfilt_quotactl(obd, obd->u.obt.obt_sb, ioqc);
- if (rc)
- GOTO(out, rc);
-
- /* trigger local qunit pre-acquire */
- if (oqctl->qc_type == USRQUOTA)
- id[USRQUOTA] = oqctl->qc_id;
- else
- id[GRPQUOTA] = oqctl->qc_id;
-
- /* initialize all slave's limit */
- rc = obd_quotactl(mds->mds_lov_exp, ioqc);
-
- rc = qctxt_adjust_qunit(obd, &obd->u.obt.obt_qctxt, id, 1, 0, NULL);
- if (rc == -EDQUOT || rc == -EBUSY) {
- CDEBUG(D_QUOTA, "rc: %d.\n", rc);
- rc = 0;
- }
- if (rc) {
- CERROR("error mds adjust local block quota! (rc:%d)\n", rc);
- GOTO(out, rc);
- }
-
- EXIT;
-out:
- OBD_FREE_PTR(ioqc);
- return rc;
-}
-
-static void adjust_lqs(struct obd_device *obd, struct quota_adjust_qunit *qaq)
-{
- struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
- int rc = 0;
-
- QAQ_SET_CREATE_LQS(qaq);
- /* adjust local lqs */
- rc = quota_adjust_slave_lqs(qaq, qctxt);
- if (rc < 0)
- CERROR("adjust master's qunit size failed!(rc=%d)\n", rc);
-
- /* adjust remote lqs */
- if (QAQ_IS_ADJBLK(qaq)) {
- rc = obd_quota_adjust_qunit(obd->u.mds.mds_lov_exp, qaq, qctxt, NULL);
- if (rc < 0)
- CERROR("adjust slaves' qunit size failed!(rc=%d)\n", rc);
-
- }
-}
-
-int mds_set_dqblk(struct obd_device *obd, struct obd_quotactl *oqctl)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct lustre_quota_ctxt *qctxt = &mds->mds_obt.obt_qctxt;
- struct obd_device *lov_obd = class_exp2obd(mds->mds_lov_exp);
- struct lov_obd *lov = &lov_obd->u.lov;
- struct quota_adjust_qunit *oqaq = NULL;
- struct lustre_quota_info *qinfo = &mds->mds_quota_info;
- __u64 ihardlimit, isoftlimit, bhardlimit, bsoftlimit;
- time_t btime, itime;
- struct lustre_dquot *dquot;
- struct obd_dqblk *dqblk = &oqctl->qc_dqblk;
- /* orig_set means if quota was set before; now_set means we are
- * setting/cancelling quota */
- int orig_set, now_set;
- struct lustre_qunit_size *lqs;
- int rc = 0, rc2 = 0, flag = 0;
- ENTRY;
-
- if (oqctl->qc_type != USRQUOTA &&
- oqctl->qc_type != GRPQUOTA)
- RETURN(-EINVAL);
-
- OBD_ALLOC_PTR(oqaq);
- if (!oqaq)
- RETURN(-ENOMEM);
-
- cfs_down_write(&mds->mds_qonoff_sem);
- init_oqaq(oqaq, qctxt, oqctl->qc_id, oqctl->qc_type);
-
- if (qinfo->qi_files[oqctl->qc_type] == NULL) {
- CWARN("quota[%u] is off\n", oqctl->qc_type);
- GOTO(out_sem, rc = -ESRCH);
- }
-
- dquot = lustre_dqget(obd, qinfo, oqctl->qc_id, oqctl->qc_type, 1);
- if (IS_ERR(dquot))
- GOTO(out_sem, rc = PTR_ERR(dquot));
- DQUOT_DEBUG(dquot, "get dquot in mds_set_blk\n");
- QINFO_DEBUG(dquot->dq_info, "get dquot in mds_set_blk\n");
-
- lqs = quota_search_lqs(LQS_KEY(oqctl->qc_type, oqctl->qc_id), qctxt, 1);
- if (lqs == NULL)
- rc = -ENOENT;
- if (IS_ERR(lqs))
- rc = PTR_ERR(lqs);
- if (rc)
- GOTO(out, rc);
-
- cfs_mutex_lock(&dquot->dq_mutex);
- cfs_spin_lock(&lqs->lqs_lock);
- if (LQS_IS_SETQUOTA(lqs) || LQS_IS_RECOVERY(lqs)) {
- cfs_spin_unlock(&lqs->lqs_lock);
- cfs_mutex_unlock(&dquot->dq_mutex);
- GOTO(skip, rc = -EBUSY);
- }
- LQS_SET_SETQUOTA(lqs);
- cfs_spin_unlock(&lqs->lqs_lock);
-
- ihardlimit = dquot->dq_dqb.dqb_ihardlimit;
- isoftlimit = dquot->dq_dqb.dqb_isoftlimit;
- bhardlimit = dquot->dq_dqb.dqb_bhardlimit;
- bsoftlimit = dquot->dq_dqb.dqb_bsoftlimit;
- btime = dquot->dq_dqb.dqb_btime;
- itime = dquot->dq_dqb.dqb_itime;
-
- if (dqblk->dqb_valid & QIF_BTIME)
- dquot->dq_dqb.dqb_btime = dqblk->dqb_btime;
- if (dqblk->dqb_valid & QIF_ITIME)
- dquot->dq_dqb.dqb_itime = dqblk->dqb_itime;
-
- if (dqblk->dqb_valid & QIF_BLIMITS) {
- dquot->dq_dqb.dqb_bhardlimit = dqblk->dqb_bhardlimit;
- dquot->dq_dqb.dqb_bsoftlimit = dqblk->dqb_bsoftlimit;
- /* clear usage (limit pool) */
- if (!dquot->dq_dqb.dqb_bhardlimit &&
- !dquot->dq_dqb.dqb_bsoftlimit)
- dquot->dq_dqb.dqb_curspace = 0;
-
- /* clear grace time */
- if (!dqblk->dqb_bsoftlimit ||
- toqb(dquot->dq_dqb.dqb_curspace) <= dqblk->dqb_bsoftlimit)
- dquot->dq_dqb.dqb_btime = 0;
- /* set grace only if user hasn't provided his own */
- else if (!(dqblk->dqb_valid & QIF_BTIME))
- dquot->dq_dqb.dqb_btime = cfs_time_current_sec() +
- qinfo->qi_info[dquot->dq_type].dqi_bgrace;
-
- flag |= LQUOTA_FLAGS_ADJBLK;
- }
-
- if (dqblk->dqb_valid & QIF_ILIMITS) {
- dquot->dq_dqb.dqb_ihardlimit = dqblk->dqb_ihardlimit;
- dquot->dq_dqb.dqb_isoftlimit = dqblk->dqb_isoftlimit;
- /* clear usage (limit pool) */
- if (!dquot->dq_dqb.dqb_ihardlimit &&
- !dquot->dq_dqb.dqb_isoftlimit)
- dquot->dq_dqb.dqb_curinodes = 0;
-
- if (!dqblk->dqb_isoftlimit ||
- dquot->dq_dqb.dqb_curinodes <= dqblk->dqb_isoftlimit)
- dquot->dq_dqb.dqb_itime = 0;
- else if (!(dqblk->dqb_valid & QIF_ITIME))
- dquot->dq_dqb.dqb_itime = cfs_time_current_sec() +
- qinfo->qi_info[dquot->dq_type].dqi_igrace;
-
- flag |= LQUOTA_FLAGS_ADJINO;
- }
- QAQ_DEBUG(oqaq, "before dquot_create_oqaq\n");
- rc = dquot_create_oqaq(qctxt, dquot, lov->desc.ld_tgt_count, 1,
- flag, oqaq);
- QAQ_DEBUG(oqaq, "after dquot_create_oqaq\n");
- if (rc < 0)
- CDEBUG(D_QUOTA, "adjust qunit size failed! (rc:%d)\n", rc);
-
-
- rc = fsfilt_dquot(obd, dquot, QFILE_WR_DQUOT);
-
- cfs_mutex_unlock(&dquot->dq_mutex);
-
- if (rc) {
- CERROR("set limit failed! (rc:%d)\n", rc);
- GOTO(update_fail, rc);
- }
-
- cfs_up_write(&mds->mds_qonoff_sem);
- adjust_lqs(obd, oqaq);
-
- orig_set = ihardlimit || isoftlimit;
- now_set = dqblk->dqb_ihardlimit || dqblk->dqb_isoftlimit;
- if (dqblk->dqb_valid & QIF_ILIMITS && orig_set != now_set) {
- cfs_mutex_lock(&dquot->dq_mutex);
- dquot->dq_dqb.dqb_curinodes = 0;
- cfs_mutex_unlock(&dquot->dq_mutex);
- rc = mds_init_slave_ilimits(obd, oqctl, orig_set);
- if (rc) {
- CERROR("init slave ilimits failed! (rc:%d)\n", rc);
- goto revoke_out;
- }
- }
-
- orig_set = bhardlimit || bsoftlimit;
- now_set = dqblk->dqb_bhardlimit || dqblk->dqb_bsoftlimit;
- if (dqblk->dqb_valid & QIF_BLIMITS && orig_set != now_set) {
- cfs_mutex_lock(&dquot->dq_mutex);
- dquot->dq_dqb.dqb_curspace = 0;
- cfs_mutex_unlock(&dquot->dq_mutex);
- rc = mds_init_slave_blimits(obd, oqctl, orig_set);
- if (rc) {
- CERROR("init slave blimits failed! (rc:%d)\n", rc);
- goto revoke_out;
- }
- }
-
-revoke_out:
- cfs_down_write(&mds->mds_qonoff_sem);
- cfs_mutex_lock(&dquot->dq_mutex);
- if (rc) {
- /* cancel previous setting */
- dquot->dq_dqb.dqb_ihardlimit = ihardlimit;
- dquot->dq_dqb.dqb_isoftlimit = isoftlimit;
- dquot->dq_dqb.dqb_bhardlimit = bhardlimit;
- dquot->dq_dqb.dqb_bsoftlimit = bsoftlimit;
- dquot->dq_dqb.dqb_btime = btime;
- dquot->dq_dqb.dqb_itime = itime;
- }
- rc2 = fsfilt_dquot(obd, dquot, QFILE_WR_DQUOT);
- cfs_mutex_unlock(&dquot->dq_mutex);
-update_fail:
- cfs_spin_lock(&lqs->lqs_lock);
- LQS_CLEAR_SETQUOTA(lqs);
- cfs_spin_unlock(&lqs->lqs_lock);
-skip:
- lqs_putref(lqs);
-out:
- lustre_dqput(dquot);
- EXIT;
-out_sem:
- cfs_up_write(&mds->mds_qonoff_sem);
-
- if (oqaq)
- OBD_FREE_PTR(oqaq);
-
- return rc ? rc : rc2;
-}
-
-static int mds_get_space(struct obd_device *obd, struct obd_quotactl *oqctl)
-{
- struct obd_quotactl *soqc;
- struct lvfs_run_ctxt saved;
- int rc, rc1;
- ENTRY;
-
- OBD_ALLOC_PTR(soqc);
- if (!soqc)
- RETURN(-ENOMEM);
-
- soqc->qc_cmd = Q_GETOQUOTA;
- soqc->qc_id = oqctl->qc_id;
- soqc->qc_type = oqctl->qc_type;
-
- /* get block usage from OSS */
- soqc->qc_dqblk.dqb_curspace = 0;
- rc = obd_quotactl(obd->u.mds.mds_lov_exp, soqc);
- if (!rc || rc == -EREMOTEIO) {
- oqctl->qc_dqblk.dqb_curspace = soqc->qc_dqblk.dqb_curspace;
- oqctl->qc_dqblk.dqb_valid |= QIF_SPACE;
- }
-
- /* get block/inode usage from MDS */
- soqc->qc_dqblk.dqb_curspace = 0;
- soqc->qc_dqblk.dqb_curinodes = 0;
- push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- rc1 = fsfilt_quotactl(obd, obd->u.obt.obt_sb, soqc);
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- if (!rc1) {
- oqctl->qc_dqblk.dqb_curspace += soqc->qc_dqblk.dqb_curspace;
- oqctl->qc_dqblk.dqb_curinodes = soqc->qc_dqblk.dqb_curinodes;
- oqctl->qc_dqblk.dqb_valid |= QIF_INODES;
- }
-
- OBD_FREE_PTR(soqc);
-
- RETURN(rc ? : rc1);
-}
-
-int mds_get_dqblk(struct obd_device *obd, struct obd_quotactl *oqctl)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct lustre_quota_info *qinfo = &mds->mds_quota_info;
- struct lustre_dquot *dquot;
- struct obd_dqblk *dqblk = &oqctl->qc_dqblk;
- int rc;
- ENTRY;
-
- if (oqctl->qc_type != USRQUOTA &&
- oqctl->qc_type != GRPQUOTA)
- RETURN(-EINVAL);
-
- cfs_down_read(&mds->mds_qonoff_sem);
- dqblk->dqb_valid = 0;
- if (qinfo->qi_files[oqctl->qc_type] == NULL) {
- CWARN("quota[%u] is off\n", oqctl->qc_type);
- GOTO(out, rc = -ESRCH);
- }
-
- dquot = lustre_dqget(obd, qinfo, oqctl->qc_id, oqctl->qc_type, 1);
- if (IS_ERR(dquot))
- GOTO(out, rc = PTR_ERR(dquot));
-
- cfs_mutex_lock(&dquot->dq_mutex);
- dqblk->dqb_ihardlimit = dquot->dq_dqb.dqb_ihardlimit;
- dqblk->dqb_isoftlimit = dquot->dq_dqb.dqb_isoftlimit;
- dqblk->dqb_bhardlimit = dquot->dq_dqb.dqb_bhardlimit;
- dqblk->dqb_bsoftlimit = dquot->dq_dqb.dqb_bsoftlimit;
- dqblk->dqb_btime = dquot->dq_dqb.dqb_btime;
- dqblk->dqb_itime = dquot->dq_dqb.dqb_itime;
- dqblk->dqb_valid |= QIF_LIMITS | QIF_TIMES;
- cfs_mutex_unlock(&dquot->dq_mutex);
-
- lustre_dqput(dquot);
- cfs_up_read(&mds->mds_qonoff_sem);
-
- /* the usages in admin quota file is inaccurate */
- dqblk->dqb_curinodes = 0;
- dqblk->dqb_curspace = 0;
- rc = mds_get_space(obd, oqctl);
-
- RETURN(rc);
-
-out:
- cfs_up_read(&mds->mds_qonoff_sem);
- return rc;
-}
-
-int mds_get_obd_quota(struct obd_device *obd, struct obd_quotactl *oqctl)
-{
- struct lvfs_run_ctxt saved;
- int rc;
- ENTRY;
-
- push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- rc = fsfilt_quotactl(obd, obd->u.obt.obt_sb, oqctl);
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
-
- RETURN(rc);
-}
-
-
-/* FIXME we only recovery block limit by now, need recovery inode
- * limits also after CMD involved in */
-static int
-dquot_recovery(struct obd_device *obd, unsigned int id, unsigned short type)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct lustre_quota_ctxt *qctxt = &mds->mds_obt.obt_qctxt;
- struct lustre_quota_info *qinfo = &mds->mds_quota_info;
- struct lustre_qunit_size *lqs;
- struct lustre_dquot *dquot;
- struct obd_quotactl *qctl;
- __u64 total_limits = 0;
- int rc = 0;
- ENTRY;
-
- OBD_ALLOC_PTR(qctl);
- if (qctl == NULL)
- RETURN(-ENOMEM);
-
- dquot = lustre_dqget(obd, qinfo, id, type, 0);
- if (IS_ERR(dquot)) {
- CERROR("Get dquot failed. (rc:%ld)\n", PTR_ERR(dquot));
- OBD_FREE_PTR(qctl);
- RETURN(PTR_ERR(dquot));
- }
-
- lqs = quota_search_lqs(LQS_KEY(type, id), qctxt, 1);
- if (lqs == NULL)
- rc = -ENOENT;
- if (IS_ERR(lqs))
- rc = PTR_ERR(lqs);
- if (rc)
- GOTO(skip, rc);
-
- cfs_mutex_lock(&dquot->dq_mutex);
-
- /* don't recover the dquot without limits or quota is setting or
- * another recovery is already going on */
- if (!(dquot->dq_dqb.dqb_bhardlimit || dquot->dq_dqb.dqb_bsoftlimit) ||
- LQS_IS_SETQUOTA(lqs) || LQS_IS_RECOVERY(lqs)) {
- cfs_mutex_unlock(&dquot->dq_mutex);
- GOTO(skip1, rc = 0);
- }
-
- cfs_spin_lock(&lqs->lqs_lock);
- LQS_SET_RECOVERY(lqs);
- cfs_spin_unlock(&lqs->lqs_lock);
- cfs_mutex_unlock(&dquot->dq_mutex);
-
- /* release mds_qonoff_sem during obd_quotactl ops here */
- cfs_up_write(&mds->mds_qonoff_sem);
-
- /* get real bhardlimit from all slaves. */
- qctl->qc_cmd = Q_GETOQUOTA;
- qctl->qc_type = type;
- qctl->qc_id = id;
- qctl->qc_stat = QUOTA_RECOVERING;
- rc = obd_quotactl(mds->mds_lov_exp, qctl);
- cfs_down_write(&mds->mds_qonoff_sem);
- if (rc)
- GOTO(out, rc);
- total_limits = qctl->qc_dqblk.dqb_bhardlimit;
-
- /* get real bhardlimit from master */
- rc = fsfilt_quotactl(obd, obd->u.obt.obt_sb, qctl);
- if (rc)
- GOTO(out, rc);
- total_limits += qctl->qc_dqblk.dqb_bhardlimit;
-
- /* amend the usage of the administrative quotafile */
- cfs_mutex_lock(&dquot->dq_mutex);
-
- dquot->dq_dqb.dqb_curspace = total_limits << QUOTABLOCK_BITS;
-
- rc = fsfilt_dquot(obd, dquot, QFILE_WR_DQUOT);
- if (rc)
- CERROR("write dquot failed! (rc:%d)\n", rc);
-
- cfs_mutex_unlock(&dquot->dq_mutex);
- EXIT;
-out:
- cfs_spin_lock(&lqs->lqs_lock);
- LQS_CLEAR_RECOVERY(lqs);
- cfs_spin_unlock(&lqs->lqs_lock);
-skip1:
- lqs_putref(lqs);
-skip:
- lustre_dqput(dquot);
- OBD_FREE_PTR(qctl);
- return rc;
-}
-
-struct qmaster_recov_thread_data {
- struct obd_device *obd;
- cfs_completion_t comp;
-};
-
-static int qmaster_recovery_main(void *arg)
-{
- struct qmaster_recov_thread_data *data = arg;
- struct obd_device *obd = data->obd;
- struct mds_obd *mds = &obd->u.mds;
- struct lustre_quota_info *qinfo = &mds->mds_quota_info;
- int rc = 0;
- unsigned short type;
- ENTRY;
-
- cfs_daemonize_ctxt("qmaster_recovd");
-
- /* for mds */
- class_incref(obd, "qmaster_recovd_mds", obd);
- /* for lov */
- class_incref(mds->mds_lov_obd, "qmaster_recovd_lov", mds->mds_lov_obd);
-
- cfs_complete(&data->comp);
-
- cfs_down_write(&mds->mds_qonoff_sem);
- for (type = USRQUOTA; type < MAXQUOTAS; type++) {
- cfs_list_t id_list;
- struct dquot_id *dqid, *tmp;
-
- if (qinfo->qi_files[type] == NULL)
- continue;
-
- CFS_INIT_LIST_HEAD(&id_list);
- rc = fsfilt_qids(obd, qinfo->qi_files[type], NULL, type,
- &id_list);
- if (rc)
- CERROR("error get ids from admin quotafile.(%d)\n", rc);
-
- cfs_list_for_each_entry_safe(dqid, tmp, &id_list, di_link) {
- cfs_list_del_init(&dqid->di_link);
- if (rc)
- goto free;
-
- rc = dquot_recovery(obd, dqid->di_id, type);
- if (rc)
- CERROR("%s: qmaster recovery failed for %sid %d"
- " rc:%d)\n", obd->obd_name,
- type ? "g" : "u", dqid->di_id, rc);
-free:
- OBD_FREE_PTR(dqid);
- }
- }
- cfs_up_write(&mds->mds_qonoff_sem);
- class_decref(mds->mds_lov_obd, "qmaster_recovd_lov", mds->mds_lov_obd);
- class_decref(obd, "qmaster_recovd_mds", obd);
- RETURN(rc);
-}
-
-int mds_quota_recovery(struct obd_device *obd)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct qmaster_recov_thread_data data;
- int rc = 0;
- ENTRY;
-
- if (!sb_any_quota_loaded(obd->u.obt.obt_qctxt.lqc_sb))
- RETURN(0);
-
- if (unlikely(!mds->mds_quota || obd->obd_stopping))
- RETURN(rc);
-
- cfs_mutex_lock(&obd->obd_dev_mutex);
- if (mds->mds_lov_desc.ld_active_tgt_count != mds->mds_lov_objid_count) {
- CWARN("Only %u/%u OSTs are active, abort quota recovery\n",
- mds->mds_lov_desc.ld_active_tgt_count,
- mds->mds_lov_objid_count);
- cfs_mutex_unlock(&obd->obd_dev_mutex);
- RETURN(rc);
- }
- cfs_mutex_unlock(&obd->obd_dev_mutex);
-
- data.obd = obd;
- cfs_init_completion(&data.comp);
-
- rc = cfs_create_thread(qmaster_recovery_main, &data,
- CFS_DAEMON_FLAGS);
- if (rc < 0)
- CERROR("%s: cannot start quota recovery thread: rc %d\n",
- obd->obd_name, rc);
-
- cfs_wait_for_completion(&data.comp);
- RETURN(rc);
-}
SRCDIR=`dirname $0`
export PATH=$PWD/$SRCDIR:$SRCDIR:$PWD/$SRCDIR/../utils:$PATH:/sbin
-if [ "$USE_OFD" = "yes" -a -z "$ONLY" ]; then
- # only accounting tests are supported with OFD for the time being
- ONLY="33 34 35"
-fi
+# only accounting tests are supported for the time being
+ONLY="33 34 35"
ONLY=${ONLY:-"$*"}
# test_11 has been used to protect a kernel bug(bz10912), now it isn't
build_test_filter
-if [ "$USE_OFD" = "yes" ]; then
- for num in `seq $OSTCOUNT`; do
- if [ $(facet_fstype ost$num) = ldiskfs ]; then
- # not the most efficient way to enable the quota feature
- # on ost, but it still allows us to test ofd accounting
- # for now
- device=$(ostdevname $num)
- stop ost$num
- do_facet ost$num "$TUNE2FS -O quota $device"
- [ ${PIPESTATUS[0]} -ne 0] && \
- error "failed to enable quota feature for ost$num"
- start ost$num $device $OST_MOUNT_OPTS
- fi
- done
-fi
+# Use OFD for all quota testing
+USE_OFD_OLD="$USE_OFD"
+LOAD_MODULES_REMOTE_OLD="$LOAD_MODULES_REMOTE"
+export USE_OFD="yes"
+export LOAD_MODULES_REMOTE="true"
+cleanup_and_setup_lustre
# set_blk_tunables(btune_sz)
set_blk_tunesz() {
run_test_with_stat() {
(($# != 2)) && error "the number of arguments is wrong"
+ if [ "$USE_OFD" == "yes" ]; then
+ run_test "$@"
+ return
+ fi
+
do_facet $SINGLEMDS "lctl set_param lquota.mdd_obd-${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
quota_init() {
do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=+quota"
- log "do the quotacheck ..."
- $LFS quotacheck -ug $DIR
+ # log "do the quotacheck ..."
+ # $LFS quotacheck -ug $DIR
- resetquota -u $TSTUSR
- resetquota -g $TSTUSR
+ # resetquota -u $TSTUSR
+ # resetquota -g $TSTUSR
}
quota_init
# turn off quota
quota_fini()
{
- $LFS quotaoff $DIR
+ #$LFS quotaoff $DIR
do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=-quota"
}
quota_fini
cd $ORIG_PWD
complete $(basename $0) $SECONDS
-check_and_cleanup_lustre
+export USE_OFD="$USE_OFD_OLD"
+export LOAD_MODULES_REMOTE="$LOAD_MODULES_REMOTE_OLD"
export QUOTA_AUTO=$QUOTA_AUTO_OLD
+cleanup_and_setup_lustre
exit_status
setup_quota_old(){
local mntpt=$1
- if [ "$USE_OFD" = "yes" ]; then
- $LFS quotacheck $mntpt || error "quotacheck failed"
- return
- fi
+ # no quota enforcement for now and accounting works out of the box
+ return
# We need save the original quota_type params, and restore them after testing
setup_quota $MOUNT || return 2
else
echo "disable quota as required"
- $LFS quotaoff -ug $MOUNT > /dev/null 2>&1
+ # $LFS quotaoff -ug $MOUNT > /dev/null 2>&1
fi
fi
return 0
}
}
-static void enable_default_ext4_features(struct mkfs_opts *mop, char *anchor,
- size_t maxbuflen, int user_spec)
+static int enable_default_ext4_features(struct mkfs_opts *mop, char *anchor,
+ size_t maxbuflen, int user_spec)
{
if (IS_OST(&mop->mo_ldd)) {
append_unique(anchor, user_spec ? "," : " -O ",
/* The following options are only valid for ext4-based ldiskfs.
* If --backfstype=ext3 is specified, do not enable them. */
if (mop->mo_ldd.ldd_mount_type == LDD_MT_EXT3)
- return;
+ return 0;
+
+ /* Enable quota by default */
+ if (is_e2fsprogs_feature_supp("-O quota") == 0) {
+ append_unique(anchor, ",", "quota", NULL, maxbuflen);
+ } else {
+ fatal();
+ fprintf(stderr, "\"-O quota\" must be supported by "
+ "e2fsprogs, please upgrade your e2fsprogs.\n");
+ return EINVAL;
+ }
/* Allow files larger than 2TB. Also needs LU-16, but not harmful. */
if (is_e2fsprogs_feature_supp("-O huge_file") == 0)
}
}
/* Don't add any more "-O" options here, see last comment above */
+ return 0;
}
/**
start = moveopts_to_end(start);
maxbuflen = sizeof(mop->mo_mkfsopts) -
(start - mop->mo_mkfsopts) - strlen(start);
- enable_default_ext4_features(mop, start, maxbuflen, 1);
+ ret = enable_default_ext4_features(mop, start, maxbuflen, 1);
} else {
start = mop->mo_mkfsopts + strlen(mop->mo_mkfsopts),
maxbuflen = sizeof(mop->mo_mkfsopts) -
strlen(mop->mo_mkfsopts);
- enable_default_ext4_features(mop, start, maxbuflen, 0);
+ ret = enable_default_ext4_features(mop, start, maxbuflen, 0);
}
+ if (ret)
+ return ret;
/* end handle -O mkfs options */
/* start handle -E mkfs options */