diff options
-rw-r--r-- | fs/ext4/dir.c | 16 | ||||
-rw-r--r-- | fs/ext4/ext4.h | 21 | ||||
-rw-r--r-- | fs/ext4/namei.c | 130 |
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 | ||
858 | static 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 | |||
867 | static 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 */ |
1099 | extern int ext4_ext_migrate(struct inode *); | 1081 | extern int ext4_ext_migrate(struct inode *); |
1082 | |||
1100 | /* namei.c */ | 1083 | /* namei.c */ |
1084 | extern unsigned int ext4_rec_len_from_disk(__le16 dlen, unsigned blocksize); | ||
1085 | extern __le16 ext4_rec_len_to_disk(unsigned len, unsigned blocksize); | ||
1101 | extern int ext4_orphan_add(handle_t *, struct inode *); | 1086 | extern int ext4_orphan_add(handle_t *, struct inode *); |
1102 | extern int ext4_orphan_del(handle_t *, struct inode *); | 1087 | extern int ext4_orphan_del(handle_t *, struct inode *); |
1103 | extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, | 1088 | extern 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[]); |
166 | static void dx_sort_map(struct dx_map_entry *map, unsigned count); | 166 | static void dx_sort_map(struct dx_map_entry *map, unsigned count); |
167 | static struct ext4_dir_entry_2 *dx_move_dirents(char *from, char *to, | 167 | static 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); |
169 | static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize); | 169 | static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize); |
170 | static void dx_insert_block(struct dx_frame *frame, | 170 | static 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, | |||
180 | static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, | 180 | static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, |
181 | struct inode *inode); | 181 | struct inode *inode); |
182 | 182 | ||
183 | unsigned 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 | */ |
186 | static inline struct ext4_dir_entry_2 * | 210 | static inline struct ext4_dir_entry_2 * |
187 | ext4_next_entry(struct ext4_dir_entry_2 *p) | 211 | ext4_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 | */ |
1111 | static struct ext4_dir_entry_2 * | 1136 | static struct ext4_dir_entry_2 * |
1112 | dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) | 1137 | dx_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); |