Whamcloud - gitweb
LU-163 MDS returns 32/64-bit dir name hash according to client type
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / ext4-export-64bit-name-hash.patch
index e920e4e..c7e01f4 100644 (file)
@@ -1,12 +1,24 @@
-Index: linux-2.6.18-194.17.1-ext4/fs/ext4/dir.c
+Index: linux-stage/fs/ext4/dir.c
 ===================================================================
---- linux-2.6.18-194.17.1-ext4.orig/fs/ext4/dir.c      2010-12-02 16:37:05.000000000 +0300
-+++ linux-2.6.18-194.17.1-ext4/fs/ext4/dir.c   2010-12-16 00:06:49.000000000 +0300
-@@ -245,19 +245,32 @@ out:
+--- linux-stage.orig/fs/ext4/dir.c     2011-04-19 01:02:34.000000000 +0800
++++ linux-stage/fs/ext4/dir.c  2011-04-19 01:24:36.000000000 +0800
+@@ -242,22 +242,50 @@
+       return ret;
+ }
+
++static inline int is_32bit_api(void)
++{
++#ifdef HAVE_IS_COMPAT_TASK
++        return is_compat_task();
++#else
++        return (BITS_PER_LONG == 32);
++#endif
++}
++
  /*
   * These functions convert from the major/minor hash to an f_pos
   * value.
-- *
+  *
 - * Currently we only use major hash numer.  This is unfortunate, but
 - * on 32-bit machines, the same VFS interface is used for lseek and
 - * llseek, so if we use the 64 bit offset, then the 32-bit versions of
@@ -15,45 +27,50 @@ Index: linux-2.6.18-194.17.1-ext4/fs/ext4/dir.c
 - * a 64-bit version of the system call or the 32-bit version of the
 - * system call.  Worse yet, NFSv2 only allows for a 32-bit readdir
 - * cookie.  Sigh.
-+ * Whether 64-bit or 32-bit hash value is exported as file pos is
-+ * controlled by "64bithash" mount option.
++ * Up layer (OSD) should specify O_32BITHASH or O_64BITHASH explicitly.
++ * On the other hand, we allow ldiskfs to be mounted directly on both 32-bit
++ * and 64-bit nodes, under such case, neither O_32BITHASH nor O_64BITHASH is
++ * specified.
   */
 -#define hash2pos(major, minor)        (major >> 1)
 -#define pos2maj_hash(pos)     ((pos << 1) & 0xffffffff)
 -#define pos2min_hash(pos)     (0)
-+static inline loff_t hash2pos(struct super_block *sb, __u32 major, __u32 minor)
++static inline loff_t hash2pos(struct file *filp, __u32 major, __u32 minor)
 +{
-+      if (test_opt(sb, 64BITHASH))
-+              return (((__u64)(major >> 1) << 32) | (__u64)minor);
-+      else
++      if ((filp->f_flags & O_32BITHASH) ||
++          (!(filp->f_flags & O_64BITHASH) && is_32bit_api()))
 +              return (major >> 1);
++      else
++              return (((__u64)(major >> 1) << 32) | (__u64)minor);
 +}
 +
-+static inline __u32 pos2maj_hash(struct super_block *sb, loff_t pos)
++static inline __u32 pos2maj_hash(struct file *filp, loff_t pos)
 +{
-+      if (test_opt(sb, 64BITHASH))
-+              return (((pos >> 32) << 1) & 0xffffffff);
-+      else
++      if ((filp->f_flags & O_32BITHASH) ||
++          (!(filp->f_flags & O_64BITHASH) && is_32bit_api()))
 +              return ((pos << 1) & 0xffffffff);
++      else
++              return (((pos >> 32) << 1) & 0xffffffff);
 +}
 +
-+static inline __u32 pos2min_hash(struct super_block *sb, loff_t pos)
++static inline __u32 pos2min_hash(struct file *filp, loff_t pos)
 +{
-+      if (test_opt(sb, 64BITHASH))
-+              return (pos  & 0xffffffff);
-+      else
++      if ((filp->f_flags & O_32BITHASH) ||
++          (!(filp->f_flags & O_64BITHASH) && is_32bit_api()))
 +              return (0);
++      else
++              return (pos & 0xffffffff);
 +}
  
  /*
   * This structure holds the nodes of the red-black tree used to store
-@@ -318,15 +331,16 @@ static void free_rb_tree_fname(struct rb
+@@ -318,15 +346,16 @@
  }
  
  
 -static struct dir_private_info *ext4_htree_create_dir_info(loff_t pos)
-+static struct dir_private_info *ext4_htree_create_dir_info(
-+        struct super_block *sb, loff_t pos)
++static struct dir_private_info *
++ext4_htree_create_dir_info(struct file *filp, loff_t pos)
  {
        struct dir_private_info *p;
  
@@ -62,79 +79,56 @@ Index: linux-2.6.18-194.17.1-ext4/fs/ext4/dir.c
                return NULL;
 -      p->curr_hash = pos2maj_hash(pos);
 -      p->curr_minor_hash = pos2min_hash(pos);
-+      p->curr_hash = pos2maj_hash(sb, pos);
-+      p->curr_minor_hash = pos2min_hash(sb, pos);
++      p->curr_hash = pos2maj_hash(filp, pos);
++      p->curr_minor_hash = pos2min_hash(filp, pos);
        return p;
  }
  
-@@ -422,7 +436,7 @@ static int call_filldir(struct file *fil
+@@ -422,7 +451,7 @@
                       "null fname?!?\n");
                return 0;
        }
 -      curr_pos = hash2pos(fname->hash, fname->minor_hash);
-+      curr_pos = hash2pos(sb, fname->hash, fname->minor_hash);
++      curr_pos = hash2pos(filp, fname->hash, fname->minor_hash);
        while (fname) {
                error = filldir(dirent, fname->name,
                                fname->name_len, curr_pos,
-@@ -447,7 +461,7 @@ static int ext4_dx_readdir(struct file *
+@@ -447,7 +476,7 @@
        int     ret;
  
        if (!info) {
 -              info = ext4_htree_create_dir_info(filp->f_pos);
-+              info = ext4_htree_create_dir_info(inode->i_sb, filp->f_pos);
++              info = ext4_htree_create_dir_info(filp, filp->f_pos);
                if (!info)
                        return -ENOMEM;
                filp->private_data = info;
-@@ -461,8 +475,8 @@ static int ext4_dx_readdir(struct file *
+@@ -461,8 +490,8 @@
                free_rb_tree_fname(&info->root);
                info->curr_node = NULL;
                info->extra_fname = NULL;
 -              info->curr_hash = pos2maj_hash(filp->f_pos);
 -              info->curr_minor_hash = pos2min_hash(filp->f_pos);
-+              info->curr_hash = pos2maj_hash(inode->i_sb, filp->f_pos);
-+              info->curr_minor_hash = pos2min_hash(inode->i_sb, filp->f_pos);
++              info->curr_hash = pos2maj_hash(filp, filp->f_pos);
++              info->curr_minor_hash = pos2min_hash(filp, filp->f_pos);
        }
  
        /*
-Index: linux-2.6.18-194.17.1-ext4/fs/ext4/ext4.h
-===================================================================
---- linux-2.6.18-194.17.1-ext4.orig/fs/ext4/ext4.h     2010-12-03 11:05:04.000000000 +0300
-+++ linux-2.6.18-194.17.1-ext4/fs/ext4/ext4.h  2010-12-16 00:13:32.000000000 +0300
-@@ -741,6 +741,7 @@ struct ext4_inode_info {
- #define EXT4_MOUNT_JOURNAL_CHECKSUM   0x800000 /* Journal checksums */
- #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT       0x1000000 /* Journal Async Commit */
- #define EXT4_MOUNT_I_VERSION            0x2000000 /* i_version support */
-+#define EXT4_MOUNT_64BITHASH          0x4000000 /* export 64-bit name hash */
- #define EXT4_MOUNT_DELALLOC           0x8000000 /* Delalloc support */
- #define EXT4_MOUNT_DATA_ERR_ABORT     0x10000000 /* Abort on file data write */
- #define EXT4_MOUNT_BLOCK_VALIDITY     0x20000000 /* Block validity checking */
-Index: linux-2.6.18-194.17.1-ext4/fs/ext4/super.c
+Index: linux-stage/fs/ext4/ext4.h
 ===================================================================
---- linux-2.6.18-194.17.1-ext4.orig/fs/ext4/super.c    2010-12-02 21:10:39.000000000 +0300
-+++ linux-2.6.18-194.17.1-ext4/fs/ext4/super.c 2010-12-15 23:57:43.000000000 +0300
-@@ -1479,6 +1479,7 @@ enum {
-       Opt_iopen, Opt_noiopen, Opt_iopen_nopriv, Opt_bigendian_extents,
-       Opt_force_over_16tb,
-       Opt_no_mbcache,
-+      Opt_64bithash,
- };
+--- linux-stage.orig/fs/ext4/ext4.h    2011-04-19 01:02:34.000000000 +0800
++++ linux-stage/fs/ext4/ext4.h 2011-04-19 01:02:34.000000000 +0800
+@@ -55,6 +55,14 @@
+ #define ext4_debug(f, a...)   do {} while (0)
+ #endif
  
- static match_table_t tokens = {
-@@ -1552,6 +1553,7 @@ static match_table_t tokens = {
-       {Opt_bigendian_extents, "bigendian_extents"},
-       {Opt_force_over_16tb, "force_over_16tb"},
-       {Opt_no_mbcache, "no_mbcache"},
-+      {Opt_64bithash, "64bithash"},
-       {Opt_err, NULL},
- };
++#ifndef O_32BITHASH
++# define O_32BITHASH  0x10000000
++#endif
++
++#ifndef O_64BITHASH
++# define O_64BITHASH  0x20000000
++#endif
++
+ #define HAVE_DISK_INODE_VERSION
  
-@@ -2004,6 +2006,9 @@ set_qf_format:
-               case Opt_no_mbcache:
-                       set_opt(sbi->s_mount_opt, NO_MBCACHE);
-                       break;
-+              case Opt_64bithash:
-+                      set_opt(sbi->s_mount_opt, 64BITHASH);
-+                      break;
-               default:
-                       ext4_msg(sb, KERN_ERR,
-                              "Unrecognized mount option \"%s\" "
+ /* data type for block offset of block group */