Linux: Use filehandles for all 2.6 kernels
authorMarc Dionne <marc.c.dionne@gmail.com>
Sat, 26 Jun 2010 00:06:08 +0000 (20:06 -0400)
committerDerrick Brashear <shadow@dementia.org>
Mon, 28 Jun 2010 03:33:12 +0000 (20:33 -0700)
This generalizes the use of the exportfs API and file handles
to open disk cache files for all 2.6 kernels.

Code outside of src/afs/LINUX (ex: afsd) can assume that file
handles are used for all 2.6 kernels and can use AFS_LINUX26_ENV
to check.

Within src/afs/LINUX/osi_file.c, NEW_EXPORT_OPS can be used to
determine if the old exportfs API (pre 2.6.24) or the new one
applies.

All traces of the LINUX_USE_FH define are removed.

FIXES 127530

Change-Id: I6803101c56981f9f674cef581f7299656723fdf3
Reviewed-on: http://gerrit.openafs.org/2260
Tested-by: Marc Dionne <marc.c.dionne@gmail.com>
Reviewed-by: Simon Wilkinson <sxw@inf.ed.ac.uk>
Reviewed-by: Derrick Brashear <shadow@dementia.org>

acinclude.m4
src/afs/LINUX/osi_compat.h
src/afs/LINUX/osi_file.c
src/afs/afs.h
src/afs/afs_dcache.c
src/afs/sysincludes.h
src/afsd/afsd.c

index a0bad9e..9cf9d22 100644 (file)
@@ -842,9 +842,6 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
                 AC_CHECK_LINUX_FUNC([i_size_read],
                                     [#include <linux/fs.h>],
                                     [i_size_read(NULL);])
-                AC_CHECK_LINUX_FUNC([iget],
-                                    [#include <linux/fs.h>],
-                                    [iget(NULL, NULL);])
                 AC_CHECK_LINUX_FUNC([kernel_setsockopt],
                                     [#include <linux/net.h>],
                                     [kernel_setsockopt(NULL, 0, 0, NULL, 0);])
@@ -872,9 +869,6 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
 
                 dnl Consequences - things which get set as a result of the
                 dnl                above tests
-                AS_IF([test "x$ac_cv_linux_func_iget" = "xno"],
-                      [AC_DEFINE([LINUX_USE_FH], 1,
-                         [define to use linux file handles for cache files])])
                 AS_IF([test "x$ac_cv_linux_func_d_alloc_anon" = "xno"],
                       [AC_DEFINE([AFS_NONFSTRANS], 1,
                                  [define to disable the nfs translator])])
index 7088625..2d7382f 100644 (file)
@@ -293,3 +293,52 @@ afs_try_to_freeze(void) {
 
 # endif
 #endif
+
+#if !defined(NEW_EXPORT_OPS)
+extern struct export_operations export_op_default;
+#endif
+
+static inline struct dentry *
+afs_get_dentry_from_fh(struct super_block *afs_cacheSBp, afs_dcache_id_t *ainode,
+               int cache_fh_len, int cache_fh_type,
+               int (*afs_fh_acceptable)(void *, struct dentry *)) {
+#if defined(NEW_EXPORT_OPS)
+    return afs_cacheSBp->s_export_op->fh_to_dentry(afs_cacheSBp, &ainode->ufs.fh,
+               cache_fh_len, cache_fh_type);
+#else
+    if (afs_cacheSBp->s_export_op && afs_cacheSBp->s_export_op->decode_fh)
+       return afs_cacheSBp->s_export_op->decode_fh(afs_cacheSBp, ainode->ufs.raw,
+                       cache_fh_len, cache_fh_type, afs_fh_acceptable, NULL);
+    else
+       return export_op_default.decode_fh(afs_cacheSBp, ainode->ufs.raw,
+                       cache_fh_len, cache_fh_type, afs_fh_acceptable, NULL);
+#endif
+}
+
+static inline int
+afs_get_fh_from_dentry(struct dentry *dp, afs_ufs_dcache_id_t *ainode, int *max_lenp) {
+    if (dp->d_sb->s_export_op->encode_fh)
+        return dp->d_sb->s_export_op->encode_fh(dp, &ainode->raw[0], max_lenp, 0);
+#if defined(NEW_EXPORT_OPS)
+    /* If fs doesn't provide an encode_fh method, assume the default INO32 type */
+    *max_lenp = sizeof(struct fid)/4;
+    ainode->fh.i32.ino = dp->d_inode->i_ino;
+    ainode->fh.i32.gen = dp->d_inode->i_generation;
+    return FILEID_INO32_GEN;
+#else
+    /* or call the default encoding function for the old API */
+    return export_op_default.encode_fh(dp, &ainode->raw[0], max_lenp, 0);
+#endif
+}
+
+static inline void
+afs_init_sb_export_ops(struct super_block *sb) {
+#if !defined(NEW_EXPORT_OPS)
+    /*
+     * decode_fh will call this function.  If not defined for this FS, make
+     * sure it points to the default
+     */
+    if (!sb->s_export_op->find_exported_dentry)
+       sb->s_export_op->find_exported_dentry = find_exported_dentry;
+#endif
+}
index c0c589b..53784ca 100644 (file)
 #include "afs/afs_stats.h"     /* afs statistics */
 #include <linux/smp_lock.h>
 #include <linux/namei.h>
-#if defined(LINUX_USE_FH)
+
+#if defined(HAVE_LINUX_EXPORTFS_H)
 #include <linux/exportfs.h>
+#endif
+#include "osi_compat.h"
+
 int cache_fh_type = -1;
 int cache_fh_len = -1;
-#endif
 
 afs_lock_t afs_xosi;           /* lock is for tvattr */
 extern struct osi_dev cacheDev;
@@ -31,6 +34,13 @@ extern struct super_block *afs_cacheSBp;
 extern struct cred *cache_creds;
 #endif
 
+/* Old export ops: decode_fh will call back here. Accept any dentry it suggests */
+int
+afs_fh_acceptable(void *context, struct dentry *dp)
+{
+    return 1;
+}
+
 struct file *
 afs_linux_raw_open(afs_dcache_id_t *ainode)
 {
@@ -38,19 +48,11 @@ afs_linux_raw_open(afs_dcache_id_t *ainode)
     struct dentry *dp = NULL;
     struct file* filp;
 
-#if !defined(LINUX_USE_FH)
-    tip = iget(afs_cacheSBp, ainode->ufs);
-    if (!tip)
-       osi_Panic("Can't get inode %d\n", (int) ainode->ufs);
-
-    dp = d_alloc_anon(tip);
-#else
-    dp = afs_cacheSBp->s_export_op->fh_to_dentry(afs_cacheSBp, &ainode->ufs.fh,
-                                                cache_fh_len, cache_fh_type);
+    dp = afs_get_dentry_from_fh(afs_cacheSBp, ainode, cache_fh_len, cache_fh_type,
+               afs_fh_acceptable);
     if (!dp)
            osi_Panic("Can't get dentry\n");
     tip = dp->d_inode;
-#endif
     tip->i_flags |= S_NOATIME; /* Disable updating access times. */
 
 #if defined(STRUCT_TASK_STRUCT_HAS_CRED)
@@ -62,11 +64,7 @@ afs_linux_raw_open(afs_dcache_id_t *ainode)
     filp = dentry_open(dp, mntget(afs_cacheMnt), O_RDWR);
 #endif
     if (IS_ERR(filp))
-#if defined(LINUX_USE_FH)
        osi_Panic("Can't open file: %d\n", (int) PTR_ERR(filp));
-#else
-       osi_Panic("Can't open inode %d\n", (int) ainode->ufs);
-#endif
     return filp;
 }
 
@@ -102,7 +100,6 @@ osi_UFSOpen(afs_dcache_id_t *ainode)
     return (void *)afile;
 }
 
-#if defined(LINUX_USE_FH)
 /*
  * Given a dentry, return the file handle as encoded by the filesystem.
  * We can't assume anything about the length (words, not bytes).
@@ -117,34 +114,19 @@ void osi_get_fh(struct dentry *dp, afs_ufs_dcache_id_t *ainode) {
        max_len = cache_fh_len;
     else
        max_len = MAX_FH_LEN;
-    if (dp->d_sb->s_export_op->encode_fh) {
-        type = dp->d_sb->s_export_op->encode_fh(dp, &ainode->raw[0], &max_len, 0);
-        if (type == 255) {
-           osi_Panic("File handle encoding failed\n");
-        }
-        if (cache_fh_type < 0)
-            cache_fh_type = type;
-        if (cache_fh_len < 0) {
-            cache_fh_len = max_len;
-        }
-        if (type != cache_fh_type || max_len != cache_fh_len) {
-           osi_Panic("Inconsistent file handles within cache\n");
-        }
-    } else {
-         /* If fs doesn't provide an encode_fh method, assume the default INO32 type */
-       if (cache_fh_type < 0)
-           cache_fh_type = FILEID_INO32_GEN;
-       if (cache_fh_len < 0)
-           cache_fh_len = sizeof(struct fid)/4;
-        ainode->fh.i32.ino = dp->d_inode->i_ino;
-        ainode->fh.i32.gen = dp->d_inode->i_generation;
+    type = afs_get_fh_from_dentry(dp, ainode, &max_len);
+    if (type == 255) {
+       osi_Panic("File handle encoding failed\n");
+    }
+    if (cache_fh_type < 0)
+       cache_fh_type = type;
+    if (cache_fh_len < 0) {
+       cache_fh_len = max_len;
+    }
+    if (type != cache_fh_type || max_len != cache_fh_len) {
+       osi_Panic("Inconsistent file handles within cache\n");
     }
 }
-#else
-void osi_get_fh(struct dentry *dp, afs_ufs_dcache_id_t *ainode) {
-    *ainode = dp->d_inode->i_ino;
-}
-#endif
 
 int
 afs_osi_Stat(register struct osi_file *afile, register struct osi_stat *astat)
@@ -357,6 +339,8 @@ osi_InitCacheInfo(char *aname)
 
     dput(dp);
 
+    afs_init_sb_export_ops(afs_cacheSBp);
+
     return 0;
 }
 
index f660464..0168ceb 100644 (file)
@@ -1067,11 +1067,13 @@ typedef char *afs_ufs_dcache_id_t;
  * the size correctly.
  */
 typedef ino64_t afs_ufs_dcache_id_t;
-#elif defined(LINUX_USE_FH)
+#elif defined(AFS_LINUX26_ENV)
 #define MAX_FH_LEN 10
 typedef union {
-     struct fid fh;
-     __u32 raw[MAX_FH_LEN];
+#if defined(NEW_EXPORT_OPS)
+    struct fid fh;
+#endif
+    __u32 raw[MAX_FH_LEN];
 } afs_ufs_dcache_id_t;
 extern int cache_fh_type;
 extern int cache_fh_len;
index 9d2bf48..77dec65 100644 (file)
@@ -2910,7 +2910,7 @@ afs_InitCacheFile(char *afile, ino_t ainode)
        }
     } else {
        /* Add any other 'complex' inode types here ... */
-#if !defined(LINUX_USE_FH) && !defined(AFS_CACHE_VNODE_PATH)
+#if !defined(AFS_LINUX26_ENV) && !defined(AFS_CACHE_VNODE_PATH)
        tdc->f.inode.ufs = ainode;
 #else
        osi_Panic("Can't init cache with inode numbers when complex inodes are "
index 71bfbcf..560ce83 100644 (file)
@@ -183,7 +183,7 @@ struct xfs_inode_info {
 # ifdef HAVE_LINUX_COMPLETION_H
 #  include <linux/completion.h>
 # endif
-# if defined(LINUX_USE_FH)
+# if defined(HAVE_LINUX_EXPORTFS_H)
 #  include <linux/exportfs.h>
 # endif
 
index 2377c2a..aecec1b 100644 (file)
@@ -325,7 +325,7 @@ int *dir_for_V = NULL;              /* Array: dir of each cache file.
                                 * -2: file exists in top-level
                                 * >=0: file exists in Dxxx
                                 */
-#if !defined(AFS_CACHE_VNODE_PATH) && !defined(LINUX_USE_FH)
+#if !defined(AFS_CACHE_VNODE_PATH) && !defined(AFS_LINUX26_ENV)
 AFSD_INO_T *inode_for_V;       /* Array of inodes for desired
                                 * cache files */
 #endif
@@ -1017,7 +1017,7 @@ doSweepAFSCache(int *vFilesFound,
             * file's inode, directory, and bump the number of files found
             * total and in this directory.
             */
-#if !defined(AFS_CACHE_VNODE_PATH) && !defined(LINUX_USE_FH)
+#if !defined(AFS_CACHE_VNODE_PATH) && !defined(AFS_LINUX26_ENV)
            inode_for_V[vFileNum] = currp->d_ino;
 #endif
            dir_for_V[vFileNum] = dirNum;       /* remember this directory */
@@ -1159,7 +1159,7 @@ doSweepAFSCache(int *vFilesFound,
                           vFileNum);
                else {
                    struct stat statb;
-#if !defined(AFS_CACHE_VNODE_PATH) && !defined(LINUX_USE_FH)
+#if !defined(AFS_CACHE_VNODE_PATH) && !defined(AFS_LINUX26_ENV)
                    assert(inode_for_V[vFileNum] == (AFSD_INO_T) 0);
 #endif
                    sprintf(vFilePtr, "D%d/V%d", thisDir, vFileNum);
@@ -1172,7 +1172,7 @@ doSweepAFSCache(int *vFilesFound,
                    if (CreateCacheFile(fullpn_VFile, &statb))
                        printf("%s: Can't create '%s'\n", rn, fullpn_VFile);
                    else {
-#if !defined(AFS_CACHE_VNODE_PATH) && !defined(LINUX_USE_FH)
+#if !defined(AFS_CACHE_VNODE_PATH) && !defined(AFS_LINUX26_ENV)
                        inode_for_V[vFileNum] = statb.st_ino;
 #endif
                        dir_for_V[vFileNum] = thisDir;
@@ -1275,7 +1275,7 @@ CheckCacheBaseDir(char *dir)
        if (res != 0) {
            return "unable to statfs cache base directory";
        }
-#if !defined(LINUX_USE_FH)
+#if !defined(AFS_LINUX26_ENV)
        if (statfsbuf.f_type == 0x52654973) {   /* REISERFS_SUPER_MAGIC */
            return "cannot use reiserfs as cache partition";
        } else if (statfsbuf.f_type == 0x58465342) {    /* XFS_SUPER_MAGIC */
@@ -2103,7 +2103,7 @@ afsd_run(void)
                   cacheStatEntries);
     }
 
-#if !defined(AFS_CACHE_VNODE_PATH) && !defined(LINUX_USE_FH)
+#if !defined(AFS_CACHE_VNODE_PATH) && !defined(AFS_LINUX26_ENV)
     /*
      * Create and zero the inode table for the desired cache files.
      */
@@ -2433,7 +2433,7 @@ afsd_run(void)
            afsd_call_syscall(AFSOP_CACHEINODE,
                         (afs_uint32) (inode_for_V[currVFile] >> 32),
                         (afs_uint32) (inode_for_V[currVFile] & 0xffffffff));
-#elif !(defined(LINUX_USE_FH) || defined(AFS_CACHE_VNODE_PATH))
+#elif !(defined(AFS_LINUX26_ENV) || defined(AFS_CACHE_VNODE_PATH))
            afsd_call_syscall(AFSOP_CACHEINODE, inode_for_V[currVFile]);
 #else
            printf