From: wangdi Date: Sun, 13 Aug 2006 17:36:07 +0000 (+0000) Subject: Branch: b_new_cmd X-Git-Tag: v1_8_0_110~486^2~1194 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=1457874dc4057488d5859ee09c26cd41341a9790;p=fs%2Flustre-release.git Branch: b_new_cmd 1) add ma_need to indicate which field it need when it call the lower layer 2) reorganize mdd setattr/getattr code. 3) fix some problems in set/get md. 4) prepare the reply buffer for close. 5) some other fixes and cleanup --- diff --git a/lustre/include/lustre_mds.h b/lustre/include/lustre_mds.h index 00ba485..33a90ee 100644 --- a/lustre/include/lustre_mds.h +++ b/lustre/include/lustre_mds.h @@ -90,6 +90,9 @@ int mds_log_op_unlink(struct obd_device *obd, struct inode *inode, int mds_log_op_setattr(struct obd_device *obd, struct inode *inode, struct lov_mds_md *lmm, int lmm_size, struct llog_cookie *logcookies, int cookies_size); +int mds_osc_setattr_async(struct obd_device *obd, __u32 uid, __u32 gid, + struct lov_mds_md *lmm, int lmm_size, + struct llog_cookie *logcookies, __u64 id, __u32 gen); /* ioctls for trying requests */ #define IOC_REQUEST_TYPE 'f' diff --git a/lustre/include/md_object.h b/lustre/include/md_object.h index 18a2053..242993b 100644 --- a/lustre/include/md_object.h +++ b/lustre/include/md_object.h @@ -54,13 +54,24 @@ enum ma_valid { }; struct md_attr { - __u64 ma_valid; + __u64 ma_valid; + __u64 ma_need; + __u64 ma_attr_flags; struct lu_attr ma_attr; struct lov_mds_md *ma_lmm; int ma_lmm_size; struct llog_cookie *ma_cookie; int ma_cookie_size; }; + +enum md_attr_flags { + MD_ATIME_SET = 1 << 0, + MD_MTIME_SET = 1 << 1, + MD_CTIME_SET = 1 << 2, + MD_ATTR_FLAG = 1 << 3, + MD_ATTR_RAW = 1 << 4 +}; + /* additional parameters for create */ struct md_create_spec { union { diff --git a/lustre/mdd/mdd_handler.c b/lustre/mdd/mdd_handler.c index 70bc64a..796b834 100644 --- a/lustre/mdd/mdd_handler.c +++ b/lustre/mdd/mdd_handler.c @@ -50,10 +50,6 @@ static struct thandle* mdd_trans_start(const struct lu_context *ctxt, static void mdd_trans_stop(const struct lu_context *ctxt, struct mdd_device *mdd, struct thandle *handle); static struct dt_object* mdd_object_child(struct mdd_object *o); -static void mdd_lock(const struct lu_context *ctx, - struct mdd_object *obj, enum dt_lock_mode mode); -static void mdd_unlock(const struct lu_context *ctx, - struct mdd_object *obj, enum dt_lock_mode mode); static void __mdd_ref_add(const struct lu_context *ctxt, struct mdd_object *obj, struct thandle *handle); static void __mdd_ref_del(const struct lu_context *ctxt, struct mdd_object *obj, @@ -152,11 +148,6 @@ static inline void mdd_object_put(const struct lu_context *ctxt, lu_object_put(ctxt, &o->mod_obj.mo_lu); } -static umode_t mdd_object_type(const struct mdd_object *obj) -{ - return lu_object_attr(&obj->mod_obj.mo_lu); -} - static void mdd_set_dead_obj(struct mdd_object *obj) { if (obj) @@ -216,66 +207,65 @@ static int mdd_may_delete(const struct lu_context *ctxt, RETURN(rc); } -static int __mdd_attr_get(const struct lu_context *ctxt, - struct mdd_object *obj, struct md_attr *ma) +static int __mdd_lmm_get(const struct lu_context *ctxt, + struct mdd_object *obj, struct md_attr *ma) { - struct dt_object *next; - int rc; - - ENTRY; - - LASSERT(lu_object_exists(ctxt, mdd2lu_obj(obj))); + int rc; - next = mdd_object_child(obj); - rc = next->do_ops->do_attr_get(ctxt, next, &ma->ma_attr); - if (rc == 0) { - LASSERT((ma->ma_attr.la_mode & S_IFMT) == - (lu_object_attr(mdd2lu_obj(obj)) & S_IFMT)); - ma->ma_valid = MA_INODE; + LASSERT(ma->ma_lmm != NULL && ma->ma_lmm_size > 0); + rc = mdd_get_md(ctxt, obj, ma->ma_lmm, &ma->ma_lmm_size, 0); + if (rc > 0) { + ma->ma_valid |= MA_LOV; + rc = 0; } - RETURN(rc); } -static int __mdd_lov_get(const struct lu_context *ctxt, - struct mdd_object *obj, struct md_attr *ma) +static int mdd_attr_get_internal (const struct lu_context *ctxt, + struct mdd_object *mdd_obj, + struct md_attr *ma, int need_locked) { struct dt_object *next; - int rc = 0; - + int rc = 0; ENTRY; - next = mdd_object_child(obj); - if ((S_ISREG(ma->ma_attr.la_mode) || S_ISDIR(ma->ma_attr.la_mode)) - && ma->ma_lmm != 0 && ma->ma_lmm_size > 0) { - rc = mdd_get_md(ctxt, &obj->mod_obj, - ma->ma_lmm, &ma->ma_lmm_size); - if (rc > 0) { - ma->ma_valid |= MA_LOV; - rc = 0; - } + if (need_locked) + mdd_lock(ctxt, mdd_obj, DT_READ_LOCK); + if (ma->ma_need & MA_INODE) { + next = mdd_object_child(mdd_obj); + rc = next->do_ops->do_attr_get(ctxt, next, &ma->ma_attr); + if (rc) + GOTO(out, rc); + ma->ma_valid = MA_INODE; } + if (ma->ma_need & MA_LOV) { + if ((S_ISREG(ma->ma_attr.la_mode) + || S_ISDIR(ma->ma_attr.la_mode))) { + rc = __mdd_lmm_get(ctxt, mdd_obj, ma); + } + } +out: + CDEBUG(D_INODE, "after getattr rc = %d, ma_valid = "LPX64"\n", + rc, ma->ma_valid); + if (need_locked) + mdd_unlock(ctxt, mdd_obj, DT_READ_LOCK); RETURN(rc); } - + static int mdd_attr_get(const struct lu_context *ctxt, struct md_object *obj, struct md_attr *ma) { struct mdd_object *mdd_obj = md2mdd_obj(obj); - struct dt_object *next; int rc; ENTRY; - next = mdd_object_child(mdd_obj); - rc = __mdd_attr_get(ctxt, mdd_obj, ma); - if (rc == 0) { - /* get LOV EA also */ - rc = __mdd_lov_get(ctxt, mdd_obj, ma); - } - CDEBUG(D_INODE, "after getattr rc = %d, ma_valid = "LPX64"\n", - rc, ma->ma_valid); + LASSERT(lu_object_exists(ctxt, &obj->mo_lu)); + + mdd_lock(ctxt, mdd_obj, DT_READ_LOCK); + rc = mdd_attr_get_internal(ctxt, mdd_obj, ma, 0); + mdd_unlock(ctxt, mdd_obj, DT_READ_LOCK); RETURN(rc); } @@ -501,16 +491,16 @@ static struct lu_object_operations mdd_lu_obj_ops = { .loo_object_exists = mdd_object_exists, }; -static void mdd_lock(const struct lu_context *ctxt, - struct mdd_object *obj, enum dt_lock_mode mode) +void mdd_lock(const struct lu_context *ctxt, struct mdd_object *obj, + enum dt_lock_mode mode) { struct dt_object *next = mdd_object_child(obj); next->do_ops->do_lock(ctxt, next, mode); } -static void mdd_unlock(const struct lu_context *ctxt, - struct mdd_object *obj, enum dt_lock_mode mode) +void mdd_unlock(const struct lu_context *ctxt, struct mdd_object *obj, + enum dt_lock_mode mode) { struct dt_object *next = mdd_object_child(obj); @@ -580,11 +570,118 @@ static int __mdd_xattr_set(const struct lu_context *ctxt, struct mdd_object *o, int fl, struct thandle *handle) { struct dt_object *next; - + int rc = 0; + LASSERT(lu_object_exists(ctxt, mdd2lu_obj(o))); next = mdd_object_child(o); - return next->do_ops->do_xattr_set(ctxt, next, buf, buf_len, name, fl, - handle); + if (buf && buf_len > 0) { + rc = next->do_ops->do_xattr_set(ctxt, next, buf, buf_len, name, + 0, handle); + }else if (buf == NULL && buf_len == 0) { + rc = next->do_ops->do_xattr_del(ctxt, next, name, handle); + } + RETURN(rc); +} +/* this gives the same functionality as the code between + * sys_chmod and inode_setattr + * chown_common and inode_setattr + * utimes and inode_setattr + * This API is ported from mds_fix_attr but remove some unnecesssary stuff. + * and port to + */ +int mdd_fix_attr(const struct lu_context *ctxt, struct mdd_object *obj, + const struct md_attr *ma) +{ + time_t now = CURRENT_SECONDS; + struct lu_attr *la = (struct lu_attr *)&ma->ma_attr; + struct lu_attr *tmp_la = &mdd_ctx_info(ctxt)->mti_la; + struct dt_object *next = mdd_object_child(obj); + int rc = 0; + ENTRY; + + rc = next->do_ops->do_attr_get(ctxt, next, tmp_la); + if (rc) + RETURN(rc); + + if (!(ma->ma_attr_flags & ATTR_CTIME_SET)) + la->la_ctime = now; + + if (!(ma->ma_attr_flags & ATTR_ATIME_SET)) + la->la_atime = now; + if (!(ma->ma_attr_flags & ATTR_MTIME_SET)) + la->la_mtime = now; + + /*XXX Check permission */ +#if 0 + if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) + RETURN((attr->ia_valid & ~ATTR_ATTR_FLAG) ? -EPERM : 0); + + /* times */ + if ((ia_valid & (ATTR_MTIME|ATTR_ATIME)) == (ATTR_MTIME|ATTR_ATIME)) { + if (current->fsuid != inode->i_uid && + (error = ll_permission(inode, MAY_WRITE, NULL)) != 0) + RETURN(error); + } + if (ia_valid & ATTR_SIZE && + /* NFSD hack for open(O_CREAT|O_TRUNC)=mknod+truncate (bug 5781) */ + !(rec->ur_uc.luc_fsuid == inode->i_uid && + ia_valid & MDS_OPEN_OWNEROVERRIDE)) { + if ((error = ll_permission(inode, MAY_WRITE, NULL)) != 0) + RETURN(error); + } +#endif + + if (la->la_valid & (LA_UID | LA_GID)) { + /* chown */ + + rc = -EPERM; + + if (la->la_uid == (uid_t) -1) + la->la_uid = tmp_la->la_uid; + if (la->la_gid == (gid_t) -1) + la->la_gid = tmp_la->la_gid; + if (!(la->la_valid & ATTR_MODE)) + la->la_mode = tmp_la->la_mode; + /* + * If the user or group of a non-directory has been + * changed by a non-root user, remove the setuid bit. + * 19981026 David C Niemi + * + * Changed this to apply to all users, including root, + * to avoid some races. This is the behavior we had in + * 2.0. The check for non-root was definitely wrong + * for 2.2 anyway, as it should have been using + * CAP_FSETID rather than fsuid -- 19990830 SD. + */ + if ((tmp_la->la_mode & S_ISUID) == S_ISUID && + !S_ISDIR(tmp_la->la_mode)) { + la->la_mode &= ~S_ISUID; + la->la_valid |= LA_MODE; + } + /* + * Likewise, if the user or group of a non-directory + * has been changed by a non-root user, remove the + * setgid bit UNLESS there is no group execute bit + * (this would be a file marked for mandatory + * locking). 19981026 David C Niemi + * + * Removed the fsuid check (see the comment above) -- + * 19990830 SD. + */ + if (((tmp_la->la_mode & (S_ISGID | S_IXGRP)) == + (S_ISGID | S_IXGRP)) && !S_ISDIR(tmp_la->la_mode)) { + la->la_mode &= ~S_ISGID; + la->la_valid |= ATTR_MODE; + } + } else if (la->la_valid & LA_MODE) { + int mode = la->la_mode; + /* chmod */ + if (la->la_mode == (umode_t)-1) + mode = tmp_la->la_mode; + la->la_mode = + (mode & S_IALLUGO) | (tmp_la->la_mode & ~S_IALLUGO); + } + RETURN(rc); } @@ -595,43 +692,82 @@ static int mdd_attr_set(const struct lu_context *ctxt, struct mdd_object *mdd_obj = md2mdd_obj(obj); struct mdd_device *mdd = mdo2mdd(obj); struct thandle *handle; - int rc; + struct lov_mds_md *lmm = NULL; + int rc = 0, lmm_size = 0, max_size; ENTRY; mdd_txn_param_build(ctxt, &MDD_TXN_ATTR_SET); handle = mdd_trans_start(ctxt, mdd); if (IS_ERR(handle)) RETURN(PTR_ERR(handle)); + /*TODO: add lock here*/ + /* start a log jounal handle if needed */ + if (S_ISREG(mdd_object_type(mdd_obj)) && + ma->ma_attr.la_valid & (LA_UID | LA_GID)) { + mdd_lov_mdsize(ctxt, mdd, &max_size); + OBD_ALLOC(lmm, max_size); + if (lmm == NULL) + GOTO(cleanup, rc = -ENOMEM); + + rc = mdd_get_md(ctxt, mdd_obj, lmm, &lmm_size, 1); + + if (rc < 0) + GOTO(cleanup, rc); + } - mdd_lock(ctxt, mdd_obj, DT_WRITE_LOCK); - - rc = mdd_attr_set_internal(ctxt, mdd_obj, &ma->ma_attr, handle); - if (rc == 0 && (ma->ma_valid & MA_LOV)) { - /* set LOV ea now */ - rc = __mdd_xattr_set(ctxt, mdd_obj, - ma->ma_lmm, ma->ma_lmm_size, - XATTR_NAME_LOV, 0, handle); + if (ma->ma_attr.la_valid & (ATTR_MTIME | ATTR_CTIME)) + CDEBUG(D_INODE, "setting mtime "LPU64", ctime "LPU64"\n", + ma->ma_attr.la_mtime, ma->ma_attr.la_ctime); + + rc = mdd_fix_attr(ctxt, mdd_obj, ma); + if (rc) + GOTO(cleanup, rc); + if (ma->ma_attr_flags & MD_ATTR_FLAG) { /* ioctl */ + rc = -ENOTSUPP; + } else if (ma->ma_attr.la_valid) { /* setattr */ + mdd_lock(ctxt, mdd_obj, DT_WRITE_LOCK); + rc = mdd_attr_set_internal(ctxt, mdd_obj, &ma->ma_attr, handle); + mdd_unlock(ctxt, mdd_obj, DT_WRITE_LOCK); + + /* journal chown/chgrp in llog, just like unlink */ + if (rc == 0 && lmm_size){ + /*TODO set_attr llog */ + } } - /* XXX: llog cancel cookie? */ - mdd_unlock(ctxt, mdd_obj, DT_WRITE_LOCK); + if (rc == 0 && ma->ma_valid & MA_LOV) { + if ((S_ISREG(mdd_object_type(mdd_obj)) || + S_ISDIR(mdd_object_type(mdd_obj)))) { + /*TODO check permission*/ + rc = mdd_lov_set_md(ctxt, NULL, mdd_obj, ma->ma_lmm, + ma->ma_lmm_size, handle, 1); + } + + } +cleanup: mdd_trans_stop(ctxt, mdd, handle); - + if (rc == 0 && lmm_size) { + /*set obd attr, if needed*/ + rc = mdd_lov_setattr_async(ctxt, mdd_obj, lmm, lmm_size); + } + if (lmm != NULL) { + OBD_FREE(lmm, max_size); + } + RETURN(rc); } -int mdd_xattr_set_txn(const struct lu_context *ctxt, struct md_object *obj, +int mdd_xattr_set_txn(const struct lu_context *ctxt, struct mdd_object *obj, const void *buf, int buf_len, const char *name, int fl, struct thandle *handle) { - struct mdd_object *mdd_obj = md2mdd_obj(obj); int rc; ENTRY; - mdd_lock(ctxt, mdd_obj, DT_WRITE_LOCK); - rc = __mdd_xattr_set(ctxt, mdd_obj, buf, buf_len, name, + mdd_lock(ctxt, obj, DT_WRITE_LOCK); + rc = __mdd_xattr_set(ctxt, obj, buf, buf_len, name, fl, handle); - mdd_unlock(ctxt, mdd_obj, DT_WRITE_LOCK); + mdd_unlock(ctxt, obj, DT_WRITE_LOCK); RETURN(rc); } @@ -649,7 +785,8 @@ static int mdd_xattr_set(const struct lu_context *ctxt, struct md_object *obj, if (IS_ERR(handle)) RETURN(PTR_ERR(handle)); - rc = mdd_xattr_set_txn(ctxt, obj, buf, buf_len, name, fl, handle); + rc = mdd_xattr_set_txn(ctxt, md2mdd_obj(obj), buf, buf_len, name, + fl, handle); mdd_trans_stop(ctxt, mdd, handle); @@ -818,20 +955,17 @@ static int __mdd_finish_unlink(const struct lu_context *ctxt, { int rc; ENTRY; - rc = __mdd_attr_get(ctxt, obj, ma); + + rc = mdd_attr_get_internal(ctxt, obj, ma, 0); if (rc) RETURN(rc); if (atomic_read(&obj->mod_count) == 0 && - ma->ma_attr.la_nlink == 0) { - rc = __mdd_lov_get(ctxt, obj, ma); - if (rc) { - CERROR("Can't get LOV attr during unlink()\n"); - } - if(S_ISREG(ma->ma_attr.la_mode) && - ma->ma_valid & MA_LOV) + ma->ma_attr.la_nlink == 0 && S_ISREG(mdd_object_type(obj))) { + rc = __mdd_lmm_get(ctxt, obj, ma); + if(S_ISREG(ma->ma_attr.la_mode) && ma->ma_valid & MA_LOV) rc = mdd_unlink_log(ctxt, mdo2mdd(&obj->mod_obj), - obj, ma); + obj, ma); } RETURN(rc); } @@ -893,6 +1027,9 @@ static int mdd_unlink(const struct lu_context *ctxt, struct md_object *pobj, /* unlink dotdot */ __mdd_ref_del(ctxt, mdd_pobj, handle); } + rc = mdd_attr_get_internal(ctxt, mdd_cobj, ma, 0); + if (rc) + GOTO(cleanup, rc); rc = __mdd_finish_unlink(ctxt, mdd_cobj, ma); @@ -1083,8 +1220,12 @@ static int mdd_rename(const struct lu_context *ctxt, struct md_object *src_pobj, __mdd_ref_del(ctxt, mdd_tobj, handle); if (S_ISDIR(mdd_object_type(mdd_tobj))) __mdd_ref_del(ctxt, mdd_tpobj, handle); - else - rc = mdd_attr_get(ctxt, tobj, ma); + else { + rc = mdd_attr_get_internal(ctxt, mdd_tobj, ma, 0); + if (rc) + GOTO(cleanup, rc); + } + mdd_set_dead_obj(mdd_tobj); } cleanup: @@ -1182,18 +1323,21 @@ static int mdd_create_data(const struct lu_context *ctxt, int rc; ENTRY; + rc = mdd_lov_create(ctxt, mdd, mdd_pobj, son, &lmm, &lmm_size, spec, + attr); + if (rc) + RETURN(rc); + mdd_txn_param_build(ctxt, &MDD_TXN_CREATE_DATA); handle = mdd_trans_start(ctxt, mdd); if (IS_ERR(handle)) RETURN(PTR_ERR(handle)); - rc = mdd_lov_create(ctxt, mdd, mdd_pobj, son, &lmm, &lmm_size, spec, - attr); if (rc == 0) { - rc = mdd_lov_set_md(ctxt, pobj, cobj, lmm, - lmm_size, attr, handle); + rc = mdd_lov_set_md(ctxt, mdd_pobj, son, lmm, lmm_size, + handle, 0); if (rc == 0) - rc = mdd_attr_get(ctxt, cobj, ma); + rc = mdd_attr_get_internal(ctxt, son, ma, 1); } mdd_trans_stop(ctxt, mdd, handle); @@ -1349,7 +1493,7 @@ static int mdd_create(const struct lu_context *ctxt, struct md_object *pobj, GOTO(cleanup, rc); inserted = 1; - rc = mdd_lov_set_md(ctxt, pobj, child, lmm, lmm_size, attr, handle); + rc = mdd_lov_set_md(ctxt, mdd_pobj, son, lmm, lmm_size, handle, 0); if (rc) { CERROR("error on stripe info copy %d \n", rc); GOTO(cleanup, rc); @@ -1369,7 +1513,7 @@ static int mdd_create(const struct lu_context *ctxt, struct md_object *pobj, rc = -EFAULT; } /* return attr back */ - mdd_attr_get(ctxt, child, ma); + rc = mdd_attr_get_internal(ctxt, son, ma, 1); cleanup: if (rc && created) { int rc2 = 0; @@ -1410,10 +1554,13 @@ static int mdd_object_create(const struct lu_context *ctxt, /* XXX: parent fid is needed here rc = __mdd_object_initialize(ctxt, mdo, son, ma, handle); */ - mdd_attr_get(ctxt, obj, ma); + if (rc) + GOTO(out, rc); - mdd_trans_stop(ctxt, mdd, handle); + rc = mdd_attr_get_internal(ctxt, md2mdd_obj(obj), ma, 1); + mdd_trans_stop(ctxt, mdd, handle); +out: RETURN(rc); } /* partial operation */ @@ -1613,6 +1760,7 @@ static int mdd_ref_del(const struct lu_context *ctxt, struct md_object *obj, } __mdd_ref_del(ctxt, mdd_obj, handle); + if (S_ISDIR(lu_object_attr(&obj->mo_lu))) { /* unlink dot */ __mdd_ref_del(ctxt, mdd_obj, handle); diff --git a/lustre/mdd/mdd_internal.h b/lustre/mdd/mdd_internal.h index 1969a1f..fd69c1b 100644 --- a/lustre/mdd/mdd_internal.h +++ b/lustre/mdd/mdd_internal.h @@ -63,27 +63,36 @@ struct mdd_thread_info { int mdd_init_obd(const struct lu_context *ctxt, struct mdd_device *mdd, char *dev); -int mdd_xattr_set_txn(const struct lu_context *ctxt, struct md_object *obj, +int mdd_xattr_set_txn(const struct lu_context *ctxt, struct mdd_object *obj, const void *buf, int buf_len, const char *name, int fl, struct thandle *txn); -int mdd_lov_set_md(const struct lu_context *ctxt, struct md_object *pobj, - struct md_object *child, struct lov_mds_md *lmm, - int lmm_size, struct lu_attr *la, struct thandle *handle); +int mdd_lov_set_md(const struct lu_context *ctxt, struct mdd_object *pobj, + struct mdd_object *child, struct lov_mds_md *lmm, + int lmm_size, struct thandle *handle, int set_stripe); int mdd_lov_create(const struct lu_context *ctxt, struct mdd_device *mdd, struct mdd_object *parent, struct mdd_object *child, struct lov_mds_md **lmm, int *lmm_size, const struct md_create_spec *spec, struct lu_attr *la); -int mdd_get_md(const struct lu_context *ctxt, struct md_object *obj, - void *md, int *md_size); +int mdd_get_md(const struct lu_context *ctxt, struct mdd_object *obj, + void *md, int *md_size, int need_locked); int mdd_unlink_log(const struct lu_context *ctxt, struct mdd_device *mdd, struct mdd_object *mdd_cobj, struct md_attr *ma); int mdd_attr_set_internal(const struct lu_context *ctxt, struct mdd_object *o, const struct lu_attr *attr, struct thandle *handle); +int mdd_get_cookie_size(const struct lu_context *ctxt, struct mdd_device *mdd, + struct lov_mds_md *lmm); + +int mdd_lov_setattr_async(const struct lu_context *ctxt, struct mdd_object *obj, + struct lov_mds_md *lmm, int lmm_size); struct mdd_thread_info *mdd_ctx_info(const struct lu_context *ctx); +void mdd_lock(const struct lu_context *ctxt, struct mdd_object *obj, + enum dt_lock_mode mode); +void mdd_unlock(const struct lu_context *ctxt, struct mdd_object *obj, + enum dt_lock_mode mode); extern struct lu_device_operations mdd_lu_ops; static inline int lu_device_is_mdd(struct lu_device *d) { @@ -142,6 +151,11 @@ static inline const struct lu_fid *mdo2fid(const struct mdd_object *obj) return lu_object_fid(&obj->mod_obj.mo_lu); } +static inline umode_t mdd_object_type(const struct mdd_object *obj) +{ + return lu_object_attr(&obj->mod_obj.mo_lu); +} + int mdd_lov_mdsize(const struct lu_context *ctxt, struct mdd_device *mdd, int *md_size); int mdd_lov_cookiesize(const struct lu_context *ctxt, struct mdd_device *mdd, diff --git a/lustre/mdd/mdd_lov.c b/lustre/mdd/mdd_lov.c index 647f881..d7b29a4 100644 --- a/lustre/mdd/mdd_lov.c +++ b/lustre/mdd/mdd_lov.c @@ -268,14 +268,16 @@ lcfg_cleanup: RETURN(rc); } -int mdd_get_md(const struct lu_context *ctxt, struct md_object *obj, - void *md, int *md_size) +int mdd_get_md(const struct lu_context *ctxt, struct mdd_object *obj, + void *md, int *md_size, int need_locked) { struct dt_object *next; int rc = 0; ENTRY; - next = mdd_object_child(md2mdd_obj(obj)); + if (need_locked) + mdd_lock(ctxt, obj, DT_READ_LOCK); + next = mdd_object_child(obj); rc = next->do_ops->do_xattr_get(ctxt, next, md, *md_size, MDS_LOV_MD_NAME); /* @@ -292,50 +294,101 @@ int mdd_get_md(const struct lu_context *ctxt, struct md_object *obj, *md_size = rc; } + if (need_locked) + mdd_unlock(ctxt, obj, DT_READ_LOCK); + RETURN (rc); } -int mdd_lov_set_md(const struct lu_context *ctxt, struct md_object *pobj, - struct md_object *child, struct lov_mds_md *lmmp, - int lmm_size, struct lu_attr *la, struct thandle *handle) +static int mdd_lov_set_stripe_md(const struct lu_context *ctxt, + struct mdd_object *obj, struct lov_mds_md *lmmp, + int lmm_size, struct thandle *handle) { - struct lu_attr *tmp_la = &mdd_ctx_info(ctxt)->mti_la; + struct mdd_device *mdd = mdo2mdd(&obj->mod_obj); + struct obd_device *obd = mdd2_obd(mdd); + struct obd_export *lov_exp = obd->u.mds.mds_osc_exp; + struct lov_stripe_md *lsm = NULL; + int rc; + ENTRY; + + LASSERT(S_ISDIR(mdd_object_type(obj)) && S_ISREG(mdd_object_type(obj))); + + rc = obd_iocontrol(OBD_IOC_LOV_SETSTRIPE, lov_exp, 0, &lsm, lmmp); + if (rc) + RETURN(rc); + obd_free_memmd(lov_exp, &lsm); + + rc = mdd_xattr_set_txn(ctxt, obj, lmmp, lmm_size, MDS_LOV_MD_NAME, 0, + handle); + + CDEBUG(D_INFO, "set lov ea of "DFID" rc %d \n", PFID(mdo2fid(obj)), rc); + RETURN(rc); +} + +static int mdd_lov_set_dir_md(const struct lu_context *ctxt, + struct mdd_object *obj, struct lov_mds_md *lmmp, + int lmm_size, struct thandle *handle) +{ + struct lov_user_md *lum = NULL; int rc = 0; ENTRY; - LASSERT(la->la_valid & LA_MODE); - if (S_ISREG(la->la_mode) && lmm_size > 0) { - LASSERT(lmmp != NULL); - rc = mdd_xattr_set_txn(ctxt, child, lmmp, lmm_size, - MDS_LOV_MD_NAME, 0, handle); - if (rc) { - CERROR("error on set stripe info: rc = %d\n", rc); - RETURN(rc); - } - if (la->la_valid & LA_BLKSIZE) { - tmp_la->la_valid = LA_BLKSIZE; - tmp_la->la_blksize = la->la_blksize; - rc = mdd_attr_set_internal(ctxt, md2mdd_obj(child), tmp_la, - handle); + /*TODO check permission*/ + LASSERT(S_ISDIR(mdd_object_type(obj))); + lum = (struct lov_user_md*)lmmp; + + /* if { size, offset, count } = { 0, -1, 0 } (i.e. all default + * values specified) then delete default striping from dir. */ + if ((lum->lmm_stripe_size == 0 && lum->lmm_stripe_count == 0 && + lum->lmm_stripe_offset == (typeof(lum->lmm_stripe_offset))(-1)) || + /* lmm_stripe_size == -1 is deprecated in 1.4.6 */ + lum->lmm_stripe_size == (typeof(lum->lmm_stripe_size))(-1)){ + rc = mdd_xattr_set_txn(ctxt, obj, NULL, 0, MDS_LOV_MD_NAME, 0, + handle); + CDEBUG(D_INFO, "delete lov ea of "DFID" rc %d \n", + PFID(mdo2fid(obj)), rc); + } else { + rc = mdd_lov_set_stripe_md(ctxt, obj, lmmp, lmm_size, handle); + } + RETURN(rc); +} + +int mdd_lov_set_md(const struct lu_context *ctxt, struct mdd_object *pobj, + struct mdd_object *child, struct lov_mds_md *lmmp, + int lmm_size, struct thandle *handle, int set_stripe) +{ + int rc = 0; + ENTRY; + + if (S_ISREG(mdd_object_type(child)) && lmm_size > 0) { + if (set_stripe) { + rc = mdd_lov_set_stripe_md(ctxt, child, lmmp, lmm_size, + handle); + } else { + rc = mdd_xattr_set_txn(ctxt, child, lmmp, lmm_size, + MDS_LOV_MD_NAME, 0, handle); } - } else if (S_ISDIR(la->la_mode)) { - struct lov_mds_md *lmm = &mdd_ctx_info(ctxt)->mti_lmm; - int size = sizeof(lmm); - rc = mdd_get_md(ctxt, pobj, &lmm, &size); - if (rc > 0) { - rc = mdd_xattr_set_txn(ctxt, child, lmm, size, - /* - * Flags are 0: we don't care - * whether attribute exists - * already. - */ + } else if (S_ISDIR(mdd_object_type(child))) { + if (lmmp == NULL && lmm_size == 0) { + struct lov_mds_md *lmm = &mdd_ctx_info(ctxt)->mti_lmm; + int size = sizeof(lmm); + /*Get parent dir stripe and set*/ + rc = mdd_get_md(ctxt, pobj, &lmm, &size, 0); + if (rc > 0) { + rc = mdd_xattr_set_txn(ctxt, child, lmm, size, MDS_LOV_MD_NAME, 0, handle); - if (rc) - CERROR("error on copy stripe info: rc = %d\n", - rc); + if (rc) + CERROR("error on copy stripe info: rc = %d\n", + rc); + } + } else { + LASSERT(lmmp != NULL && lmm_size > 0); + /*delete lmm*/ + rc = mdd_lov_set_dir_md(ctxt, child, lmmp, lmm_size, handle); } } - + CDEBUG(D_INFO, "Set lov md %p size %d for fid "DFID" rc%d/n", + lmmp, lmm_size, PFID(mdo2fid(child)), rc); RETURN(rc); } @@ -439,8 +492,8 @@ int mdd_lov_create(const struct lu_context *ctxt, struct mdd_device *mdd, if (__lmm == NULL) GOTO(out_oa, rc = -ENOMEM); - rc = mdd_get_md(ctxt, &parent->mod_obj, __lmm, - &returned_lmm_size); + rc = mdd_get_md(ctxt, parent, __lmm, + &returned_lmm_size, 1); if (rc > 0) rc = obd_iocontrol(OBD_IOC_LOV_SETSTRIPE, lov_exp, 0, &lsm, __lmm); @@ -479,7 +532,7 @@ int mdd_lov_create(const struct lu_context *ctxt, struct mdd_device *mdd, * by filter_fid, but can not see what is the usages. So just * pack o_seq o_ver here, maybe fix it after this cycle*/ oa->o_fid = lu_object_fid(mdd2lu_obj(child))->f_seq; - oa->o_generation = lu_object_fid(mdd2lu_obj(child))->f_ver; + oa->o_generation = lu_object_fid(mdd2lu_obj(child))->f_oid; oa->o_valid |= OBD_MD_FLFID | OBD_MD_FLGENER; rc = obd_setattr(lov_exp, oa, lsm, NULL); @@ -523,6 +576,27 @@ int mdd_unlink_log(const struct lu_context *ctxt, struct mdd_device *mdd, } return 0; } +int mdd_lov_setattr_async(const struct lu_context *ctxt, struct mdd_object *obj, + struct lov_mds_md *lmm, int lmm_size) +{ + struct mdd_device *mdd = mdo2mdd(&obj->mod_obj); + struct obd_device *obd = mdd2_obd(mdd); + struct lu_attr *tmp_la = &mdd_ctx_info(ctxt)->mti_la; + struct dt_object *next = mdd_object_child(obj); + __u32 seq = lu_object_fid(mdd2lu_obj(obj))->f_seq; + __u32 oid = lu_object_fid(mdd2lu_obj(obj))->f_oid; + int rc = 0; + ENTRY; + + rc = next->do_ops->do_attr_get(ctxt, next, tmp_la); + if (rc) + RETURN(rc); + + rc = mds_osc_setattr_async(obd, tmp_la->la_uid, tmp_la->la_gid, lmm, + lmm_size, NULL, seq, oid); + + RETURN(rc); +} int mdd_lov_mdsize(const struct lu_context *ctxt, struct mdd_device *mdd, int *md_size) diff --git a/lustre/mds/mds_internal.h b/lustre/mds/mds_internal.h index 0952e43..f6acec3 100644 --- a/lustre/mds/mds_internal.h +++ b/lustre/mds/mds_internal.h @@ -137,9 +137,6 @@ int mds_get_parent_child_locked(struct obd_device *obd, struct mds_obd *mds, __u64 child_lockpart); int mds_lock_new_child(struct obd_device *obd, struct inode *inode, struct lustre_handle *child_lockh); -int mds_osc_setattr_async(struct obd_device *obd, struct inode *inode, - struct lov_mds_md *lmm, int lmm_size, - struct llog_cookie *logcookies, struct ll_fid *fid); int mds_get_parents_children_locked(struct obd_device *obd, struct mds_obd *mds, diff --git a/lustre/mds/mds_log.c b/lustre/mds/mds_log.c index a736954..a3351ef 100644 --- a/lustre/mds/mds_log.c +++ b/lustre/mds/mds_log.c @@ -166,6 +166,7 @@ int mds_log_op_setattr(struct obd_device *obd, struct inode *inode, obd_free_memmd(mds->mds_osc_exp, &lsm); RETURN(rc); } +EXPORT_SYMBOL(mds_log_op_setattr); static struct llog_operations mds_ost_orig_logops = { lop_add: mds_llog_origin_add, diff --git a/lustre/mds/mds_reint.c b/lustre/mds/mds_reint.c index 02ad8b7..96bb8b4 100644 --- a/lustre/mds/mds_reint.c +++ b/lustre/mds/mds_reint.c @@ -390,9 +390,9 @@ static void reconstruct_reint_setattr(struct mds_update_record *rec, l_dput(de); } -int mds_osc_setattr_async(struct obd_device *obd, struct inode *inode, +int mds_osc_setattr_async(struct obd_device *obd, __u32 uid, __u32 gid, struct lov_mds_md *lmm, int lmm_size, - struct llog_cookie *logcookies, struct ll_fid *fid) + struct llog_cookie *logcookies, __u64 id, __u32 gen) { struct mds_obd *mds = &obd->u.mds; struct lov_stripe_md *lsm = NULL; @@ -413,7 +413,7 @@ int mds_osc_setattr_async(struct obd_device *obd, struct inode *inode, rc = obd_unpackmd(mds->mds_osc_exp, &lsm, lmm, lmm_size); if (rc < 0) { - CERROR("Error unpack md %p for inode %lu\n", lmm, inode->i_ino); + CERROR("Error unpack md %p for inode "LPU64"\n", lmm, id); GOTO(out, rc); } @@ -425,17 +425,16 @@ int mds_osc_setattr_async(struct obd_device *obd, struct inode *inode, /* then fill oa */ oa->o_id = lsm->lsm_object_id; - oa->o_uid = inode->i_uid; - oa->o_gid = inode->i_gid; + oa->o_uid = uid; + oa->o_gid = gid; oa->o_valid = OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID; if (logcookies) { oa->o_valid |= OBD_MD_FLCOOKIE; oti.oti_logcookies = logcookies; } - LASSERT(fid != NULL); - oa->o_fid = fid->id; - oa->o_generation = fid->generation; + oa->o_fid = id; + oa->o_generation = gen; oa->o_valid |= OBD_MD_FLFID | OBD_MD_FLGENER; /* do setattr from mds to ost asynchronously */ @@ -449,6 +448,7 @@ out: obdo_free(oa); RETURN(rc); } +EXPORT_SYMBOL(mds_osc_setattr_async); /* In the raw-setattr case, we lock the child inode. * In the write-back case or if being called from open, the client holds a lock @@ -644,8 +644,9 @@ static int mds_reint_setattr(struct mds_update_record *rec, int offset, err = mds_finish_transno(mds, inode, handle, req, rc, 0); /* do mds to ost setattr if needed */ if (!rc && !err && lmm_size) - mds_osc_setattr_async(obd, inode, lmm, lmm_size, - logcookies, rec->ur_fid1); + mds_osc_setattr_async(obd, inode->i_ino, inode->i_generation, lmm, + lmm_size, logcookies, rec->ur_fid1->id, + rec->ur_fid1->generation); switch (cleanup_phase) { case 2: diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index 6f9ea7a..2b9f4b0 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -233,7 +233,8 @@ static int mdt_getattr_internal(struct mdt_thread_info *info, ma->ma_lmm = req_capsule_server_get(pill, &RMF_MDT_MD); ma->ma_lmm_size = req_capsule_get_size(pill, &RMF_MDT_MD, RCL_SERVER); - rc = mo_attr_get(ctxt, next, &info->mti_attr); + ma->ma_need = MA_INODE | MA_LOV; + rc = mo_attr_get(ctxt, next, ma); if (rc == -EREMOTE) { /* This object is located on remote node.*/ repbody->fid1 = *mdt_object_fid(o); @@ -733,6 +734,7 @@ static int mdt_sync(struct mdt_thread_info *info) const struct lu_fid *fid; next = mdt_object_child(info->mti_object); fid = mdt_object_fid(info->mti_object); + info->mti_attr.ma_need = MA_INODE; rc = mo_attr_get(info->mti_ctxt, next, &info->mti_attr); if (rc == 0) { @@ -2870,7 +2872,7 @@ DEF_MDT_HNDL_F(HABEO_CORPUS, GETXATTR, mdt_getxattr), DEF_MDT_HNDL_F(0 |HABEO_REFERO, STATFS, mdt_statfs), DEF_MDT_HNDL_F(0 |MUTABOR, REINT, mdt_reint), -DEF_MDT_HNDL_F(HABEO_CORPUS|HABEO_REFERO, CLOSE, mdt_close), +DEF_MDT_HNDL_F(HABEO_CORPUS , CLOSE, mdt_close), DEF_MDT_HNDL_0(0, DONE_WRITING, mdt_done_writing), DEF_MDT_HNDL_F(0 |HABEO_REFERO, PIN, mdt_pin), DEF_MDT_HNDL_0(0, SYNC, mdt_sync), diff --git a/lustre/mdt/mdt_internal.h b/lustre/mdt/mdt_internal.h index 4590d12..975bd11 100644 --- a/lustre/mdt/mdt_internal.h +++ b/lustre/mdt/mdt_internal.h @@ -188,7 +188,7 @@ struct mdt_reint_record { }; enum mdt_reint_flag { - MRF_SETATTR_LOCKED = 1 << 0 + MRF_SETATTR_LOCKED = 1 << 0, }; enum { diff --git a/lustre/mdt/mdt_lib.c b/lustre/mdt/mdt_lib.c index 6d9a8aa..8d08e09 100644 --- a/lustre/mdt/mdt_lib.c +++ b/lustre/mdt/mdt_lib.c @@ -129,7 +129,8 @@ int mdt_handle_last_unlink(struct mdt_thread_info *info, struct mdt_object *mo, RETURN(0); } -static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr) +static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr, + struct md_attr *ma) { __u64 out; @@ -152,8 +153,25 @@ static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr) if (in & ATTR_FROM_OPEN) rr->rr_flags |= MRF_SETATTR_LOCKED; + if (in & ATTR_ATIME_SET) + ma->ma_attr_flags |= MD_ATIME_SET; + + if (in & ATTR_CTIME_SET) + ma->ma_attr_flags |= MD_CTIME_SET; + + if (in & ATTR_MTIME_SET) + ma->ma_attr_flags |= MD_MTIME_SET; + + if (in & ATTR_ATTR_FLAG) + ma->ma_attr_flags |= MD_ATTR_FLAG; + + if (in & ATTR_RAW) + ma->ma_attr_flags |= MD_ATTR_RAW; + in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE| - ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN); + ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN| + ATTR_ATIME_SET|ATTR_CTIME_SET|ATTR_MTIME_SET| + ATTR_ATTR_FLAG|ATTR_RAW); if (in != 0) CERROR("Unknown attr bits: %#llx\n", in); return out; @@ -174,7 +192,7 @@ static int mdt_setattr_unpack(struct mdt_thread_info *info) RETURN(-EFAULT); rr->rr_fid1 = &rec->sa_fid; - la->la_valid = mdt_attr_valid_xlate(rec->sa_valid, rr); + la->la_valid = mdt_attr_valid_xlate(rec->sa_valid, rr, ma); la->la_mode = rec->sa_mode; la->la_uid = rec->sa_uid; la->la_gid = rec->sa_gid; diff --git a/lustre/mdt/mdt_open.c b/lustre/mdt/mdt_open.c index 0fe38f1..86ab3a4 100644 --- a/lustre/mdt/mdt_open.c +++ b/lustre/mdt/mdt_open.c @@ -72,8 +72,8 @@ static void mdt_mfd_free(struct mdt_file_data *mfd) OBD_FREE_PTR(mfd); } -static int mdt_create_data_obj(struct mdt_thread_info *info, - struct mdt_object *p, struct mdt_object *o) +static int mdt_create_data(struct mdt_thread_info *info, + struct mdt_object *p, struct mdt_object *o) { struct md_attr *ma = &info->mti_attr; /* XXX: md_create_spec using should be made clear @@ -81,6 +81,7 @@ static int mdt_create_data_obj(struct mdt_thread_info *info, */ struct md_create_spec *spec = &info->mti_spec; + ma->ma_need = MA_INODE | MA_LOV; return mdo_create_data(info->mti_ctxt, mdt_object_child(p), mdt_object_child(o), spec, ma); } @@ -187,6 +188,7 @@ static int mdt_mfd_open(struct mdt_thread_info *info, if (!created) { /* we have to get attr & lov ea for this object*/ + ma->ma_need = MA_INODE | MA_LOV; rc = mo_attr_get(info->mti_ctxt, mdt_object_child(o), ma); if (rc) RETURN(rc); @@ -229,7 +231,7 @@ static int mdt_mfd_open(struct mdt_thread_info *info, &RMF_MDT_MD, RCL_SERVER); LASSERT(p != NULL); - rc = mdt_create_data_obj(info, p, o); + rc = mdt_create_data(info, p, o); if (rc) RETURN(rc); } @@ -327,6 +329,7 @@ int mdt_open_by_fid(struct mdt_thread_info* info, const struct lu_fid *fid, } else { rc = -ENOENT; if (flags & MDS_OPEN_CREAT) { + info->mti_attr.ma_need = MA_INODE | MA_LOV; rc = mo_object_create(info->mti_ctxt, mdt_object_child(o), &info->mti_spec, @@ -439,6 +442,7 @@ int mdt_reint_open(struct mdt_thread_info *info) if (result == -ENOENT) { /* not found and with MDS_OPEN_CREAT: let's create it */ + ma->ma_need = MA_INODE | MA_LOV; result = mdo_create(info->mti_ctxt, mdt_object_child(parent), rr->rr_name, @@ -458,6 +462,7 @@ int mdt_reint_open(struct mdt_thread_info *info) finish_open: if (result != 0 && created) { + ma->ma_need = 0; int rc2 = mdo_unlink(info->mti_ctxt, mdt_object_child(parent), mdt_object_child(child), rr->rr_name, &info->mti_attr); @@ -499,6 +504,14 @@ int mdt_close(struct mdt_thread_info *info) int rc; ENTRY; + req_capsule_set_size(&info->mti_pill, &RMF_MDT_MD, RCL_SERVER, + info->mti_mdt->mdt_max_mdsize); + req_capsule_set_size(&info->mti_pill, &RMF_LOGCOOKIES, RCL_SERVER, + info->mti_mdt->mdt_max_cookiesize); + rc = req_capsule_pack(&info->mti_pill); + if (rc) + RETURN(rc); + med = &mdt_info_req(info)->rq_export->exp_mdt_data; spin_lock(&med->med_open_lock); @@ -519,6 +532,13 @@ int mdt_close(struct mdt_thread_info *info) ma->ma_lmm_size = req_capsule_get_size(&info->mti_pill, &RMF_MDT_MD, RCL_SERVER); + + ma->ma_cookie = req_capsule_server_get(&info->mti_pill, + &RMF_LOGCOOKIES); + ma->ma_cookie_size = req_capsule_get_size(&info->mti_pill, + &RMF_LOGCOOKIES, + RCL_SERVER); + ma->ma_need = MA_INODE; o = mfd->mfd_object; mdt_mfd_close(info->mti_ctxt, info->mti_mdt, mfd, ma); rc = mdt_handle_last_unlink(info, o, ma); diff --git a/lustre/mdt/mdt_reint.c b/lustre/mdt/mdt_reint.c index 291b49c..5e7e485 100644 --- a/lustre/mdt/mdt_reint.c +++ b/lustre/mdt/mdt_reint.c @@ -63,6 +63,7 @@ static int mdt_md_create(struct mdt_thread_info *info) if (!IS_ERR(child)) { struct md_object *next = mdt_object_child(parent); + ma->ma_need = MA_INODE; rc = mdo_create(info->mti_ctxt, next, rr->rr_name, mdt_object_child(child), &info->mti_spec, /* rr->rr_tgt, NULL, 0, */ @@ -96,6 +97,7 @@ static int mdt_md_mkobj(struct mdt_thread_info *info) if (!IS_ERR(o)) { struct md_object *next = mdt_object_child(o); + ma->ma_need = MA_INODE | MA_LOV; rc = mo_object_create(info->mti_ctxt, next, &info->mti_spec, ma); if (rc == 0) { @@ -163,6 +165,7 @@ static int mdt_reint_setattr(struct mdt_thread_info *info) if (rc != 0) GOTO(out_unlock, rc); + info->mti_attr.ma_need = MA_INODE; rc = mo_attr_get(info->mti_ctxt, next, &info->mti_attr); if (rc != 0) GOTO(out_unlock, rc); @@ -290,11 +293,15 @@ static int mdt_reint_unlink(struct mdt_thread_info *info) if (!ma->ma_lmm || !ma->ma_cookie) GOTO(out_unlock_parent, rc = -EINVAL); + /*Now we can only make sure we need MA_INODE, in mdd layer, + *will check whether need MA_LOV and MA_COOKIE*/ + ma->ma_need = MA_INODE; rc = mdo_unlink(info->mti_ctxt, mdt_object_child(mp), mdt_object_child(mc), rr->rr_name, ma); if (rc) GOTO(out_unlock_child, rc); + rc = mdt_handle_last_unlink(info, mc, ma); GOTO(out_unlock_child, rc); @@ -537,11 +544,12 @@ static int mdt_reint_rename(struct mdt_thread_info *info) if (!ma->ma_lmm || !ma->ma_cookie) GOTO(out_unlock_new, rc = -EINVAL); + ma->ma_need = MA_INODE | MA_LOV | MA_COOKIE; rc = mdo_rename(info->mti_ctxt, mdt_object_child(msrcdir), mdt_object_child(mtgtdir), old_fid, rr->rr_name, mnew ? mdt_object_child(mnew): NULL, rr->rr_tgt, ma); - /*TODO: handle tgt object*/ + /*TODO: handle last link of tgt object*/ out_unlock_new: if (mnew) {