Linux: Add autoconf macro for structure checks
[openafs.git] / src / afs / LINUX / osi_vnodeops.c
index 83a5ab0..eb667cc 100644 (file)
@@ -41,7 +41,7 @@
 #include "osi_compat.h"
 #include "osi_pagecopy.h"
 
-#ifndef HAVE_PAGEVEC_LRU_ADD_FILE
+#ifndef HAVE_LINUX_PAGEVEC_LRU_ADD_FILE
 #define __pagevec_lru_add_file __pagevec_lru_add
 #endif
 
@@ -49,7 +49,7 @@
 #define MAX_ERRNO 1000L
 #endif
 
-extern struct backing_dev_info afs_backing_dev_info;
+extern struct backing_dev_info *afs_backing_dev_info;
 
 extern struct vcache *afs_globalVp;
 extern int afs_notify_change(struct dentry *dp, struct iattr *iattrp);
@@ -481,7 +481,10 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
     flock.l_pid = flp->fl_pid;
     flock.l_whence = 0;
     flock.l_start = flp->fl_start;
-    flock.l_len = flp->fl_end - flp->fl_start + 1;
+    if (flp->fl_end == OFFSET_MAX)
+       flock.l_len = 0; /* Lock to end of file */
+    else
+       flock.l_len = flp->fl_end - flp->fl_start + 1;
 
     /* Safe because there are no large files, yet */
 #if defined(F_GETLK64) && (F_GETLK != F_GETLK64)
@@ -525,7 +528,10 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
     flp->fl_type = flock.l_type;
     flp->fl_pid = flock.l_pid;
     flp->fl_start = flock.l_start;
-    flp->fl_end = flock.l_start + flock.l_len - 1;
+    if (flock.l_len == 0)
+       flp->fl_end = OFFSET_MAX; /* Lock to end of file */
+    else
+       flp->fl_end = flock.l_start + flock.l_len - 1;
 
     crfree(credp);
     return afs_convert_code(code);
@@ -544,7 +550,7 @@ afs_linux_flock(struct file *fp, int cmd, struct file_lock *flp) {
     flock.l_pid = flp->fl_pid;
     flock.l_whence = 0;
     flock.l_start = 0;
-    flock.l_len = OFFSET_MAX;
+    flock.l_len = 0;
 
     /* Safe because there are no large files, yet */
 #if defined(F_GETLK64) && (F_GETLK != F_GETLK64)
@@ -674,7 +680,7 @@ struct file_operations afs_dir_fops = {
 struct file_operations afs_file_fops = {
   .read =      afs_linux_read,
   .write =     afs_linux_write,
-#ifdef GENERIC_FILE_AIO_READ
+#ifdef HAVE_LINUX_GENERIC_FILE_AIO_READ
   .aio_read =  generic_file_aio_read,
   .aio_write = generic_file_aio_write,
 #endif
@@ -729,8 +735,12 @@ static inline void
 check_bad_parent(struct dentry *dp)
 {
     cred_t *credp;
-    struct vcache *vcp = VTOAFS(dp->d_inode), *avc = NULL;
-    struct vcache *pvc = VTOAFS(dp->d_parent->d_inode);
+    struct dentry *parent;
+    struct vcache *vcp, *pvc, *avc = NULL;
+
+    vcp = VTOAFS(dp->d_inode);
+    parent = dget_parent(dp);
+    pvc = VTOAFS(parent->d_inode);
 
     if (vcp->mvid->Fid.Volume != pvc->f.fid.Fid.Volume) {      /* bad parent */
        credp = crref();
@@ -748,6 +758,8 @@ check_bad_parent(struct dentry *dp)
        crfree(credp);
     }
 
+    dput(parent);
+
     return;
 }
 
@@ -830,6 +842,7 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
     struct vattr vattr;
     cred_t *credp = NULL;
     struct vcache *vcp, *pvcp, *tvc = NULL;
+    struct dentry *parent;
     int valid;
     struct afs_fakestat_state fakestate;
 
@@ -838,9 +851,7 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
     afs_InitFakeStat(&fakestate);
 
     if (dp->d_inode) {
-
        vcp = VTOAFS(dp->d_inode);
-       pvcp = VTOAFS(dp->d_parent->d_inode);           /* dget_parent()? */
 
        if (vcp == afs_globalVp)
            goto good_dentry;
@@ -883,6 +894,9 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
        }
 #endif
 
+       parent = dget_parent(dp);
+       pvcp = VTOAFS(parent->d_inode);
+
        /* If the parent's DataVersion has changed or the vnode
         * is longer valid, we need to do a full lookup.  VerifyVCache
         * isn't enough since the vnode may have been renamed.
@@ -892,11 +906,15 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
 
            credp = crref();
            afs_lookup(pvcp, (char *)dp->d_name.name, &tvc, credp);
-           if (!tvc || tvc != vcp)
+           if (!tvc || tvc != vcp) {
+               dput(parent);
                goto bad_dentry;
+           }
 
-           if (afs_getattr(vcp, &vattr, credp))
+           if (afs_getattr(vcp, &vattr, credp)) {
+               dput(parent);
                goto bad_dentry;
+           }
 
            vattr2inode(AFSTOV(vcp), &vattr);
            dp->d_time = hgetlo(pvcp->f.m.DataVersion);
@@ -905,9 +923,13 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
        /* should we always update the attributes at this point? */
        /* unlikely--the vcache entry hasn't changed */
 
+       dput(parent);
     } else {
 #ifdef notyet
-       pvcp = VTOAFS(dp->d_parent->d_inode);           /* dget_parent()? */
+       /* If this code is ever enabled, we should use dget_parent to handle
+        * getting the parent, and dput() to dispose of it. See above for an
+        * example ... */
+       pvcp = VTOAFS(dp->d_parent->d_inode);
        if (hgetlo(pvcp->f.m.DataVersion) > dp->d_time)
            goto bad_dentry;
 #endif
@@ -1939,6 +1961,9 @@ afs_linux_readpages(struct file *fp, struct address_space *mapping,
     if (afs_linux_bypass_check(inode))
        return afs_linux_bypass_readpages(fp, mapping, page_list, num_pages);
 
+    if (cacheDiskType == AFS_FCACHE_TYPE_MEM)
+       return 0;
+
     AFS_GLOCK();
     if ((code = afs_linux_VerifyVCache(avc, NULL))) {
        AFS_GUNLOCK();
@@ -2171,7 +2196,10 @@ afs_linux_writepage(struct page *pp)
     /* Grab the creds structure currently held in the vnode, and
      * get a reference to it, in case it goes away ... */
     credp = vcp->cred;
-    crhold(credp);
+    if (credp)
+       crhold(credp);
+    else
+       credp = crref();
     ReleaseWriteLock(&vcp->lock);
     AFS_GUNLOCK();
 
@@ -2306,7 +2334,7 @@ afs_linux_prepare_write(struct file *file, struct page *page, unsigned from,
     return 0;
 }
 
-#if defined(HAVE_WRITE_BEGIN)
+#if defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN)
 static int
 afs_linux_write_end(struct file *file, struct address_space *mapping,
                                 loff_t pos, unsigned len, unsigned copied,
@@ -2356,7 +2384,7 @@ static struct address_space_operations afs_file_aops = {
   .readpage =          afs_linux_readpage,
   .readpages =                 afs_linux_readpages,
   .writepage =         afs_linux_writepage,
-#if defined (HAVE_WRITE_BEGIN)
+#if defined (STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN)
   .write_begin =        afs_linux_write_begin,
   .write_end =          afs_linux_write_end,
 #else
@@ -2427,7 +2455,7 @@ static struct address_space_operations afs_symlink_aops = {
 static struct inode_operations afs_symlink_iops = {
 #if defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
   .readlink =          page_readlink,
-# if defined(HAVE_KERNEL_PAGE_FOLLOW_LINK)
+# if defined(HAVE_LINUX_PAGE_FOLLOW_LINK)
   .follow_link =       page_follow_link,
 # else
   .follow_link =       page_follow_link_light,
@@ -2447,7 +2475,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;
+    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;