ceph: fix blindly expanding the readahead windows
[platform/kernel/linux-rpi.git] / fs / ceph / addr.c
index 19c4f08..59cbfb8 100644 (file)
@@ -187,16 +187,42 @@ static void ceph_netfs_expand_readahead(struct netfs_io_request *rreq)
        struct inode *inode = rreq->inode;
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct ceph_file_layout *lo = &ci->i_layout;
+       unsigned long max_pages = inode->i_sb->s_bdi->ra_pages;
+       loff_t end = rreq->start + rreq->len, new_end;
+       struct ceph_netfs_request_data *priv = rreq->netfs_priv;
+       unsigned long max_len;
        u32 blockoff;
-       u64 blockno;
 
-       /* Expand the start downward */
-       blockno = div_u64_rem(rreq->start, lo->stripe_unit, &blockoff);
-       rreq->start = blockno * lo->stripe_unit;
-       rreq->len += blockoff;
+       if (priv) {
+               /* Readahead is disabled by posix_fadvise POSIX_FADV_RANDOM */
+               if (priv->file_ra_disabled)
+                       max_pages = 0;
+               else
+                       max_pages = priv->file_ra_pages;
+
+       }
+
+       /* Readahead is disabled */
+       if (!max_pages)
+               return;
+
+       max_len = max_pages << PAGE_SHIFT;
 
-       /* Now, round up the length to the next block */
-       rreq->len = roundup(rreq->len, lo->stripe_unit);
+       /*
+        * Try to expand the length forward by rounding up it to the next
+        * block, but do not exceed the file size, unless the original
+        * request already exceeds it.
+        */
+       new_end = min(round_up(end, lo->stripe_unit), rreq->i_size);
+       if (new_end > end && new_end <= rreq->start + max_len)
+               rreq->len = new_end - rreq->start;
+
+       /* Try to expand the start downward */
+       div_u64_rem(rreq->start, lo->stripe_unit, &blockoff);
+       if (rreq->len + blockoff <= max_len) {
+               rreq->start -= blockoff;
+               rreq->len += blockoff;
+       }
 }
 
 static bool ceph_netfs_clamp_length(struct netfs_io_subrequest *subreq)