If bl_map begins *after* the first item in buffer_extents, we want to
skip only the first buffer extent before doing 'continue' to loop to the
next one.
This fixes a crash caused by underflow with a pattern like:
2012-11-20 13:54:30.347861
7f9404ed6700 10 striper add_partial_sparse_result(0x1efa088) 192 covering {12288=192} (offset 2906) to [0,5286,38054,4288]
2012-11-20 13:54:30.347863
7f9404ed6700 20 striper t 0~5286 bl has 192 off 2906
2012-11-20 13:54:30.347866
7f9404ed6700 20 striper s gap 9382, skipping
2012-11-20 13:54:30.347867
7f9404ed6700 20 striper s has 192, copying
2012-11-20 13:54:30.347872
7f9404ed6700 20 striper t 9574~
18446744073709547328 bl has 0 off 12480
2012-11-20 13:54:30.347874
7f9404ed6700 20 striper s at end
2012-11-20 13:54:30.347876
7f9404ed6700 20 striper t 38054~4288 bl has 0 off 12480
2012-11-20 13:54:30.347877
7f9404ed6700 20 striper s at end
Dan reproduced this with
./test_librbd_fsx -d -W -R -p 10 -t 1 -S 4 -N 300 rbd fsx
(although I was unable to do so).
Re-fixes #3428.
Reported-and-tested-by: Dan Mick <dan.mick@inktank.com>
Signed-off-by: Sage Weil <sage@inktank.com>
if (s->first > bl_off) {
// gap in sparse read result
pair<bufferlist, uint64_t>& r = partial[tofs];
- size_t gap = s->first - bl_off;
+ size_t gap = MIN(s->first - bl_off, tlen);
ldout(cct, 20) << " s gap " << gap << ", skipping" << dendl;
r.second = gap;
bl_off += gap;
tofs += gap;
tlen -= gap;
+ if (tlen == 0) {
+ continue;
+ }
}
assert(s->first <= bl_off);