}
/* rename is split to local/remote by location of new parent dir */
+struct md_object *md_object_find(const struct lu_context *ctx,
+ struct md_device *md,
+ const struct lu_fid *f)
+{
+ struct lu_object *o;
+ struct md_object *m;
+ ENTRY;
+
+ o = lu_object_find(ctx, md2lu_dev(md)->ld_site, f);
+ if (IS_ERR(o))
+ m = (struct md_object *)o;
+ else {
+ o = lu_object_locate(o->lo_header, md2lu_dev(md)->ld_type);
+ m = o ? lu2md(o) : NULL;
+ }
+ RETURN(m);
+}
+
static int cml_rename(const struct lu_context *ctx, struct md_object *mo_po,
struct md_object *mo_pn, const struct lu_fid *lf,
const char *s_name, struct md_object *mo_t,
const char *t_name, struct md_attr *ma)
{
+ struct cmm_thread_info *cmi;
+ struct md_object *mo_s = md_object_find(ctx, md_obj2dev(mo_po), lf);
+ struct md_attr *tmp_ma;
int rc;
ENTRY;
+ cmi = lu_context_key_get(ctx, &cmm_thread_key);
+ LASSERT(cmi);
+ tmp_ma = &cmi->cmi_ma;
+ tmp_ma->ma_need = MA_INODE;
+
+ /* get type from src, can be remote req */
+ rc = mo_attr_get(ctx, md_object_next(mo_s), tmp_ma);
+ if (rc != 0)
+ RETURN(rc);
+
+ ma->ma_attr.la_mode = tmp_ma->ma_attr.la_mode;
+
if (mo_t && lu_object_exists(&mo_t->mo_lu) < 0) {
/* mo_t is remote object and there is RPC to unlink it */
rc = mo_ref_del(ctx, md_object_next(mo_t), ma);
mdc_body2attr(body, ma);
}
+static int mdc_attr_get(const struct lu_context *ctx, struct md_object *mo,
+ struct md_attr *ma)
+{
+ struct mdc_device *mc = md2mdc_dev(md_obj2dev(mo));
+ struct mdc_thread_info *mci;
+ int rc;
+ ENTRY;
+
+ mci = lu_context_key_get(ctx, &mdc_thread_key);
+ LASSERT(mci);
+
+ memset(&mci->mci_opdata, 0, sizeof(mci->mci_opdata));
+
+ rc = md_getattr(mc->mc_desc.cl_exp, lu_object_fid(&mo->mo_lu),
+ OBD_MD_FLMODE | OBD_MD_FLUID | OBD_MD_FLGID,
+ 0, &mci->mci_req);
+
+ if (rc == 0) {
+ /* get attr from request */
+ mdc_req2attr_update(ctx, ma);
+ }
+
+ ptlrpc_req_finished(mci->mci_req);
+
+ RETURN(rc);
+}
+
+
static int mdc_object_create(const struct lu_context *ctx,
struct md_object *mo,
const struct md_create_spec *spec,
#endif
static struct md_object_operations mdc_mo_ops = {
+ .moo_attr_get = mdc_attr_get,
.moo_object_create = mdc_object_create,
.moo_ref_add = mdc_ref_add,
.moo_ref_del = mdc_ref_del,
}
/*
- * return 0: if p2 is the parent of p1
+ * return 0: if lf is the fid of the ancestor of p1
* otherwise: other_value
*/
static int mdd_is_parent(const struct lu_context *ctxt,
struct mdd_device *mdd,
struct mdd_object *p1,
- struct mdd_object *p2)
+ const struct lu_fid *lf)
{
struct lu_fid * pfid;
struct mdd_object *parent = NULL;
rc = mdd_parent_fid(ctxt, p1, pfid);
if (rc)
GOTO(out, rc);
- if (lu_fid_eq(pfid, mdo2fid(p2)))
+ if (lu_fid_eq(pfid, lf))
GOTO(out, rc = 0);
if (lu_fid_eq(pfid, &mdd->mdd_root_fid))
GOTO(out, rc = 1);
RETURN(0);
}
- if (!mdd_is_parent(ctxt, mdd, src_pobj, tgt_pobj)) {
+ if (!mdd_is_parent(ctxt, mdd, src_pobj, mdo2fid(tgt_pobj))) {
mdd_lock2(ctxt, tgt_pobj, src_pobj);
RETURN(0);
}
static int mdd_rename_sanity_check(const struct lu_context *ctxt,
struct mdd_object *src_pobj,
struct mdd_object *tgt_pobj,
- struct mdd_object *sobj,
+ const struct lu_fid *sfid,
+ int src_is_dir,
struct mdd_object *tobj)
{
struct mdd_device *mdd =mdo2mdd(&src_pobj->mod_obj);
- int rc = 0, src_is_dir, tgt_is_dir;
+ int rc = 0, tgt_is_dir;
ENTRY;
- src_is_dir = S_ISDIR(mdd_object_type(sobj));
- rc = mdd_may_delete(ctxt, src_pobj, sobj, src_is_dir);
- if (rc)
- GOTO(out, rc);
+ if (mdd_is_dead_obj(src_pobj))
+ RETURN(-ENOENT);
if (!tobj) {
rc = mdd_may_create(ctxt, tgt_pobj, NULL);
}
}
if (rc)
- GOTO(out, rc);
+ RETURN(rc);
/* source should not be ancestor of target dir */
- if (src_is_dir && !mdd_is_parent(ctxt, mdd, tgt_pobj, sobj))
+ if (src_is_dir && !mdd_is_parent(ctxt, mdd, tgt_pobj, sfid))
rc = -EINVAL;
-out:
- mdd_object_put(ctxt, sobj);
RETURN(rc);
}
-
+/* src object can be remote that is why we use only fid and type of object */
static int mdd_rename(const struct lu_context *ctxt, struct md_object *src_pobj,
struct md_object *tgt_pobj, const struct lu_fid *lf,
const char *sname, struct md_object *tobj,
int rc;
ENTRY;
- /* the source can be remote one, not supported yet */
- if (mdd_sobj == NULL)
- RETURN(-EOPNOTSUPP);
-
- is_dir = S_ISDIR(mdd_object_type(mdd_sobj));
+ LASSERT(ma->ma_attr.la_mode & S_IFMT);
+ is_dir = S_ISDIR(ma->ma_attr.la_mode);
if (tobj)
mdd_tobj = md2mdd_obj(tobj);
/*XXX: shouldn't this check be done under lock below? */
rc = mdd_rename_sanity_check(ctxt, mdd_spobj, mdd_tpobj,
- mdd_sobj, mdd_tobj);
+ lf, is_dir, mdd_tobj);
if (rc)
RETURN(rc);
*la_copy = ma->ma_attr;
la_copy->la_valid = LA_CTIME;
- rc = mdd_attr_set_internal_locked(ctxt, mdd_sobj, la_copy, handle);
- if (rc)
- GOTO(cleanup, rc);
-
+ if (mdd_sobj) {
+ /*XXX: how to update ctime for remote sobj? */
+ rc = mdd_attr_set_internal_locked(ctxt, mdd_sobj, la_copy, handle);
+ if (rc)
+ GOTO(cleanup, rc);
+ }
if (tobj && lu_object_exists(&tobj->mo_lu)) {
mdd_write_lock(ctxt, mdd_tobj);
__mdd_ref_del(ctxt, mdd_tobj, handle);