X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fptlrpc%2Fpack_generic.c;h=634f7d63d4a866459a873f670c7f1e4542bed709;hp=e733648205744a8f2b957ec400bd3845e75692f7;hb=2b905746ee3b5d9dbafcdb1af5930aea18120a7b;hpb=f843facff59226d3788d855d1d6948523ab8d944 diff --git a/lustre/ptlrpc/pack_generic.c b/lustre/ptlrpc/pack_generic.c index e733648..634f7d6 100644 --- a/lustre/ptlrpc/pack_generic.c +++ b/lustre/ptlrpc/pack_generic.c @@ -60,13 +60,15 @@ static inline __u32 lustre_msg_hdr_size_v2(__u32 count) __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, @@ -125,13 +127,14 @@ 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); @@ -177,20 +180,22 @@ __u32 lustre_packed_msg_size(struct lustre_msg *msg) 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++) { @@ -317,24 +322,25 @@ void lustre_put_emerg_rs(struct ptlrpc_reply_state *rs) } 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 */ @@ -346,16 +352,16 @@ int lustre_pack_reply_v2(struct ptlrpc_request *req, int count, 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); @@ -399,28 +405,29 @@ void *lustre_msg_buf_v2(struct lustre_msg_v2 *m, __u32 n, __u32 min_size) { __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) @@ -495,6 +502,57 @@ int lustre_shrink_msg(struct lustre_msg *msg, int segment, } 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); @@ -513,52 +571,60 @@ void lustre_free_reply_state(struct ptlrpc_reply_state *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) @@ -747,6 +813,11 @@ char *lustre_msg_string(struct lustre_msg *m, __u32 index, __u32 max_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) { @@ -2002,21 +2073,32 @@ static void lustre_swab_fiemap_extent(struct fiemap_extent *fm_extent) __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);