From 4325b1e456647f519a0eca32204554e0c358646f Mon Sep 17 00:00:00 2001 From: Lai Siyao Date: Sun, 21 Jan 2018 15:57:22 +0800 Subject: [PATCH] LU-4684 xattr: add list support for remote object XATTR_LIST may be issued to a remote object in directory migration, add this support for OSP and OUT. Signed-off-by: Lai Siyao Change-Id: I9681e149703de2837a04dc1448d1bd583659205d Reviewed-on: https://review.whamcloud.com/31426 Reviewed-by: Andreas Dilger Reviewed-by: Fan Yong Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/include/lustre_update.h | 3 + lustre/include/uapi/linux/lustre/lustre_idl.h | 1 + lustre/osp/osp_md_object.c | 90 +++++++++++++++++++++++++++ lustre/ptlrpc/wiretest.c | 4 ++ lustre/target/out_handler.c | 60 +++++++++++++++++- lustre/target/out_lib.c | 10 +++ lustre/utils/wirecheck.c | 2 + lustre/utils/wiretest.c | 4 ++ 8 files changed, 171 insertions(+), 3 deletions(-) diff --git a/lustre/include/lustre_update.h b/lustre/include/lustre_update.h index f8766f6..78cd3d4 100644 --- a/lustre/include/lustre_update.h +++ b/lustre/include/lustre_update.h @@ -454,6 +454,9 @@ int out_xattr_get_pack(const struct lu_env *env, struct object_update *update, size_t *max_update_size, const struct lu_fid *fid, const char *name, const int bufsize); +int out_xattr_list_pack(const struct lu_env *env, struct object_update *update, + size_t *max_update_size, const struct lu_fid *fid, + const int bufsize); int out_read_pack(const struct lu_env *env, struct object_update *update, size_t *max_update_length, const struct lu_fid *fid, size_t size, loff_t pos); diff --git a/lustre/include/uapi/linux/lustre/lustre_idl.h b/lustre/include/uapi/linux/lustre/lustre_idl.h index 8ddc060..b2423fc 100644 --- a/lustre/include/uapi/linux/lustre/lustre_idl.h +++ b/lustre/include/uapi/linux/lustre/lustre_idl.h @@ -3305,6 +3305,7 @@ enum update_type { OUT_PUNCH = 14, OUT_READ = 15, OUT_NOOP = 16, + OUT_XATTR_LIST = 17, OUT_LAST }; diff --git a/lustre/osp/osp_md_object.c b/lustre/osp/osp_md_object.c index eabec88..7acbc51 100644 --- a/lustre/osp/osp_md_object.c +++ b/lustre/osp/osp_md_object.c @@ -818,6 +818,95 @@ const struct dt_index_operations osp_md_index_ops = { }; /** + * Implement OSP layer dt_object_operations::do_xattr_list() interface. + * + * List extended attribute from the specified MDT/OST object, result is not + * cached because this is called by directory migration only. + * + * \param[in] env pointer to the thread context + * \param[in] dt pointer to the OSP layer dt_object + * \param[out] buf pointer to the lu_buf to hold the extended attribute + * + * \retval positive bytes used/required in the buffer + * \retval negative error number on failure + */ +static int osp_md_xattr_list(const struct lu_env *env, struct dt_object *dt, + const struct lu_buf *buf) +{ + struct osp_device *osp = lu2osp_dev(dt->do_lu.lo_dev); + struct osp_object *obj = dt2osp_obj(dt); + struct dt_device *dev = &osp->opd_dt_dev; + struct lu_buf *rbuf = &osp_env_info(env)->osi_lb2; + struct osp_update_request *update = NULL; + struct ptlrpc_request *req = NULL; + struct object_update_reply *reply; + const char *dname = dt->do_lu.lo_dev->ld_obd->obd_name; + int rc = 0; + + ENTRY; + + LASSERT(buf); + + if (unlikely(obj->opo_non_exist)) + RETURN(-ENOENT); + + update = osp_update_request_create(dev); + if (IS_ERR(update)) + RETURN(PTR_ERR(update)); + + rc = osp_update_rpc_pack(env, xattr_list, update, OUT_XATTR_LIST, + lu_object_fid(&dt->do_lu), buf->lb_len); + if (rc) { + CERROR("%s: Insert update error "DFID": rc = %d\n", + dname, PFID(lu_object_fid(&dt->do_lu)), rc); + GOTO(out, rc); + } + + rc = osp_remote_sync(env, osp, update, &req); + if (rc < 0) { + if (rc == -ENOENT) { + dt->do_lu.lo_header->loh_attr &= ~LOHA_EXISTS; + obj->opo_non_exist = 1; + } + GOTO(out, rc); + } + + reply = req_capsule_server_sized_get(&req->rq_pill, + &RMF_OUT_UPDATE_REPLY, + OUT_UPDATE_REPLY_SIZE); + if (reply->ourp_magic != UPDATE_REPLY_MAGIC) { + DEBUG_REQ(D_ERROR, req, + "%s: Wrong version %x expected %x "DFID": rc = %d\n", + dname, reply->ourp_magic, UPDATE_REPLY_MAGIC, + PFID(lu_object_fid(&dt->do_lu)), -EPROTO); + + GOTO(out, rc = -EPROTO); + } + + rc = object_update_result_data_get(reply, rbuf, 0); + if (rc < 0) + GOTO(out, rc); + + if (!buf->lb_buf) + GOTO(out, rc); + + if (unlikely(buf->lb_len < rbuf->lb_len)) + GOTO(out, rc = -ERANGE); + + memcpy(buf->lb_buf, rbuf->lb_buf, rbuf->lb_len); + EXIT; + +out: + if (req) + ptlrpc_req_finished(req); + + if (update && !IS_ERR(update)) + osp_update_request_destroy(env, update); + + return rc; +} + +/** * Implementation of dt_object_operations::do_index_try * * Try to initialize the index API pointer for the given object. This @@ -994,6 +1083,7 @@ struct dt_object_operations osp_md_obj_ops = { .do_declare_attr_set = osp_md_declare_attr_set, .do_attr_set = osp_md_attr_set, .do_xattr_get = osp_xattr_get, + .do_xattr_list = osp_md_xattr_list, .do_declare_xattr_set = osp_declare_xattr_set, .do_xattr_set = osp_xattr_set, .do_declare_xattr_del = osp_declare_xattr_del, diff --git a/lustre/ptlrpc/wiretest.c b/lustre/ptlrpc/wiretest.c index fed37ca..0e4321a 100644 --- a/lustre/ptlrpc/wiretest.c +++ b/lustre/ptlrpc/wiretest.c @@ -499,6 +499,10 @@ void lustre_assert_wire_constants(void) (long long)OUT_PUNCH); LASSERTF(OUT_READ == 15, "found %lld\n", (long long)OUT_READ); + LASSERTF(OUT_NOOP == 16, "found %lld\n", + (long long)OUT_NOOP); + LASSERTF(OUT_XATTR_LIST == 17, "found %lld\n", + (long long)OUT_XATTR_LIST); /* Checks for struct hsm_attrs */ LASSERTF((int)sizeof(struct hsm_attrs) == 24, "found %lld\n", diff --git a/lustre/target/out_handler.c b/lustre/target/out_handler.c index 91f0012..7dc9d42 100644 --- a/lustre/target/out_handler.c +++ b/lustre/target/out_handler.c @@ -289,10 +289,62 @@ static int out_xattr_get(struct tgt_session_info *tsi) } else if (lbuf->lb_buf) { lbuf->lb_len = rc; } - - CDEBUG(D_INFO, "%s: "DFID" get xattr %s len %d: rc = %d\n", + CDEBUG(D_INFO, "%s: "DFID" get xattr %s len %d\n", tgt_name(tsi->tsi_tgt), PFID(lu_object_fid(&obj->do_lu)), - name, (int)lbuf->lb_len, rc); + name, rc); + + GOTO(out, rc); + +out: + object_update_result_insert(reply, lbuf->lb_buf, lbuf->lb_len, idx, rc); + RETURN(0); +} + +static int out_xattr_list(struct tgt_session_info *tsi) +{ + const struct lu_env *env = tsi->tsi_env; + struct tgt_thread_info *tti = tgt_th_info(env); + struct lu_buf *lbuf = &tti->tti_buf; + struct object_update_reply *reply = tti->tti_u.update.tti_update_reply; + struct dt_object *obj = tti->tti_u.update.tti_dt_object; + struct object_update_result *update_result; + int idx = tti->tti_u.update.tti_update_reply_index; + int rc; + + ENTRY; + + if (!lu_object_exists(&obj->do_lu)) { + set_bit(LU_OBJECT_HEARD_BANSHEE, + &obj->do_lu.lo_header->loh_flags); + RETURN(-ENOENT); + } + + update_result = object_update_result_get(reply, 0, NULL); + if (!update_result) { + rc = -EPROTO; + CERROR("%s: empty buf for xattr list: rc = %d\n", + tgt_name(tsi->tsi_tgt), rc); + RETURN(rc); + } + + lbuf->lb_len = (int)tti->tti_u.update.tti_update->ou_result_size; + lbuf->lb_buf = update_result->our_data; + if (lbuf->lb_len == 0) + lbuf->lb_buf = 0; + + dt_read_lock(env, obj, MOR_TGT_CHILD); + rc = dt_xattr_list(env, obj, lbuf); + dt_read_unlock(env, obj); + if (rc <= 0) { + lbuf->lb_len = 0; + if (unlikely(!rc)) + rc = -ENODATA; + } else if (lbuf->lb_buf) { + lbuf->lb_len = rc; + } + + CDEBUG(D_INFO, "%s: "DFID" list xattr len %d\n", + tgt_name(tsi->tsi_tgt), PFID(lu_object_fid(&obj->do_lu)), rc); /* Since we directly use update_result->our_data as the lbuf->lb_buf, * then use NULL for result_insert to avoid unnecessary memory copy. */ @@ -759,6 +811,8 @@ static struct tgt_handler out_update_ops[] = { DEF_OUT_HNDL(OUT_WRITE, "out_write", MUTABOR | HABEO_REFERO, out_write), DEF_OUT_HNDL(OUT_READ, "out_read", HABEO_REFERO, out_read), DEF_OUT_HNDL(OUT_NOOP, "out_noop", HABEO_REFERO, out_noop), + DEF_OUT_HNDL(OUT_XATTR_LIST, "out_xattr_list", HABEO_REFERO, + out_xattr_list), }; static struct tgt_handler *out_handler_find(__u32 opc) diff --git a/lustre/target/out_lib.c b/lustre/target/out_lib.c index d1fcffd..57987e1 100644 --- a/lustre/target/out_lib.c +++ b/lustre/target/out_lib.c @@ -53,6 +53,7 @@ const char *update_op_str(__u16 opc) [OUT_ATTR_GET] = "attr_get", [OUT_XATTR_SET] = "xattr_set", [OUT_XATTR_GET] = "xattr_get", + [OUT_XATTR_LIST] = "xattr_list", [OUT_INDEX_LOOKUP] = "lookup", [OUT_INDEX_INSERT] = "insert", [OUT_INDEX_DELETE] = "delete", @@ -404,6 +405,15 @@ int out_xattr_get_pack(const struct lu_env *env, struct object_update *update, } EXPORT_SYMBOL(out_xattr_get_pack); +int out_xattr_list_pack(const struct lu_env *env, struct object_update *update, + size_t *max_update_size, const struct lu_fid *fid, + const int bufsize) +{ + return out_update_pack(env, update, max_update_size, OUT_XATTR_LIST, + fid, 0, NULL, NULL, bufsize); +} +EXPORT_SYMBOL(out_xattr_list_pack); + int out_read_pack(const struct lu_env *env, struct object_update *update, size_t *max_update_size, const struct lu_fid *fid, size_t size, loff_t pos) diff --git a/lustre/utils/wirecheck.c b/lustre/utils/wirecheck.c index bcb6e55..d43eea0 100644 --- a/lustre/utils/wirecheck.c +++ b/lustre/utils/wirecheck.c @@ -2737,6 +2737,8 @@ main(int argc, char **argv) CHECK_VALUE(OUT_XATTR_DEL); CHECK_VALUE(OUT_PUNCH); CHECK_VALUE(OUT_READ); + CHECK_VALUE(OUT_NOOP); + CHECK_VALUE(OUT_XATTR_LIST); check_hsm_attrs(); check_ost_id(); diff --git a/lustre/utils/wiretest.c b/lustre/utils/wiretest.c index b66a928..6e5193e 100644 --- a/lustre/utils/wiretest.c +++ b/lustre/utils/wiretest.c @@ -520,6 +520,10 @@ void lustre_assert_wire_constants(void) (long long)OUT_PUNCH); LASSERTF(OUT_READ == 15, "found %lld\n", (long long)OUT_READ); + LASSERTF(OUT_NOOP == 16, "found %lld\n", + (long long)OUT_NOOP); + LASSERTF(OUT_XATTR_LIST == 17, "found %lld\n", + (long long)OUT_XATTR_LIST); /* Checks for struct hsm_attrs */ LASSERTF((int)sizeof(struct hsm_attrs) == 24, "found %lld\n", -- 1.8.3.1