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);
OUT_PUNCH = 14,
OUT_READ = 15,
OUT_NOOP = 16,
+ OUT_XATTR_LIST = 17,
OUT_LAST
};
};
/**
+ * 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
.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,
(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",
} 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. */
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)
[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",
}
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)
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();
(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",