return rc;
}
-/* has not lock on pobj yet */
-static int mdd_ni_sanity_check(const struct lu_env *env,
- struct md_object *pobj,
- const struct md_attr *ma)
-{
- struct mdd_object *obj = md2mdd_obj(pobj);
- int rc;
- ENTRY;
-
- if (ma->ma_attr_flags & MDS_PERM_BYPASS)
- RETURN(0);
-
- rc = mdd_may_create(env, obj, NULL, 1, S_ISDIR(ma->ma_attr.la_mode));
-
- RETURN(rc);
-}
-
-/*
- * Partial operation.
- */
-static int mdd_name_insert(const struct lu_env *env,
- struct md_object *pobj,
- const struct lu_name *lname,
- const struct lu_fid *fid,
- const struct md_attr *ma)
-{
- const char *name = lname->ln_name;
- struct lu_attr *la = &mdd_env_info(env)->mti_la_for_fix;
- struct mdd_object *mdd_obj = md2mdd_obj(pobj);
- struct dynlock_handle *dlh;
- struct thandle *handle;
- int is_dir = S_ISDIR(ma->ma_attr.la_mode);
-#ifdef HAVE_QUOTA_SUPPORT
- struct mdd_device *mdd = mdo2mdd(pobj);
- struct md_ucred *uc = md_ucred(env);
- 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 };
- cfs_cap_t save = uc->mu_cap;
-#endif
- int rc;
- ENTRY;
-
- /* XXX: this code won't be used ever:
- * DNE uses slightly different approach */
- LBUG();
-
-#ifdef HAVE_QUOTA_SUPPORT
- if (mds->mds_quota) {
- if (!(ma->ma_attr_flags & MDS_QUOTA_IGNORE)) {
- struct lu_attr *la_tmp = &mdd_env_info(env)->mti_la;
-
- rc = mdd_la_get(env, mdd_obj, la_tmp, BYPASS_CAPA);
- if (!rc) {
- void *data = NULL;
- mdd_data_get(env, mdd_obj, &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);
- }
- } else {
- uc->mu_cap |= CFS_CAP_SYS_RESOURCE_MASK;
- }
- }
-#endif
- handle = mdd_trans_create(env, mdo2mdd(pobj));
- if (IS_ERR(handle))
- GOTO(out_pending, rc = PTR_ERR(handle));
-
- rc = mdd_trans_start(env, mdo2mdd(pobj), handle);
-
- dlh = mdd_pdo_write_lock(env, mdd_obj, name, MOR_TGT_PARENT);
- if (dlh == NULL)
- GOTO(out_trans, rc = -ENOMEM);
-
- rc = mdd_ni_sanity_check(env, pobj, ma);
- if (rc)
- GOTO(out_unlock, rc);
-
- rc = __mdd_index_insert(env, mdd_obj, fid, name, is_dir,
- handle, BYPASS_CAPA);
- if (rc)
- GOTO(out_unlock, rc);
-
- /*
- * For some case, no need update obj's ctime (LA_CTIME is not set),
- * e.g. split_dir.
- * For other cases, update obj's ctime (LA_CTIME is set),
- * e.g. cmr_link.
- */
- if (ma->ma_attr.la_valid & LA_CTIME) {
- la->la_ctime = la->la_mtime = ma->ma_attr.la_ctime;
- la->la_valid = LA_CTIME | LA_MTIME;
- rc = mdd_attr_check_set_internal_locked(env, mdd_obj, la,
- handle, 0);
- }
- EXIT;
-out_unlock:
- mdd_pdo_write_unlock(env, mdd_obj, dlh);
-out_trans:
- mdd_trans_stop(env, mdo2mdd(pobj), rc, handle);
-out_pending:
-#ifdef HAVE_QUOTA_SUPPORT
- if (mds->mds_quota) {
- 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);
- } else {
- uc->mu_cap = save;
- }
- }
-#endif
- return rc;
-}
-
-/* has not lock on pobj yet */
-static int mdd_nr_sanity_check(const struct lu_env *env,
- struct md_object *pobj,
- const struct md_attr *ma)
-{
- struct mdd_object *obj = md2mdd_obj(pobj);
- int rc;
- ENTRY;
-
- if (ma->ma_attr_flags & MDS_PERM_BYPASS)
- RETURN(0);
-
- rc = mdd_may_unlink(env, obj, ma);
-
- RETURN(rc);
-}
-
-/*
- * Partial operation.
- */
-static int mdd_name_remove(const struct lu_env *env,
- struct md_object *pobj,
- const struct lu_name *lname,
- const struct md_attr *ma)
-{
- const char *name = lname->ln_name;
- struct lu_attr *la = &mdd_env_info(env)->mti_la_for_fix;
- struct mdd_object *mdd_obj = md2mdd_obj(pobj);
- struct mdd_device *mdd = mdo2mdd(pobj);
- struct dynlock_handle *dlh;
- struct thandle *handle;
- int is_dir = S_ISDIR(ma->ma_attr.la_mode);
-#ifdef HAVE_QUOTA_SUPPORT
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct mds_obd *mds = &obd->u.mds;
- unsigned int qids[MAXQUOTAS] = { 0, 0 };
- int quota_opc = 0;
-#endif
- int rc;
- ENTRY;
-
- /* XXX: this code won't be used ever:
- * DNE uses slightly different approach */
- LBUG();
-
-#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_obj, la_tmp, BYPASS_CAPA);
- if (!rc) {
- quota_opc = FSFILT_OP_UNLINK_PARTIAL_PARENT;
- mdd_quota_wrapper(la_tmp, qids);
- }
- }
-#endif
- handle = mdd_trans_create(env, mdd);
- if (IS_ERR(handle))
- GOTO(out_pending, rc = PTR_ERR(handle));
-
- rc = mdd_trans_start(env, mdd, handle);
-
- dlh = mdd_pdo_write_lock(env, mdd_obj, name, MOR_TGT_PARENT);
- if (dlh == NULL)
- GOTO(out_trans, rc = -ENOMEM);
-
- rc = mdd_nr_sanity_check(env, pobj, ma);
- if (rc)
- GOTO(out_unlock, rc);
-
- rc = __mdd_index_delete(env, mdd_obj, name, is_dir,
- handle, BYPASS_CAPA);
- if (rc)
- GOTO(out_unlock, rc);
-
- /*
- * For some case, no need update obj's ctime (LA_CTIME is not set),
- * e.g. split_dir.
- * For other cases, update obj's ctime (LA_CTIME is set),
- * e.g. cmr_unlink.
- */
- if (ma->ma_attr.la_valid & LA_CTIME) {
- la->la_ctime = la->la_mtime = ma->ma_attr.la_ctime;
- la->la_valid = LA_CTIME | LA_MTIME;
- rc = mdd_attr_check_set_internal_locked(env, mdd_obj, la,
- handle, 0);
- }
- EXIT;
-out_unlock:
- mdd_pdo_write_unlock(env, mdd_obj, dlh);
-out_trans:
- mdd_trans_stop(env, mdd, rc, handle);
-out_pending:
-#ifdef HAVE_QUOTA_SUPPORT
- /* Trigger dqrel for the parent owner.
- * If failed, the next call for lquota_chkquota will process it. */
- if (quota_opc)
- lquota_adjust(mds_quota_interface_ref, obd, 0, qids, rc,
- quota_opc);
-#endif
- return rc;
-}
-
-/*
- * tobj maybe NULL
- * has mdd_write_lock on tobj alreay, but not on tgt_pobj yet
- */
-static int mdd_rt_sanity_check(const struct lu_env *env,
- struct mdd_object *tgt_pobj,
- struct mdd_object *tobj,
- struct md_attr *ma)
-{
- int rc;
- ENTRY;
-
- if (unlikely(ma->ma_attr_flags & MDS_PERM_BYPASS))
- RETURN(0);
-
- /* XXX: for mdd_rename_tgt, "tobj == NULL" does not mean tobj not
- * exist. In fact, tobj must exist, otherwise the call trace will be:
- * mdt_reint_rename_tgt -> mdo_name_insert -> ... -> mdd_name_insert.
- * When get here, tobj must be NOT NULL, the other case has been
- * processed in cmr_rename_tgt before mdd_rename_tgt and enable
- * MDS_PERM_BYPASS.
- * So check may_delete, but not check nlink of tgt_pobj. */
-
- rc = mdd_may_delete(env, tgt_pobj, tobj, ma, 1, 1);
-
- RETURN(rc);
-}
-
-/* Partial rename op on slave MDD */
-static int mdd_rename_tgt(const struct lu_env *env,
- struct md_object *pobj, struct md_object *tobj,
- const struct lu_fid *lf, const struct lu_name *lname,
- struct md_attr *ma)
-{
- const char *name = lname->ln_name;
- struct lu_attr *la = &mdd_env_info(env)->mti_la_for_fix;
- struct mdd_object *mdd_tpobj = md2mdd_obj(pobj);
- struct mdd_object *mdd_tobj = md2mdd_obj(tobj);
- 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 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_copc = 0, quota_popc = 0;
- int rec_pending[MAXQUOTAS] = { 0, 0 };
-#endif
- int cl_flags = 0;
- int rc;
- ENTRY;
-
- /* XXX: this code won't be used ever:
- * DNE uses slightly different approach */
- LBUG();
-
-#ifdef HAVE_QUOTA_SUPPORT
- if (mds->mds_quota && !tobj) {
- struct lu_attr *la_tmp = &mdd_env_info(env)->mti_la;
-
- 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, qpids);
- /* get block quota for target parent */
- lquota_chkquota(mds_quota_interface_ref, obd, exp,
- qpids, 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));
-
- rc = mdd_trans_start(env, mdd, handle);
-
- dlh = mdd_pdo_write_lock(env, mdd_tpobj, name, MOR_TGT_PARENT);
- if (dlh == NULL)
- GOTO(out_trans, rc = -ENOMEM);
- if (tobj)
- mdd_write_lock(env, mdd_tobj, MOR_TGT_CHILD);
-
- rc = mdd_rt_sanity_check(env, mdd_tpobj, mdd_tobj, ma);
- if (rc)
- GOTO(cleanup, rc);
-
- /*
- * If rename_tgt is called then we should just re-insert name with
- * correct fid, no need to dec/inc parent nlink if obj is dir.
- */
- rc = __mdd_index_delete(env, mdd_tpobj, name, 0, handle, BYPASS_CAPA);
- if (rc)
- GOTO(cleanup, rc);
-
- rc = __mdd_index_insert_only(env, mdd_tpobj, lf, name, handle,
- BYPASS_CAPA);
- if (rc)
- GOTO(cleanup, rc);
-
- LASSERT(ma->ma_attr.la_valid & LA_CTIME);
- la->la_ctime = la->la_mtime = ma->ma_attr.la_ctime;
-
- la->la_valid = LA_CTIME | LA_MTIME;
- rc = mdd_attr_check_set_internal_locked(env, mdd_tpobj, la, handle, 0);
- if (rc)
- GOTO(cleanup, rc);
-
- /*
- * For tobj is remote case cmm layer has processed
- * and pass NULL tobj to here. So when tobj is NOT NULL,
- * it must be local one.
- */
- if (tobj && mdd_object_exists(mdd_tobj)) {
- mdo_ref_del(env, mdd_tobj, handle);
-
- /* Remove dot reference. */
- if (S_ISDIR(ma->ma_attr.la_mode))
- mdo_ref_del(env, mdd_tobj, handle);
-
- la->la_valid = LA_CTIME;
- rc = mdd_attr_check_set_internal(env, mdd_tobj, la, handle, 0);
- if (rc)
- GOTO(cleanup, rc);
-
- rc = mdd_finish_unlink(env, mdd_tobj, ma, handle);
- if (rc)
- GOTO(cleanup, rc);
-
- if (ma->ma_valid & MA_INODE && ma->ma_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, qcids);
- }
-#endif
- }
- }
- EXIT;
-cleanup:
- if (tobj)
- mdd_write_unlock(env, mdd_tobj);
- mdd_pdo_write_unlock(env, mdd_tpobj, dlh);
-out_trans:
- if (rc == 0)
- /* Bare EXT record with no RENAME in front of it signifies
- a partial slave op */
- rc = mdd_changelog_ns_store(env, mdd, CL_EXT, cl_flags,
- mdd_tobj, mdd_tpobj, lname, handle);
-
- mdd_trans_stop(env, mdd, rc, handle);
-out_pending:
-#ifdef HAVE_QUOTA_SUPPORT
- if (mds->mds_quota) {
- if (quota_popc)
- lquota_pending_commit(mds_quota_interface_ref, obd,
- qpids, rec_pending, 1);
-
- if (quota_copc)
- /* 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, qcids, qpids,
- rc, quota_copc);
- }
-#endif
- return rc;
-}
-
/*
* The permission has been checked when obj created, no need check again.
*/
.mdo_rename = mdd_rename,
.mdo_link = mdd_link,
.mdo_unlink = mdd_unlink,
- .mdo_lum_lmm_cmp = mdd_lum_lmm_cmp,
- .mdo_name_insert = mdd_name_insert,
- .mdo_name_remove = mdd_name_remove,
- .mdo_rename_tgt = mdd_rename_tgt,
.mdo_create_data = mdd_create_data,
};
RETURN(rc);
}
-static int grouplock_blocking_ast(struct ldlm_lock *lock,
- struct ldlm_lock_desc *desc,
- void *data, int flag)
-{
- struct md_attr *ma = data;
- struct lustre_handle lockh;
- int rc = 0;
- ENTRY;
-
- switch (flag)
- {
- case LDLM_CB_BLOCKING :
- /* lock is canceled */
- CDEBUG(D_DLMTRACE, "Lock %p is canceled\n", lock);
-
- ldlm_lock2handle(lock, &lockh);
- rc = ldlm_cli_cancel(&lockh);
-
- break;
- case LDLM_CB_CANCELING :
- CDEBUG(D_DLMTRACE,
- "Lock %p has been canceled, do cleaning\n",
- lock);
-
- if (ma && ma->ma_som)
- OBD_FREE_PTR(ma->ma_som);
- if (ma)
- OBD_FREE_PTR(ma);
- break;
- default:
- LBUG();
- }
- RETURN(rc);
-}
-
-static int grouplock_glimpse_ast(struct ldlm_lock *lock, void *data)
-{
- struct ptlrpc_request *req = data;
- struct ost_lvb *lvb;
- int rc;
- struct md_attr *ma;
- ENTRY;
-
- ma = lock->l_ast_data;
-
- req_capsule_extend(&req->rq_pill, &RQF_LDLM_GL_CALLBACK);
- req_capsule_set_size(&req->rq_pill, &RMF_DLM_LVB, RCL_SERVER,
- sizeof(*lvb));
- rc = req_capsule_server_pack(&req->rq_pill);
- if (rc) {
- CERROR("failed pack reply: %d\n", rc);
- GOTO(out, rc);
- }
-
- lvb = req_capsule_server_get(&req->rq_pill, &RMF_DLM_LVB);
-
- if ((ma) && (ma->ma_valid & MA_SOM)) {
- lvb->lvb_size = ma->ma_som->msd_size;
- lvb->lvb_blocks = ma->ma_som->msd_blocks;
- } else if ((ma) && (ma->ma_valid & MA_INODE)) {
- lvb->lvb_size = ma->ma_attr.la_size;
- lvb->lvb_blocks = ma->ma_attr.la_blocks;
- } else {
- lvb->lvb_size = 0;
- rc = -ELDLM_NO_LOCK_DATA;
- }
-
- EXIT;
-out:
- if (rc == -ELDLM_NO_LOCK_DATA)
- lustre_pack_reply(req, 1, NULL, NULL);
-
- req->rq_status = rc;
- return rc;
-}
-
-int mdd_file_lock(const struct lu_env *env, struct md_object *obj,
- struct lov_mds_md *lmm, struct ldlm_extent *extent,
- struct lustre_handle *lockh)
-{
- struct ldlm_enqueue_info einfo = { 0 };
- struct obd_info oinfo = { { { 0 } } };
- struct obd_device *obd;
- struct obd_export *lov_exp;
- struct lov_stripe_md *lsm = NULL;
- struct md_attr *ma = NULL;
- int rc;
- ENTRY;
-
- obd = mdo2mdd(obj)->mdd_obd_dev;
- lov_exp = obd->u.mds.mds_lov_exp;
-
- obd_unpackmd(lov_exp, &lsm, lmm,
- lov_mds_md_size(lmm->lmm_stripe_count, lmm->lmm_magic));
-
- OBD_ALLOC_PTR(ma);
- if (ma == NULL)
- GOTO(out, rc = -ENOMEM);
-
- OBD_ALLOC_PTR(ma->ma_som);
- if (ma->ma_som == NULL)
- GOTO(out, rc = -ENOMEM);
-
- ma->ma_need = MA_SOM | MA_INODE;
- mo_attr_get(env, obj, ma);
-
- einfo.ei_type = LDLM_EXTENT;
- einfo.ei_mode = LCK_GROUP;
- einfo.ei_cb_bl = grouplock_blocking_ast;
- einfo.ei_cb_cp = ldlm_completion_ast;
- einfo.ei_cb_gl = grouplock_glimpse_ast;
-
- if (ma->ma_valid & (MA_SOM | MA_INODE))
- einfo.ei_cbdata = ma;
- else
- einfo.ei_cbdata = NULL;
-
- memset(&oinfo.oi_policy, 0, sizeof(oinfo.oi_policy));
- oinfo.oi_policy.l_extent = *extent;
- oinfo.oi_lockh = lockh;
- oinfo.oi_md = lsm;
- oinfo.oi_flags = 0;
-
- rc = obd_enqueue(lov_exp, &oinfo, &einfo, NULL);
- /* ei_cbdata is used as a free flag at exit */
- if (rc)
- einfo.ei_cbdata = NULL;
-
- obd_unpackmd(lov_exp, &lsm, NULL, 0);
-
-out:
- /* ma is freed if not used as callback data */
- if ((einfo.ei_cbdata == NULL) && ma && ma->ma_som)
- OBD_FREE_PTR(ma->ma_som);
- if ((einfo.ei_cbdata == NULL) && ma)
- OBD_FREE_PTR(ma);
-
- RETURN(rc);
-}
-
-int mdd_file_unlock(const struct lu_env *env, struct md_object *obj,
- struct lov_mds_md *lmm, struct lustre_handle *lockh)
-{
- struct obd_device *obd;
- struct obd_export *lov_exp;
- struct lov_stripe_md *lsm = NULL;
- int rc;
- ENTRY;
-
- LASSERT(lustre_handle_is_used(lockh));
-
- obd = mdo2mdd(obj)->mdd_obd_dev;
- lov_exp = obd->u.mds.mds_lov_exp;
-
- obd_unpackmd(lov_exp, &lsm, lmm,
- lov_mds_md_size(lmm->lmm_stripe_count, lmm->lmm_magic));
-
- rc = obd_cancel(lov_exp, lsm, LCK_GROUP, lockh);
-
- obd_unpackmd(lov_exp, &lsm, NULL, 0);
-
- RETURN(rc);
-}
-
-/* file lov is in ma->ma_lmm */
-/* requested lov is in info->mti_spec.u.sp_ea.eadata */
-int mdd_lum_lmm_cmp(const struct lu_env *env, struct md_object *cobj,
- const struct md_op_spec *spec, struct md_attr *ma)
-{
- struct obd_export *lov_exp =
- mdd2obd_dev(mdo2mdd(cobj))->u.mds.mds_lov_exp;
- struct lov_mds_md *lmm = ma->ma_lmm;
- struct lov_user_md_v3 *lum =
- (struct lov_user_md_v3 *)(spec->u.sp_ea.eadata);
- struct lov_stripe_md *lsm = NULL;
- int lmm_magic, rc;
- ENTRY;
-
- rc = obd_unpackmd(lov_exp, &lsm, lmm,
- lov_mds_md_size(lmm->lmm_stripe_count,
- lmm->lmm_magic));
- ma->ma_layout_gen = lsm->lsm_layout_gen;
- ma->ma_valid |= MA_LAY_GEN;
-
- rc = lov_lum_swab_if_needed(lum, &lmm_magic, NULL);
- if (rc)
- GOTO(out, rc);
-
- rc = lov_lum_lsm_cmp((struct lov_user_md *)lum, lsm);
- if (rc)
- GOTO(out, rc); /* keep GOTO to for traces */
-
-out:
- /* free lsm */
- obd_unpackmd(lov_exp, &lsm, NULL, 0);
- return rc;
-}
RETURN(rc);
}
-/* partial unlink */
-static int mdd_ref_del(const struct lu_env *env, struct md_object *obj,
- struct md_attr *ma)
-{
- struct lu_attr *la_copy = &mdd_env_info(env)->mti_la_for_fix;
- struct mdd_object *mdd_obj = md2mdd_obj(obj);
- struct mdd_device *mdd = mdo2mdd(obj);
- struct thandle *handle;
-#ifdef HAVE_QUOTA_SUPPORT
- struct obd_device *obd = mdd->mdd_obd_dev;
- struct mds_obd *mds = &obd->u.mds;
- unsigned int qids[MAXQUOTAS] = { 0, 0 };
- int quota_opc = 0;
-#endif
- int rc;
- ENTRY;
-
- /* XXX: this code won't be used ever:
- * DNE uses slightly different approach */
- LBUG();
-
- /*
- * Check -ENOENT early here because we need to get object type
- * to calculate credits before transaction start
- */
- if (mdd_object_exists(mdd_obj) == 0) {
- CERROR("%s: object "DFID" not found: rc = -2\n",
- mdd_obj_dev_name(mdd_obj),PFID(mdd_object_fid(mdd_obj)));
- RETURN(-ENOENT);
- }
-
- LASSERT(mdd_object_exists(mdd_obj) > 0);
-
- handle = mdd_trans_create(env, mdd);
- if (IS_ERR(handle))
- RETURN(-ENOMEM);
-
- rc = mdd_trans_start(env, mdd, handle);
-
- mdd_write_lock(env, mdd_obj, MOR_TGT_CHILD);
-
- rc = mdd_unlink_sanity_check(env, NULL, mdd_obj, ma);
- if (rc)
- GOTO(cleanup, rc);
-
- mdo_ref_del(env, mdd_obj, handle);
-
- if (S_ISDIR(lu_object_attr(&obj->mo_lu))) {
- /* unlink dot */
- mdo_ref_del(env, mdd_obj, handle);
- }
-
- LASSERT(ma->ma_attr.la_valid & LA_CTIME);
- la_copy->la_ctime = ma->ma_attr.la_ctime;
-
- la_copy->la_valid = LA_CTIME;
- rc = mdd_attr_check_set_internal(env, mdd_obj, la_copy, handle, 0);
- if (rc)
- GOTO(cleanup, rc);
-
- rc = mdd_finish_unlink(env, mdd_obj, ma, handle);
-#ifdef HAVE_QUOTA_SUPPORT
- if (mds->mds_quota && ma->ma_valid & MA_INODE &&
- ma->ma_attr.la_nlink == 0 && mdd_obj->mod_count == 0) {
- quota_opc = FSFILT_OP_UNLINK_PARTIAL_CHILD;
- mdd_quota_wrapper(&ma->ma_attr, qids);
- }
-#endif
-
-
- EXIT;
-cleanup:
- mdd_write_unlock(env, mdd_obj);
- 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;
-}
-
-/* partial operation */
-static int mdd_oc_sanity_check(const struct lu_env *env,
- struct mdd_object *obj,
- struct md_attr *ma)
-{
- int rc;
- ENTRY;
-
- switch (ma->ma_attr.la_mode & S_IFMT) {
- case S_IFREG:
- case S_IFDIR:
- case S_IFLNK:
- case S_IFCHR:
- case S_IFBLK:
- case S_IFIFO:
- case S_IFSOCK:
- rc = 0;
- break;
- default:
- rc = -EINVAL;
- break;
- }
- RETURN(rc);
-}
-
-static int mdd_object_create(const struct lu_env *env,
- struct md_object *obj,
- const struct md_op_spec *spec,
- struct md_attr *ma)
-{
-
- struct mdd_device *mdd = mdo2mdd(obj);
- struct mdd_object *mdd_obj = md2mdd_obj(obj);
- const struct lu_fid *pfid = spec->u.sp_pfid;
- 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, block_count = 0;
- int inode_pending[MAXQUOTAS] = { 0, 0 };
- int block_pending[MAXQUOTAS] = { 0, 0 };
-#endif
- int rc = 0;
- ENTRY;
-
- /* XXX: this code won't be used ever:
- * DNE uses slightly different approach */
- LBUG();
-
-#ifdef HAVE_QUOTA_SUPPORT
- if (mds->mds_quota) {
- quota_opc = FSFILT_OP_CREATE_PARTIAL_CHILD;
- mdd_quota_wrapper(&ma->ma_attr, qids);
- /* get file quota for child */
- lquota_chkquota(mds_quota_interface_ref, obd, exp,
- qids, inode_pending, 1, NULL, 0,
- NULL, 0);
- switch (ma->ma_attr.la_mode & S_IFMT) {
- case S_IFLNK:
- case S_IFDIR:
- block_count = 2;
- break;
- case S_IFREG:
- block_count = 1;
- break;
- }
- /* get block quota for child */
- if (block_count)
- lquota_chkquota(mds_quota_interface_ref, obd, exp,
- qids, block_pending, block_count,
- NULL, LQUOTA_FLAGS_BLK, NULL, 0);
- }
-#endif
-
- handle = mdd_trans_create(env, mdd);
- if (IS_ERR(handle))
- GOTO(out_pending, rc = PTR_ERR(handle));
-
- rc = mdd_trans_start(env, mdd, handle);
-
- mdd_write_lock(env, mdd_obj, MOR_TGT_CHILD);
- rc = mdd_oc_sanity_check(env, mdd_obj, ma);
- if (rc)
- GOTO(unlock, rc);
-
- rc = mdd_object_create_internal(env, NULL, mdd_obj, ma, handle, spec);
- if (rc)
- GOTO(unlock, rc);
-
- if (spec->sp_cr_flags & MDS_CREATE_SLAVE_OBJ) {
- /* If creating the slave object, set slave EA here. */
- int lmv_size = spec->u.sp_ea.eadatalen;
- struct lmv_stripe_md *lmv;
-
- lmv = (struct lmv_stripe_md *)spec->u.sp_ea.eadata;
- LASSERT(lmv != NULL && lmv_size > 0);
-
- rc = __mdd_xattr_set(env, mdd_obj,
- mdd_buf_get_const(env, lmv, lmv_size),
- XATTR_NAME_LMV, 0, handle);
- if (rc)
- GOTO(unlock, rc);
-
- rc = mdd_attr_set_internal(env, mdd_obj, &ma->ma_attr,
- handle, 0);
- } else {
-#ifdef CONFIG_FS_POSIX_ACL
- if (spec->sp_cr_flags & MDS_CREATE_RMT_ACL) {
- struct lu_buf *buf = &mdd_env_info(env)->mti_buf;
-
- buf->lb_buf = (void *)spec->u.sp_ea.eadata;
- buf->lb_len = spec->u.sp_ea.eadatalen;
- if ((buf->lb_len > 0) && (buf->lb_buf != NULL)) {
- rc = __mdd_acl_init(env, mdd_obj, buf,
- &ma->ma_attr.la_mode,
- handle);
- if (rc)
- GOTO(unlock, rc);
- else
- ma->ma_attr.la_valid |= LA_MODE;
- }
-
- pfid = spec->u.sp_ea.fid;
- }
-#endif
- rc = mdd_object_initialize(env, pfid, NULL, mdd_obj, ma, handle,
- spec);
- }
- EXIT;
-unlock:
- if (rc == 0)
- rc = mdd_attr_get_internal(env, mdd_obj, ma);
- mdd_write_unlock(env, mdd_obj);
-
- 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,
- inode_pending, 0);
- lquota_pending_commit(mds_quota_interface_ref, obd, qids,
- block_pending, 1);
- /* Trigger dqacq 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;
-}
-
-/* partial link */
-static int mdd_ref_add(const struct lu_env *env, struct md_object *obj,
- const struct md_attr *ma)
-{
- struct lu_attr *la_copy = &mdd_env_info(env)->mti_la_for_fix;
- struct mdd_object *mdd_obj = md2mdd_obj(obj);
- struct mdd_device *mdd = mdo2mdd(obj);
- struct thandle *handle;
- int rc;
- ENTRY;
-
- /* XXX: this code won't be used ever:
- * DNE uses slightly different approach */
- LBUG();
-
- handle = mdd_trans_create(env, mdd);
- if (IS_ERR(handle))
- RETURN(-ENOMEM);
-
- rc = mdd_trans_start(env, mdd, handle);
-
- mdd_write_lock(env, mdd_obj, MOR_TGT_CHILD);
- rc = mdd_link_sanity_check(env, NULL, NULL, mdd_obj);
- if (rc == 0)
- mdo_ref_add(env, mdd_obj, handle);
- mdd_write_unlock(env, mdd_obj);
- if (rc == 0) {
- LASSERT(ma->ma_attr.la_valid & LA_CTIME);
- la_copy->la_ctime = ma->ma_attr.la_ctime;
-
- la_copy->la_valid = LA_CTIME;
- rc = mdd_attr_check_set_internal_locked(env, mdd_obj, la_copy,
- handle, 0);
- }
- mdd_trans_stop(env, mdd, 0, handle);
-
- RETURN(rc);
-}
-
void mdd_object_make_hint(const struct lu_env *env, struct mdd_object *parent,
struct mdd_object *child, struct lu_attr *attr)
{
.moo_xattr_set = mdd_xattr_set,
.moo_xattr_list = mdd_xattr_list,
.moo_xattr_del = mdd_xattr_del,
- .moo_object_create = mdd_object_create,
- .moo_ref_add = mdd_ref_add,
- .moo_ref_del = mdd_ref_del,
.moo_open = mdd_open,
.moo_close = mdd_close,
.moo_readpage = mdd_readpage,
.moo_capa_get = mdd_capa_get,
.moo_object_sync = mdd_object_sync,
.moo_path = mdd_path,
- .moo_file_lock = mdd_file_lock,
- .moo_file_unlock = mdd_file_unlock,
};