struct lov_stripe_md *lsm = lio->lis_object->lo_lsm;
struct lov_io_sub *sub;
loff_t offset = -ENXIO;
+ __u64 hole_off = 0;
bool seek_hole = io->u.ci_lseek.ls_whence == SEEK_HOLE;
ENTRY;
int index = lov_comp_entry(sub->sub_subio_index);
int stripe = lov_comp_stripe(sub->sub_subio_index);
loff_t sub_off, lov_off;
+ __u64 comp_end = lsm->lsm_entries[index]->lsme_extent.e_end;
lov_io_end_wrapper(sub->sub_env, subio);
/* resulting offset can be out of component range if stripe
* object is full and its file size was returned as virtual
* hole start. Skip this result, the next component will give
- * us correct lseek result.
+ * us correct lseek result but keep possible hole offset in
+ * case there is no more components ahead
*/
- if (lov_off >= lsm->lsm_entries[index]->lsme_extent.e_end)
+ if (lov_off >= comp_end) {
+ /* must be SEEK_HOLE case */
+ if (likely(seek_hole)) {
+ /* save comp end as potential hole offset */
+ hole_off = max_t(__u64, comp_end, hole_off);
+ } else {
+ io->ci_result = -EINVAL;
+ CDEBUG(D_INFO,
+ "off %lld >= comp_end %llu: rc = %d\n",
+ lov_off, comp_end, io->ci_result);
+ }
continue;
+ }
CDEBUG(D_INFO, "SEEK_%s: %lld->%lld/%lld: rc = %d\n",
seek_hole ? "HOLE" : "DATA",
sub->sub_io.ci_result);
offset = min_t(__u64, offset, lov_off);
}
+ /* no result but some component returns hole as component end */
+ if (seek_hole && offset == -ENXIO && hole_off > 0)
+ offset = hole_off;
+
io->u.ci_lseek.ls_result = offset;
RETURN_EXIT;
}
[[ $offset == 1000000 ]] || error "offset $offset != 1000000"
printf "Seeking data from 1000000 ... "
lseek_test -d 1000000 $file && error "lseek should fail"
- # full first component, non-inited second one
+ rm $file
+
+ # full component followed by non-inited one
+ $LFS setstripe -E 1M -c2 -E eof $file
dd if=/dev/urandom of=$file bs=1M count=1
printf "Seeking hole from 1000000 ... "
offset=$(lseek_test -l 1000000 $file)
# init second component and truncate back
echo "123" >> $file
$TRUNCATE $file 1048576
- ls -lia $file
printf "Seeking hole from 1000000 ... "
offset=$(lseek_test -l 1000000 $file)
echo $offset