[OpenAFS-devel] OpenAFS, Linux and truncate_inode_pages()

chas williams - CONTRACTOR chas@cmf.nrl.navy.mil
Wed, 01 Mar 2006 16:09:43 -0500


In message <4405CB2C.1010702@pclella.cern.ch>,Rainer Toebbicke writes:
>Corrupted on the local client, in the chunk file (witnessed by grep on 
>the cache files).  File normal again after 'fs flush'.

i guess this wouldnt make me to suspect something wrong in osi_vm.c.
regardless, the following might be a little more "correct".  give
it a try.

Index: src/afs/LINUX/osi_vm.c
===================================================================
RCS file: /cvs/openafs/src/afs/LINUX/osi_vm.c,v
retrieving revision 1.16.2.1
diff -u -u -r1.16.2.1 osi_vm.c
--- src/afs/LINUX/osi_vm.c	11 Jul 2005 19:29:56 -0000	1.16.2.1
+++ src/afs/LINUX/osi_vm.c	1 Mar 2006 20:50:45 -0000
@@ -51,6 +51,8 @@
     if (avc->opens != 0)
 	return EBUSY;
 
+    down(&ip->i_sem);
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     truncate_inode_pages(&ip->i_data, 0);
 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15)
@@ -58,6 +60,9 @@
 #else
     invalidate_inode_pages(ip);
 #endif
+
+    up(&ip->i_sem);
+
     return 0;
 }
 
@@ -100,18 +105,28 @@
 void
 osi_VM_StoreAllSegments(struct vcache *avc)
 {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,5)
     struct inode *ip = AFSTOV(avc);
+    int err;
+    int need_unlock = 1;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,5)
-    /* filemap_fdatasync() only exported in 2.4.5 and above */
     ReleaseWriteLock(&avc->lock);
     AFS_GUNLOCK();
-#if defined(AFS_LINUX26_ENV)
-    filemap_fdatawrite(ip->i_mapping);
+
+    if (down_trylock(&ip->i_sem))
+	need_unlock = 0;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    err = filemap_fdatawrite(ip->i_mapping);
 #else
-    filemap_fdatasync(ip->i_mapping);
+    err = filemap_fdatasync(ip->i_mapping);
 #endif
-    filemap_fdatawait(ip->i_mapping);
+    if (err == 0)
+	filemap_fdatawait(ip->i_mapping);
+
+    if (need_unlock)
+	up(&ip->i_sem);
+
     AFS_GLOCK();
     ObtainWriteLock(&avc->lock, 121);
 #endif
@@ -124,17 +139,20 @@
 void
 osi_VM_FlushPages(struct vcache *avc, struct AFS_UCRED *credp)
 {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     struct inode *ip = AFSTOV(avc);
 
+    down(&ip->i_sem);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     truncate_inode_pages(&ip->i_data, 0);
 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15)
-    struct inode *ip = AFSTOV(avc);
 
     truncate_inode_pages(ip, 0);
 #else
-    invalidate_inode_pages(AFSTOV(avc));
+    invalidate_inode_pages(ip);
 #endif
+
+    up(&ip->i_sem);
 }
 
 /* Purge pages beyond end-of-file, when truncating a file.
@@ -146,15 +164,13 @@
 void
 osi_VM_Truncate(struct vcache *avc, int alen, struct AFS_UCRED *acred)
 {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     struct inode *ip = AFSTOV(avc);
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     truncate_inode_pages(&ip->i_data, alen);
 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15)
-    struct inode *ip = AFSTOV(avc);
-
     truncate_inode_pages(ip, alen);
 #else
-    invalidate_inode_pages(AFSTOV(avc));
+    invalidate_inode_pages(ip);
 #endif
 }