@@ -319,7 +319,7 @@ static int striped_read(struct inode *inode,
int read;
struct page **page_pos;
int ret;
- bool hit_stripe, was_short;
+ bool hit_stripe, was_short, hit_hole = false;
/*
* we may need to do multiple reads. not atomic, unfortunately.
@@ -342,21 +342,30 @@ more:
ci->i_truncate_seq,
ci->i_truncate_size,
page_pos, pages_left, page_align);
- if (ret == -ENOENT)
+
+ if ((ret == 0 || ret == -ENOENT) && pos < inode->i_size)
+ hit_hole = true;
+ else if (ret == -ENOENT)
ret = 0;
+
hit_stripe = this_len < left;
- was_short = ret >= 0 && ret < this_len;
- dout("striped_read %llu~%u (read %u) got %d%s%s\n", pos, left, read,
- ret, hit_stripe ? " HITSTRIPE" : "", was_short ? " SHORT" : "");
-
- if (ret > 0) {
- int didpages = (page_align + ret) >> PAGE_CACHE_SHIFT;
-
- if (read < pos - off) {
- dout(" zero gap %llu to %llu\n", off + read, pos);
- ceph_zero_page_vector_range(page_align + read,
- pos - off - read, pages);
+ was_short = ret > 0 && ret < this_len;
+ dout("striped_read %llu~%u (read %u) got %d%s%s%s\n", pos, left, read,
+ ret, hit_stripe ? " HITSTRIPE" : "", was_short ? " SHORT" : "",
+ hit_hole ? " HITHOLE" : "");
+
+ if (ret > 0 || hit_hole) {
+ int didpages;
+
+ if (hit_hole) {
+ ret = this_len;
+ dout(" zero hole %llu to %llu\n", pos , pos + ret);
+ ceph_zero_page_vector_range(page_align + read,
+ ret, pages);
+ hit_hole = false;
}
+ didpages = (page_align + ret) >> PAGE_CACHE_SHIFT;
+
pos += ret;
read = pos - off;
left -= ret;