aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorWei Yongjun <yjwei@cn.fujitsu.com>2009-02-14 23:01:36 -0500
committerTheodore Ts'o <tytso@mit.edu>2009-02-14 23:01:36 -0500
commit3d0518f4758eca4339e75e5b9dbb7e06a5ce08b4 (patch)
tree30a45a1c82d830646a69591c470680573e14de07 /fs
parent8bad4597c2d71365adfa846ea1ca6cf99161a455 (diff)
ext4: New rec_len encoding for very large blocksizes
The rec_len field in the directory entry is 16 bits, so to encode blocksizes larger than 64k becomes problematic. This patch allows us to supprot block sizes up to 256k, by using the low 2 bits to extend the range of rec_len to 2**18-1 (since valid rec_len sizes must be a multiple of 4). We use the convention that a rec_len of 0 or 65535 means the filesystem block size, for compatibility with older kernels. It's unlikely we'll see VM pages of up to 256k, but at some point we might find that the Linux VM has been enhanced to support filesystem block sizes > than the VM page size, at which point it might be useful for some applications to allow very large filesystem block sizes. Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/dir.c16
-rw-r--r--fs/ext4/ext4.h21
-rw-r--r--fs/ext4/namei.c130
3 files changed, 98 insertions, 69 deletions
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index 2df2e40b01af..b64789929a65 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -67,7 +67,8 @@ int ext4_check_dir_entry(const char *function, struct inode *dir,
67 unsigned int offset) 67 unsigned int offset)
68{ 68{
69 const char *error_msg = NULL; 69 const char *error_msg = NULL;
70 const int rlen = ext4_rec_len_from_disk(de->rec_len); 70 const int rlen = ext4_rec_len_from_disk(de->rec_len,
71 dir->i_sb->s_blocksize);
71 72
72 if (rlen < EXT4_DIR_REC_LEN(1)) 73 if (rlen < EXT4_DIR_REC_LEN(1))
73 error_msg = "rec_len is smaller than minimal"; 74 error_msg = "rec_len is smaller than minimal";
@@ -178,10 +179,11 @@ revalidate:
178 * least that it is non-zero. A 179 * least that it is non-zero. A
179 * failure will be detected in the 180 * failure will be detected in the
180 * dirent test below. */ 181 * dirent test below. */
181 if (ext4_rec_len_from_disk(de->rec_len) 182 if (ext4_rec_len_from_disk(de->rec_len,
182 < EXT4_DIR_REC_LEN(1)) 183 sb->s_blocksize) < EXT4_DIR_REC_LEN(1))
183 break; 184 break;
184 i += ext4_rec_len_from_disk(de->rec_len); 185 i += ext4_rec_len_from_disk(de->rec_len,
186 sb->s_blocksize);
185 } 187 }
186 offset = i; 188 offset = i;
187 filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) 189 filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
@@ -203,7 +205,8 @@ revalidate:
203 ret = stored; 205 ret = stored;
204 goto out; 206 goto out;
205 } 207 }
206 offset += ext4_rec_len_from_disk(de->rec_len); 208 offset += ext4_rec_len_from_disk(de->rec_len,
209 sb->s_blocksize);
207 if (le32_to_cpu(de->inode)) { 210 if (le32_to_cpu(de->inode)) {
208 /* We might block in the next section 211 /* We might block in the next section
209 * if the data destination is 212 * if the data destination is
@@ -225,7 +228,8 @@ revalidate:
225 goto revalidate; 228 goto revalidate;
226 stored++; 229 stored++;
227 } 230 }
228 filp->f_pos += ext4_rec_len_from_disk(de->rec_len); 231 filp->f_pos += ext4_rec_len_from_disk(de->rec_len,
232 sb->s_blocksize);
229 } 233 }
230 offset = 0; 234 offset = 0;
231 brelse(bh); 235 brelse(bh);
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 0db01421da3e..d5193b55ca94 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -855,24 +855,6 @@ struct ext4_dir_entry_2 {
855 ~EXT4_DIR_ROUND) 855 ~EXT4_DIR_ROUND)
856#define EXT4_MAX_REC_LEN ((1<<16)-1) 856#define EXT4_MAX_REC_LEN ((1<<16)-1)
857 857
858static inline unsigned ext4_rec_len_from_disk(__le16 dlen)
859{
860 unsigned len = le16_to_cpu(dlen);
861
862 if (len == EXT4_MAX_REC_LEN || len == 0)
863 return 1 << 16;
864 return len;
865}
866
867static inline __le16 ext4_rec_len_to_disk(unsigned len)
868{
869 if (len == (1 << 16))
870 return cpu_to_le16(EXT4_MAX_REC_LEN);
871 else if (len > (1 << 16))
872 BUG();
873 return cpu_to_le16(len);
874}
875
876/* 858/*
877 * Hash Tree Directory indexing 859 * Hash Tree Directory indexing
878 * (c) Daniel Phillips, 2001 860 * (c) Daniel Phillips, 2001
@@ -1097,7 +1079,10 @@ extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long);
1097 1079
1098/* migrate.c */ 1080/* migrate.c */
1099extern int ext4_ext_migrate(struct inode *); 1081extern int ext4_ext_migrate(struct inode *);
1082
1100/* namei.c */ 1083/* namei.c */
1084extern unsigned int ext4_rec_len_from_disk(__le16 dlen, unsigned blocksize);
1085extern __le16 ext4_rec_len_to_disk(unsigned len, unsigned blocksize);
1101extern int ext4_orphan_add(handle_t *, struct inode *); 1086extern int ext4_orphan_add(handle_t *, struct inode *);
1102extern int ext4_orphan_del(handle_t *, struct inode *); 1087extern int ext4_orphan_del(handle_t *, struct inode *);
1103extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, 1088extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 04824958cba5..a5ba1a858094 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -165,7 +165,7 @@ static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize,
165 struct dx_hash_info *hinfo, struct dx_map_entry map[]); 165 struct dx_hash_info *hinfo, struct dx_map_entry map[]);
166static void dx_sort_map(struct dx_map_entry *map, unsigned count); 166static void dx_sort_map(struct dx_map_entry *map, unsigned count);
167static struct ext4_dir_entry_2 *dx_move_dirents(char *from, char *to, 167static struct ext4_dir_entry_2 *dx_move_dirents(char *from, char *to,
168 struct dx_map_entry *offsets, int count); 168 struct dx_map_entry *offsets, int count, unsigned blocksize);
169static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize); 169static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize);
170static void dx_insert_block(struct dx_frame *frame, 170static void dx_insert_block(struct dx_frame *frame,
171 u32 hash, ext4_lblk_t block); 171 u32 hash, ext4_lblk_t block);
@@ -180,14 +180,38 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
180static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, 180static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
181 struct inode *inode); 181 struct inode *inode);
182 182
183unsigned int ext4_rec_len_from_disk(__le16 dlen, unsigned blocksize)
184{
185 unsigned len = le16_to_cpu(dlen);
186
187 if (len == EXT4_MAX_REC_LEN || len == 0)
188 return blocksize;
189 return (len & 65532) | ((len & 3) << 16);
190}
191
192__le16 ext4_rec_len_to_disk(unsigned len, unsigned blocksize)
193{
194 if ((len > blocksize) || (blocksize > (1 << 18)) || (len & 3))
195 BUG();
196 if (len < 65536)
197 return cpu_to_le16(len);
198 if (len == blocksize) {
199 if (blocksize == 65536)
200 return cpu_to_le16(EXT4_MAX_REC_LEN);
201 else
202 return cpu_to_le16(0);
203 }
204 return cpu_to_le16((len & 65532) | ((len >> 16) & 3));
205}
206
183/* 207/*
184 * p is at least 6 bytes before the end of page 208 * p is at least 6 bytes before the end of page
185 */ 209 */
186static inline struct ext4_dir_entry_2 * 210static inline struct ext4_dir_entry_2 *
187ext4_next_entry(struct ext4_dir_entry_2 *p) 211ext4_next_entry(struct ext4_dir_entry_2 *p, unsigned long blocksize)
188{ 212{
189 return (struct ext4_dir_entry_2 *)((char *)p + 213 return (struct ext4_dir_entry_2 *)((char *)p +
190 ext4_rec_len_from_disk(p->rec_len)); 214 ext4_rec_len_from_disk(p->rec_len, blocksize));
191} 215}
192 216
193/* 217/*
@@ -294,7 +318,7 @@ static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext4_dir_ent
294 space += EXT4_DIR_REC_LEN(de->name_len); 318 space += EXT4_DIR_REC_LEN(de->name_len);
295 names++; 319 names++;
296 } 320 }
297 de = ext4_next_entry(de); 321 de = ext4_next_entry(de, size);
298 } 322 }
299 printk("(%i)\n", names); 323 printk("(%i)\n", names);
300 return (struct stats) { names, space, 1 }; 324 return (struct stats) { names, space, 1 };
@@ -585,7 +609,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
585 top = (struct ext4_dir_entry_2 *) ((char *) de + 609 top = (struct ext4_dir_entry_2 *) ((char *) de +
586 dir->i_sb->s_blocksize - 610 dir->i_sb->s_blocksize -
587 EXT4_DIR_REC_LEN(0)); 611 EXT4_DIR_REC_LEN(0));
588 for (; de < top; de = ext4_next_entry(de)) { 612 for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) {
589 if (!ext4_check_dir_entry("htree_dirblock_to_tree", dir, de, bh, 613 if (!ext4_check_dir_entry("htree_dirblock_to_tree", dir, de, bh,
590 (block<<EXT4_BLOCK_SIZE_BITS(dir->i_sb)) 614 (block<<EXT4_BLOCK_SIZE_BITS(dir->i_sb))
591 +((char *)de - bh->b_data))) { 615 +((char *)de - bh->b_data))) {
@@ -663,7 +687,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
663 } 687 }
664 if (start_hash < 2 || (start_hash ==2 && start_minor_hash==0)) { 688 if (start_hash < 2 || (start_hash ==2 && start_minor_hash==0)) {
665 de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data; 689 de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data;
666 de = ext4_next_entry(de); 690 de = ext4_next_entry(de, dir->i_sb->s_blocksize);
667 if ((err = ext4_htree_store_dirent(dir_file, 2, 0, de)) != 0) 691 if ((err = ext4_htree_store_dirent(dir_file, 2, 0, de)) != 0)
668 goto errout; 692 goto errout;
669 count++; 693 count++;
@@ -732,7 +756,7 @@ static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize,
732 cond_resched(); 756 cond_resched();
733 } 757 }
734 /* XXX: do we need to check rec_len == 0 case? -Chris */ 758 /* XXX: do we need to check rec_len == 0 case? -Chris */
735 de = ext4_next_entry(de); 759 de = ext4_next_entry(de, blocksize);
736 } 760 }
737 return count; 761 return count;
738} 762}
@@ -832,7 +856,8 @@ static inline int search_dirblock(struct buffer_head *bh,
832 return 1; 856 return 1;
833 } 857 }
834 /* prevent looping on a bad block */ 858 /* prevent looping on a bad block */
835 de_len = ext4_rec_len_from_disk(de->rec_len); 859 de_len = ext4_rec_len_from_disk(de->rec_len,
860 dir->i_sb->s_blocksize);
836 if (de_len <= 0) 861 if (de_len <= 0)
837 return -1; 862 return -1;
838 offset += de_len; 863 offset += de_len;
@@ -996,7 +1021,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
996 de = (struct ext4_dir_entry_2 *) bh->b_data; 1021 de = (struct ext4_dir_entry_2 *) bh->b_data;
997 top = (struct ext4_dir_entry_2 *) ((char *) de + sb->s_blocksize - 1022 top = (struct ext4_dir_entry_2 *) ((char *) de + sb->s_blocksize -
998 EXT4_DIR_REC_LEN(0)); 1023 EXT4_DIR_REC_LEN(0));
999 for (; de < top; de = ext4_next_entry(de)) { 1024 for (; de < top; de = ext4_next_entry(de, sb->s_blocksize)) {
1000 int off = (block << EXT4_BLOCK_SIZE_BITS(sb)) 1025 int off = (block << EXT4_BLOCK_SIZE_BITS(sb))
1001 + ((char *) de - bh->b_data); 1026 + ((char *) de - bh->b_data);
1002 1027
@@ -1109,7 +1134,8 @@ static inline void ext4_set_de_type(struct super_block *sb,
1109 * Returns pointer to last entry moved. 1134 * Returns pointer to last entry moved.
1110 */ 1135 */
1111static struct ext4_dir_entry_2 * 1136static struct ext4_dir_entry_2 *
1112dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) 1137dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count,
1138 unsigned blocksize)
1113{ 1139{
1114 unsigned rec_len = 0; 1140 unsigned rec_len = 0;
1115 1141
@@ -1118,7 +1144,7 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
1118 rec_len = EXT4_DIR_REC_LEN(de->name_len); 1144 rec_len = EXT4_DIR_REC_LEN(de->name_len);
1119 memcpy (to, de, rec_len); 1145 memcpy (to, de, rec_len);
1120 ((struct ext4_dir_entry_2 *) to)->rec_len = 1146 ((struct ext4_dir_entry_2 *) to)->rec_len =
1121 ext4_rec_len_to_disk(rec_len); 1147 ext4_rec_len_to_disk(rec_len, blocksize);
1122 de->inode = 0; 1148 de->inode = 0;
1123 map++; 1149 map++;
1124 to += rec_len; 1150 to += rec_len;
@@ -1137,12 +1163,12 @@ static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize)
1137 1163
1138 prev = to = de; 1164 prev = to = de;
1139 while ((char*)de < base + blocksize) { 1165 while ((char*)de < base + blocksize) {
1140 next = ext4_next_entry(de); 1166 next = ext4_next_entry(de, blocksize);
1141 if (de->inode && de->name_len) { 1167 if (de->inode && de->name_len) {
1142 rec_len = EXT4_DIR_REC_LEN(de->name_len); 1168 rec_len = EXT4_DIR_REC_LEN(de->name_len);
1143 if (de > to) 1169 if (de > to)
1144 memmove(to, de, rec_len); 1170 memmove(to, de, rec_len);
1145 to->rec_len = ext4_rec_len_to_disk(rec_len); 1171 to->rec_len = ext4_rec_len_to_disk(rec_len, blocksize);
1146 prev = to; 1172 prev = to;
1147 to = (struct ext4_dir_entry_2 *) (((char *) to) + rec_len); 1173 to = (struct ext4_dir_entry_2 *) (((char *) to) + rec_len);
1148 } 1174 }
@@ -1215,10 +1241,12 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
1215 hash2, split, count-split)); 1241 hash2, split, count-split));
1216 1242
1217 /* Fancy dance to stay within two buffers */ 1243 /* Fancy dance to stay within two buffers */
1218 de2 = dx_move_dirents(data1, data2, map + split, count - split); 1244 de2 = dx_move_dirents(data1, data2, map + split, count - split, blocksize);
1219 de = dx_pack_dirents(data1, blocksize); 1245 de = dx_pack_dirents(data1, blocksize);
1220 de->rec_len = ext4_rec_len_to_disk(data1 + blocksize - (char *) de); 1246 de->rec_len = ext4_rec_len_to_disk(data1 + blocksize - (char *) de,
1221 de2->rec_len = ext4_rec_len_to_disk(data2 + blocksize - (char *) de2); 1247 blocksize);
1248 de2->rec_len = ext4_rec_len_to_disk(data2 + blocksize - (char *) de2,
1249 blocksize);
1222 dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data1, blocksize, 1)); 1250 dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data1, blocksize, 1));
1223 dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1)); 1251 dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1));
1224 1252
@@ -1268,6 +1296,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
1268 const char *name = dentry->d_name.name; 1296 const char *name = dentry->d_name.name;
1269 int namelen = dentry->d_name.len; 1297 int namelen = dentry->d_name.len;
1270 unsigned int offset = 0; 1298 unsigned int offset = 0;
1299 unsigned int blocksize = dir->i_sb->s_blocksize;
1271 unsigned short reclen; 1300 unsigned short reclen;
1272 int nlen, rlen, err; 1301 int nlen, rlen, err;
1273 char *top; 1302 char *top;
@@ -1275,7 +1304,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
1275 reclen = EXT4_DIR_REC_LEN(namelen); 1304 reclen = EXT4_DIR_REC_LEN(namelen);
1276 if (!de) { 1305 if (!de) {
1277 de = (struct ext4_dir_entry_2 *)bh->b_data; 1306 de = (struct ext4_dir_entry_2 *)bh->b_data;
1278 top = bh->b_data + dir->i_sb->s_blocksize - reclen; 1307 top = bh->b_data + blocksize - reclen;
1279 while ((char *) de <= top) { 1308 while ((char *) de <= top) {
1280 if (!ext4_check_dir_entry("ext4_add_entry", dir, de, 1309 if (!ext4_check_dir_entry("ext4_add_entry", dir, de,
1281 bh, offset)) { 1310 bh, offset)) {
@@ -1287,7 +1316,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
1287 return -EEXIST; 1316 return -EEXIST;
1288 } 1317 }
1289 nlen = EXT4_DIR_REC_LEN(de->name_len); 1318 nlen = EXT4_DIR_REC_LEN(de->name_len);
1290 rlen = ext4_rec_len_from_disk(de->rec_len); 1319 rlen = ext4_rec_len_from_disk(de->rec_len, blocksize);
1291 if ((de->inode? rlen - nlen: rlen) >= reclen) 1320 if ((de->inode? rlen - nlen: rlen) >= reclen)
1292 break; 1321 break;
1293 de = (struct ext4_dir_entry_2 *)((char *)de + rlen); 1322 de = (struct ext4_dir_entry_2 *)((char *)de + rlen);
@@ -1306,11 +1335,11 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
1306 1335
1307 /* By now the buffer is marked for journaling */ 1336 /* By now the buffer is marked for journaling */
1308 nlen = EXT4_DIR_REC_LEN(de->name_len); 1337 nlen = EXT4_DIR_REC_LEN(de->name_len);
1309 rlen = ext4_rec_len_from_disk(de->rec_len); 1338 rlen = ext4_rec_len_from_disk(de->rec_len, blocksize);
1310 if (de->inode) { 1339 if (de->inode) {
1311 struct ext4_dir_entry_2 *de1 = (struct ext4_dir_entry_2 *)((char *)de + nlen); 1340 struct ext4_dir_entry_2 *de1 = (struct ext4_dir_entry_2 *)((char *)de + nlen);
1312 de1->rec_len = ext4_rec_len_to_disk(rlen - nlen); 1341 de1->rec_len = ext4_rec_len_to_disk(rlen - nlen, blocksize);
1313 de->rec_len = ext4_rec_len_to_disk(nlen); 1342 de->rec_len = ext4_rec_len_to_disk(nlen, blocksize);
1314 de = de1; 1343 de = de1;
1315 } 1344 }
1316 de->file_type = EXT4_FT_UNKNOWN; 1345 de->file_type = EXT4_FT_UNKNOWN;
@@ -1380,7 +1409,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
1380 /* The 0th block becomes the root, move the dirents out */ 1409 /* The 0th block becomes the root, move the dirents out */
1381 fde = &root->dotdot; 1410 fde = &root->dotdot;
1382 de = (struct ext4_dir_entry_2 *)((char *)fde + 1411 de = (struct ext4_dir_entry_2 *)((char *)fde +
1383 ext4_rec_len_from_disk(fde->rec_len)); 1412 ext4_rec_len_from_disk(fde->rec_len, blocksize));
1384 if ((char *) de >= (((char *) root) + blocksize)) { 1413 if ((char *) de >= (((char *) root) + blocksize)) {
1385 ext4_error(dir->i_sb, __func__, 1414 ext4_error(dir->i_sb, __func__,
1386 "invalid rec_len for '..' in inode %lu", 1415 "invalid rec_len for '..' in inode %lu",
@@ -1402,12 +1431,14 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
1402 memcpy (data1, de, len); 1431 memcpy (data1, de, len);
1403 de = (struct ext4_dir_entry_2 *) data1; 1432 de = (struct ext4_dir_entry_2 *) data1;
1404 top = data1 + len; 1433 top = data1 + len;
1405 while ((char *)(de2 = ext4_next_entry(de)) < top) 1434 while ((char *)(de2 = ext4_next_entry(de, blocksize)) < top)
1406 de = de2; 1435 de = de2;
1407 de->rec_len = ext4_rec_len_to_disk(data1 + blocksize - (char *) de); 1436 de->rec_len = ext4_rec_len_to_disk(data1 + blocksize - (char *) de,
1437 blocksize);
1408 /* Initialize the root; the dot dirents already exist */ 1438 /* Initialize the root; the dot dirents already exist */
1409 de = (struct ext4_dir_entry_2 *) (&root->dotdot); 1439 de = (struct ext4_dir_entry_2 *) (&root->dotdot);
1410 de->rec_len = ext4_rec_len_to_disk(blocksize - EXT4_DIR_REC_LEN(2)); 1440 de->rec_len = ext4_rec_len_to_disk(blocksize - EXT4_DIR_REC_LEN(2),
1441 blocksize);
1411 memset (&root->info, 0, sizeof(root->info)); 1442 memset (&root->info, 0, sizeof(root->info));
1412 root->info.info_length = sizeof(root->info); 1443 root->info.info_length = sizeof(root->info);
1413 root->info.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version; 1444 root->info.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version;
@@ -1488,7 +1519,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
1488 return retval; 1519 return retval;
1489 de = (struct ext4_dir_entry_2 *) bh->b_data; 1520 de = (struct ext4_dir_entry_2 *) bh->b_data;
1490 de->inode = 0; 1521 de->inode = 0;
1491 de->rec_len = ext4_rec_len_to_disk(blocksize); 1522 de->rec_len = ext4_rec_len_to_disk(blocksize, blocksize);
1492 return add_dirent_to_buf(handle, dentry, inode, de, bh); 1523 return add_dirent_to_buf(handle, dentry, inode, de, bh);
1493} 1524}
1494 1525
@@ -1551,7 +1582,8 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
1551 goto cleanup; 1582 goto cleanup;
1552 node2 = (struct dx_node *)(bh2->b_data); 1583 node2 = (struct dx_node *)(bh2->b_data);
1553 entries2 = node2->entries; 1584 entries2 = node2->entries;
1554 node2->fake.rec_len = ext4_rec_len_to_disk(sb->s_blocksize); 1585 node2->fake.rec_len = ext4_rec_len_to_disk(sb->s_blocksize,
1586 sb->s_blocksize);
1555 node2->fake.inode = 0; 1587 node2->fake.inode = 0;
1556 BUFFER_TRACE(frame->bh, "get_write_access"); 1588 BUFFER_TRACE(frame->bh, "get_write_access");
1557 err = ext4_journal_get_write_access(handle, frame->bh); 1589 err = ext4_journal_get_write_access(handle, frame->bh);
@@ -1639,6 +1671,7 @@ static int ext4_delete_entry(handle_t *handle,
1639 struct buffer_head *bh) 1671 struct buffer_head *bh)
1640{ 1672{
1641 struct ext4_dir_entry_2 *de, *pde; 1673 struct ext4_dir_entry_2 *de, *pde;
1674 unsigned int blocksize = dir->i_sb->s_blocksize;
1642 int i; 1675 int i;
1643 1676
1644 i = 0; 1677 i = 0;
@@ -1652,8 +1685,11 @@ static int ext4_delete_entry(handle_t *handle,
1652 ext4_journal_get_write_access(handle, bh); 1685 ext4_journal_get_write_access(handle, bh);
1653 if (pde) 1686 if (pde)
1654 pde->rec_len = ext4_rec_len_to_disk( 1687 pde->rec_len = ext4_rec_len_to_disk(
1655 ext4_rec_len_from_disk(pde->rec_len) + 1688 ext4_rec_len_from_disk(pde->rec_len,
1656 ext4_rec_len_from_disk(de->rec_len)); 1689 blocksize) +
1690 ext4_rec_len_from_disk(de->rec_len,
1691 blocksize),
1692 blocksize);
1657 else 1693 else
1658 de->inode = 0; 1694 de->inode = 0;
1659 dir->i_version++; 1695 dir->i_version++;
@@ -1661,9 +1697,9 @@ static int ext4_delete_entry(handle_t *handle,
1661 ext4_handle_dirty_metadata(handle, dir, bh); 1697 ext4_handle_dirty_metadata(handle, dir, bh);
1662 return 0; 1698 return 0;
1663 } 1699 }
1664 i += ext4_rec_len_from_disk(de->rec_len); 1700 i += ext4_rec_len_from_disk(de->rec_len, blocksize);
1665 pde = de; 1701 pde = de;
1666 de = ext4_next_entry(de); 1702 de = ext4_next_entry(de, blocksize);
1667 } 1703 }
1668 return -ENOENT; 1704 return -ENOENT;
1669} 1705}
@@ -1793,6 +1829,7 @@ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1793 struct inode *inode; 1829 struct inode *inode;
1794 struct buffer_head *dir_block; 1830 struct buffer_head *dir_block;
1795 struct ext4_dir_entry_2 *de; 1831 struct ext4_dir_entry_2 *de;
1832 unsigned int blocksize = dir->i_sb->s_blocksize;
1796 int err, retries = 0; 1833 int err, retries = 0;
1797 1834
1798 if (EXT4_DIR_LINK_MAX(dir)) 1835 if (EXT4_DIR_LINK_MAX(dir))
@@ -1824,13 +1861,14 @@ retry:
1824 de = (struct ext4_dir_entry_2 *) dir_block->b_data; 1861 de = (struct ext4_dir_entry_2 *) dir_block->b_data;
1825 de->inode = cpu_to_le32(inode->i_ino); 1862 de->inode = cpu_to_le32(inode->i_ino);
1826 de->name_len = 1; 1863 de->name_len = 1;
1827 de->rec_len = ext4_rec_len_to_disk(EXT4_DIR_REC_LEN(de->name_len)); 1864 de->rec_len = ext4_rec_len_to_disk(EXT4_DIR_REC_LEN(de->name_len),
1865 blocksize);
1828 strcpy(de->name, "."); 1866 strcpy(de->name, ".");
1829 ext4_set_de_type(dir->i_sb, de, S_IFDIR); 1867 ext4_set_de_type(dir->i_sb, de, S_IFDIR);
1830 de = ext4_next_entry(de); 1868 de = ext4_next_entry(de, blocksize);
1831 de->inode = cpu_to_le32(dir->i_ino); 1869 de->inode = cpu_to_le32(dir->i_ino);
1832 de->rec_len = ext4_rec_len_to_disk(inode->i_sb->s_blocksize - 1870 de->rec_len = ext4_rec_len_to_disk(blocksize - EXT4_DIR_REC_LEN(1),
1833 EXT4_DIR_REC_LEN(1)); 1871 blocksize);
1834 de->name_len = 2; 1872 de->name_len = 2;
1835 strcpy(de->name, ".."); 1873 strcpy(de->name, "..");
1836 ext4_set_de_type(dir->i_sb, de, S_IFDIR); 1874 ext4_set_de_type(dir->i_sb, de, S_IFDIR);
@@ -1885,7 +1923,7 @@ static int empty_dir(struct inode *inode)
1885 return 1; 1923 return 1;
1886 } 1924 }
1887 de = (struct ext4_dir_entry_2 *) bh->b_data; 1925 de = (struct ext4_dir_entry_2 *) bh->b_data;
1888 de1 = ext4_next_entry(de); 1926 de1 = ext4_next_entry(de, sb->s_blocksize);
1889 if (le32_to_cpu(de->inode) != inode->i_ino || 1927 if (le32_to_cpu(de->inode) != inode->i_ino ||
1890 !le32_to_cpu(de1->inode) || 1928 !le32_to_cpu(de1->inode) ||
1891 strcmp(".", de->name) || 1929 strcmp(".", de->name) ||
@@ -1896,9 +1934,9 @@ static int empty_dir(struct inode *inode)
1896 brelse(bh); 1934 brelse(bh);
1897 return 1; 1935 return 1;
1898 } 1936 }
1899 offset = ext4_rec_len_from_disk(de->rec_len) + 1937 offset = ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize) +
1900 ext4_rec_len_from_disk(de1->rec_len); 1938 ext4_rec_len_from_disk(de1->rec_len, sb->s_blocksize);
1901 de = ext4_next_entry(de1); 1939 de = ext4_next_entry(de1, sb->s_blocksize);
1902 while (offset < inode->i_size) { 1940 while (offset < inode->i_size) {
1903 if (!bh || 1941 if (!bh ||
1904 (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { 1942 (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
@@ -1927,8 +1965,8 @@ static int empty_dir(struct inode *inode)
1927 brelse(bh); 1965 brelse(bh);
1928 return 0; 1966 return 0;
1929 } 1967 }
1930 offset += ext4_rec_len_from_disk(de->rec_len); 1968 offset += ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize);
1931 de = ext4_next_entry(de); 1969 de = ext4_next_entry(de, sb->s_blocksize);
1932 } 1970 }
1933 brelse(bh); 1971 brelse(bh);
1934 return 1; 1972 return 1;
@@ -2297,8 +2335,8 @@ retry:
2297 return err; 2335 return err;
2298} 2336}
2299 2337
2300#define PARENT_INO(buffer) \ 2338#define PARENT_INO(buffer, size) \
2301 (ext4_next_entry((struct ext4_dir_entry_2 *)(buffer))->inode) 2339 (ext4_next_entry((struct ext4_dir_entry_2 *)(buffer), size)->inode)
2302 2340
2303/* 2341/*
2304 * Anybody can rename anything with this: the permission checks are left to the 2342 * Anybody can rename anything with this: the permission checks are left to the
@@ -2358,7 +2396,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
2358 dir_bh = ext4_bread(handle, old_inode, 0, 0, &retval); 2396 dir_bh = ext4_bread(handle, old_inode, 0, 0, &retval);
2359 if (!dir_bh) 2397 if (!dir_bh)
2360 goto end_rename; 2398 goto end_rename;
2361 if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino) 2399 if (le32_to_cpu(PARENT_INO(dir_bh->b_data,
2400 old_dir->i_sb->s_blocksize)) != old_dir->i_ino)
2362 goto end_rename; 2401 goto end_rename;
2363 retval = -EMLINK; 2402 retval = -EMLINK;
2364 if (!new_inode && new_dir != old_dir && 2403 if (!new_inode && new_dir != old_dir &&
@@ -2430,7 +2469,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
2430 if (dir_bh) { 2469 if (dir_bh) {
2431 BUFFER_TRACE(dir_bh, "get_write_access"); 2470 BUFFER_TRACE(dir_bh, "get_write_access");
2432 ext4_journal_get_write_access(handle, dir_bh); 2471 ext4_journal_get_write_access(handle, dir_bh);
2433 PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino); 2472 PARENT_INO(dir_bh->b_data, new_dir->i_sb->s_blocksize) =
2473 cpu_to_le32(new_dir->i_ino);
2434 BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata"); 2474 BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata");
2435 ext4_handle_dirty_metadata(handle, old_dir, dir_bh); 2475 ext4_handle_dirty_metadata(handle, old_dir, dir_bh);
2436 ext4_dec_count(handle, old_dir); 2476 ext4_dec_count(handle, old_dir);