@@ -5857,8 +5857,8 @@ static int osd_sparse_read(struct ceph_connection *con,
struct ceph_osd *o = con->private;
struct ceph_sparse_read *sr = &o->o_sparse_read;
u32 count = sr->sr_count;
- u64 eoff, elen;
- int ret;
+ u64 eoff, elen, len = 0;
+ int i, ret;
switch (sr->sr_state) {
case CEPH_SPARSE_READ_HDR:
@@ -5909,6 +5909,13 @@ static int osd_sparse_read(struct ceph_connection *con,
/* Convert sr_datalen to host-endian */
sr->sr_datalen = le32_to_cpu((__force __le32)sr->sr_datalen);
sr->sr_state = CEPH_SPARSE_READ_DATA;
+ for (i = 0; i < count; i++)
+ len += sr->sr_extent[i].len;
+ if (sr->sr_datalen != len) {
+ pr_warn_ratelimited("data len %u != extent len %llu\n",
+ sr->sr_datalen, len);
+ return -EREMOTEIO;
+ }
fallthrough;
case CEPH_SPARSE_READ_DATA:
if (sr->sr_index >= count) {
@@ -5919,6 +5926,8 @@ static int osd_sparse_read(struct ceph_connection *con,
eoff = sr->sr_extent[sr->sr_index].off;
elen = sr->sr_extent[sr->sr_index].len;
+ sr->sr_datalen -= elen;
+
dout("[%d] ext %d off 0x%llx len 0x%llx\n",
o->o_osd, sr->sr_index, eoff, elen);