DEVEL15-linux-disable-readahad-20081108
[openafs.git] / src / afs / LINUX / osi_vnodeops.c
index b780f52..7a5a26e 100644 (file)
@@ -53,6 +53,7 @@ RCSID
 #if defined(AFS_LINUX26_ENV)
 #define LockPage(pp) lock_page(pp)
 #define UnlockPage(pp) unlock_page(pp)
+extern struct backing_dev_info afs_backing_dev_info;
 #endif
 
 extern struct vcache *afs_globalVp;
@@ -94,21 +95,24 @@ afs_linux_read(struct file *fp, char *buf, size_t count, loff_t * offp)
     if (code)
        code = -code;
     else {
-        isize = (i_size_read(fp->f_mapping->host) - 1) >> PAGE_CACHE_SHIFT;
+#if defined(AFS_CACHE_BYPASS)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+       isize = (i_size_read(fp->f_mapping->host) - 1) >> PAGE_CACHE_SHIFT;
         offindex = *offp >> PAGE_CACHE_SHIFT;
         if(offindex > isize) {
             code=0;
             goto done;
         }
-
-           osi_FlushPages(vcp, credp); /* ensure stale pages are gone */
-           AFS_GUNLOCK();
+#endif
+#endif
+       osi_FlushPages(vcp, credp);     /* ensure stale pages are gone */
+       AFS_GUNLOCK();
 #ifdef DO_SYNC_READ
-           code = do_sync_read(fp, buf, count, offp);
+       code = do_sync_read(fp, buf, count, offp);
 #else
-           code = generic_file_read(fp, buf, count, offp);
+       code = generic_file_read(fp, buf, count, offp);
 #endif
-           AFS_GLOCK();
+       AFS_GLOCK();
     }
 
     afs_Trace4(afs_iclSetp, CM_TRACE_READOP, ICL_TYPE_POINTER, vcp,
@@ -831,7 +835,7 @@ afs_linux_revalidate(struct dentry *dp)
     credp = crref();
     code = afs_getattr(vcp, &vattr, credp);
     if (!code)
-        vattr2inode(AFSTOV(vcp), &vattr);
+        afs_fill_inode(AFSTOV(vcp), &vattr);
 
     AFS_GUNLOCK();
 #ifdef AFS_LINUX24_ENV
@@ -876,11 +880,13 @@ afs_linux_dentry_revalidate(struct dentry *dp)
     cred_t *credp = NULL;
     struct vcache *vcp, *pvcp, *tvc = NULL;
     int valid;
+    struct afs_fakestat_state fakestate;
 
 #ifdef AFS_LINUX24_ENV
     maybe_lock_kernel();
 #endif
     AFS_GLOCK();
+    afs_InitFakeStat(&fakestate);
 
     if (dp->d_inode) {
 
@@ -892,8 +898,28 @@ afs_linux_dentry_revalidate(struct dentry *dp)
 
        if (vcp->mvstat == 1) {         /* mount point */
            if (vcp->mvid && (vcp->states & CMValid)) {
-               /* a mount point, not yet replaced by its directory */
-               goto bad_dentry;
+               int tryEvalOnly = 0;
+               int code = 0;
+               struct vrequest treq;
+
+               credp = crref();
+               code = afs_InitReq(&treq, credp);
+               if (
+#ifdef AFS_DARWIN_ENV
+                   (strcmp(dp->d_name.name, ".DS_Store") == 0) ||
+                   (strcmp(dp->d_name.name, "Contents") == 0) ||
+#endif
+                   (strcmp(dp->d_name.name, ".directory") == 0)) {
+                   tryEvalOnly = 1;
+               }
+               if (tryEvalOnly)
+                   code = afs_TryEvalFakeStat(&vcp, &fakestate, &treq);
+               else
+                   code = afs_EvalFakeStat(&vcp, &fakestate, &treq);
+               if ((tryEvalOnly && vcp->mvstat == 1) || code) {
+                   /* a mount point, not yet replaced by its directory */
+                   goto bad_dentry;
+               }
            }
        } else
            if (*dp->d_name.name != '/' && vcp->mvstat == 2) /* root vnode */
@@ -957,6 +983,7 @@ afs_linux_dentry_revalidate(struct dentry *dp)
     /* Clean up */
     if (tvc)
        afs_PutVCache(tvc);
+    afs_PutFakeStat(&fakestate);
     AFS_GUNLOCK();
     if (credp)
        crfree(credp);
@@ -971,7 +998,10 @@ afs_linux_dentry_revalidate(struct dentry *dp)
     return valid;
 
   bad_dentry:
-    valid = 0;
+    if (have_submounts(dp))
+       valid = 1;
+    else 
+       valid = 0;
     goto done;
 }
 
@@ -1708,6 +1738,8 @@ afs_linux_readpage(struct file *fp, struct page *pp)
         set_bit(PG_locked, &pp->flags);        /* other bits? See mm.h */
         clear_bit(PG_error, &pp->flags);
 #endif
+#if defined(AFS_CACHE_BYPASS)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
         /* If the page is past the end of the file, skip it */
         isize = (i_size_read(fp->f_mapping->host) - 1) >> PAGE_CACHE_SHIFT;
         if(pp->index > isize) {
@@ -1715,6 +1747,8 @@ afs_linux_readpage(struct file *fp, struct page *pp)
                           UnlockPage(pp);
                  goto done;
         }
+#endif
+#endif
         /* if bypasscache, receiver frees, else we do */
         auio = osi_Alloc(sizeof(uio_t));
         iovecp = osi_Alloc(sizeof(struct iovec));
@@ -1861,6 +1895,26 @@ afs_linux_writepage_sync(struct inode *ip, struct page *pp,
               ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
               ICL_TYPE_INT32, 99999);
 
+    ObtainReadLock(&vcp->lock);
+    if (vcp->states & CPageWrite) {
+       ReleaseReadLock(&vcp->lock);
+       AFS_GUNLOCK();
+       maybe_unlock_kernel();
+       crfree(credp);
+       kunmap(pp);
+#ifdef AFS_LINUX26_ENV
+#if defined(WRITEPAGE_ACTIVATE)
+       return WRITEPAGE_ACTIVATE;
+#else
+       return AOP_WRITEPAGE_ACTIVATE;
+#endif
+#else
+       /* should mark it dirty? */
+       return(0); 
+#endif
+    }
+    ReleaseReadLock(&vcp->lock);
+
     setup_uio(&tuio, &iovec, buffer, base, count, UIO_WRITE, AFS_UIOSYS);
 
     code = afs_write(vcp, &tuio, f_flags, credp, 0);
@@ -2178,6 +2232,7 @@ afs_fill_inode(struct inode *ip, struct vattr *vattr)
     if (vattr)
        vattr2inode(ip, vattr);
 
+    ip->i_mapping->backing_dev_info = &afs_backing_dev_info;
 /* Reset ops if symlink or directory. */
     if (S_ISREG(ip->i_mode)) {
        ip->i_op = &afs_file_iops;