[snip]
Test case
A: touch file
dd if=file of=/dev/null bs=5M count=1 iflag=direct
B: [data(2M)|hole(2m)][data(2M)]
dd if=file of=/dev/null bs=8M count=1 iflag=direct
C: [data(4M)[hole(4M)][hole(4M)][data(2M)]
dd if=file of=/dev/null bs=16M count=1 iflag=direct
D: touch file;truncate -s 5M file
dd if=file of=/dev/null bs=8M count=1 iflag=direct
Those cases can work.
Now i make different processing for short-read between 'ret > 0' and "ret =0".
For the short-read which ret > 0, it don't do read-page rather than zero the
left area.
This means reduce one meaningless read operation.
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 2ddf061..f643ec8 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -350,13 +350,17 @@ more:
ret, hit_stripe ? " HITSTRIPE" : "", was_short ? " SHORT" : "");
if (ret > 0) {
- int didpages = (page_align + ret) >> PAGE_CACHE_SHIFT;
-
- if (read < pos - off) {
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 2ddf061..f643ec8 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -350,13 +350,17 @@ more:
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);
+ int didpages;
+
+ if (was_short && pos + ret < inode->i_size) {
+ u64 tmp = min(this_len - ret,
+ inode->i_size - pos - ret);
+ dout(" zero gap %llu to %llu\n", pos + ret, pos + ret
+ tmp);
+ ceph_zero_page_vector_range(page_align + read + ret,
+ tmp, pages);
+ ret += tmp;
}
+ didpages = (page_align + ret) >> PAGE_CACHE_SHIFT;
pos += ret;
read = pos - off;
left -= ret;
@@ -375,13 +379,25 @@ more:
/* zero trailing bytes (inside i_size) */
if (left > 0 && pos < inode->i_size) {
+ int didpages;
if (pos + left > inode->i_size)
left = inode->i_size - pos;
- dout("zero tail %d\n", left);
- ceph_zero_page_vector_range(page_align + read, left,
+ ret = min(left, this_len);
+ dout("zero tail %d\n", ret);
+ ceph_zero_page_vector_range(page_align + read, ret,
pages);
- read += left;
+ didpages = (page_align + ret) >> PAGE_CACHE_SHIFT;
+
+ pos += ret;
+ read = pos - off;
+ left -= ret;
+ page_pos += didpages;
+ pages_left -= didpages;
+
+ /* hit stripe? */
+ if (left && hit_stripe)
+ goto more;
}
}