Whamcloud - gitweb
LU-9749 llite: Reduce overhead for ll_do_fast_read
[fs/lustre-release.git] / lustre / llite / rw.c
index 761dd04..e359b60 100644 (file)
  *
  * You should have received a copy of the GNU General Public License
  * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * GPL HEADER END
  */
@@ -27,7 +23,7 @@
  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, 2015, Intel Corporation.
+ * Copyright (c) 2011, 2016, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -120,8 +116,8 @@ void ll_ra_count_put(struct ll_sb_info *sbi, unsigned long len)
 
 static void ll_ra_stats_inc_sbi(struct ll_sb_info *sbi, enum ra_stat which)
 {
-        LASSERTF(which >= 0 && which < _NR_RA_STAT, "which: %u\n", which);
-        lprocfs_counter_incr(sbi->ll_ra_stats, which);
+       LASSERTF(which < _NR_RA_STAT, "which: %u\n", which);
+       lprocfs_counter_incr(sbi->ll_ra_stats, which);
 }
 
 void ll_ra_stats_inc(struct inode *inode, enum ra_stat which)
@@ -806,12 +802,19 @@ static void ras_update(struct ll_sb_info *sbi, struct inode *inode,
                if (ra_miss) {
                        if (index_in_stride_window(ras, index) &&
                            stride_io_mode(ras)) {
-                               /*If stride-RA hit cache miss, the stride dector
-                                *will not be reset to avoid the overhead of
-                                *redetecting read-ahead mode */
                                if (index != ras->ras_last_readpage + 1)
                                        ras->ras_consecutive_pages = 0;
                                ras_reset(inode, ras, index);
+
+                               /* If stride-RA hit cache miss, the stride
+                                * detector will not be reset to avoid the
+                                * overhead of redetecting read-ahead mode,
+                                * but on the condition that the stride window
+                                * is still intersect with normal sequential
+                                * read-ahead window. */
+                               if (ras->ras_window_start <
+                                   ras->ras_stride_offset)
+                                       ras_stride_reset(ras);
                                RAS_CDEBUG(ras);
                        } else {
                                /* Reset both stride window and normal RA
@@ -984,13 +987,11 @@ out:
 int ll_writepages(struct address_space *mapping, struct writeback_control *wbc)
 {
        struct inode *inode = mapping->host;
-       struct ll_sb_info *sbi = ll_i2sbi(inode);
        loff_t start;
        loff_t end;
        enum cl_fsync_mode mode;
        int range_whole = 0;
        int result;
-       int ignore_layout = 0;
        ENTRY;
 
        if (wbc->range_cyclic) {
@@ -1009,16 +1010,13 @@ int ll_writepages(struct address_space *mapping, struct writeback_control *wbc)
        if (wbc->sync_mode == WB_SYNC_ALL)
                mode = CL_FSYNC_LOCAL;
 
-       if (sbi->ll_umounting)
-               /* if the mountpoint is being umounted, all pages have to be
-                * evicted to avoid hitting LBUG when truncate_inode_pages()
-                * is called later on. */
-               ignore_layout = 1;
-
        if (ll_i2info(inode)->lli_clob == NULL)
                RETURN(0);
 
-       result = cl_sync_file_range(inode, start, end, mode, ignore_layout);
+       /* for directio, it would call writepages() to evict cached pages
+        * inside the IO context of write, which will cause deadlock at
+        * layout_conf since it waits for active IOs to complete. */
+       result = cl_sync_file_range(inode, start, end, mode, 1);
        if (result > 0) {
                wbc->nr_to_write -= result;
                result = 0;
@@ -1144,24 +1142,23 @@ int ll_readpage(struct file *file, struct page *vmpage)
        struct inode *inode = file_inode(file);
        struct cl_object *clob = ll_i2info(inode)->lli_clob;
        struct ll_cl_context *lcc;
-       const struct lu_env  *env;
-       struct cl_io   *io;
+       const struct lu_env  *env = NULL;
+       struct cl_io   *io = NULL;
        struct cl_page *page;
        int result;
        ENTRY;
 
        lcc = ll_cl_find(file);
-       if (lcc == NULL) {
-               unlock_page(vmpage);
-               RETURN(-EIO);
+       if (lcc != NULL) {
+               env = lcc->lcc_env;
+               io  = lcc->lcc_io;
        }
 
-       env = lcc->lcc_env;
-       io  = lcc->lcc_io;
        if (io == NULL) { /* fast read */
                struct inode *inode = file_inode(file);
                struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
                struct ll_readahead_state *ras = &fd->fd_ras;
+               struct lu_env  *local_env = NULL;
                struct vvp_page *vpg;
 
                result = -ENODATA;
@@ -1174,11 +1171,16 @@ int ll_readpage(struct file *file, struct page *vmpage)
                        RETURN(result);
                }
 
+               if (!env) {
+                       local_env = cl_env_percpu_get();
+                       env = local_env;
+               }
+
                vpg = cl2vvp_page(cl_object_page_slice(page->cp_obj, page));
                if (vpg->vpg_defer_uptodate) {
                        enum ras_update_flags flags = LL_RAS_HIT;
 
-                       if (lcc->lcc_type == LCC_MMAP)
+                       if (lcc && lcc->lcc_type == LCC_MMAP)
                                flags |= LL_RAS_MMAP;
 
                        /* For fast read, it updates read ahead state only
@@ -1201,8 +1203,14 @@ int ll_readpage(struct file *file, struct page *vmpage)
                        }
                }
 
-               unlock_page(vmpage);
+               /* release page refcount before unlocking the page to ensure
+                * the object won't be destroyed in the calling path of
+                * cl_page_put(). Please see comment in ll_releasepage(). */
                cl_page_put(env, page);
+               unlock_page(vmpage);
+               if (local_env)
+                       cl_env_percpu_put(local_env);
+
                RETURN(result);
        }