diff options
Diffstat (limited to 'fs/ext4/namei.c')
-rw-r--r-- | fs/ext4/namei.c | 164 |
1 files changed, 108 insertions, 56 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 83410244d3ee..22098e1cd085 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -161,12 +161,12 @@ static struct dx_frame *dx_probe(const struct qstr *d_name, | |||
161 | struct dx_frame *frame, | 161 | struct dx_frame *frame, |
162 | int *err); | 162 | int *err); |
163 | static void dx_release(struct dx_frame *frames); | 163 | static void dx_release(struct dx_frame *frames); |
164 | static int dx_make_map(struct ext4_dir_entry_2 *de, int size, | 164 | 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, int size); | 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); |
172 | static int ext4_htree_next_block(struct inode *dir, __u32 hash, | 172 | static int ext4_htree_next_block(struct inode *dir, __u32 hash, |
@@ -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++; |
@@ -713,15 +737,15 @@ errout: | |||
713 | * Create map of hash values, offsets, and sizes, stored at end of block. | 737 | * Create map of hash values, offsets, and sizes, stored at end of block. |
714 | * Returns number of entries mapped. | 738 | * Returns number of entries mapped. |
715 | */ | 739 | */ |
716 | static int dx_make_map (struct ext4_dir_entry_2 *de, int size, | 740 | static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize, |
717 | struct dx_hash_info *hinfo, struct dx_map_entry *map_tail) | 741 | struct dx_hash_info *hinfo, |
742 | struct dx_map_entry *map_tail) | ||
718 | { | 743 | { |
719 | int count = 0; | 744 | int count = 0; |
720 | char *base = (char *) de; | 745 | char *base = (char *) de; |
721 | struct dx_hash_info h = *hinfo; | 746 | struct dx_hash_info h = *hinfo; |
722 | 747 | ||
723 | while ((char *) de < base + size) | 748 | while ((char *) de < base + blocksize) { |
724 | { | ||
725 | if (de->name_len && de->inode) { | 749 | if (de->name_len && de->inode) { |
726 | ext4fs_dirhash(de->name, de->name_len, &h); | 750 | ext4fs_dirhash(de->name, de->name_len, &h); |
727 | map_tail--; | 751 | map_tail--; |
@@ -732,7 +756,7 @@ static int dx_make_map (struct ext4_dir_entry_2 *de, int size, | |||
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 | ||
@@ -1052,8 +1077,16 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, stru | |||
1052 | return ERR_PTR(-EIO); | 1077 | return ERR_PTR(-EIO); |
1053 | } | 1078 | } |
1054 | inode = ext4_iget(dir->i_sb, ino); | 1079 | inode = ext4_iget(dir->i_sb, ino); |
1055 | if (IS_ERR(inode)) | 1080 | if (unlikely(IS_ERR(inode))) { |
1056 | return ERR_CAST(inode); | 1081 | if (PTR_ERR(inode) == -ESTALE) { |
1082 | ext4_error(dir->i_sb, __func__, | ||
1083 | "deleted inode referenced: %u", | ||
1084 | ino); | ||
1085 | return ERR_PTR(-EIO); | ||
1086 | } else { | ||
1087 | return ERR_CAST(inode); | ||
1088 | } | ||
1089 | } | ||
1057 | } | 1090 | } |
1058 | return d_splice_alias(inode, dentry); | 1091 | return d_splice_alias(inode, dentry); |
1059 | } | 1092 | } |
@@ -1109,7 +1142,8 @@ static inline void ext4_set_de_type(struct super_block *sb, | |||
1109 | * Returns pointer to last entry moved. | 1142 | * Returns pointer to last entry moved. |
1110 | */ | 1143 | */ |
1111 | static struct ext4_dir_entry_2 * | 1144 | static struct ext4_dir_entry_2 * |
1112 | dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) | 1145 | dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count, |
1146 | unsigned blocksize) | ||
1113 | { | 1147 | { |
1114 | unsigned rec_len = 0; | 1148 | unsigned rec_len = 0; |
1115 | 1149 | ||
@@ -1118,7 +1152,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); | 1152 | rec_len = EXT4_DIR_REC_LEN(de->name_len); |
1119 | memcpy (to, de, rec_len); | 1153 | memcpy (to, de, rec_len); |
1120 | ((struct ext4_dir_entry_2 *) to)->rec_len = | 1154 | ((struct ext4_dir_entry_2 *) to)->rec_len = |
1121 | ext4_rec_len_to_disk(rec_len); | 1155 | ext4_rec_len_to_disk(rec_len, blocksize); |
1122 | de->inode = 0; | 1156 | de->inode = 0; |
1123 | map++; | 1157 | map++; |
1124 | to += rec_len; | 1158 | to += rec_len; |
@@ -1130,19 +1164,19 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) | |||
1130 | * Compact each dir entry in the range to the minimal rec_len. | 1164 | * Compact each dir entry in the range to the minimal rec_len. |
1131 | * Returns pointer to last entry in range. | 1165 | * Returns pointer to last entry in range. |
1132 | */ | 1166 | */ |
1133 | static struct ext4_dir_entry_2* dx_pack_dirents(char *base, int size) | 1167 | static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize) |
1134 | { | 1168 | { |
1135 | struct ext4_dir_entry_2 *next, *to, *prev, *de = (struct ext4_dir_entry_2 *) base; | 1169 | struct ext4_dir_entry_2 *next, *to, *prev, *de = (struct ext4_dir_entry_2 *) base; |
1136 | unsigned rec_len = 0; | 1170 | unsigned rec_len = 0; |
1137 | 1171 | ||
1138 | prev = to = de; | 1172 | prev = to = de; |
1139 | while ((char*)de < base + size) { | 1173 | while ((char*)de < base + blocksize) { |
1140 | next = ext4_next_entry(de); | 1174 | next = ext4_next_entry(de, blocksize); |
1141 | if (de->inode && de->name_len) { | 1175 | if (de->inode && de->name_len) { |
1142 | rec_len = EXT4_DIR_REC_LEN(de->name_len); | 1176 | rec_len = EXT4_DIR_REC_LEN(de->name_len); |
1143 | if (de > to) | 1177 | if (de > to) |
1144 | memmove(to, de, rec_len); | 1178 | memmove(to, de, rec_len); |
1145 | to->rec_len = ext4_rec_len_to_disk(rec_len); | 1179 | to->rec_len = ext4_rec_len_to_disk(rec_len, blocksize); |
1146 | prev = to; | 1180 | prev = to; |
1147 | to = (struct ext4_dir_entry_2 *) (((char *) to) + rec_len); | 1181 | to = (struct ext4_dir_entry_2 *) (((char *) to) + rec_len); |
1148 | } | 1182 | } |
@@ -1215,10 +1249,12 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, | |||
1215 | hash2, split, count-split)); | 1249 | hash2, split, count-split)); |
1216 | 1250 | ||
1217 | /* Fancy dance to stay within two buffers */ | 1251 | /* Fancy dance to stay within two buffers */ |
1218 | de2 = dx_move_dirents(data1, data2, map + split, count - split); | 1252 | de2 = dx_move_dirents(data1, data2, map + split, count - split, blocksize); |
1219 | de = dx_pack_dirents(data1, blocksize); | 1253 | de = dx_pack_dirents(data1, blocksize); |
1220 | de->rec_len = ext4_rec_len_to_disk(data1 + blocksize - (char *) de); | 1254 | 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); | 1255 | blocksize); |
1256 | de2->rec_len = ext4_rec_len_to_disk(data2 + blocksize - (char *) de2, | ||
1257 | blocksize); | ||
1222 | dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data1, blocksize, 1)); | 1258 | 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)); | 1259 | dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1)); |
1224 | 1260 | ||
@@ -1268,6 +1304,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, | |||
1268 | const char *name = dentry->d_name.name; | 1304 | const char *name = dentry->d_name.name; |
1269 | int namelen = dentry->d_name.len; | 1305 | int namelen = dentry->d_name.len; |
1270 | unsigned int offset = 0; | 1306 | unsigned int offset = 0; |
1307 | unsigned int blocksize = dir->i_sb->s_blocksize; | ||
1271 | unsigned short reclen; | 1308 | unsigned short reclen; |
1272 | int nlen, rlen, err; | 1309 | int nlen, rlen, err; |
1273 | char *top; | 1310 | char *top; |
@@ -1275,7 +1312,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, | |||
1275 | reclen = EXT4_DIR_REC_LEN(namelen); | 1312 | reclen = EXT4_DIR_REC_LEN(namelen); |
1276 | if (!de) { | 1313 | if (!de) { |
1277 | de = (struct ext4_dir_entry_2 *)bh->b_data; | 1314 | de = (struct ext4_dir_entry_2 *)bh->b_data; |
1278 | top = bh->b_data + dir->i_sb->s_blocksize - reclen; | 1315 | top = bh->b_data + blocksize - reclen; |
1279 | while ((char *) de <= top) { | 1316 | while ((char *) de <= top) { |
1280 | if (!ext4_check_dir_entry("ext4_add_entry", dir, de, | 1317 | if (!ext4_check_dir_entry("ext4_add_entry", dir, de, |
1281 | bh, offset)) { | 1318 | bh, offset)) { |
@@ -1287,7 +1324,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, | |||
1287 | return -EEXIST; | 1324 | return -EEXIST; |
1288 | } | 1325 | } |
1289 | nlen = EXT4_DIR_REC_LEN(de->name_len); | 1326 | nlen = EXT4_DIR_REC_LEN(de->name_len); |
1290 | rlen = ext4_rec_len_from_disk(de->rec_len); | 1327 | rlen = ext4_rec_len_from_disk(de->rec_len, blocksize); |
1291 | if ((de->inode? rlen - nlen: rlen) >= reclen) | 1328 | if ((de->inode? rlen - nlen: rlen) >= reclen) |
1292 | break; | 1329 | break; |
1293 | de = (struct ext4_dir_entry_2 *)((char *)de + rlen); | 1330 | de = (struct ext4_dir_entry_2 *)((char *)de + rlen); |
@@ -1306,11 +1343,11 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, | |||
1306 | 1343 | ||
1307 | /* By now the buffer is marked for journaling */ | 1344 | /* By now the buffer is marked for journaling */ |
1308 | nlen = EXT4_DIR_REC_LEN(de->name_len); | 1345 | nlen = EXT4_DIR_REC_LEN(de->name_len); |
1309 | rlen = ext4_rec_len_from_disk(de->rec_len); | 1346 | rlen = ext4_rec_len_from_disk(de->rec_len, blocksize); |
1310 | if (de->inode) { | 1347 | if (de->inode) { |
1311 | struct ext4_dir_entry_2 *de1 = (struct ext4_dir_entry_2 *)((char *)de + nlen); | 1348 | 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); | 1349 | de1->rec_len = ext4_rec_len_to_disk(rlen - nlen, blocksize); |
1313 | de->rec_len = ext4_rec_len_to_disk(nlen); | 1350 | de->rec_len = ext4_rec_len_to_disk(nlen, blocksize); |
1314 | de = de1; | 1351 | de = de1; |
1315 | } | 1352 | } |
1316 | de->file_type = EXT4_FT_UNKNOWN; | 1353 | de->file_type = EXT4_FT_UNKNOWN; |
@@ -1380,7 +1417,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, | |||
1380 | /* The 0th block becomes the root, move the dirents out */ | 1417 | /* The 0th block becomes the root, move the dirents out */ |
1381 | fde = &root->dotdot; | 1418 | fde = &root->dotdot; |
1382 | de = (struct ext4_dir_entry_2 *)((char *)fde + | 1419 | de = (struct ext4_dir_entry_2 *)((char *)fde + |
1383 | ext4_rec_len_from_disk(fde->rec_len)); | 1420 | ext4_rec_len_from_disk(fde->rec_len, blocksize)); |
1384 | if ((char *) de >= (((char *) root) + blocksize)) { | 1421 | if ((char *) de >= (((char *) root) + blocksize)) { |
1385 | ext4_error(dir->i_sb, __func__, | 1422 | ext4_error(dir->i_sb, __func__, |
1386 | "invalid rec_len for '..' in inode %lu", | 1423 | "invalid rec_len for '..' in inode %lu", |
@@ -1402,12 +1439,14 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, | |||
1402 | memcpy (data1, de, len); | 1439 | memcpy (data1, de, len); |
1403 | de = (struct ext4_dir_entry_2 *) data1; | 1440 | de = (struct ext4_dir_entry_2 *) data1; |
1404 | top = data1 + len; | 1441 | top = data1 + len; |
1405 | while ((char *)(de2 = ext4_next_entry(de)) < top) | 1442 | while ((char *)(de2 = ext4_next_entry(de, blocksize)) < top) |
1406 | de = de2; | 1443 | de = de2; |
1407 | de->rec_len = ext4_rec_len_to_disk(data1 + blocksize - (char *) de); | 1444 | de->rec_len = ext4_rec_len_to_disk(data1 + blocksize - (char *) de, |
1445 | blocksize); | ||
1408 | /* Initialize the root; the dot dirents already exist */ | 1446 | /* Initialize the root; the dot dirents already exist */ |
1409 | de = (struct ext4_dir_entry_2 *) (&root->dotdot); | 1447 | de = (struct ext4_dir_entry_2 *) (&root->dotdot); |
1410 | de->rec_len = ext4_rec_len_to_disk(blocksize - EXT4_DIR_REC_LEN(2)); | 1448 | de->rec_len = ext4_rec_len_to_disk(blocksize - EXT4_DIR_REC_LEN(2), |
1449 | blocksize); | ||
1411 | memset (&root->info, 0, sizeof(root->info)); | 1450 | memset (&root->info, 0, sizeof(root->info)); |
1412 | root->info.info_length = sizeof(root->info); | 1451 | root->info.info_length = sizeof(root->info); |
1413 | root->info.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version; | 1452 | root->info.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version; |
@@ -1488,7 +1527,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, | |||
1488 | return retval; | 1527 | return retval; |
1489 | de = (struct ext4_dir_entry_2 *) bh->b_data; | 1528 | de = (struct ext4_dir_entry_2 *) bh->b_data; |
1490 | de->inode = 0; | 1529 | de->inode = 0; |
1491 | de->rec_len = ext4_rec_len_to_disk(blocksize); | 1530 | de->rec_len = ext4_rec_len_to_disk(blocksize, blocksize); |
1492 | return add_dirent_to_buf(handle, dentry, inode, de, bh); | 1531 | return add_dirent_to_buf(handle, dentry, inode, de, bh); |
1493 | } | 1532 | } |
1494 | 1533 | ||
@@ -1551,7 +1590,8 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, | |||
1551 | goto cleanup; | 1590 | goto cleanup; |
1552 | node2 = (struct dx_node *)(bh2->b_data); | 1591 | node2 = (struct dx_node *)(bh2->b_data); |
1553 | entries2 = node2->entries; | 1592 | entries2 = node2->entries; |
1554 | node2->fake.rec_len = ext4_rec_len_to_disk(sb->s_blocksize); | 1593 | node2->fake.rec_len = ext4_rec_len_to_disk(sb->s_blocksize, |
1594 | sb->s_blocksize); | ||
1555 | node2->fake.inode = 0; | 1595 | node2->fake.inode = 0; |
1556 | BUFFER_TRACE(frame->bh, "get_write_access"); | 1596 | BUFFER_TRACE(frame->bh, "get_write_access"); |
1557 | err = ext4_journal_get_write_access(handle, frame->bh); | 1597 | err = ext4_journal_get_write_access(handle, frame->bh); |
@@ -1639,6 +1679,7 @@ static int ext4_delete_entry(handle_t *handle, | |||
1639 | struct buffer_head *bh) | 1679 | struct buffer_head *bh) |
1640 | { | 1680 | { |
1641 | struct ext4_dir_entry_2 *de, *pde; | 1681 | struct ext4_dir_entry_2 *de, *pde; |
1682 | unsigned int blocksize = dir->i_sb->s_blocksize; | ||
1642 | int i; | 1683 | int i; |
1643 | 1684 | ||
1644 | i = 0; | 1685 | i = 0; |
@@ -1652,8 +1693,11 @@ static int ext4_delete_entry(handle_t *handle, | |||
1652 | ext4_journal_get_write_access(handle, bh); | 1693 | ext4_journal_get_write_access(handle, bh); |
1653 | if (pde) | 1694 | if (pde) |
1654 | pde->rec_len = ext4_rec_len_to_disk( | 1695 | pde->rec_len = ext4_rec_len_to_disk( |
1655 | ext4_rec_len_from_disk(pde->rec_len) + | 1696 | ext4_rec_len_from_disk(pde->rec_len, |
1656 | ext4_rec_len_from_disk(de->rec_len)); | 1697 | blocksize) + |
1698 | ext4_rec_len_from_disk(de->rec_len, | ||
1699 | blocksize), | ||
1700 | blocksize); | ||
1657 | else | 1701 | else |
1658 | de->inode = 0; | 1702 | de->inode = 0; |
1659 | dir->i_version++; | 1703 | dir->i_version++; |
@@ -1661,9 +1705,9 @@ static int ext4_delete_entry(handle_t *handle, | |||
1661 | ext4_handle_dirty_metadata(handle, dir, bh); | 1705 | ext4_handle_dirty_metadata(handle, dir, bh); |
1662 | return 0; | 1706 | return 0; |
1663 | } | 1707 | } |
1664 | i += ext4_rec_len_from_disk(de->rec_len); | 1708 | i += ext4_rec_len_from_disk(de->rec_len, blocksize); |
1665 | pde = de; | 1709 | pde = de; |
1666 | de = ext4_next_entry(de); | 1710 | de = ext4_next_entry(de, blocksize); |
1667 | } | 1711 | } |
1668 | return -ENOENT; | 1712 | return -ENOENT; |
1669 | } | 1713 | } |
@@ -1793,6 +1837,7 @@ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
1793 | struct inode *inode; | 1837 | struct inode *inode; |
1794 | struct buffer_head *dir_block; | 1838 | struct buffer_head *dir_block; |
1795 | struct ext4_dir_entry_2 *de; | 1839 | struct ext4_dir_entry_2 *de; |
1840 | unsigned int blocksize = dir->i_sb->s_blocksize; | ||
1796 | int err, retries = 0; | 1841 | int err, retries = 0; |
1797 | 1842 | ||
1798 | if (EXT4_DIR_LINK_MAX(dir)) | 1843 | if (EXT4_DIR_LINK_MAX(dir)) |
@@ -1824,13 +1869,14 @@ retry: | |||
1824 | de = (struct ext4_dir_entry_2 *) dir_block->b_data; | 1869 | de = (struct ext4_dir_entry_2 *) dir_block->b_data; |
1825 | de->inode = cpu_to_le32(inode->i_ino); | 1870 | de->inode = cpu_to_le32(inode->i_ino); |
1826 | de->name_len = 1; | 1871 | de->name_len = 1; |
1827 | de->rec_len = ext4_rec_len_to_disk(EXT4_DIR_REC_LEN(de->name_len)); | 1872 | de->rec_len = ext4_rec_len_to_disk(EXT4_DIR_REC_LEN(de->name_len), |
1873 | blocksize); | ||
1828 | strcpy(de->name, "."); | 1874 | strcpy(de->name, "."); |
1829 | ext4_set_de_type(dir->i_sb, de, S_IFDIR); | 1875 | ext4_set_de_type(dir->i_sb, de, S_IFDIR); |
1830 | de = ext4_next_entry(de); | 1876 | de = ext4_next_entry(de, blocksize); |
1831 | de->inode = cpu_to_le32(dir->i_ino); | 1877 | de->inode = cpu_to_le32(dir->i_ino); |
1832 | de->rec_len = ext4_rec_len_to_disk(inode->i_sb->s_blocksize - | 1878 | de->rec_len = ext4_rec_len_to_disk(blocksize - EXT4_DIR_REC_LEN(1), |
1833 | EXT4_DIR_REC_LEN(1)); | 1879 | blocksize); |
1834 | de->name_len = 2; | 1880 | de->name_len = 2; |
1835 | strcpy(de->name, ".."); | 1881 | strcpy(de->name, ".."); |
1836 | ext4_set_de_type(dir->i_sb, de, S_IFDIR); | 1882 | ext4_set_de_type(dir->i_sb, de, S_IFDIR); |
@@ -1885,7 +1931,7 @@ static int empty_dir(struct inode *inode) | |||
1885 | return 1; | 1931 | return 1; |
1886 | } | 1932 | } |
1887 | de = (struct ext4_dir_entry_2 *) bh->b_data; | 1933 | de = (struct ext4_dir_entry_2 *) bh->b_data; |
1888 | de1 = ext4_next_entry(de); | 1934 | de1 = ext4_next_entry(de, sb->s_blocksize); |
1889 | if (le32_to_cpu(de->inode) != inode->i_ino || | 1935 | if (le32_to_cpu(de->inode) != inode->i_ino || |
1890 | !le32_to_cpu(de1->inode) || | 1936 | !le32_to_cpu(de1->inode) || |
1891 | strcmp(".", de->name) || | 1937 | strcmp(".", de->name) || |
@@ -1896,9 +1942,9 @@ static int empty_dir(struct inode *inode) | |||
1896 | brelse(bh); | 1942 | brelse(bh); |
1897 | return 1; | 1943 | return 1; |
1898 | } | 1944 | } |
1899 | offset = ext4_rec_len_from_disk(de->rec_len) + | 1945 | offset = ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize) + |
1900 | ext4_rec_len_from_disk(de1->rec_len); | 1946 | ext4_rec_len_from_disk(de1->rec_len, sb->s_blocksize); |
1901 | de = ext4_next_entry(de1); | 1947 | de = ext4_next_entry(de1, sb->s_blocksize); |
1902 | while (offset < inode->i_size) { | 1948 | while (offset < inode->i_size) { |
1903 | if (!bh || | 1949 | if (!bh || |
1904 | (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { | 1950 | (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { |
@@ -1927,8 +1973,8 @@ static int empty_dir(struct inode *inode) | |||
1927 | brelse(bh); | 1973 | brelse(bh); |
1928 | return 0; | 1974 | return 0; |
1929 | } | 1975 | } |
1930 | offset += ext4_rec_len_from_disk(de->rec_len); | 1976 | offset += ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize); |
1931 | de = ext4_next_entry(de); | 1977 | de = ext4_next_entry(de, sb->s_blocksize); |
1932 | } | 1978 | } |
1933 | brelse(bh); | 1979 | brelse(bh); |
1934 | return 1; | 1980 | return 1; |
@@ -2297,8 +2343,8 @@ retry: | |||
2297 | return err; | 2343 | return err; |
2298 | } | 2344 | } |
2299 | 2345 | ||
2300 | #define PARENT_INO(buffer) \ | 2346 | #define PARENT_INO(buffer, size) \ |
2301 | (ext4_next_entry((struct ext4_dir_entry_2 *)(buffer))->inode) | 2347 | (ext4_next_entry((struct ext4_dir_entry_2 *)(buffer), size)->inode) |
2302 | 2348 | ||
2303 | /* | 2349 | /* |
2304 | * Anybody can rename anything with this: the permission checks are left to the | 2350 | * Anybody can rename anything with this: the permission checks are left to the |
@@ -2311,7 +2357,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2311 | struct inode *old_inode, *new_inode; | 2357 | struct inode *old_inode, *new_inode; |
2312 | struct buffer_head *old_bh, *new_bh, *dir_bh; | 2358 | struct buffer_head *old_bh, *new_bh, *dir_bh; |
2313 | struct ext4_dir_entry_2 *old_de, *new_de; | 2359 | struct ext4_dir_entry_2 *old_de, *new_de; |
2314 | int retval; | 2360 | int retval, force_da_alloc = 0; |
2315 | 2361 | ||
2316 | old_bh = new_bh = dir_bh = NULL; | 2362 | old_bh = new_bh = dir_bh = NULL; |
2317 | 2363 | ||
@@ -2358,7 +2404,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2358 | dir_bh = ext4_bread(handle, old_inode, 0, 0, &retval); | 2404 | dir_bh = ext4_bread(handle, old_inode, 0, 0, &retval); |
2359 | if (!dir_bh) | 2405 | if (!dir_bh) |
2360 | goto end_rename; | 2406 | goto end_rename; |
2361 | if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino) | 2407 | if (le32_to_cpu(PARENT_INO(dir_bh->b_data, |
2408 | old_dir->i_sb->s_blocksize)) != old_dir->i_ino) | ||
2362 | goto end_rename; | 2409 | goto end_rename; |
2363 | retval = -EMLINK; | 2410 | retval = -EMLINK; |
2364 | if (!new_inode && new_dir != old_dir && | 2411 | if (!new_inode && new_dir != old_dir && |
@@ -2430,7 +2477,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2430 | if (dir_bh) { | 2477 | if (dir_bh) { |
2431 | BUFFER_TRACE(dir_bh, "get_write_access"); | 2478 | BUFFER_TRACE(dir_bh, "get_write_access"); |
2432 | ext4_journal_get_write_access(handle, dir_bh); | 2479 | ext4_journal_get_write_access(handle, dir_bh); |
2433 | PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino); | 2480 | PARENT_INO(dir_bh->b_data, new_dir->i_sb->s_blocksize) = |
2481 | cpu_to_le32(new_dir->i_ino); | ||
2434 | BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata"); | 2482 | BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata"); |
2435 | ext4_handle_dirty_metadata(handle, old_dir, dir_bh); | 2483 | ext4_handle_dirty_metadata(handle, old_dir, dir_bh); |
2436 | ext4_dec_count(handle, old_dir); | 2484 | ext4_dec_count(handle, old_dir); |
@@ -2449,6 +2497,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2449 | ext4_mark_inode_dirty(handle, new_inode); | 2497 | ext4_mark_inode_dirty(handle, new_inode); |
2450 | if (!new_inode->i_nlink) | 2498 | if (!new_inode->i_nlink) |
2451 | ext4_orphan_add(handle, new_inode); | 2499 | ext4_orphan_add(handle, new_inode); |
2500 | if (!test_opt(new_dir->i_sb, NO_AUTO_DA_ALLOC)) | ||
2501 | force_da_alloc = 1; | ||
2452 | } | 2502 | } |
2453 | retval = 0; | 2503 | retval = 0; |
2454 | 2504 | ||
@@ -2457,6 +2507,8 @@ end_rename: | |||
2457 | brelse(old_bh); | 2507 | brelse(old_bh); |
2458 | brelse(new_bh); | 2508 | brelse(new_bh); |
2459 | ext4_journal_stop(handle); | 2509 | ext4_journal_stop(handle); |
2510 | if (retval == 0 && force_da_alloc) | ||
2511 | ext4_alloc_da_blocks(old_inode); | ||
2460 | return retval; | 2512 | return retval; |
2461 | } | 2513 | } |
2462 | 2514 | ||