__u32 lustre_msg_hdr_size(__u32 magic, __u32 count)
{
- switch (magic) {
- case LUSTRE_MSG_MAGIC_V2:
- return lustre_msg_hdr_size_v2(count);
- default:
- LASSERTF(0, "incorrect message magic: %08x\n", magic);
+ LASSERT(count > 0);
+
+ switch (magic) {
+ case LUSTRE_MSG_MAGIC_V2:
+ return lustre_msg_hdr_size_v2(count);
+ default:
+ LASSERTF(0, "incorrect message magic: %08x\n", magic);
return 0;
- }
+ }
}
void ptlrpc_buf_set_swabbed(struct ptlrpc_request *req, const int inout,
/* early reply size */
__u32 lustre_msg_early_size()
{
- static __u32 size;
- if (!size) {
- /* Always reply old ptlrpc_body_v2 to keep interoprability
- * with the old client (< 2.3) which doesn't have pb_jobid
- * in the ptlrpc_body.
- *
- * XXX Remove this whenever we dorp interoprability with such
- * client.
- */
- __u32 pblen = sizeof(struct ptlrpc_body_v2);
- size = lustre_msg_size(LUSTRE_MSG_MAGIC_V2, 1, &pblen);
- }
- return size;
+ __u32 pblen = sizeof(struct ptlrpc_body);
+
+ return lustre_msg_size(LUSTRE_MSG_MAGIC_V2, 1, &pblen);
}
EXPORT_SYMBOL(lustre_msg_early_size);
__u32 lustre_msg_size_v2(int count, __u32 *lengths)
{
__u32 size;
- int i;
+ int i;
- size = lustre_msg_hdr_size_v2(count);
- for (i = 0; i < count; i++)
- size += cfs_size_round(lengths[i]);
+ LASSERT(count > 0);
+ size = lustre_msg_hdr_size_v2(count);
+ for (i = 0; i < count; i++)
+ size += cfs_size_round(lengths[i]);
- return size;
+ return size;
}
EXPORT_SYMBOL(lustre_msg_size_v2);
EXPORT_SYMBOL(lustre_packed_msg_size);
void lustre_init_msg_v2(struct lustre_msg_v2 *msg, int count, __u32 *lens,
- char **bufs)
+ char **bufs)
{
- char *ptr;
- int i;
+ char *ptr;
+ int i;
- msg->lm_bufcount = count;
- /* XXX: lm_secflvr uninitialized here */
- msg->lm_magic = LUSTRE_MSG_MAGIC_V2;
+ LASSERT(count > 0);
- for (i = 0; i < count; i++)
- msg->lm_buflens[i] = lens[i];
+ msg->lm_bufcount = count;
+ /* XXX: lm_secflvr uninitialized here */
+ msg->lm_magic = LUSTRE_MSG_MAGIC_V2;
- if (bufs == NULL)
- return;
+ for (i = 0; i < count; i++)
+ msg->lm_buflens[i] = lens[i];
+
+ if (bufs == NULL)
+ return;
ptr = (char *)msg + lustre_msg_hdr_size_v2(count);
for (i = 0; i < count; i++) {
}
int lustre_pack_reply_v2(struct ptlrpc_request *req, int count,
- __u32 *lens, char **bufs, int flags)
+ __u32 *lens, char **bufs, int flags)
{
- struct ptlrpc_reply_state *rs;
- int msg_len, rc;
- ENTRY;
+ struct ptlrpc_reply_state *rs;
+ int msg_len, rc;
+ ENTRY;
- LASSERT(req->rq_reply_state == NULL);
+ LASSERT(req->rq_reply_state == NULL);
+ LASSERT(count > 0);
- if ((flags & LPRFL_EARLY_REPLY) == 0) {
+ if ((flags & LPRFL_EARLY_REPLY) == 0) {
spin_lock(&req->rq_lock);
req->rq_packed_final = 1;
spin_unlock(&req->rq_lock);
- }
+ }
- msg_len = lustre_msg_size_v2(count, lens);
- rc = sptlrpc_svc_alloc_rs(req, msg_len);
- if (rc)
- RETURN(rc);
+ msg_len = lustre_msg_size_v2(count, lens);
+ rc = sptlrpc_svc_alloc_rs(req, msg_len);
+ if (rc)
+ RETURN(rc);
rs = req->rq_reply_state;
atomic_set(&rs->rs_refcount, 1); /* 1 ref for rq_reply_state */
INIT_LIST_HEAD(&rs->rs_list);
spin_lock_init(&rs->rs_lock);
- req->rq_replen = msg_len;
- req->rq_reply_state = rs;
- req->rq_repmsg = rs->rs_msg;
+ req->rq_replen = msg_len;
+ req->rq_reply_state = rs;
+ req->rq_repmsg = rs->rs_msg;
- lustre_init_msg_v2(rs->rs_msg, count, lens, bufs);
- lustre_msg_add_version(rs->rs_msg, PTLRPC_MSG_VERSION);
+ lustre_init_msg_v2(rs->rs_msg, count, lens, bufs);
+ lustre_msg_add_version(rs->rs_msg, PTLRPC_MSG_VERSION);
- PTLRPC_RS_DEBUG_LRU_ADD(rs);
+ PTLRPC_RS_DEBUG_LRU_ADD(rs);
- RETURN(0);
+ RETURN(0);
}
EXPORT_SYMBOL(lustre_pack_reply_v2);
{
__u32 i, offset, buflen, bufcount;
- LASSERT(m != NULL);
+ LASSERT(m != NULL);
+ LASSERT(m->lm_bufcount > 0);
- bufcount = m->lm_bufcount;
- if (unlikely(n >= bufcount)) {
- CDEBUG(D_INFO, "msg %p buffer[%d] not present (count %d)\n",
- m, n, bufcount);
- return NULL;
- }
+ bufcount = m->lm_bufcount;
+ if (unlikely(n >= bufcount)) {
+ CDEBUG(D_INFO, "msg %p buffer[%d] not present (count %d)\n",
+ m, n, bufcount);
+ return NULL;
+ }
- buflen = m->lm_buflens[n];
- if (unlikely(buflen < min_size)) {
- CERROR("msg %p buffer[%d] size %d too small "
- "(required %d, opc=%d)\n", m, n, buflen, min_size,
- n == MSG_PTLRPC_BODY_OFF ? -1 : lustre_msg_get_opc(m));
- return NULL;
- }
+ buflen = m->lm_buflens[n];
+ if (unlikely(buflen < min_size)) {
+ CERROR("msg %p buffer[%d] size %d too small "
+ "(required %d, opc=%d)\n", m, n, buflen, min_size,
+ n == MSG_PTLRPC_BODY_OFF ? -1 : lustre_msg_get_opc(m));
+ return NULL;
+ }
- offset = lustre_msg_hdr_size_v2(bufcount);
- for (i = 0; i < n; i++)
- offset += cfs_size_round(m->lm_buflens[i]);
+ offset = lustre_msg_hdr_size_v2(bufcount);
+ for (i = 0; i < n; i++)
+ offset += cfs_size_round(m->lm_buflens[i]);
- return (char *)m + offset;
+ return (char *)m + offset;
}
void *lustre_msg_buf(struct lustre_msg *m, __u32 n, __u32 min_size)
}
EXPORT_SYMBOL(lustre_shrink_msg);
+static int lustre_grow_msg_v2(struct lustre_msg_v2 *msg, __u32 segment,
+ unsigned int newlen)
+{
+ char *tail = NULL, *newpos;
+ int tail_len = 0, n;
+
+ LASSERT(msg);
+ LASSERT(msg->lm_bufcount > segment);
+ LASSERT(msg->lm_buflens[segment] <= newlen);
+
+ if (msg->lm_buflens[segment] == newlen)
+ goto out;
+
+ if (msg->lm_bufcount > segment + 1) {
+ tail = lustre_msg_buf_v2(msg, segment + 1, 0);
+ for (n = segment + 1; n < msg->lm_bufcount; n++)
+ tail_len += cfs_size_round(msg->lm_buflens[n]);
+ }
+
+ msg->lm_buflens[segment] = newlen;
+
+ if (tail && tail_len) {
+ newpos = lustre_msg_buf_v2(msg, segment + 1, 0);
+ memmove(newpos, tail, tail_len);
+ }
+out:
+ return lustre_msg_size_v2(msg->lm_bufcount, msg->lm_buflens);
+}
+
+/*
+ * for @msg, grow @segment to size @newlen.
+ * Always move higher buffer forward.
+ *
+ * return new msg size after growing.
+ *
+ * CAUTION:
+ * - caller must make sure there is enough space in allocated message buffer
+ * - caller should NOT keep pointers to msg buffers which higher than @segment
+ * after call shrink.
+ */
+int lustre_grow_msg(struct lustre_msg *msg, int segment, unsigned int newlen)
+{
+ switch (msg->lm_magic) {
+ case LUSTRE_MSG_MAGIC_V2:
+ return lustre_grow_msg_v2(msg, segment, newlen);
+ default:
+ LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+ }
+}
+EXPORT_SYMBOL(lustre_grow_msg);
+
void lustre_free_reply_state(struct ptlrpc_reply_state *rs)
{
PTLRPC_RS_DEBUG_LRU_DEL(rs);
static int lustre_unpack_msg_v2(struct lustre_msg_v2 *m, int len)
{
- int swabbed, required_len, i;
+ int swabbed, required_len, i, buflen;
- /* Now we know the sender speaks my language. */
- required_len = lustre_msg_hdr_size_v2(0);
- if (len < required_len) {
- /* can't even look inside the message */
- CERROR("message length %d too small for lustre_msg\n", len);
- return -EINVAL;
- }
+ /* Now we know the sender speaks my language. */
+ required_len = lustre_msg_hdr_size_v2(0);
+ if (len < required_len) {
+ /* can't even look inside the message */
+ CERROR("message length %d too small for lustre_msg\n", len);
+ return -EINVAL;
+ }
- swabbed = (m->lm_magic == LUSTRE_MSG_MAGIC_V2_SWABBED);
-
- if (swabbed) {
- __swab32s(&m->lm_magic);
- __swab32s(&m->lm_bufcount);
- __swab32s(&m->lm_secflvr);
- __swab32s(&m->lm_repsize);
- __swab32s(&m->lm_cksum);
- __swab32s(&m->lm_flags);
- CLASSERT(offsetof(typeof(*m), lm_padding_2) != 0);
- CLASSERT(offsetof(typeof(*m), lm_padding_3) != 0);
- }
+ swabbed = (m->lm_magic == LUSTRE_MSG_MAGIC_V2_SWABBED);
- required_len = lustre_msg_hdr_size_v2(m->lm_bufcount);
- if (len < required_len) {
- /* didn't receive all the buffer lengths */
- CERROR ("message length %d too small for %d buflens\n",
- len, m->lm_bufcount);
- return -EINVAL;
- }
+ if (swabbed) {
+ __swab32s(&m->lm_magic);
+ __swab32s(&m->lm_bufcount);
+ __swab32s(&m->lm_secflvr);
+ __swab32s(&m->lm_repsize);
+ __swab32s(&m->lm_cksum);
+ __swab32s(&m->lm_flags);
+ CLASSERT(offsetof(typeof(*m), lm_padding_2) != 0);
+ CLASSERT(offsetof(typeof(*m), lm_padding_3) != 0);
+ }
- for (i = 0; i < m->lm_bufcount; i++) {
- if (swabbed)
- __swab32s(&m->lm_buflens[i]);
- required_len += cfs_size_round(m->lm_buflens[i]);
- }
+ if (m->lm_bufcount == 0 || m->lm_bufcount > PTLRPC_MAX_BUFCOUNT) {
+ CERROR("message bufcount %d is not valid\n", m->lm_bufcount);
+ return -EINVAL;
+ }
+ required_len = lustre_msg_hdr_size_v2(m->lm_bufcount);
+ if (len < required_len) {
+ /* didn't receive all the buffer lengths */
+ CERROR("message length %d too small for %d buflens\n",
+ len, m->lm_bufcount);
+ return -EINVAL;
+ }
- if (len < required_len) {
- CERROR("len: %d, required_len %d\n", len, required_len);
- CERROR("bufcount: %d\n", m->lm_bufcount);
- for (i = 0; i < m->lm_bufcount; i++)
- CERROR("buffer %d length %d\n", i, m->lm_buflens[i]);
- return -EINVAL;
- }
+ for (i = 0; i < m->lm_bufcount; i++) {
+ if (swabbed)
+ __swab32s(&m->lm_buflens[i]);
+ buflen = cfs_size_round(m->lm_buflens[i]);
+ if (buflen < 0 || buflen > PTLRPC_MAX_BUFLEN) {
+ CERROR("buffer %d length %d is not valid\n", i, buflen);
+ return -EINVAL;
+ }
+ required_len += buflen;
+ }
+ if (len < required_len || required_len > PTLRPC_MAX_BUFLEN) {
+ CERROR("len: %d, required_len %d, bufcount: %d\n",
+ len, required_len, m->lm_bufcount);
+ for (i = 0; i < m->lm_bufcount; i++)
+ CERROR("buffer %d length %d\n", i, m->lm_buflens[i]);
+ return -EINVAL;
+ }
- return swabbed;
+ return swabbed;
}
int __lustre_unpack_msg(struct lustre_msg *m, int len)
"msg %p buffer[%d] len %d\n", m, index, blen);
return NULL;
}
+ if (blen > PTLRPC_MAX_BUFLEN) {
+ CERROR("buffer length of msg %p buffer[%d] is invalid(%d)\n",
+ m, index, blen);
+ return NULL;
+ }
if (max_len == 0) {
if (slen != blen - 1) {
CERROR("invalid msg %p: no ptlrpc body!\n", msg);
}
- /* no break */
+ /* fallthrough */
default:
/* flags might be printed in debug code while message
* uninitialized */
CERROR("invalid msg %p: no ptlrpc body!\n", msg);
}
- /* no break */
+ /* fallthrough */
default:
return 0;
}
return pb->pb_status;
CERROR("invalid msg %p: no ptlrpc body!\n", msg);
}
- /* no break */
+ /* fallthrough */
default:
/* status might be printed in debug code while message
* uninitialized */
{
switch (msg->lm_magic) {
case LUSTRE_MSG_MAGIC_V2: {
- struct ptlrpc_body *pb =
- lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF,
+ struct ptlrpc_body *pb;
+
+ /* the old pltrpc_body_v2 is smaller; doesn't include jobid */
+ if (msg->lm_buflens[MSG_PTLRPC_BODY_OFF] <
+ sizeof(struct ptlrpc_body))
+ return NULL;
+
+ pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF,
sizeof(struct ptlrpc_body));
if (!pb)
return NULL;
__swab32s(&fm_extent->fe_device);
}
+static void lustre_swab_fiemap_hdr(struct fiemap *fiemap)
+{
+ __swab64s(&fiemap->fm_start);
+ __swab64s(&fiemap->fm_length);
+ __swab32s(&fiemap->fm_flags);
+ __swab32s(&fiemap->fm_mapped_extents);
+ __swab32s(&fiemap->fm_extent_count);
+ __swab32s(&fiemap->fm_reserved);
+}
+
void lustre_swab_fiemap(struct fiemap *fiemap)
{
__u32 i;
- __swab64s(&fiemap->fm_start);
- __swab64s(&fiemap->fm_length);
- __swab32s(&fiemap->fm_flags);
- __swab32s(&fiemap->fm_mapped_extents);
- __swab32s(&fiemap->fm_extent_count);
- __swab32s(&fiemap->fm_reserved);
+ lustre_swab_fiemap_hdr(fiemap);
for (i = 0; i < fiemap->fm_mapped_extents; i++)
lustre_swab_fiemap_extent(&fiemap->fm_extents[i]);
}
+void lustre_swab_fiemap_info_key(struct ll_fiemap_info_key *fiemap_info)
+{
+ lustre_swab_obdo(&fiemap_info->lfik_oa);
+ lustre_swab_fiemap_hdr(&fiemap_info->lfik_fiemap);
+}
+
void lustre_swab_idx_info(struct idx_info *ii)
{
__swab32s(&ii->ii_magic);
switch (lum->lum_magic) {
case LMV_USER_MAGIC_SPECIFIC:
count = lum->lum_stripe_count;
+ /* fallthrough */
case __swab32(LMV_USER_MAGIC_SPECIFIC):
lustre_swab_lmv_user_md_objects(lum->lum_objects, count);
break;
}
EXPORT_SYMBOL(lustre_swab_lov_user_md_objects);
-void lustre_swab_lov_user_md(struct lov_user_md *lum)
+void lustre_swab_lov_user_md(struct lov_user_md *lum, size_t size)
{
+ struct lov_user_md_v1 *v1;
+ struct lov_user_md_v3 *v3;
+ struct lov_foreign_md *lfm;
+ __u16 stripe_count;
ENTRY;
CDEBUG(D_IOCTL, "swabbing lov_user_md\n");
switch (lum->lmm_magic) {
case __swab32(LOV_MAGIC_V1):
case LOV_USER_MAGIC_V1:
- lustre_swab_lov_user_md_v1((struct lov_user_md_v1 *)lum);
+ {
+ v1 = (struct lov_user_md_v1 *)lum;
+ stripe_count = v1->lmm_stripe_count;
+
+ if (lum->lmm_magic != LOV_USER_MAGIC_V1)
+ __swab16s(&stripe_count);
+
+ lustre_swab_lov_user_md_v1(v1);
+ if (size > sizeof(*v1))
+ lustre_swab_lov_user_md_objects(v1->lmm_objects,
+ stripe_count);
+
break;
+ }
case __swab32(LOV_MAGIC_V3):
case LOV_USER_MAGIC_V3:
- lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lum);
+ {
+ v3 = (struct lov_user_md_v3 *)lum;
+ stripe_count = v3->lmm_stripe_count;
+
+ if (lum->lmm_magic != LOV_USER_MAGIC_V3)
+ __swab16s(&stripe_count);
+
+ lustre_swab_lov_user_md_v3(v3);
+ if (size > sizeof(*v3))
+ lustre_swab_lov_user_md_objects(v3->lmm_objects,
+ stripe_count);
break;
+ }
case __swab32(LOV_USER_MAGIC_SPECIFIC):
case LOV_USER_MAGIC_SPECIFIC:
{
- struct lov_user_md_v3 *v3 = (struct lov_user_md_v3 *)lum;
- __u16 stripe_count = v3->lmm_stripe_count;
+ v3 = (struct lov_user_md_v3 *)lum;
+ stripe_count = v3->lmm_stripe_count;
if (lum->lmm_magic != LOV_USER_MAGIC_SPECIFIC)
__swab16s(&stripe_count);
case __swab32(LOV_MAGIC_FOREIGN):
case LOV_USER_MAGIC_FOREIGN:
{
- struct lov_foreign_md *lfm = (struct lov_foreign_md *)lum;
+ lfm = (struct lov_foreign_md *)lum;
__swab32s(&lfm->lfm_magic);
__swab32s(&lfm->lfm_length);
__swab32s(&lfm->lfm_type);
DEBUG_REQ_FLAGS(req),
req_ok ? lustre_msg_get_flags(req->rq_reqmsg) : -1,
rep_flags, req->rq_status, rep_status,
- req_ok ? lustre_msg_get_jobid(req->rq_reqmsg) : "");
+ req_ok ? lustre_msg_get_jobid(req->rq_reqmsg) ?: ""
+ : "");
va_end(args);
}
EXPORT_SYMBOL(_debug_req);