linux-splice-support-20071106
[openafs.git] / src / afs / LINUX / osi_vnodeops.c
index 3da1aa6..b5b29d1 100644 (file)
@@ -491,11 +491,11 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
 #ifdef AFS_LINUX24_ENV
     if ((code == 0 || flp->fl_type == F_UNLCK) && 
         (cmd == F_SETLK || cmd == F_SETLKW)) {
-#ifdef AFS_LINUX26_ENV
+#ifdef POSIX_LOCK_FILE_WAIT_ARG
+       code = posix_lock_file(fp, flp, 0);
+#else
        flp->fl_flags &=~ FL_SLEEP;
        code = posix_lock_file(fp, flp);
-#else
-       code = posix_lock_file(fp, flp, 0);
 #endif 
        if (code && flp->fl_type != F_UNLCK) {
            struct AFS_FLOCK flock2;
@@ -575,7 +575,11 @@ afs_linux_flock(struct file *fp, int cmd, struct file_lock *flp) {
  * afs_StoreAllSegments() with AFS_LASTSTORE
  */
 static int
+#if defined(FOP_FLUSH_TAKES_FL_OWNER_T)
+afs_linux_flush(struct file *fp, fl_owner_t id)
+#else
 afs_linux_flush(struct file *fp)
+#endif
 {
     struct vrequest treq;
     struct vcache *vcp = VTOAFS(FILE_INODE(fp));
@@ -654,9 +658,13 @@ struct file_operations afs_file_fops = {
   .mmap =      afs_linux_mmap,
   .open =      afs_linux_open,
   .flush =     afs_linux_flush,
-#ifdef AFS_LINUX26_ENV
+#if defined(AFS_LINUX26_ENV) && defined(STRUCT_FILE_OPERATIONS_HAS_SENDFILE)
   .sendfile =   generic_file_sendfile,
 #endif
+#if defined(AFS_LINUX26_ENV) && defined(STRUCT_FILE_OPERATIONS_HAS_SPLICE)
+  .splice_write = generic_file_splice_write,
+  .splice_read = generic_file_splice_read,
+#endif
   .release =   afs_linux_release,
   .fsync =     afs_linux_fsync,
   .lock =      afs_linux_lock,
@@ -892,6 +900,15 @@ afs_dentry_iput(struct dentry *dp, struct inode *ip)
     AFS_GLOCK();
     (void) afs_InactiveVCache(vcp, NULL);
     AFS_GUNLOCK();
+#ifdef DCACHE_NFSFS_RENAMED
+#ifdef AFS_LINUX26_ENV
+    spin_lock(&dp->d_lock);
+#endif
+    dp->d_flags &= ~DCACHE_NFSFS_RENAMED;   
+#ifdef AFS_LINUX26_ENV
+    spin_unlock(&dp->d_lock);
+#endif
+#endif
 
     iput(ip);
 }
@@ -1127,6 +1144,15 @@ afs_linux_unlink(struct inode *dip, struct dentry *dp)
             }
             tvc->uncred = credp;
            tvc->states |= CUnlinked;
+#ifdef DCACHE_NFSFS_RENAMED
+#ifdef AFS_LINUX26_ENV
+           spin_lock(&dp->d_lock);
+#endif
+           dp->d_flags |= DCACHE_NFSFS_RENAMED;   
+#ifdef AFS_LINUX26_ENV
+           spin_unlock(&dp->d_lock);
+#endif
+#endif
        } else {
            osi_FreeSmallSpace(__name); 
        }
@@ -1317,7 +1343,7 @@ afs_linux_ireadlink(struct inode *ip, char *target, int maxlen, uio_seg_t seg)
        return -code;
 }
 
-#if !defined(AFS_LINUX24_ENV)
+#if !defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
 /* afs_linux_readlink 
  * Fill target (which is in user space) with contents of symlink.
  */
@@ -1337,6 +1363,36 @@ afs_linux_readlink(struct dentry *dp, char *target, int maxlen)
 /* afs_linux_follow_link
  * a file system dependent link following routine.
  */
+#if defined(AFS_LINUX24_ENV)
+static int afs_linux_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+    int code;
+    char *name;
+
+    name = osi_Alloc(PATH_MAX);
+    if (!name) {
+       return -EIO;
+    }
+
+    AFS_GLOCK();
+    code = afs_linux_ireadlink(dentry->d_inode, name, PATH_MAX - 1, AFS_UIOSYS);
+    AFS_GUNLOCK();
+
+    if (code < 0) {
+       goto out;
+    }
+
+    name[code] = '\0';
+    code = vfs_follow_link(nd, name);
+
+out:
+    osi_Free(name, PATH_MAX);
+
+    return code;
+}
+
+#else /* !defined(AFS_LINUX24_ENV) */
+
 static struct dentry *
 afs_linux_follow_link(struct dentry *dp, struct dentry *basep,
                      unsigned int follow)
@@ -1370,7 +1426,8 @@ afs_linux_follow_link(struct dentry *dp, struct dentry *basep,
     AFS_GUNLOCK();
     return res;
 }
-#endif
+#endif /* AFS_LINUX24_ENV */
+#endif /* USABLE_KERNEL_PAGE_SYMLINK_CACHE */
 
 /* afs_linux_readpage
  * all reads come through here. A strategy-like read call.
@@ -1735,7 +1792,7 @@ static struct inode_operations afs_dir_iops = {
 /* We really need a separate symlink set of ops, since do_follow_link()
  * determines if it _is_ a link by checking if the follow_link op is set.
  */
-#if defined(AFS_LINUX24_ENV)
+#if defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
 static int
 afs_symlink_filler(struct file *file, struct page *page)
 {
@@ -1770,10 +1827,10 @@ afs_symlink_filler(struct file *file, struct page *page)
 static struct address_space_operations afs_symlink_aops = {
   .readpage =  afs_symlink_filler
 };
-#endif
+#endif /* USABLE_KERNEL_PAGE_SYMLINK_CACHE */
 
 static struct inode_operations afs_symlink_iops = {
-#if defined(AFS_LINUX24_ENV)
+#if defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
   .readlink =          page_readlink,
 #if defined(HAVE_KERNEL_PAGE_FOLLOW_LINK)
   .follow_link =       page_follow_link,
@@ -1781,13 +1838,17 @@ static struct inode_operations afs_symlink_iops = {
   .follow_link =       page_follow_link_light,
   .put_link =           page_put_link,
 #endif
-  .setattr =           afs_notify_change,
-#else
+#else /* !defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE) */
   .readlink =          afs_linux_readlink,
   .follow_link =       afs_linux_follow_link,
+#if !defined(AFS_LINUX24_ENV)
   .permission =                afs_linux_permission,
   .revalidate =                afs_linux_revalidate,
 #endif
+#endif /* USABLE_KERNEL_PAGE_SYMLINK_CACHE */
+#if defined(AFS_LINUX24_ENV)
+  .setattr =           afs_notify_change,
+#endif
 };
 
 void
@@ -1813,7 +1874,7 @@ afs_fill_inode(struct inode *ip, struct vattr *vattr)
 
     } else if (S_ISLNK(ip->i_mode)) {
        ip->i_op = &afs_symlink_iops;
-#if defined(AFS_LINUX24_ENV)
+#if defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
        ip->i_data.a_ops = &afs_symlink_aops;
        ip->i_mapping = &ip->i_data;
 #endif