1 Index: linux-stage/fs/ext4/dir.c
2 ===================================================================
3 --- linux-stage.orig/fs/ext4/dir.c 2011-03-31 10:35:49.000000000 +0800
4 +++ linux-stage/fs/ext4/dir.c 2011-04-01 09:33:58.706267179 +0800
7 * These functions convert from the major/minor hash to an f_pos
10 - * Currently we only use major hash numer. This is unfortunate, but
11 - * on 32-bit machines, the same VFS interface is used for lseek and
12 - * llseek, so if we use the 64 bit offset, then the 32-bit versions of
13 - * lseek/telldir/seekdir will blow out spectacularly, and from within
14 - * the ext2 low-level routine, we don't know if we're being called by
15 - * a 64-bit version of the system call or the 32-bit version of the
16 - * system call. Worse yet, NFSv2 only allows for a 32-bit readdir
18 + * Whether 64-bit or 32-bit hash value is exported as file pos is
19 + * controlled by "64bithash" mount option.
21 -#define hash2pos(major, minor) (major >> 1)
22 -#define pos2maj_hash(pos) ((pos << 1) & 0xffffffff)
23 -#define pos2min_hash(pos) (0)
24 +static inline loff_t hash2pos(struct super_block *sb, __u32 major, __u32 minor)
26 + if (test_opt(sb, 64BITHASH))
27 + return (((__u64)(major >> 1) << 32) | (__u64)minor);
29 + return (major >> 1);
32 +static inline __u32 pos2maj_hash(struct super_block *sb, loff_t pos)
34 + if (test_opt(sb, 64BITHASH))
35 + return (((pos >> 32) << 1) & 0xffffffff);
37 + return ((pos << 1) & 0xffffffff);
40 +static inline __u32 pos2min_hash(struct super_block *sb, loff_t pos)
42 + if (test_opt(sb, 64BITHASH))
43 + return (pos & 0xffffffff);
49 * This structure holds the nodes of the red-black tree used to store
54 -static struct dir_private_info *ext4_htree_create_dir_info(loff_t pos)
55 +static struct dir_private_info *ext4_htree_create_dir_info(
56 + struct super_block *sb, loff_t pos)
58 struct dir_private_info *p;
60 p = kzalloc(sizeof(struct dir_private_info), GFP_KERNEL);
63 - p->curr_hash = pos2maj_hash(pos);
64 - p->curr_minor_hash = pos2min_hash(pos);
65 + p->curr_hash = pos2maj_hash(sb, pos);
66 + p->curr_minor_hash = pos2min_hash(sb, pos);
74 - curr_pos = hash2pos(fname->hash, fname->minor_hash);
75 + curr_pos = hash2pos(sb, fname->hash, fname->minor_hash);
77 error = filldir(dirent, fname->name,
78 fname->name_len, curr_pos,
83 - info = ext4_htree_create_dir_info(filp->f_pos);
84 + info = ext4_htree_create_dir_info(inode->i_sb, filp->f_pos);
87 filp->private_data = info;
89 free_rb_tree_fname(&info->root);
90 info->curr_node = NULL;
91 info->extra_fname = NULL;
92 - info->curr_hash = pos2maj_hash(filp->f_pos);
93 - info->curr_minor_hash = pos2min_hash(filp->f_pos);
94 + info->curr_hash = pos2maj_hash(inode->i_sb, filp->f_pos);
95 + info->curr_minor_hash = pos2min_hash(inode->i_sb, filp->f_pos);
99 Index: linux-stage/fs/ext4/ext4.h
100 ===================================================================
101 --- linux-stage.orig/fs/ext4/ext4.h 2011-03-31 10:35:50.000000000 +0800
102 +++ linux-stage/fs/ext4/ext4.h 2011-04-01 09:33:58.740267284 +0800
104 #define EXT4_MOUNT_JOURNAL_CHECKSUM 0x800000 /* Journal checksums */
105 #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */
106 #define EXT4_MOUNT_I_VERSION 0x2000000 /* i_version support */
107 +#define EXT4_MOUNT_64BITHASH 0x4000000 /* export 64-bit name hash */
108 #define EXT4_MOUNT_DELALLOC 0x8000000 /* Delalloc support */
109 #define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000 /* Abort on file data write */
110 #define EXT4_MOUNT_BLOCK_VALIDITY 0x20000000 /* Block validity checking */
111 Index: linux-stage/fs/ext4/super.c
112 ===================================================================
113 --- linux-stage.orig/fs/ext4/super.c 2011-03-31 10:35:50.000000000 +0800
114 +++ linux-stage/fs/ext4/super.c 2011-04-01 09:35:00.251453404 +0800
115 @@ -1540,7 +1540,7 @@
116 Opt_inode_readahead_blks, Opt_journal_ioprio,
117 Opt_discard, Opt_nodiscard,
118 Opt_mballoc, Opt_bigendian_extents, Opt_force_over_16tb,
120 + Opt_no_mbcache, Opt_64bithash,
121 Opt_extents, Opt_noextents,
124 @@ -1614,6 +1614,7 @@
125 {Opt_discard, "discard"},
126 {Opt_nodiscard, "nodiscard"},
127 {Opt_no_mbcache, "no_mbcache"},
128 + {Opt_64bithash, "64bithash"},
129 {Opt_extents, "extents"},
130 {Opt_noextents, "noextents"},
132 @@ -2092,6 +2093,9 @@
134 set_opt(sbi->s_mount_opt, NO_MBCACHE);
136 + case Opt_64bithash:
137 + set_opt(sbi->s_mount_opt, 64BITHASH);
140 ext4_msg(sb, KERN_ERR,
141 "Unrecognized mount option \"%s\" "