Whamcloud - gitweb
- use truncate instead of invalidate to drop referenced pages from cache. This
authortappro <tappro>
Thu, 5 Mar 2009 06:54:15 +0000 (06:54 +0000)
committertappro <tappro>
Thu, 5 Mar 2009 06:54:15 +0000 (06:54 +0000)
  is needed to disable ROC correctly
b:18520
i:adilger,green

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

index dbf064d..60c2bc5 100644 (file)
@@ -1178,6 +1178,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],[
@@ -1394,6 +1403,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 eeb8c7c..bd0ad34 100644 (file)
@@ -325,14 +325,40 @@ void filter_invalidate_cache(struct obd_device *obd, struct obd_ioobj *obj,
         int i;
 
         LASSERT(inode != NULL);
-
         for (i = 0, rnb = nb; i < obj->ioo_bufcnt; i++, rnb++) {
-                invalidate_mapping_pages(inode->i_mapping, 
+                invalidate_mapping_pages(inode->i_mapping,
                                          rnb->offset >> CFS_PAGE_SHIFT,
                                          (rnb->offset + rnb->len) >>
                                          CFS_PAGE_SHIFT);
         }
-        
+}
+
+/*
+ * 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,
@@ -874,15 +900,17 @@ static int filter_commitrw_read(struct obd_export *exp, struct obdo *oa,
                 inode = res->dentry->d_inode;
 
         for (i = 0, lnb = res; i < pages; i++, lnb++) {
-                if (lnb->page != NULL) {
+                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, pages, res,
+                                      inode);
+
+        for (i = 0, lnb = res; i < pages; i++, lnb++)
+                lnb->page = NULL;
 
         if (res->dentry != NULL)
                 f_dput(res->dentry);