* GPL HEADER END
*/
/*
- * Copyright (c) 2012, Intel, Inc.
+ * Copyright (c) 2012, 2013, Intel Corporation.
* Use is subject to license terms.
*
* lustre/mdt/mdt_lvb.c
/* Called with res->lr_lvb_sem held */
static int mdt_lvbo_init(struct ldlm_resource *res)
{
+ if (IS_LQUOTA_RES(res)) {
+ struct mdt_device *mdt;
+
+ mdt = ldlm_res_to_ns(res)->ns_lvbp;
+ if (mdt->mdt_qmt_dev == NULL)
+ return 0;
+
+ /* call lvbo init function of quota master */
+ return qmt_hdls.qmth_lvbo_init(mdt->mdt_qmt_dev, res);
+ }
+
+ return 0;
+}
+
+static int mdt_lvbo_update(struct ldlm_resource *res,
+ struct ptlrpc_request *req,
+ int increase_only)
+{
+ if (IS_LQUOTA_RES(res)) {
+ struct mdt_device *mdt;
+
+ mdt = ldlm_res_to_ns(res)->ns_lvbp;
+ if (mdt->mdt_qmt_dev == NULL)
+ return 0;
+
+ /* call lvbo update function of quota master */
+ return qmt_hdls.qmth_lvbo_update(mdt->mdt_qmt_dev, res, req,
+ increase_only);
+ }
+
return 0;
}
+
static int mdt_lvbo_size(struct ldlm_lock *lock)
{
+ struct mdt_device *mdt;
+
+ /* resource on server side never changes. */
+ mdt = ldlm_res_to_ns(lock->l_resource)->ns_lvbp;
+ LASSERT(mdt != NULL);
+
+ if (IS_LQUOTA_RES(lock->l_resource)) {
+ if (mdt->mdt_qmt_dev == NULL)
+ return 0;
+
+ /* call lvbo size function of quota master */
+ return qmt_hdls.qmth_lvbo_size(mdt->mdt_qmt_dev, lock);
+ }
+
+ if (ldlm_has_layout(lock))
+ return mdt->mdt_max_mdsize;
+
return 0;
}
static int mdt_lvbo_fill(struct ldlm_lock *lock, void *lvb, int lvblen)
{
+ struct lu_env env;
+ struct mdt_thread_info *info;
+ struct mdt_device *mdt;
+ struct lu_fid *fid;
+ struct mdt_object *obj = NULL;
+ struct md_object *child = NULL;
+ int rc;
+ ENTRY;
+
+ mdt = ldlm_lock_to_ns(lock)->ns_lvbp;
+ if (IS_LQUOTA_RES(lock->l_resource)) {
+ if (mdt->mdt_qmt_dev == NULL)
+ RETURN(0);
+
+ /* call lvbo fill function of quota master */
+ rc = qmt_hdls.qmth_lvbo_fill(mdt->mdt_qmt_dev, lock, lvb,
+ lvblen);
+ RETURN(rc);
+ }
+
+ if (!ldlm_has_layout(lock))
+ RETURN(0);
+
+ /* layout lock will be granted to client, fill in lvb with layout */
+
+ /* XXX create an env to talk to mdt stack. We should get this env from
+ * ptlrpc_thread->t_env. */
+ rc = lu_env_init(&env, LCT_MD_THREAD);
+ LASSERT(rc == 0);
+
+ info = lu_context_key_get(&env.le_ctx, &mdt_thread_key);
+ LASSERT(info != NULL);
+ memset(info, 0, sizeof *info);
+ info->mti_env = &env;
+ info->mti_exp = lock->l_export;
+ info->mti_mdt = mdt;
+
+ /* XXX get fid by resource id. why don't include fid in ldlm_resource */
+ fid = &info->mti_tmp_fid2;
+ fid_extract_from_res_name(fid, &lock->l_resource->lr_name);
+
+ obj = mdt_object_find(&env, info->mti_mdt, fid);
+ if (IS_ERR(obj))
+ GOTO(out, rc = PTR_ERR(obj));
+
+ if (!mdt_object_exists(obj) || mdt_object_remote(obj))
+ GOTO(out, rc = -ENOENT);
+
+ child = mdt_object_child(obj);
+
+ /* get the length of lsm */
+ rc = mo_xattr_get(&env, child, &LU_BUF_NULL, XATTR_NAME_LOV);
+ if (rc < 0)
+ GOTO(out, rc);
+
+ if (rc > 0) {
+ struct lu_buf *lmm = NULL;
+
+ if (lvblen < rc) {
+ CERROR("%s: expected %d actual %d.\n",
+ mdt_obd_name(mdt), rc, lvblen);
+ GOTO(out, rc = -ERANGE);
+ }
+
+ lmm = &info->mti_buf;
+ lmm->lb_buf = lvb;
+ lmm->lb_len = rc;
+
+ rc = mo_xattr_get(&env, child, lmm, XATTR_NAME_LOV);
+ if (rc < 0)
+ GOTO(out, rc);
+ }
+
+out:
+ if (obj != NULL && !IS_ERR(obj))
+ mdt_object_put(&env, obj);
+ lu_env_fini(&env);
+ RETURN(rc < 0 ? 0 : rc);
+}
+
+static int mdt_lvbo_free(struct ldlm_resource *res)
+{
+ if (IS_LQUOTA_RES(res)) {
+ struct mdt_device *mdt;
+
+ mdt = ldlm_res_to_ns(res)->ns_lvbp;
+ if (mdt->mdt_qmt_dev == NULL)
+ return 0;
+
+ /* call lvbo free function of quota master */
+ return qmt_hdls.qmth_lvbo_free(mdt->mdt_qmt_dev, res);
+ }
+
return 0;
}
struct ldlm_valblock_ops mdt_lvbo = {
lvbo_init: mdt_lvbo_init,
- lvbo_size: mdt_lvbo_size,
- lvbo_fill: mdt_lvbo_fill
+ lvbo_update: mdt_lvbo_update,
+ lvbo_size: mdt_lvbo_size,
+ lvbo_fill: mdt_lvbo_fill,
+ lvbo_free: mdt_lvbo_free
};