Whamcloud - gitweb
- use truncate instead of invalidate to drop pages from cache if ROC is disabled
authortappro <tappro>
Thu, 5 Mar 2009 12:36:43 +0000 (12:36 +0000)
committertappro <tappro>
Thu, 5 Mar 2009 12:36:43 +0000 (12:36 +0000)
b:18520
i:adilger, green

lustre/autoconf/lustre-core.m4
lustre/obdfilter/filter_io.c

index 19051bc..2088f90 100644 (file)
@@ -1170,6 +1170,15 @@ AC_DEFINE(HAVE_TRUNCATE_COMPLETE_PAGE, 1,
 ])
 ])
 
+AC_DEFUN([LC_EXPORT_TRUNCATE_RANGE],
+[LB_CHECK_SYMBOL_EXPORT([truncate_inode_pages_range],
+[mm/truncate.c],[
+AC_DEFINE(HAVE_TRUNCATE_RANGE, 1,
+            [kernel export truncate_inode_pages_range])
+],[
+])
+])
+
 AC_DEFUN([LC_EXPORT_D_REHASH_COND],
 [LB_CHECK_SYMBOL_EXPORT([d_rehash_cond],
 [fs/dcache.c],[
@@ -1495,6 +1504,7 @@ AC_DEFUN([LC_PROG_LINUX],
          LC_TASK_PPTR
          # RHEL4 patches
          LC_EXPORT_TRUNCATE_COMPLETE
+         LC_EXPORT_TRUNCATE_RANGE
          LC_EXPORT_D_REHASH_COND
          LC_EXPORT___D_REHASH
          LC_EXPORT_D_MOVE_LOCKED
index 7e75c80..bfd7092 100644 (file)
@@ -359,6 +359,34 @@ void filter_invalidate_cache(struct obd_device *obd, struct obd_ioobj *obj,
         }
 }
 
+/*
+ * the invalidate above doesn't work during read because lnet pins pages.
+ * The truncate is used here instead to drop pages from cache
+ */
+void filter_truncate_cache(struct obd_device *obd, struct obd_ioobj *obj,
+                           struct niobuf_remote *nb, int pages,
+                           struct niobuf_local *res, struct inode *inode)
+{
+        struct niobuf_remote *rnb;
+        int i;
+
+        LASSERT(inode != NULL);
+#ifdef HAVE_TRUNCATE_RANGE
+        for (i = 0, rnb = nb; i < obj->ioo_bufcnt; i++, rnb++) {
+                /* remove pages in which range is fit */
+                truncate_inode_pages_range(inode->i_mapping,
+                                           rnb->offset & CFS_PAGE_MASK,
+                                           (rnb->offset + rnb->len - 1) |
+                                           ~CFS_PAGE_MASK);
+        }
+#elif (defined HAVE_TRUNCATE_COMPLETE)
+        for (i = 0, lnb = res; i < pages; i++, lnb++)
+                truncate_complete_page(inode->i_mapping, lnb->page);
+#else
+#error "Nor truncate_inode_pages_range or truncate_complete_page are supported"
+#endif
+}
+
 static int filter_preprw_read(int cmd, struct obd_export *exp, struct obdo *oa,
                               int objcount, struct obd_ioobj *obj,
                               struct niobuf_remote *nb,
@@ -891,16 +919,17 @@ static int filter_commitrw_read(struct obd_export *exp, struct obdo *oa,
         if (res->dentry != NULL)
                 inode = res->dentry->d_inode;
 
-        for (i = 0, lnb = res; i < npages; i++, lnb++) {
-                if (lnb->page != NULL) {
+        for (i = 0, lnb = res; i < npages; i++, lnb++)
+                if (lnb->page != NULL)
                         page_cache_release(lnb->page);
-                        lnb->page = NULL;
-                }
-        }
 
         if (inode && (fo->fo_read_cache == 0 ||
-                        i_size_read(inode) > fo->fo_readcache_max_filesize))
-                filter_invalidate_cache(exp->exp_obd, obj, rnb, inode);
+                      i_size_read(inode) > fo->fo_readcache_max_filesize))
+                filter_truncate_cache(exp->exp_obd, obj, rnb, npages, res,
+                                      inode);
+
+        for (i = 0, lnb = res; i < npages; i++, lnb++)
+                lnb->page = NULL;
 
         if (res->dentry != NULL)
                 f_dput(res->dentry);