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
1 Index: linux-stage/fs/ext4/dir.c
2 ===================================================================
3 --- linux-stage.orig/fs/ext4/dir.c      2011-04-19 01:02:34.000000000 +0800
4 +++ linux-stage/fs/ext4/dir.c   2011-04-19 01:24:36.000000000 +0800
5 @@ -242,22 +242,50 @@
6         return ret;
7  }
8
9 +static inline int is_32bit_api(void)
10 +{
11 +#ifdef HAVE_IS_COMPAT_TASK
12 +        return is_compat_task();
13 +#else
14 +        return (BITS_PER_LONG == 32);
15 +#endif
16 +}
17 +
18  /*
19   * These functions convert from the major/minor hash to an f_pos
20   * value.
21   *
22 - * Currently we only use major hash numer.  This is unfortunate, but
23 - * on 32-bit machines, the same VFS interface is used for lseek and
24 - * llseek, so if we use the 64 bit offset, then the 32-bit versions of
25 - * lseek/telldir/seekdir will blow out spectacularly, and from within
26 - * the ext2 low-level routine, we don't know if we're being called by
27 - * a 64-bit version of the system call or the 32-bit version of the
28 - * system call.  Worse yet, NFSv2 only allows for a 32-bit readdir
29 - * cookie.  Sigh.
30 + * Up layer (OSD) should specify O_32BITHASH or O_64BITHASH explicitly.
31 + * On the other hand, we allow ldiskfs to be mounted directly on both 32-bit
32 + * and 64-bit nodes, under such case, neither O_32BITHASH nor O_64BITHASH is
33 + * specified.
34   */
35 -#define hash2pos(major, minor) (major >> 1)
36 -#define pos2maj_hash(pos)      ((pos << 1) & 0xffffffff)
37 -#define pos2min_hash(pos)      (0)
38 +static inline loff_t hash2pos(struct file *filp, __u32 major, __u32 minor)
39 +{
40 +       if ((filp->f_flags & O_32BITHASH) ||
41 +           (!(filp->f_flags & O_64BITHASH) && is_32bit_api()))
42 +               return (major >> 1);
43 +       else
44 +               return (((__u64)(major >> 1) << 32) | (__u64)minor);
45 +}
46 +
47 +static inline __u32 pos2maj_hash(struct file *filp, loff_t pos)
48 +{
49 +       if ((filp->f_flags & O_32BITHASH) ||
50 +           (!(filp->f_flags & O_64BITHASH) && is_32bit_api()))
51 +               return ((pos << 1) & 0xffffffff);
52 +       else
53 +               return (((pos >> 32) << 1) & 0xffffffff);
54 +}
55 +
56 +static inline __u32 pos2min_hash(struct file *filp, loff_t pos)
57 +{
58 +       if ((filp->f_flags & O_32BITHASH) ||
59 +           (!(filp->f_flags & O_64BITHASH) && is_32bit_api()))
60 +               return (0);
61 +       else
62 +               return (pos & 0xffffffff);
63 +}
64  
65  /*
66   * This structure holds the nodes of the red-black tree used to store
67 @@ -318,15 +346,16 @@
68  }
69  
70  
71 -static struct dir_private_info *ext4_htree_create_dir_info(loff_t pos)
72 +static struct dir_private_info *
73 +ext4_htree_create_dir_info(struct file *filp, loff_t pos)
74  {
75         struct dir_private_info *p;
76  
77         p = kzalloc(sizeof(struct dir_private_info), GFP_KERNEL);
78         if (!p)
79                 return NULL;
80 -       p->curr_hash = pos2maj_hash(pos);
81 -       p->curr_minor_hash = pos2min_hash(pos);
82 +       p->curr_hash = pos2maj_hash(filp, pos);
83 +       p->curr_minor_hash = pos2min_hash(filp, pos);
84         return p;
85  }
86  
87 @@ -422,7 +451,7 @@
88                        "null fname?!?\n");
89                 return 0;
90         }
91 -       curr_pos = hash2pos(fname->hash, fname->minor_hash);
92 +       curr_pos = hash2pos(filp, fname->hash, fname->minor_hash);
93         while (fname) {
94                 error = filldir(dirent, fname->name,
95                                 fname->name_len, curr_pos,
96 @@ -447,7 +476,7 @@
97         int     ret;
98  
99         if (!info) {
100 -               info = ext4_htree_create_dir_info(filp->f_pos);
101 +               info = ext4_htree_create_dir_info(filp, filp->f_pos);
102                 if (!info)
103                         return -ENOMEM;
104                 filp->private_data = info;
105 @@ -461,8 +490,8 @@
106                 free_rb_tree_fname(&info->root);
107                 info->curr_node = NULL;
108                 info->extra_fname = NULL;
109 -               info->curr_hash = pos2maj_hash(filp->f_pos);
110 -               info->curr_minor_hash = pos2min_hash(filp->f_pos);
111 +               info->curr_hash = pos2maj_hash(filp, filp->f_pos);
112 +               info->curr_minor_hash = pos2min_hash(filp, filp->f_pos);
113         }
114  
115         /*
116 Index: linux-stage/fs/ext4/ext4.h
117 ===================================================================
118 --- linux-stage.orig/fs/ext4/ext4.h     2011-04-19 01:02:34.000000000 +0800
119 +++ linux-stage/fs/ext4/ext4.h  2011-04-19 01:02:34.000000000 +0800
120 @@ -55,6 +55,14 @@
121  #define ext4_debug(f, a...)    do {} while (0)
122  #endif
123  
124 +#ifndef O_32BITHASH
125 +# define O_32BITHASH   0x10000000
126 +#endif
127 +
128 +#ifndef O_64BITHASH
129 +# define O_64BITHASH   0x20000000
130 +#endif
131 +
132  #define HAVE_DISK_INODE_VERSION
133  
134  /* data type for block offset of block group */