.. | .. |
---|
54 | 54 | struct inode *inode, |
---|
55 | 55 | ext4_lblk_t *block) |
---|
56 | 56 | { |
---|
| 57 | + struct ext4_map_blocks map; |
---|
57 | 58 | struct buffer_head *bh; |
---|
58 | 59 | int err; |
---|
59 | 60 | |
---|
.. | .. |
---|
63 | 64 | return ERR_PTR(-ENOSPC); |
---|
64 | 65 | |
---|
65 | 66 | *block = inode->i_size >> inode->i_sb->s_blocksize_bits; |
---|
| 67 | + map.m_lblk = *block; |
---|
| 68 | + map.m_len = 1; |
---|
| 69 | + |
---|
| 70 | + /* |
---|
| 71 | + * We're appending new directory block. Make sure the block is not |
---|
| 72 | + * allocated yet, otherwise we will end up corrupting the |
---|
| 73 | + * directory. |
---|
| 74 | + */ |
---|
| 75 | + err = ext4_map_blocks(NULL, inode, &map, 0); |
---|
| 76 | + if (err < 0) |
---|
| 77 | + return ERR_PTR(err); |
---|
| 78 | + if (err) { |
---|
| 79 | + EXT4_ERROR_INODE(inode, "Logical block already allocated"); |
---|
| 80 | + return ERR_PTR(-EFSCORRUPTED); |
---|
| 81 | + } |
---|
66 | 82 | |
---|
67 | 83 | bh = ext4_bread(handle, inode, *block, EXT4_GET_BLOCKS_CREATE); |
---|
68 | 84 | if (IS_ERR(bh)) |
---|
.. | .. |
---|
109 | 125 | struct ext4_dir_entry *dirent; |
---|
110 | 126 | int is_dx_block = 0; |
---|
111 | 127 | |
---|
112 | | - bh = ext4_bread(NULL, inode, block, 0); |
---|
| 128 | + if (block >= inode->i_size >> inode->i_blkbits) { |
---|
| 129 | + ext4_error_inode(inode, func, line, block, |
---|
| 130 | + "Attempting to read directory block (%u) that is past i_size (%llu)", |
---|
| 131 | + block, inode->i_size); |
---|
| 132 | + return ERR_PTR(-EFSCORRUPTED); |
---|
| 133 | + } |
---|
| 134 | + |
---|
| 135 | + if (ext4_simulate_fail(inode->i_sb, EXT4_SIM_DIRBLOCK_EIO)) |
---|
| 136 | + bh = ERR_PTR(-EIO); |
---|
| 137 | + else |
---|
| 138 | + bh = ext4_bread(NULL, inode, block, 0); |
---|
113 | 139 | if (IS_ERR(bh)) { |
---|
114 | 140 | __ext4_warning(inode->i_sb, func, line, |
---|
115 | 141 | "inode #%lu: lblock %lu: comm %s: " |
---|
.. | .. |
---|
153 | 179 | * caller is sure it should be an index block. |
---|
154 | 180 | */ |
---|
155 | 181 | if (is_dx_block && type == INDEX) { |
---|
156 | | - if (ext4_dx_csum_verify(inode, dirent)) |
---|
| 182 | + if (ext4_dx_csum_verify(inode, dirent) && |
---|
| 183 | + !ext4_simulate_fail(inode->i_sb, EXT4_SIM_DIRBLOCK_CRC)) |
---|
157 | 184 | set_buffer_verified(bh); |
---|
158 | 185 | else { |
---|
159 | | - ext4_error_inode(inode, func, line, block, |
---|
160 | | - "Directory index failed checksum"); |
---|
| 186 | + ext4_error_inode_err(inode, func, line, block, |
---|
| 187 | + EFSBADCRC, |
---|
| 188 | + "Directory index failed checksum"); |
---|
161 | 189 | brelse(bh); |
---|
162 | 190 | return ERR_PTR(-EFSBADCRC); |
---|
163 | 191 | } |
---|
164 | 192 | } |
---|
165 | 193 | if (!is_dx_block) { |
---|
166 | | - if (ext4_dirent_csum_verify(inode, dirent)) |
---|
| 194 | + if (ext4_dirblock_csum_verify(inode, bh) && |
---|
| 195 | + !ext4_simulate_fail(inode->i_sb, EXT4_SIM_DIRBLOCK_CRC)) |
---|
167 | 196 | set_buffer_verified(bh); |
---|
168 | 197 | else { |
---|
169 | | - ext4_error_inode(inode, func, line, block, |
---|
170 | | - "Directory block failed checksum"); |
---|
| 198 | + ext4_error_inode_err(inode, func, line, block, |
---|
| 199 | + EFSBADCRC, |
---|
| 200 | + "Directory block failed checksum"); |
---|
171 | 201 | brelse(bh); |
---|
172 | 202 | return ERR_PTR(-EFSBADCRC); |
---|
173 | 203 | } |
---|
.. | .. |
---|
226 | 256 | u8 unused_flags; |
---|
227 | 257 | } |
---|
228 | 258 | info; |
---|
229 | | - struct dx_entry entries[0]; |
---|
| 259 | + struct dx_entry entries[]; |
---|
230 | 260 | }; |
---|
231 | 261 | |
---|
232 | 262 | struct dx_node |
---|
233 | 263 | { |
---|
234 | 264 | struct fake_dirent fake; |
---|
235 | | - struct dx_entry entries[0]; |
---|
| 265 | + struct dx_entry entries[]; |
---|
236 | 266 | }; |
---|
237 | 267 | |
---|
238 | 268 | |
---|
.. | .. |
---|
295 | 325 | struct inode *dir, struct inode *inode); |
---|
296 | 326 | |
---|
297 | 327 | /* checksumming functions */ |
---|
298 | | -void initialize_dirent_tail(struct ext4_dir_entry_tail *t, |
---|
299 | | - unsigned int blocksize) |
---|
| 328 | +void ext4_initialize_dirent_tail(struct buffer_head *bh, |
---|
| 329 | + unsigned int blocksize) |
---|
300 | 330 | { |
---|
| 331 | + struct ext4_dir_entry_tail *t = EXT4_DIRENT_TAIL(bh->b_data, blocksize); |
---|
| 332 | + |
---|
301 | 333 | memset(t, 0, sizeof(struct ext4_dir_entry_tail)); |
---|
302 | 334 | t->det_rec_len = ext4_rec_len_to_disk( |
---|
303 | 335 | sizeof(struct ext4_dir_entry_tail), blocksize); |
---|
.. | .. |
---|
306 | 338 | |
---|
307 | 339 | /* Walk through a dirent block to find a checksum "dirent" at the tail */ |
---|
308 | 340 | static struct ext4_dir_entry_tail *get_dirent_tail(struct inode *inode, |
---|
309 | | - struct ext4_dir_entry *de) |
---|
| 341 | + struct buffer_head *bh) |
---|
310 | 342 | { |
---|
311 | 343 | struct ext4_dir_entry_tail *t; |
---|
| 344 | + int blocksize = EXT4_BLOCK_SIZE(inode->i_sb); |
---|
312 | 345 | |
---|
313 | 346 | #ifdef PARANOID |
---|
314 | 347 | struct ext4_dir_entry *d, *top; |
---|
315 | 348 | |
---|
316 | | - d = de; |
---|
317 | | - top = (struct ext4_dir_entry *)(((void *)de) + |
---|
318 | | - (EXT4_BLOCK_SIZE(inode->i_sb) - |
---|
319 | | - sizeof(struct ext4_dir_entry_tail))); |
---|
320 | | - while (d < top && d->rec_len) |
---|
| 349 | + d = (struct ext4_dir_entry *)bh->b_data; |
---|
| 350 | + top = (struct ext4_dir_entry *)(bh->b_data + |
---|
| 351 | + (blocksize - sizeof(struct ext4_dir_entry_tail))); |
---|
| 352 | + while (d < top && ext4_rec_len_from_disk(d->rec_len, blocksize)) |
---|
321 | 353 | d = (struct ext4_dir_entry *)(((void *)d) + |
---|
322 | | - le16_to_cpu(d->rec_len)); |
---|
| 354 | + ext4_rec_len_from_disk(d->rec_len, blocksize)); |
---|
323 | 355 | |
---|
324 | 356 | if (d != top) |
---|
325 | 357 | return NULL; |
---|
326 | 358 | |
---|
327 | 359 | t = (struct ext4_dir_entry_tail *)d; |
---|
328 | 360 | #else |
---|
329 | | - t = EXT4_DIRENT_TAIL(de, EXT4_BLOCK_SIZE(inode->i_sb)); |
---|
| 361 | + t = EXT4_DIRENT_TAIL(bh->b_data, EXT4_BLOCK_SIZE(inode->i_sb)); |
---|
330 | 362 | #endif |
---|
331 | 363 | |
---|
332 | 364 | if (t->det_reserved_zero1 || |
---|
333 | | - le16_to_cpu(t->det_rec_len) != sizeof(struct ext4_dir_entry_tail) || |
---|
| 365 | + (ext4_rec_len_from_disk(t->det_rec_len, blocksize) != |
---|
| 366 | + sizeof(struct ext4_dir_entry_tail)) || |
---|
334 | 367 | t->det_reserved_zero2 || |
---|
335 | 368 | t->det_reserved_ft != EXT4_FT_DIR_CSUM) |
---|
336 | 369 | return NULL; |
---|
.. | .. |
---|
338 | 371 | return t; |
---|
339 | 372 | } |
---|
340 | 373 | |
---|
341 | | -static __le32 ext4_dirent_csum(struct inode *inode, |
---|
342 | | - struct ext4_dir_entry *dirent, int size) |
---|
| 374 | +static __le32 ext4_dirblock_csum(struct inode *inode, void *dirent, int size) |
---|
343 | 375 | { |
---|
344 | 376 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
---|
345 | 377 | struct ext4_inode_info *ei = EXT4_I(inode); |
---|
.. | .. |
---|
359 | 391 | "No space for directory leaf checksum. Please run e2fsck -D."); |
---|
360 | 392 | } |
---|
361 | 393 | |
---|
362 | | -int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent) |
---|
| 394 | +int ext4_dirblock_csum_verify(struct inode *inode, struct buffer_head *bh) |
---|
363 | 395 | { |
---|
364 | 396 | struct ext4_dir_entry_tail *t; |
---|
365 | 397 | |
---|
366 | 398 | if (!ext4_has_metadata_csum(inode->i_sb)) |
---|
367 | 399 | return 1; |
---|
368 | 400 | |
---|
369 | | - t = get_dirent_tail(inode, dirent); |
---|
| 401 | + t = get_dirent_tail(inode, bh); |
---|
370 | 402 | if (!t) { |
---|
371 | 403 | warn_no_space_for_csum(inode); |
---|
372 | 404 | return 0; |
---|
373 | 405 | } |
---|
374 | 406 | |
---|
375 | | - if (t->det_checksum != ext4_dirent_csum(inode, dirent, |
---|
376 | | - (void *)t - (void *)dirent)) |
---|
| 407 | + if (t->det_checksum != ext4_dirblock_csum(inode, bh->b_data, |
---|
| 408 | + (char *)t - bh->b_data)) |
---|
377 | 409 | return 0; |
---|
378 | 410 | |
---|
379 | 411 | return 1; |
---|
380 | 412 | } |
---|
381 | 413 | |
---|
382 | | -static void ext4_dirent_csum_set(struct inode *inode, |
---|
383 | | - struct ext4_dir_entry *dirent) |
---|
| 414 | +static void ext4_dirblock_csum_set(struct inode *inode, |
---|
| 415 | + struct buffer_head *bh) |
---|
384 | 416 | { |
---|
385 | 417 | struct ext4_dir_entry_tail *t; |
---|
386 | 418 | |
---|
387 | 419 | if (!ext4_has_metadata_csum(inode->i_sb)) |
---|
388 | 420 | return; |
---|
389 | 421 | |
---|
390 | | - t = get_dirent_tail(inode, dirent); |
---|
| 422 | + t = get_dirent_tail(inode, bh); |
---|
391 | 423 | if (!t) { |
---|
392 | 424 | warn_no_space_for_csum(inode); |
---|
393 | 425 | return; |
---|
394 | 426 | } |
---|
395 | 427 | |
---|
396 | | - t->det_checksum = ext4_dirent_csum(inode, dirent, |
---|
397 | | - (void *)t - (void *)dirent); |
---|
| 428 | + t->det_checksum = ext4_dirblock_csum(inode, bh->b_data, |
---|
| 429 | + (char *)t - bh->b_data); |
---|
398 | 430 | } |
---|
399 | 431 | |
---|
400 | | -int ext4_handle_dirty_dirent_node(handle_t *handle, |
---|
401 | | - struct inode *inode, |
---|
402 | | - struct buffer_head *bh) |
---|
| 432 | +int ext4_handle_dirty_dirblock(handle_t *handle, |
---|
| 433 | + struct inode *inode, |
---|
| 434 | + struct buffer_head *bh) |
---|
403 | 435 | { |
---|
404 | | - ext4_dirent_csum_set(inode, (struct ext4_dir_entry *)bh->b_data); |
---|
| 436 | + ext4_dirblock_csum_set(inode, bh); |
---|
405 | 437 | return ext4_handle_dirty_metadata(handle, inode, bh); |
---|
406 | 438 | } |
---|
407 | 439 | |
---|
.. | .. |
---|
412 | 444 | struct ext4_dir_entry *dp; |
---|
413 | 445 | struct dx_root_info *root; |
---|
414 | 446 | int count_offset; |
---|
| 447 | + int blocksize = EXT4_BLOCK_SIZE(inode->i_sb); |
---|
| 448 | + unsigned int rlen = ext4_rec_len_from_disk(dirent->rec_len, blocksize); |
---|
415 | 449 | |
---|
416 | | - if (le16_to_cpu(dirent->rec_len) == EXT4_BLOCK_SIZE(inode->i_sb)) |
---|
| 450 | + if (rlen == blocksize) |
---|
417 | 451 | count_offset = 8; |
---|
418 | | - else if (le16_to_cpu(dirent->rec_len) == 12) { |
---|
| 452 | + else if (rlen == 12) { |
---|
419 | 453 | dp = (struct ext4_dir_entry *)(((void *)dirent) + 12); |
---|
420 | | - if (le16_to_cpu(dp->rec_len) != |
---|
421 | | - EXT4_BLOCK_SIZE(inode->i_sb) - 12) |
---|
| 454 | + if (ext4_rec_len_from_disk(dp->rec_len, blocksize) != blocksize - 12) |
---|
422 | 455 | return NULL; |
---|
423 | 456 | root = (struct dx_root_info *)(((void *)dp + 12)); |
---|
424 | 457 | if (root->reserved_zero || |
---|
.. | .. |
---|
639 | 672 | |
---|
640 | 673 | name = de->name; |
---|
641 | 674 | len = de->name_len; |
---|
642 | | - if (IS_ENCRYPTED(dir)) |
---|
643 | | - res = fscrypt_get_encryption_info(dir); |
---|
644 | | - if (res) { |
---|
645 | | - printk(KERN_WARNING "Error setting up" |
---|
646 | | - " fname crypto: %d\n", res); |
---|
647 | | - } |
---|
648 | | - if (!fscrypt_has_encryption_key(dir)) { |
---|
| 675 | + if (!IS_ENCRYPTED(dir)) { |
---|
649 | 676 | /* Directory is not encrypted */ |
---|
650 | 677 | ext4fs_dirhash(dir, de->name, |
---|
651 | 678 | de->name_len, &h); |
---|
.. | .. |
---|
659 | 686 | |
---|
660 | 687 | /* Directory is encrypted */ |
---|
661 | 688 | res = fscrypt_fname_alloc_buffer( |
---|
662 | | - dir, len, |
---|
663 | | - &fname_crypto_str); |
---|
| 689 | + len, &fname_crypto_str); |
---|
664 | 690 | if (res) |
---|
665 | 691 | printk(KERN_WARNING "Error " |
---|
666 | 692 | "allocating crypto " |
---|
.. | .. |
---|
756 | 782 | dx_probe(struct ext4_filename *fname, struct inode *dir, |
---|
757 | 783 | struct dx_hash_info *hinfo, struct dx_frame *frame_in) |
---|
758 | 784 | { |
---|
759 | | - unsigned count, indirect; |
---|
| 785 | + unsigned count, indirect, level, i; |
---|
760 | 786 | struct dx_entry *at, *entries, *p, *q, *m; |
---|
761 | 787 | struct dx_root *root; |
---|
762 | 788 | struct dx_frame *frame = frame_in; |
---|
763 | 789 | struct dx_frame *ret_err = ERR_PTR(ERR_BAD_DX_DIR); |
---|
764 | 790 | u32 hash; |
---|
| 791 | + ext4_lblk_t block; |
---|
| 792 | + ext4_lblk_t blocks[EXT4_HTREE_LEVEL]; |
---|
765 | 793 | |
---|
766 | 794 | memset(frame_in, 0, EXT4_HTREE_LEVEL * sizeof(frame_in[0])); |
---|
767 | 795 | frame->bh = ext4_read_dirblock(dir, 0, INDEX); |
---|
.. | .. |
---|
833 | 861 | } |
---|
834 | 862 | |
---|
835 | 863 | dxtrace(printk("Look up %x", hash)); |
---|
| 864 | + level = 0; |
---|
| 865 | + blocks[0] = 0; |
---|
836 | 866 | while (1) { |
---|
837 | 867 | count = dx_get_count(entries); |
---|
838 | 868 | if (!count || count > dx_get_limit(entries)) { |
---|
.. | .. |
---|
874 | 904 | dx_get_block(at))); |
---|
875 | 905 | frame->entries = entries; |
---|
876 | 906 | frame->at = at; |
---|
877 | | - if (!indirect--) |
---|
| 907 | + |
---|
| 908 | + block = dx_get_block(at); |
---|
| 909 | + for (i = 0; i <= level; i++) { |
---|
| 910 | + if (blocks[i] == block) { |
---|
| 911 | + ext4_warning_inode(dir, |
---|
| 912 | + "dx entry: tree cycle block %u points back to block %u", |
---|
| 913 | + blocks[level], block); |
---|
| 914 | + goto fail; |
---|
| 915 | + } |
---|
| 916 | + } |
---|
| 917 | + if (++level > indirect) |
---|
878 | 918 | return frame; |
---|
| 919 | + blocks[level] = block; |
---|
879 | 920 | frame++; |
---|
880 | | - frame->bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX); |
---|
| 921 | + frame->bh = ext4_read_dirblock(dir, block, INDEX); |
---|
881 | 922 | if (IS_ERR(frame->bh)) { |
---|
882 | 923 | ret_err = (struct dx_frame *) frame->bh; |
---|
883 | 924 | frame->bh = NULL; |
---|
884 | 925 | goto fail; |
---|
885 | 926 | } |
---|
| 927 | + |
---|
886 | 928 | entries = ((struct dx_node *) frame->bh->b_data)->entries; |
---|
887 | 929 | |
---|
888 | 930 | if (dx_get_limit(entries) != dx_node_limit(dir)) { |
---|
.. | .. |
---|
972 | 1014 | * If the hash is 1, then continue only if the next page has a |
---|
973 | 1015 | * continuation hash of any value. This is used for readdir |
---|
974 | 1016 | * handling. Otherwise, check to see if the hash matches the |
---|
975 | | - * desired contiuation hash. If it doesn't, return since |
---|
| 1017 | + * desired continuation hash. If it doesn't, return since |
---|
976 | 1018 | * there's no point to read in the successive index pages. |
---|
977 | 1019 | */ |
---|
978 | 1020 | bhash = dx_get_hash(p->at); |
---|
.. | .. |
---|
1027 | 1069 | dir->i_sb->s_blocksize - |
---|
1028 | 1070 | ext4_dir_rec_len(0, |
---|
1029 | 1071 | csum ? NULL : dir)); |
---|
1030 | | -#ifdef CONFIG_FS_ENCRYPTION |
---|
1031 | 1072 | /* Check if the directory is encrypted */ |
---|
1032 | 1073 | if (IS_ENCRYPTED(dir)) { |
---|
1033 | | - err = fscrypt_get_encryption_info(dir); |
---|
| 1074 | + err = fscrypt_prepare_readdir(dir); |
---|
1034 | 1075 | if (err < 0) { |
---|
1035 | 1076 | brelse(bh); |
---|
1036 | 1077 | return err; |
---|
1037 | 1078 | } |
---|
1038 | | - err = fscrypt_fname_alloc_buffer(dir, EXT4_NAME_LEN, |
---|
1039 | | - &fname_crypto_str); |
---|
| 1079 | + err = fscrypt_fname_alloc_buffer(EXT4_NAME_LEN, |
---|
| 1080 | + &fname_crypto_str); |
---|
1040 | 1081 | if (err < 0) { |
---|
1041 | 1082 | brelse(bh); |
---|
1042 | 1083 | return err; |
---|
1043 | 1084 | } |
---|
1044 | 1085 | } |
---|
1045 | | -#endif |
---|
| 1086 | + |
---|
1046 | 1087 | for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) { |
---|
1047 | 1088 | if (ext4_check_dir_entry(dir, NULL, de, bh, |
---|
1048 | 1089 | bh->b_data, bh->b_size, block, |
---|
.. | .. |
---|
1100 | 1141 | } |
---|
1101 | 1142 | errout: |
---|
1102 | 1143 | brelse(bh); |
---|
1103 | | -#ifdef CONFIG_FS_ENCRYPTION |
---|
1104 | 1144 | fscrypt_fname_free_buffer(&fname_crypto_str); |
---|
1105 | | -#endif |
---|
1106 | 1145 | return count; |
---|
1107 | 1146 | } |
---|
1108 | 1147 | |
---|
.. | .. |
---|
1143 | 1182 | hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed; |
---|
1144 | 1183 | if (ext4_has_inline_data(dir)) { |
---|
1145 | 1184 | int has_inline_data = 1; |
---|
1146 | | - count = htree_inlinedir_to_tree(dir_file, dir, 0, |
---|
1147 | | - &hinfo, start_hash, |
---|
1148 | | - start_minor_hash, |
---|
1149 | | - &has_inline_data); |
---|
| 1185 | + count = ext4_inlinedir_to_tree(dir_file, dir, 0, |
---|
| 1186 | + &hinfo, start_hash, |
---|
| 1187 | + start_minor_hash, |
---|
| 1188 | + &has_inline_data); |
---|
1150 | 1189 | if (has_inline_data) { |
---|
1151 | 1190 | *next_hash = ~0; |
---|
1152 | 1191 | return count; |
---|
.. | .. |
---|
1262 | 1301 | map_tail--; |
---|
1263 | 1302 | map_tail->hash = h.hash; |
---|
1264 | 1303 | map_tail->offs = ((char *) de - base)>>2; |
---|
1265 | | - map_tail->size = le16_to_cpu(de->rec_len); |
---|
| 1304 | + map_tail->size = ext4_rec_len_from_disk(de->rec_len, |
---|
| 1305 | + blocksize); |
---|
1266 | 1306 | count++; |
---|
1267 | 1307 | cond_resched(); |
---|
1268 | 1308 | } |
---|
1269 | | - /* XXX: do we need to check rec_len == 0 case? -Chris */ |
---|
1270 | 1309 | de = ext4_next_entry(de, blocksize); |
---|
1271 | 1310 | } |
---|
1272 | 1311 | return count; |
---|
.. | .. |
---|
1354 | 1393 | /* Handle invalid character sequence as either an error |
---|
1355 | 1394 | * or as an opaque byte sequence. |
---|
1356 | 1395 | */ |
---|
1357 | | - if (sb_has_enc_strict_mode(sb)) |
---|
| 1396 | + if (sb_has_strict_encoding(sb)) |
---|
1358 | 1397 | ret = -EINVAL; |
---|
1359 | 1398 | else if (name->len != entry.len) |
---|
1360 | 1399 | ret = 1; |
---|
.. | .. |
---|
1373 | 1412 | struct dx_hash_info *hinfo = &name->hinfo; |
---|
1374 | 1413 | int len; |
---|
1375 | 1414 | |
---|
1376 | | - if (!needs_casefold(dir)) { |
---|
| 1415 | + if (!IS_CASEFOLDED(dir) || !dir->i_sb->s_encoding || |
---|
| 1416 | + (IS_ENCRYPTED(dir) && !fscrypt_has_encryption_key(dir))) { |
---|
1377 | 1417 | cf_name->name = NULL; |
---|
1378 | 1418 | return 0; |
---|
1379 | 1419 | } |
---|
.. | .. |
---|
1424 | 1464 | #endif |
---|
1425 | 1465 | |
---|
1426 | 1466 | #ifdef CONFIG_UNICODE |
---|
1427 | | - if (needs_casefold(parent)) { |
---|
| 1467 | + if (parent->i_sb->s_encoding && IS_CASEFOLDED(parent) && |
---|
| 1468 | + (!IS_ENCRYPTED(parent) || fscrypt_has_encryption_key(parent))) { |
---|
1428 | 1469 | if (fname->cf_name.name) { |
---|
1429 | 1470 | struct qstr cf = {.name = fname->cf_name.name, |
---|
1430 | 1471 | .len = fname->cf_name.len}; |
---|
.. | .. |
---|
1461 | 1502 | |
---|
1462 | 1503 | de = (struct ext4_dir_entry_2 *)search_buf; |
---|
1463 | 1504 | dlimit = search_buf + buf_size; |
---|
1464 | | - while ((char *) de < dlimit) { |
---|
| 1505 | + while ((char *) de < dlimit - EXT4_BASE_DIR_LEN) { |
---|
1465 | 1506 | /* this code is executed quadratically often */ |
---|
1466 | 1507 | /* do minimal checking `by hand' */ |
---|
1467 | | - if ((char *) de + de->name_len <= dlimit && |
---|
| 1508 | + if (de->name + de->name_len <= dlimit && |
---|
1468 | 1509 | ext4_match(dir, fname, de)) { |
---|
1469 | 1510 | /* found a match - just to be sure, do |
---|
1470 | 1511 | * a full check */ |
---|
.. | .. |
---|
1541 | 1582 | &has_inline_data); |
---|
1542 | 1583 | if (lblk) |
---|
1543 | 1584 | *lblk = 0; |
---|
1544 | | - if (has_inline_data) { |
---|
1545 | | - if (inlined) |
---|
1546 | | - *inlined = 1; |
---|
| 1585 | + if (inlined) |
---|
| 1586 | + *inlined = has_inline_data; |
---|
| 1587 | + if (has_inline_data) |
---|
1547 | 1588 | goto cleanup_and_exit; |
---|
1548 | | - } |
---|
1549 | 1589 | } |
---|
1550 | 1590 | |
---|
1551 | 1591 | if ((namelen <= 2) && (name[0] == '.') && |
---|
.. | .. |
---|
1606 | 1646 | goto next; |
---|
1607 | 1647 | wait_on_buffer(bh); |
---|
1608 | 1648 | if (!buffer_uptodate(bh)) { |
---|
1609 | | - EXT4_ERROR_INODE(dir, "reading directory lblock %lu", |
---|
1610 | | - (unsigned long) block); |
---|
| 1649 | + EXT4_ERROR_INODE_ERR(dir, EIO, |
---|
| 1650 | + "reading directory lblock %lu", |
---|
| 1651 | + (unsigned long) block); |
---|
1611 | 1652 | brelse(bh); |
---|
1612 | 1653 | ret = ERR_PTR(-EIO); |
---|
1613 | 1654 | goto cleanup_and_exit; |
---|
.. | .. |
---|
1615 | 1656 | if (!buffer_verified(bh) && |
---|
1616 | 1657 | !is_dx_internal_node(dir, block, |
---|
1617 | 1658 | (struct ext4_dir_entry *)bh->b_data) && |
---|
1618 | | - !ext4_dirent_csum_verify(dir, |
---|
1619 | | - (struct ext4_dir_entry *)bh->b_data)) { |
---|
1620 | | - EXT4_ERROR_INODE(dir, "checksumming directory " |
---|
1621 | | - "block %lu", (unsigned long)block); |
---|
| 1659 | + !ext4_dirblock_csum_verify(dir, bh)) { |
---|
| 1660 | + EXT4_ERROR_INODE_ERR(dir, EFSBADCRC, |
---|
| 1661 | + "checksumming directory " |
---|
| 1662 | + "block %lu", (unsigned long)block); |
---|
1622 | 1663 | brelse(bh); |
---|
1623 | 1664 | ret = ERR_PTR(-EFSBADCRC); |
---|
1624 | 1665 | goto cleanup_and_exit; |
---|
.. | .. |
---|
1690 | 1731 | struct buffer_head *bh; |
---|
1691 | 1732 | |
---|
1692 | 1733 | err = ext4_fname_prepare_lookup(dir, dentry, &fname); |
---|
1693 | | - generic_set_encrypted_ci_d_ops(dir, dentry); |
---|
| 1734 | + generic_set_encrypted_ci_d_ops(dentry); |
---|
1694 | 1735 | if (err == -ENOENT) |
---|
1695 | 1736 | return NULL; |
---|
1696 | 1737 | if (err) |
---|
.. | .. |
---|
1768 | 1809 | |
---|
1769 | 1810 | bh = ext4_lookup_entry(dir, dentry, &de); |
---|
1770 | 1811 | if (IS_ERR(bh)) |
---|
1771 | | - return (struct dentry *) bh; |
---|
| 1812 | + return ERR_CAST(bh); |
---|
1772 | 1813 | inode = NULL; |
---|
1773 | 1814 | if (bh) { |
---|
1774 | 1815 | __u32 ino = le32_to_cpu(de->inode); |
---|
.. | .. |
---|
1823 | 1864 | |
---|
1824 | 1865 | bh = ext4_find_entry(d_inode(child), &dotdot, &de, NULL, NULL); |
---|
1825 | 1866 | if (IS_ERR(bh)) |
---|
1826 | | - return (struct dentry *) bh; |
---|
| 1867 | + return ERR_CAST(bh); |
---|
1827 | 1868 | if (!bh) |
---|
1828 | 1869 | return ERR_PTR(-ENOENT); |
---|
1829 | 1870 | ino = le32_to_cpu(de->inode); |
---|
.. | .. |
---|
1900 | 1941 | struct dx_hash_info *hinfo, ext4_lblk_t *newblock) |
---|
1901 | 1942 | { |
---|
1902 | 1943 | unsigned blocksize = dir->i_sb->s_blocksize; |
---|
1903 | | - unsigned count, continued; |
---|
| 1944 | + unsigned continued; |
---|
| 1945 | + int count; |
---|
1904 | 1946 | struct buffer_head *bh2; |
---|
1905 | 1947 | u32 hash2; |
---|
1906 | 1948 | struct dx_map_entry *map; |
---|
1907 | 1949 | char *data1 = (*bh)->b_data, *data2; |
---|
1908 | 1950 | unsigned split, move, size; |
---|
1909 | 1951 | struct ext4_dir_entry_2 *de = NULL, *de2; |
---|
1910 | | - struct ext4_dir_entry_tail *t; |
---|
1911 | 1952 | int csum_size = 0; |
---|
1912 | 1953 | int err = 0, i; |
---|
1913 | 1954 | |
---|
.. | .. |
---|
1978 | 2019 | (char *) de2, |
---|
1979 | 2020 | blocksize); |
---|
1980 | 2021 | if (csum_size) { |
---|
1981 | | - t = EXT4_DIRENT_TAIL(data2, blocksize); |
---|
1982 | | - initialize_dirent_tail(t, blocksize); |
---|
1983 | | - |
---|
1984 | | - t = EXT4_DIRENT_TAIL(data1, blocksize); |
---|
1985 | | - initialize_dirent_tail(t, blocksize); |
---|
| 2022 | + ext4_initialize_dirent_tail(*bh, blocksize); |
---|
| 2023 | + ext4_initialize_dirent_tail(bh2, blocksize); |
---|
1986 | 2024 | } |
---|
1987 | 2025 | |
---|
1988 | 2026 | dxtrace(dx_show_leaf(dir, hinfo, (struct ext4_dir_entry_2 *) data1, |
---|
.. | .. |
---|
1996 | 2034 | de = de2; |
---|
1997 | 2035 | } |
---|
1998 | 2036 | dx_insert_block(frame, hash2 + continued, *newblock); |
---|
1999 | | - err = ext4_handle_dirty_dirent_node(handle, dir, bh2); |
---|
| 2037 | + err = ext4_handle_dirty_dirblock(handle, dir, bh2); |
---|
2000 | 2038 | if (err) |
---|
2001 | 2039 | goto journal_error; |
---|
2002 | 2040 | err = ext4_handle_dirty_dx_node(handle, dir, frame->bh); |
---|
.. | .. |
---|
2097 | 2135 | { |
---|
2098 | 2136 | unsigned int blocksize = dir->i_sb->s_blocksize; |
---|
2099 | 2137 | int csum_size = 0; |
---|
2100 | | - int err; |
---|
| 2138 | + int err, err2; |
---|
2101 | 2139 | |
---|
2102 | 2140 | if (ext4_has_metadata_csum(inode->i_sb)) |
---|
2103 | 2141 | csum_size = sizeof(struct ext4_dir_entry_tail); |
---|
.. | .. |
---|
2132 | 2170 | dir->i_mtime = dir->i_ctime = current_time(dir); |
---|
2133 | 2171 | ext4_update_dx_flag(dir); |
---|
2134 | 2172 | inode_inc_iversion(dir); |
---|
2135 | | - ext4_mark_inode_dirty(handle, dir); |
---|
| 2173 | + err2 = ext4_mark_inode_dirty(handle, dir); |
---|
2136 | 2174 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); |
---|
2137 | | - err = ext4_handle_dirty_dirent_node(handle, dir, bh); |
---|
| 2175 | + err = ext4_handle_dirty_dirblock(handle, dir, bh); |
---|
2138 | 2176 | if (err) |
---|
2139 | 2177 | ext4_std_error(dir->i_sb, err); |
---|
2140 | | - return 0; |
---|
| 2178 | + return err ? err : err2; |
---|
2141 | 2179 | } |
---|
2142 | 2180 | |
---|
2143 | 2181 | /* |
---|
.. | .. |
---|
2153 | 2191 | struct dx_frame frames[EXT4_HTREE_LEVEL], *frame; |
---|
2154 | 2192 | struct dx_entry *entries; |
---|
2155 | 2193 | struct ext4_dir_entry_2 *de, *de2; |
---|
2156 | | - struct ext4_dir_entry_tail *t; |
---|
2157 | | - char *data1, *top; |
---|
| 2194 | + char *data2, *top; |
---|
2158 | 2195 | unsigned len; |
---|
2159 | 2196 | int retval; |
---|
2160 | 2197 | unsigned blocksize; |
---|
.. | .. |
---|
2194 | 2231 | return PTR_ERR(bh2); |
---|
2195 | 2232 | } |
---|
2196 | 2233 | ext4_set_inode_flag(dir, EXT4_INODE_INDEX); |
---|
2197 | | - data1 = bh2->b_data; |
---|
| 2234 | + data2 = bh2->b_data; |
---|
2198 | 2235 | |
---|
2199 | | - memcpy (data1, de, len); |
---|
2200 | | - de = (struct ext4_dir_entry_2 *) data1; |
---|
2201 | | - top = data1 + len; |
---|
2202 | | - while ((char *)(de2 = ext4_next_entry(de, blocksize)) < top) |
---|
| 2236 | + memcpy(data2, de, len); |
---|
| 2237 | + de = (struct ext4_dir_entry_2 *) data2; |
---|
| 2238 | + top = data2 + len; |
---|
| 2239 | + while ((char *)(de2 = ext4_next_entry(de, blocksize)) < top) { |
---|
| 2240 | + if (ext4_check_dir_entry(dir, NULL, de, bh2, data2, len, block, |
---|
| 2241 | + (data2 + (blocksize - csum_size) - |
---|
| 2242 | + (char *) de))) { |
---|
| 2243 | + brelse(bh2); |
---|
| 2244 | + brelse(bh); |
---|
| 2245 | + return -EFSCORRUPTED; |
---|
| 2246 | + } |
---|
2203 | 2247 | de = de2; |
---|
2204 | | - de->rec_len = ext4_rec_len_to_disk(data1 + (blocksize - csum_size) - |
---|
2205 | | - (char *) de, |
---|
2206 | | - blocksize); |
---|
2207 | | - |
---|
2208 | | - if (csum_size) { |
---|
2209 | | - t = EXT4_DIRENT_TAIL(data1, blocksize); |
---|
2210 | | - initialize_dirent_tail(t, blocksize); |
---|
2211 | 2248 | } |
---|
| 2249 | + de->rec_len = ext4_rec_len_to_disk(data2 + (blocksize - csum_size) - |
---|
| 2250 | + (char *) de, blocksize); |
---|
| 2251 | + |
---|
| 2252 | + if (csum_size) |
---|
| 2253 | + ext4_initialize_dirent_tail(bh2, blocksize); |
---|
2212 | 2254 | |
---|
2213 | 2255 | /* Initialize the root; the dot dirents already exist */ |
---|
2214 | 2256 | de = (struct ext4_dir_entry_2 *) (&root->dotdot); |
---|
.. | .. |
---|
2247 | 2289 | retval = ext4_handle_dirty_dx_node(handle, dir, frame->bh); |
---|
2248 | 2290 | if (retval) |
---|
2249 | 2291 | goto out_frames; |
---|
2250 | | - retval = ext4_handle_dirty_dirent_node(handle, dir, bh2); |
---|
| 2292 | + retval = ext4_handle_dirty_dirblock(handle, dir, bh2); |
---|
2251 | 2293 | if (retval) |
---|
2252 | 2294 | goto out_frames; |
---|
2253 | 2295 | |
---|
.. | .. |
---|
2287 | 2329 | struct inode *dir = d_inode(dentry->d_parent); |
---|
2288 | 2330 | struct buffer_head *bh = NULL; |
---|
2289 | 2331 | struct ext4_dir_entry_2 *de; |
---|
2290 | | - struct ext4_dir_entry_tail *t; |
---|
2291 | 2332 | struct super_block *sb; |
---|
2292 | 2333 | struct ext4_filename fname; |
---|
2293 | 2334 | int retval; |
---|
.. | .. |
---|
2304 | 2345 | if (!dentry->d_name.len) |
---|
2305 | 2346 | return -EINVAL; |
---|
2306 | 2347 | |
---|
| 2348 | + if (fscrypt_is_nokey_name(dentry)) |
---|
| 2349 | + return -ENOKEY; |
---|
| 2350 | + |
---|
2307 | 2351 | #ifdef CONFIG_UNICODE |
---|
2308 | | - if (sb_has_enc_strict_mode(sb) && IS_CASEFOLDED(dir) && |
---|
| 2352 | + if (sb_has_strict_encoding(sb) && IS_CASEFOLDED(dir) && |
---|
2309 | 2353 | sb->s_encoding && utf8_validate(sb->s_encoding, &dentry->d_name)) |
---|
2310 | 2354 | return -EINVAL; |
---|
2311 | 2355 | #endif |
---|
2312 | | - |
---|
2313 | | - if (fscrypt_is_nokey_name(dentry)) |
---|
2314 | | - return -ENOKEY; |
---|
2315 | 2356 | |
---|
2316 | 2357 | retval = ext4_fname_setup_filename(dir, &dentry->d_name, 0, &fname); |
---|
2317 | 2358 | if (retval) |
---|
.. | .. |
---|
2340 | 2381 | } |
---|
2341 | 2382 | ext4_clear_inode_flag(dir, EXT4_INODE_INDEX); |
---|
2342 | 2383 | dx_fallback++; |
---|
2343 | | - ext4_mark_inode_dirty(handle, dir); |
---|
| 2384 | + retval = ext4_mark_inode_dirty(handle, dir); |
---|
| 2385 | + if (unlikely(retval)) |
---|
| 2386 | + goto out; |
---|
2344 | 2387 | } |
---|
2345 | 2388 | blocks = dir->i_size >> sb->s_blocksize_bits; |
---|
2346 | 2389 | for (block = 0; block < blocks; block++) { |
---|
.. | .. |
---|
2380 | 2423 | de->inode = 0; |
---|
2381 | 2424 | de->rec_len = ext4_rec_len_to_disk(blocksize - csum_size, blocksize); |
---|
2382 | 2425 | |
---|
2383 | | - if (csum_size) { |
---|
2384 | | - t = EXT4_DIRENT_TAIL(bh->b_data, blocksize); |
---|
2385 | | - initialize_dirent_tail(t, blocksize); |
---|
2386 | | - } |
---|
| 2426 | + if (csum_size) |
---|
| 2427 | + ext4_initialize_dirent_tail(bh, blocksize); |
---|
2387 | 2428 | |
---|
2388 | 2429 | retval = add_dirent_to_buf(handle, &fname, dir, inode, de, block, bh); |
---|
2389 | 2430 | out: |
---|
.. | .. |
---|
2573 | 2614 | * ext4_generic_delete_entry deletes a directory entry by merging it |
---|
2574 | 2615 | * with the previous entry |
---|
2575 | 2616 | */ |
---|
2576 | | -int ext4_generic_delete_entry(handle_t *handle, |
---|
2577 | | - struct inode *dir, |
---|
| 2617 | +int ext4_generic_delete_entry(struct inode *dir, |
---|
2578 | 2618 | struct ext4_dir_entry_2 *de_del, |
---|
2579 | 2619 | ext4_lblk_t lblk, |
---|
2580 | 2620 | struct buffer_head *bh, |
---|
.. | .. |
---|
2637 | 2677 | if (unlikely(err)) |
---|
2638 | 2678 | goto out; |
---|
2639 | 2679 | |
---|
2640 | | - err = ext4_generic_delete_entry(handle, dir, de_del, lblk, |
---|
2641 | | - bh, bh->b_data, |
---|
| 2680 | + err = ext4_generic_delete_entry(dir, de_del, lblk, bh, bh->b_data, |
---|
2642 | 2681 | dir->i_sb->s_blocksize, csum_size); |
---|
2643 | 2682 | if (err) |
---|
2644 | 2683 | goto out; |
---|
2645 | 2684 | |
---|
2646 | 2685 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); |
---|
2647 | | - err = ext4_handle_dirty_dirent_node(handle, dir, bh); |
---|
| 2686 | + err = ext4_handle_dirty_dirblock(handle, dir, bh); |
---|
2648 | 2687 | if (unlikely(err)) |
---|
2649 | 2688 | goto out; |
---|
2650 | 2689 | |
---|
.. | .. |
---|
2666 | 2705 | * for checking S_ISDIR(inode) (since the INODE_INDEX feature will not be set |
---|
2667 | 2706 | * on regular files) and to avoid creating huge/slow non-HTREE directories. |
---|
2668 | 2707 | */ |
---|
2669 | | -static void ext4_inc_count(handle_t *handle, struct inode *inode) |
---|
| 2708 | +static void ext4_inc_count(struct inode *inode) |
---|
2670 | 2709 | { |
---|
2671 | 2710 | inc_nlink(inode); |
---|
2672 | 2711 | if (is_dx(inode) && |
---|
.. | .. |
---|
2678 | 2717 | * If a directory had nlink == 1, then we should let it be 1. This indicates |
---|
2679 | 2718 | * directory has >EXT4_LINK_MAX subdirs. |
---|
2680 | 2719 | */ |
---|
2681 | | -static void ext4_dec_count(handle_t *handle, struct inode *inode) |
---|
| 2720 | +static void ext4_dec_count(struct inode *inode) |
---|
2682 | 2721 | { |
---|
2683 | 2722 | if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2) |
---|
2684 | 2723 | drop_nlink(inode); |
---|
2685 | 2724 | } |
---|
2686 | 2725 | |
---|
2687 | 2726 | |
---|
| 2727 | +/* |
---|
| 2728 | + * Add non-directory inode to a directory. On success, the inode reference is |
---|
| 2729 | + * consumed by dentry is instantiation. This is also indicated by clearing of |
---|
| 2730 | + * *inodep pointer. On failure, the caller is responsible for dropping the |
---|
| 2731 | + * inode reference in the safe context. |
---|
| 2732 | + */ |
---|
2688 | 2733 | static int ext4_add_nondir(handle_t *handle, |
---|
2689 | | - struct dentry *dentry, struct inode *inode) |
---|
| 2734 | + struct dentry *dentry, struct inode **inodep) |
---|
2690 | 2735 | { |
---|
| 2736 | + struct inode *dir = d_inode(dentry->d_parent); |
---|
| 2737 | + struct inode *inode = *inodep; |
---|
2691 | 2738 | int err = ext4_add_entry(handle, dentry, inode); |
---|
2692 | 2739 | if (!err) { |
---|
2693 | | - ext4_mark_inode_dirty(handle, inode); |
---|
| 2740 | + err = ext4_mark_inode_dirty(handle, inode); |
---|
| 2741 | + if (IS_DIRSYNC(dir)) |
---|
| 2742 | + ext4_handle_sync(handle); |
---|
2694 | 2743 | d_instantiate_new(dentry, inode); |
---|
2695 | | - return 0; |
---|
| 2744 | + *inodep = NULL; |
---|
| 2745 | + return err; |
---|
2696 | 2746 | } |
---|
2697 | 2747 | drop_nlink(inode); |
---|
| 2748 | + ext4_orphan_add(handle, inode); |
---|
2698 | 2749 | unlock_new_inode(inode); |
---|
2699 | | - iput(inode); |
---|
2700 | 2750 | return err; |
---|
2701 | 2751 | } |
---|
2702 | 2752 | |
---|
.. | .. |
---|
2730 | 2780 | inode->i_op = &ext4_file_inode_operations; |
---|
2731 | 2781 | inode->i_fop = &ext4_file_operations; |
---|
2732 | 2782 | ext4_set_aops(inode); |
---|
2733 | | - err = ext4_add_nondir(handle, dentry, inode); |
---|
2734 | | - if (!err && IS_DIRSYNC(dir)) |
---|
2735 | | - ext4_handle_sync(handle); |
---|
| 2783 | + err = ext4_add_nondir(handle, dentry, &inode); |
---|
| 2784 | + if (!err) |
---|
| 2785 | + ext4_fc_track_create(handle, dentry); |
---|
2736 | 2786 | } |
---|
2737 | 2787 | if (handle) |
---|
2738 | 2788 | ext4_journal_stop(handle); |
---|
| 2789 | + if (!IS_ERR_OR_NULL(inode)) |
---|
| 2790 | + iput(inode); |
---|
2739 | 2791 | if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) |
---|
2740 | 2792 | goto retry; |
---|
2741 | 2793 | return err; |
---|
.. | .. |
---|
2762 | 2814 | if (!IS_ERR(inode)) { |
---|
2763 | 2815 | init_special_inode(inode, inode->i_mode, rdev); |
---|
2764 | 2816 | inode->i_op = &ext4_special_inode_operations; |
---|
2765 | | - err = ext4_add_nondir(handle, dentry, inode); |
---|
2766 | | - if (!err && IS_DIRSYNC(dir)) |
---|
2767 | | - ext4_handle_sync(handle); |
---|
| 2817 | + err = ext4_add_nondir(handle, dentry, &inode); |
---|
| 2818 | + if (!err) |
---|
| 2819 | + ext4_fc_track_create(handle, dentry); |
---|
2768 | 2820 | } |
---|
2769 | 2821 | if (handle) |
---|
2770 | 2822 | ext4_journal_stop(handle); |
---|
| 2823 | + if (!IS_ERR_OR_NULL(inode)) |
---|
| 2824 | + iput(inode); |
---|
2771 | 2825 | if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) |
---|
2772 | 2826 | goto retry; |
---|
2773 | 2827 | return err; |
---|
.. | .. |
---|
2842 | 2896 | return ext4_next_entry(de, blocksize); |
---|
2843 | 2897 | } |
---|
2844 | 2898 | |
---|
2845 | | -static int ext4_init_new_dir(handle_t *handle, struct inode *dir, |
---|
| 2899 | +int ext4_init_new_dir(handle_t *handle, struct inode *dir, |
---|
2846 | 2900 | struct inode *inode) |
---|
2847 | 2901 | { |
---|
2848 | 2902 | struct buffer_head *dir_block = NULL; |
---|
2849 | 2903 | struct ext4_dir_entry_2 *de; |
---|
2850 | | - struct ext4_dir_entry_tail *t; |
---|
2851 | 2904 | ext4_lblk_t block = 0; |
---|
2852 | 2905 | unsigned int blocksize = dir->i_sb->s_blocksize; |
---|
2853 | 2906 | int csum_size = 0; |
---|
.. | .. |
---|
2871 | 2924 | de = (struct ext4_dir_entry_2 *)dir_block->b_data; |
---|
2872 | 2925 | ext4_init_dot_dotdot(inode, de, blocksize, csum_size, dir->i_ino, 0); |
---|
2873 | 2926 | set_nlink(inode, 2); |
---|
2874 | | - if (csum_size) { |
---|
2875 | | - t = EXT4_DIRENT_TAIL(dir_block->b_data, blocksize); |
---|
2876 | | - initialize_dirent_tail(t, blocksize); |
---|
2877 | | - } |
---|
| 2927 | + if (csum_size) |
---|
| 2928 | + ext4_initialize_dirent_tail(dir_block, blocksize); |
---|
2878 | 2929 | |
---|
2879 | 2930 | BUFFER_TRACE(dir_block, "call ext4_handle_dirty_metadata"); |
---|
2880 | | - err = ext4_handle_dirty_dirent_node(handle, inode, dir_block); |
---|
| 2931 | + err = ext4_handle_dirty_dirblock(handle, inode, dir_block); |
---|
2881 | 2932 | if (err) |
---|
2882 | 2933 | goto out; |
---|
2883 | 2934 | set_buffer_verified(dir_block); |
---|
.. | .. |
---|
2890 | 2941 | { |
---|
2891 | 2942 | handle_t *handle; |
---|
2892 | 2943 | struct inode *inode; |
---|
2893 | | - int err, credits, retries = 0; |
---|
| 2944 | + int err, err2 = 0, credits, retries = 0; |
---|
2894 | 2945 | |
---|
2895 | 2946 | if (EXT4_DIR_LINK_MAX(dir)) |
---|
2896 | 2947 | return -EMLINK; |
---|
.. | .. |
---|
2921 | 2972 | if (err) { |
---|
2922 | 2973 | out_clear_inode: |
---|
2923 | 2974 | clear_nlink(inode); |
---|
| 2975 | + ext4_orphan_add(handle, inode); |
---|
2924 | 2976 | unlock_new_inode(inode); |
---|
2925 | | - ext4_mark_inode_dirty(handle, inode); |
---|
| 2977 | + err2 = ext4_mark_inode_dirty(handle, inode); |
---|
| 2978 | + if (unlikely(err2)) |
---|
| 2979 | + err = err2; |
---|
| 2980 | + ext4_journal_stop(handle); |
---|
2926 | 2981 | iput(inode); |
---|
2927 | | - goto out_stop; |
---|
| 2982 | + goto out_retry; |
---|
2928 | 2983 | } |
---|
2929 | | - ext4_inc_count(handle, dir); |
---|
| 2984 | + ext4_inc_count(dir); |
---|
| 2985 | + |
---|
2930 | 2986 | ext4_update_dx_flag(dir); |
---|
2931 | 2987 | err = ext4_mark_inode_dirty(handle, dir); |
---|
2932 | 2988 | if (err) |
---|
2933 | 2989 | goto out_clear_inode; |
---|
2934 | 2990 | d_instantiate_new(dentry, inode); |
---|
| 2991 | + ext4_fc_track_create(handle, dentry); |
---|
2935 | 2992 | if (IS_DIRSYNC(dir)) |
---|
2936 | 2993 | ext4_handle_sync(handle); |
---|
2937 | 2994 | |
---|
2938 | 2995 | out_stop: |
---|
2939 | 2996 | if (handle) |
---|
2940 | 2997 | ext4_journal_stop(handle); |
---|
| 2998 | +out_retry: |
---|
2941 | 2999 | if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) |
---|
2942 | 3000 | goto retry; |
---|
2943 | 3001 | return err; |
---|
.. | .. |
---|
2966 | 3024 | if (inode->i_size < ext4_dir_rec_len(1, NULL) + |
---|
2967 | 3025 | ext4_dir_rec_len(2, NULL)) { |
---|
2968 | 3026 | EXT4_ERROR_INODE(inode, "invalid size"); |
---|
2969 | | - return true; |
---|
| 3027 | + return false; |
---|
2970 | 3028 | } |
---|
2971 | 3029 | /* The first directory block must not be a hole, |
---|
2972 | 3030 | * so treat it as DIRENT_HTREE |
---|
2973 | 3031 | */ |
---|
2974 | 3032 | bh = ext4_read_dirblock(inode, 0, DIRENT_HTREE); |
---|
2975 | 3033 | if (IS_ERR(bh)) |
---|
2976 | | - return true; |
---|
| 3034 | + return false; |
---|
2977 | 3035 | |
---|
2978 | 3036 | de = (struct ext4_dir_entry_2 *) bh->b_data; |
---|
2979 | 3037 | if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, bh->b_size, 0, |
---|
.. | .. |
---|
2981 | 3039 | le32_to_cpu(de->inode) != inode->i_ino || strcmp(".", de->name)) { |
---|
2982 | 3040 | ext4_warning_inode(inode, "directory missing '.'"); |
---|
2983 | 3041 | brelse(bh); |
---|
2984 | | - return true; |
---|
| 3042 | + return false; |
---|
2985 | 3043 | } |
---|
2986 | 3044 | offset = ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize); |
---|
2987 | 3045 | de = ext4_next_entry(de, sb->s_blocksize); |
---|
.. | .. |
---|
2990 | 3048 | le32_to_cpu(de->inode) == 0 || strcmp("..", de->name)) { |
---|
2991 | 3049 | ext4_warning_inode(inode, "directory missing '..'"); |
---|
2992 | 3050 | brelse(bh); |
---|
2993 | | - return true; |
---|
| 3051 | + return false; |
---|
2994 | 3052 | } |
---|
2995 | 3053 | offset += ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize); |
---|
2996 | 3054 | while (offset < inode->i_size) { |
---|
.. | .. |
---|
3004 | 3062 | continue; |
---|
3005 | 3063 | } |
---|
3006 | 3064 | if (IS_ERR(bh)) |
---|
3007 | | - return true; |
---|
| 3065 | + return false; |
---|
3008 | 3066 | } |
---|
3009 | 3067 | de = (struct ext4_dir_entry_2 *) (bh->b_data + |
---|
3010 | 3068 | (offset & (sb->s_blocksize - 1))); |
---|
3011 | 3069 | if (ext4_check_dir_entry(inode, NULL, de, bh, |
---|
3012 | | - bh->b_data, bh->b_size, 0, offset)) { |
---|
3013 | | - offset = (offset | (sb->s_blocksize - 1)) + 1; |
---|
3014 | | - continue; |
---|
3015 | | - } |
---|
3016 | | - if (le32_to_cpu(de->inode)) { |
---|
| 3070 | + bh->b_data, bh->b_size, 0, offset) || |
---|
| 3071 | + le32_to_cpu(de->inode)) { |
---|
3017 | 3072 | brelse(bh); |
---|
3018 | 3073 | return false; |
---|
3019 | 3074 | } |
---|
.. | .. |
---|
3263 | 3318 | inode->i_size = 0; |
---|
3264 | 3319 | ext4_orphan_add(handle, inode); |
---|
3265 | 3320 | inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode); |
---|
3266 | | - ext4_mark_inode_dirty(handle, inode); |
---|
3267 | | - ext4_dec_count(handle, dir); |
---|
| 3321 | + retval = ext4_mark_inode_dirty(handle, inode); |
---|
| 3322 | + if (retval) |
---|
| 3323 | + goto end_rmdir; |
---|
| 3324 | + ext4_dec_count(dir); |
---|
3268 | 3325 | ext4_update_dx_flag(dir); |
---|
3269 | | - ext4_mark_inode_dirty(handle, dir); |
---|
| 3326 | + ext4_fc_track_unlink(handle, dentry); |
---|
| 3327 | + retval = ext4_mark_inode_dirty(handle, dir); |
---|
3270 | 3328 | |
---|
3271 | 3329 | #ifdef CONFIG_UNICODE |
---|
3272 | 3330 | /* VFS negative dentries are incompatible with Encoding and |
---|
.. | .. |
---|
3286 | 3344 | return retval; |
---|
3287 | 3345 | } |
---|
3288 | 3346 | |
---|
3289 | | -static int ext4_unlink(struct inode *dir, struct dentry *dentry) |
---|
| 3347 | +int __ext4_unlink(struct inode *dir, const struct qstr *d_name, |
---|
| 3348 | + struct inode *inode, |
---|
| 3349 | + struct dentry *dentry /* NULL during fast_commit recovery */) |
---|
3290 | 3350 | { |
---|
3291 | | - int retval; |
---|
3292 | | - struct inode *inode; |
---|
| 3351 | + int retval = -ENOENT; |
---|
3293 | 3352 | struct buffer_head *bh; |
---|
3294 | 3353 | struct ext4_dir_entry_2 *de; |
---|
3295 | | - handle_t *handle = NULL; |
---|
| 3354 | + handle_t *handle; |
---|
| 3355 | + int skip_remove_dentry = 0; |
---|
3296 | 3356 | ext4_lblk_t lblk; |
---|
3297 | 3357 | |
---|
3298 | | - if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb)))) |
---|
3299 | | - return -EIO; |
---|
3300 | | - |
---|
3301 | | - trace_ext4_unlink_enter(dir, dentry); |
---|
3302 | | - /* Initialize quotas before so that eventual writes go |
---|
3303 | | - * in separate transaction */ |
---|
3304 | | - retval = dquot_initialize(dir); |
---|
3305 | | - if (retval) |
---|
3306 | | - return retval; |
---|
3307 | | - retval = dquot_initialize(d_inode(dentry)); |
---|
3308 | | - if (retval) |
---|
3309 | | - return retval; |
---|
3310 | | - |
---|
3311 | | - retval = -ENOENT; |
---|
3312 | | - bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL, &lblk); |
---|
| 3358 | + /* |
---|
| 3359 | + * Keep this outside the transaction; it may have to set up the |
---|
| 3360 | + * directory's encryption key, which isn't GFP_NOFS-safe. |
---|
| 3361 | + */ |
---|
| 3362 | + bh = ext4_find_entry(dir, d_name, &de, NULL, &lblk); |
---|
3313 | 3363 | if (IS_ERR(bh)) |
---|
3314 | 3364 | return PTR_ERR(bh); |
---|
| 3365 | + |
---|
3315 | 3366 | if (!bh) |
---|
3316 | | - goto end_unlink; |
---|
| 3367 | + return -ENOENT; |
---|
3317 | 3368 | |
---|
3318 | | - inode = d_inode(dentry); |
---|
3319 | | - |
---|
3320 | | - retval = -EFSCORRUPTED; |
---|
3321 | | - if (le32_to_cpu(de->inode) != inode->i_ino) |
---|
3322 | | - goto end_unlink; |
---|
| 3369 | + if (le32_to_cpu(de->inode) != inode->i_ino) { |
---|
| 3370 | + /* |
---|
| 3371 | + * It's okay if we find dont find dentry which matches |
---|
| 3372 | + * the inode. That's because it might have gotten |
---|
| 3373 | + * renamed to a different inode number |
---|
| 3374 | + */ |
---|
| 3375 | + if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY) |
---|
| 3376 | + skip_remove_dentry = 1; |
---|
| 3377 | + else |
---|
| 3378 | + goto out_bh; |
---|
| 3379 | + } |
---|
3323 | 3380 | |
---|
3324 | 3381 | handle = ext4_journal_start(dir, EXT4_HT_DIR, |
---|
3325 | 3382 | EXT4_DATA_TRANS_BLOCKS(dir->i_sb)); |
---|
3326 | 3383 | if (IS_ERR(handle)) { |
---|
3327 | 3384 | retval = PTR_ERR(handle); |
---|
3328 | | - handle = NULL; |
---|
3329 | | - goto end_unlink; |
---|
| 3385 | + goto out_bh; |
---|
3330 | 3386 | } |
---|
3331 | 3387 | |
---|
3332 | 3388 | if (IS_DIRSYNC(dir)) |
---|
3333 | 3389 | ext4_handle_sync(handle); |
---|
3334 | 3390 | |
---|
3335 | | - retval = ext4_delete_entry(handle, dir, de, lblk, bh); |
---|
3336 | | - if (retval) |
---|
3337 | | - goto end_unlink; |
---|
3338 | | - dir->i_ctime = dir->i_mtime = current_time(dir); |
---|
3339 | | - ext4_update_dx_flag(dir); |
---|
3340 | | - ext4_mark_inode_dirty(handle, dir); |
---|
| 3391 | + if (!skip_remove_dentry) { |
---|
| 3392 | + retval = ext4_delete_entry(handle, dir, de, lblk, bh); |
---|
| 3393 | + if (retval) |
---|
| 3394 | + goto out_handle; |
---|
| 3395 | + dir->i_ctime = dir->i_mtime = current_time(dir); |
---|
| 3396 | + ext4_update_dx_flag(dir); |
---|
| 3397 | + retval = ext4_mark_inode_dirty(handle, dir); |
---|
| 3398 | + if (retval) |
---|
| 3399 | + goto out_handle; |
---|
| 3400 | + } else { |
---|
| 3401 | + retval = 0; |
---|
| 3402 | + } |
---|
3341 | 3403 | if (inode->i_nlink == 0) |
---|
3342 | 3404 | ext4_warning_inode(inode, "Deleting file '%.*s' with no links", |
---|
3343 | | - dentry->d_name.len, dentry->d_name.name); |
---|
| 3405 | + d_name->len, d_name->name); |
---|
3344 | 3406 | else |
---|
3345 | 3407 | drop_nlink(inode); |
---|
3346 | 3408 | if (!inode->i_nlink) |
---|
3347 | 3409 | ext4_orphan_add(handle, inode); |
---|
3348 | 3410 | inode->i_ctime = current_time(inode); |
---|
3349 | | - ext4_mark_inode_dirty(handle, inode); |
---|
| 3411 | + retval = ext4_mark_inode_dirty(handle, inode); |
---|
| 3412 | + if (dentry && !retval) |
---|
| 3413 | + ext4_fc_track_unlink(handle, dentry); |
---|
| 3414 | +out_handle: |
---|
| 3415 | + ext4_journal_stop(handle); |
---|
| 3416 | +out_bh: |
---|
| 3417 | + brelse(bh); |
---|
| 3418 | + return retval; |
---|
| 3419 | +} |
---|
3350 | 3420 | |
---|
| 3421 | +static int ext4_unlink(struct inode *dir, struct dentry *dentry) |
---|
| 3422 | +{ |
---|
| 3423 | + int retval; |
---|
| 3424 | + |
---|
| 3425 | + if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb)))) |
---|
| 3426 | + return -EIO; |
---|
| 3427 | + |
---|
| 3428 | + trace_ext4_unlink_enter(dir, dentry); |
---|
| 3429 | + /* |
---|
| 3430 | + * Initialize quotas before so that eventual writes go |
---|
| 3431 | + * in separate transaction |
---|
| 3432 | + */ |
---|
| 3433 | + retval = dquot_initialize(dir); |
---|
| 3434 | + if (retval) |
---|
| 3435 | + goto out_trace; |
---|
| 3436 | + retval = dquot_initialize(d_inode(dentry)); |
---|
| 3437 | + if (retval) |
---|
| 3438 | + goto out_trace; |
---|
| 3439 | + |
---|
| 3440 | + retval = __ext4_unlink(dir, &dentry->d_name, d_inode(dentry), dentry); |
---|
3351 | 3441 | #ifdef CONFIG_UNICODE |
---|
3352 | 3442 | /* VFS negative dentries are incompatible with Encoding and |
---|
3353 | 3443 | * Case-insensitiveness. Eventually we'll want avoid |
---|
.. | .. |
---|
3359 | 3449 | d_invalidate(dentry); |
---|
3360 | 3450 | #endif |
---|
3361 | 3451 | |
---|
3362 | | -end_unlink: |
---|
3363 | | - brelse(bh); |
---|
3364 | | - if (handle) |
---|
3365 | | - ext4_journal_stop(handle); |
---|
| 3452 | +out_trace: |
---|
3366 | 3453 | trace_ext4_unlink_exit(dentry, retval); |
---|
3367 | 3454 | return retval; |
---|
3368 | 3455 | } |
---|
.. | .. |
---|
3442 | 3529 | */ |
---|
3443 | 3530 | drop_nlink(inode); |
---|
3444 | 3531 | err = ext4_orphan_add(handle, inode); |
---|
3445 | | - ext4_journal_stop(handle); |
---|
| 3532 | + if (handle) |
---|
| 3533 | + ext4_journal_stop(handle); |
---|
3446 | 3534 | handle = NULL; |
---|
3447 | 3535 | if (err) |
---|
3448 | 3536 | goto err_drop_inode; |
---|
.. | .. |
---|
3477 | 3565 | inode->i_size = disk_link.len - 1; |
---|
3478 | 3566 | } |
---|
3479 | 3567 | EXT4_I(inode)->i_disksize = inode->i_size; |
---|
3480 | | - err = ext4_add_nondir(handle, dentry, inode); |
---|
3481 | | - if (!err && IS_DIRSYNC(dir)) |
---|
3482 | | - ext4_handle_sync(handle); |
---|
3483 | | - |
---|
| 3568 | + err = ext4_add_nondir(handle, dentry, &inode); |
---|
3484 | 3569 | if (handle) |
---|
3485 | 3570 | ext4_journal_stop(handle); |
---|
| 3571 | + if (inode) |
---|
| 3572 | + iput(inode); |
---|
3486 | 3573 | goto out_free_encrypted_link; |
---|
3487 | 3574 | |
---|
3488 | 3575 | err_drop_inode: |
---|
.. | .. |
---|
3497 | 3584 | return err; |
---|
3498 | 3585 | } |
---|
3499 | 3586 | |
---|
| 3587 | +int __ext4_link(struct inode *dir, struct inode *inode, struct dentry *dentry) |
---|
| 3588 | +{ |
---|
| 3589 | + handle_t *handle; |
---|
| 3590 | + int err, retries = 0; |
---|
| 3591 | +retry: |
---|
| 3592 | + handle = ext4_journal_start(dir, EXT4_HT_DIR, |
---|
| 3593 | + (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + |
---|
| 3594 | + EXT4_INDEX_EXTRA_TRANS_BLOCKS) + 1); |
---|
| 3595 | + if (IS_ERR(handle)) |
---|
| 3596 | + return PTR_ERR(handle); |
---|
| 3597 | + |
---|
| 3598 | + if (IS_DIRSYNC(dir)) |
---|
| 3599 | + ext4_handle_sync(handle); |
---|
| 3600 | + |
---|
| 3601 | + inode->i_ctime = current_time(inode); |
---|
| 3602 | + ext4_inc_count(inode); |
---|
| 3603 | + ihold(inode); |
---|
| 3604 | + |
---|
| 3605 | + err = ext4_add_entry(handle, dentry, inode); |
---|
| 3606 | + if (!err) { |
---|
| 3607 | + err = ext4_mark_inode_dirty(handle, inode); |
---|
| 3608 | + /* this can happen only for tmpfile being |
---|
| 3609 | + * linked the first time |
---|
| 3610 | + */ |
---|
| 3611 | + if (inode->i_nlink == 1) |
---|
| 3612 | + ext4_orphan_del(handle, inode); |
---|
| 3613 | + d_instantiate(dentry, inode); |
---|
| 3614 | + ext4_fc_track_link(handle, dentry); |
---|
| 3615 | + } else { |
---|
| 3616 | + drop_nlink(inode); |
---|
| 3617 | + iput(inode); |
---|
| 3618 | + } |
---|
| 3619 | + ext4_journal_stop(handle); |
---|
| 3620 | + if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) |
---|
| 3621 | + goto retry; |
---|
| 3622 | + return err; |
---|
| 3623 | +} |
---|
| 3624 | + |
---|
3500 | 3625 | static int ext4_link(struct dentry *old_dentry, |
---|
3501 | 3626 | struct inode *dir, struct dentry *dentry) |
---|
3502 | 3627 | { |
---|
3503 | | - handle_t *handle; |
---|
3504 | 3628 | struct inode *inode = d_inode(old_dentry); |
---|
3505 | | - int err, retries = 0; |
---|
| 3629 | + int err; |
---|
3506 | 3630 | |
---|
3507 | 3631 | if (inode->i_nlink >= EXT4_LINK_MAX) |
---|
3508 | 3632 | return -EMLINK; |
---|
.. | .. |
---|
3519 | 3643 | err = dquot_initialize(dir); |
---|
3520 | 3644 | if (err) |
---|
3521 | 3645 | return err; |
---|
3522 | | - |
---|
3523 | | -retry: |
---|
3524 | | - handle = ext4_journal_start(dir, EXT4_HT_DIR, |
---|
3525 | | - (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + |
---|
3526 | | - EXT4_INDEX_EXTRA_TRANS_BLOCKS) + 1); |
---|
3527 | | - if (IS_ERR(handle)) |
---|
3528 | | - return PTR_ERR(handle); |
---|
3529 | | - |
---|
3530 | | - if (IS_DIRSYNC(dir)) |
---|
3531 | | - ext4_handle_sync(handle); |
---|
3532 | | - |
---|
3533 | | - inode->i_ctime = current_time(inode); |
---|
3534 | | - ext4_inc_count(handle, inode); |
---|
3535 | | - ihold(inode); |
---|
3536 | | - |
---|
3537 | | - err = ext4_add_entry(handle, dentry, inode); |
---|
3538 | | - if (!err) { |
---|
3539 | | - ext4_mark_inode_dirty(handle, inode); |
---|
3540 | | - /* this can happen only for tmpfile being |
---|
3541 | | - * linked the first time |
---|
3542 | | - */ |
---|
3543 | | - if (inode->i_nlink == 1) |
---|
3544 | | - ext4_orphan_del(handle, inode); |
---|
3545 | | - d_instantiate(dentry, inode); |
---|
3546 | | - } else { |
---|
3547 | | - drop_nlink(inode); |
---|
3548 | | - iput(inode); |
---|
3549 | | - } |
---|
3550 | | - ext4_journal_stop(handle); |
---|
3551 | | - if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) |
---|
3552 | | - goto retry; |
---|
3553 | | - return err; |
---|
| 3646 | + return __ext4_link(dir, inode, dentry); |
---|
3554 | 3647 | } |
---|
3555 | | - |
---|
3556 | 3648 | |
---|
3557 | 3649 | /* |
---|
3558 | 3650 | * Try to find buffer head where contains the parent block. |
---|
.. | .. |
---|
3568 | 3660 | struct buffer_head *bh; |
---|
3569 | 3661 | |
---|
3570 | 3662 | if (!ext4_has_inline_data(inode)) { |
---|
| 3663 | + struct ext4_dir_entry_2 *de; |
---|
| 3664 | + unsigned int offset; |
---|
| 3665 | + |
---|
3571 | 3666 | /* The first directory block must not be a hole, so |
---|
3572 | 3667 | * treat it as DIRENT_HTREE |
---|
3573 | 3668 | */ |
---|
.. | .. |
---|
3576 | 3671 | *retval = PTR_ERR(bh); |
---|
3577 | 3672 | return NULL; |
---|
3578 | 3673 | } |
---|
3579 | | - *parent_de = ext4_next_entry( |
---|
3580 | | - (struct ext4_dir_entry_2 *)bh->b_data, |
---|
3581 | | - inode->i_sb->s_blocksize); |
---|
| 3674 | + |
---|
| 3675 | + de = (struct ext4_dir_entry_2 *) bh->b_data; |
---|
| 3676 | + if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, |
---|
| 3677 | + bh->b_size, 0, 0) || |
---|
| 3678 | + le32_to_cpu(de->inode) != inode->i_ino || |
---|
| 3679 | + strcmp(".", de->name)) { |
---|
| 3680 | + EXT4_ERROR_INODE(inode, "directory missing '.'"); |
---|
| 3681 | + brelse(bh); |
---|
| 3682 | + *retval = -EFSCORRUPTED; |
---|
| 3683 | + return NULL; |
---|
| 3684 | + } |
---|
| 3685 | + offset = ext4_rec_len_from_disk(de->rec_len, |
---|
| 3686 | + inode->i_sb->s_blocksize); |
---|
| 3687 | + de = ext4_next_entry(de, inode->i_sb->s_blocksize); |
---|
| 3688 | + if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, |
---|
| 3689 | + bh->b_size, 0, offset) || |
---|
| 3690 | + le32_to_cpu(de->inode) == 0 || strcmp("..", de->name)) { |
---|
| 3691 | + EXT4_ERROR_INODE(inode, "directory missing '..'"); |
---|
| 3692 | + brelse(bh); |
---|
| 3693 | + *retval = -EFSCORRUPTED; |
---|
| 3694 | + return NULL; |
---|
| 3695 | + } |
---|
| 3696 | + *parent_de = de; |
---|
| 3697 | + |
---|
3582 | 3698 | return bh; |
---|
3583 | 3699 | } |
---|
3584 | 3700 | |
---|
.. | .. |
---|
3633 | 3749 | ent->inode, |
---|
3634 | 3750 | ent->dir_bh); |
---|
3635 | 3751 | } else { |
---|
3636 | | - retval = ext4_handle_dirty_dirent_node(handle, |
---|
3637 | | - ent->inode, |
---|
3638 | | - ent->dir_bh); |
---|
| 3752 | + retval = ext4_handle_dirty_dirblock(handle, ent->inode, |
---|
| 3753 | + ent->dir_bh); |
---|
3639 | 3754 | } |
---|
3640 | 3755 | } else { |
---|
3641 | 3756 | retval = ext4_mark_inode_dirty(handle, ent->inode); |
---|
.. | .. |
---|
3650 | 3765 | static int ext4_setent(handle_t *handle, struct ext4_renament *ent, |
---|
3651 | 3766 | unsigned ino, unsigned file_type) |
---|
3652 | 3767 | { |
---|
3653 | | - int retval; |
---|
| 3768 | + int retval, retval2; |
---|
3654 | 3769 | |
---|
3655 | 3770 | BUFFER_TRACE(ent->bh, "get write access"); |
---|
3656 | 3771 | retval = ext4_journal_get_write_access(handle, ent->bh); |
---|
.. | .. |
---|
3662 | 3777 | inode_inc_iversion(ent->dir); |
---|
3663 | 3778 | ent->dir->i_ctime = ent->dir->i_mtime = |
---|
3664 | 3779 | current_time(ent->dir); |
---|
3665 | | - ext4_mark_inode_dirty(handle, ent->dir); |
---|
| 3780 | + retval = ext4_mark_inode_dirty(handle, ent->dir); |
---|
3666 | 3781 | BUFFER_TRACE(ent->bh, "call ext4_handle_dirty_metadata"); |
---|
3667 | 3782 | if (!ent->inlined) { |
---|
3668 | | - retval = ext4_handle_dirty_dirent_node(handle, |
---|
3669 | | - ent->dir, ent->bh); |
---|
3670 | | - if (unlikely(retval)) { |
---|
3671 | | - ext4_std_error(ent->dir->i_sb, retval); |
---|
3672 | | - return retval; |
---|
| 3783 | + retval2 = ext4_handle_dirty_dirblock(handle, ent->dir, ent->bh); |
---|
| 3784 | + if (unlikely(retval2)) { |
---|
| 3785 | + ext4_std_error(ent->dir->i_sb, retval2); |
---|
| 3786 | + return retval2; |
---|
3673 | 3787 | } |
---|
3674 | 3788 | } |
---|
3675 | | - |
---|
3676 | | - return 0; |
---|
| 3789 | + return retval; |
---|
3677 | 3790 | } |
---|
3678 | 3791 | |
---|
3679 | 3792 | static void ext4_resetent(handle_t *handle, struct ext4_renament *ent, |
---|
.. | .. |
---|
3687 | 3800 | * so the old->de may no longer valid and need to find it again |
---|
3688 | 3801 | * before reset old inode info. |
---|
3689 | 3802 | */ |
---|
3690 | | - old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL, |
---|
3691 | | - NULL); |
---|
| 3803 | + old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, |
---|
| 3804 | + &old.inlined, NULL); |
---|
3692 | 3805 | if (IS_ERR(old.bh)) |
---|
3693 | 3806 | retval = PTR_ERR(old.bh); |
---|
3694 | 3807 | if (!old.bh) |
---|
.. | .. |
---|
3757 | 3870 | { |
---|
3758 | 3871 | if (ent->dir_nlink_delta) { |
---|
3759 | 3872 | if (ent->dir_nlink_delta == -1) |
---|
3760 | | - ext4_dec_count(handle, ent->dir); |
---|
| 3873 | + ext4_dec_count(ent->dir); |
---|
3761 | 3874 | else |
---|
3762 | | - ext4_inc_count(handle, ent->dir); |
---|
| 3875 | + ext4_inc_count(ent->dir); |
---|
3763 | 3876 | ext4_mark_inode_dirty(handle, ent->dir); |
---|
3764 | 3877 | } |
---|
3765 | 3878 | } |
---|
.. | .. |
---|
3840 | 3953 | retval = dquot_initialize(old.dir); |
---|
3841 | 3954 | if (retval) |
---|
3842 | 3955 | return retval; |
---|
| 3956 | + retval = dquot_initialize(old.inode); |
---|
| 3957 | + if (retval) |
---|
| 3958 | + return retval; |
---|
3843 | 3959 | retval = dquot_initialize(new.dir); |
---|
3844 | 3960 | if (retval) |
---|
3845 | 3961 | return retval; |
---|
.. | .. |
---|
3852 | 3968 | return retval; |
---|
3853 | 3969 | } |
---|
3854 | 3970 | |
---|
3855 | | - old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL, |
---|
3856 | | - &old.lblk); |
---|
| 3971 | + old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, |
---|
| 3972 | + &old.inlined, &old.lblk); |
---|
3857 | 3973 | if (IS_ERR(old.bh)) |
---|
3858 | 3974 | return PTR_ERR(old.bh); |
---|
| 3975 | + |
---|
3859 | 3976 | /* |
---|
3860 | 3977 | * Check for inode number is _not_ due to possible IO errors. |
---|
3861 | 3978 | * We might rmdir the source, keep it as pwd of some process |
---|
.. | .. |
---|
3935 | 4052 | EXT4_FT_CHRDEV); |
---|
3936 | 4053 | if (retval) |
---|
3937 | 4054 | goto end_rename; |
---|
3938 | | - ext4_mark_inode_dirty(handle, whiteout); |
---|
| 4055 | + retval = ext4_mark_inode_dirty(handle, whiteout); |
---|
| 4056 | + if (unlikely(retval)) |
---|
| 4057 | + goto end_rename; |
---|
| 4058 | + |
---|
3939 | 4059 | } |
---|
3940 | 4060 | if (!new.bh) { |
---|
3941 | 4061 | retval = ext4_add_entry(handle, new.dentry, old.inode); |
---|
.. | .. |
---|
3956 | 4076 | * rename. |
---|
3957 | 4077 | */ |
---|
3958 | 4078 | old.inode->i_ctime = current_time(old.inode); |
---|
3959 | | - ext4_mark_inode_dirty(handle, old.inode); |
---|
| 4079 | + retval = ext4_mark_inode_dirty(handle, old.inode); |
---|
| 4080 | + if (unlikely(retval)) |
---|
| 4081 | + goto end_rename; |
---|
3960 | 4082 | |
---|
3961 | 4083 | if (!whiteout) { |
---|
3962 | 4084 | /* |
---|
.. | .. |
---|
3966 | 4088 | } |
---|
3967 | 4089 | |
---|
3968 | 4090 | if (new.inode) { |
---|
3969 | | - ext4_dec_count(handle, new.inode); |
---|
| 4091 | + ext4_dec_count(new.inode); |
---|
3970 | 4092 | new.inode->i_ctime = current_time(new.inode); |
---|
3971 | 4093 | } |
---|
3972 | 4094 | old.dir->i_ctime = old.dir->i_mtime = current_time(old.dir); |
---|
.. | .. |
---|
3976 | 4098 | if (retval) |
---|
3977 | 4099 | goto end_rename; |
---|
3978 | 4100 | |
---|
3979 | | - ext4_dec_count(handle, old.dir); |
---|
| 4101 | + ext4_dec_count(old.dir); |
---|
3980 | 4102 | if (new.inode) { |
---|
3981 | 4103 | /* checked ext4_empty_dir above, can't have another |
---|
3982 | 4104 | * parent, ext4_dec_count() won't work for many-linked |
---|
3983 | 4105 | * dirs */ |
---|
3984 | 4106 | clear_nlink(new.inode); |
---|
3985 | 4107 | } else { |
---|
3986 | | - ext4_inc_count(handle, new.dir); |
---|
| 4108 | + ext4_inc_count(new.dir); |
---|
3987 | 4109 | ext4_update_dx_flag(new.dir); |
---|
3988 | | - ext4_mark_inode_dirty(handle, new.dir); |
---|
| 4110 | + retval = ext4_mark_inode_dirty(handle, new.dir); |
---|
| 4111 | + if (unlikely(retval)) |
---|
| 4112 | + goto end_rename; |
---|
3989 | 4113 | } |
---|
3990 | 4114 | } |
---|
3991 | | - ext4_mark_inode_dirty(handle, old.dir); |
---|
| 4115 | + retval = ext4_mark_inode_dirty(handle, old.dir); |
---|
| 4116 | + if (unlikely(retval)) |
---|
| 4117 | + goto end_rename; |
---|
| 4118 | + |
---|
| 4119 | + if (S_ISDIR(old.inode->i_mode)) { |
---|
| 4120 | + /* |
---|
| 4121 | + * We disable fast commits here that's because the |
---|
| 4122 | + * replay code is not yet capable of changing dot dot |
---|
| 4123 | + * dirents in directories. |
---|
| 4124 | + */ |
---|
| 4125 | + ext4_fc_mark_ineligible(old.inode->i_sb, |
---|
| 4126 | + EXT4_FC_REASON_RENAME_DIR); |
---|
| 4127 | + } else { |
---|
| 4128 | + if (new.inode) |
---|
| 4129 | + ext4_fc_track_unlink(handle, new.dentry); |
---|
| 4130 | + __ext4_fc_track_link(handle, old.inode, new.dentry); |
---|
| 4131 | + __ext4_fc_track_unlink(handle, old.inode, old.dentry); |
---|
| 4132 | + if (whiteout) |
---|
| 4133 | + __ext4_fc_track_create(handle, whiteout, old.dentry); |
---|
| 4134 | + } |
---|
| 4135 | + |
---|
3992 | 4136 | if (new.inode) { |
---|
3993 | | - ext4_mark_inode_dirty(handle, new.inode); |
---|
| 4137 | + retval = ext4_mark_inode_dirty(handle, new.inode); |
---|
| 4138 | + if (unlikely(retval)) |
---|
| 4139 | + goto end_rename; |
---|
3994 | 4140 | if (!new.inode->i_nlink) |
---|
3995 | 4141 | ext4_orphan_add(handle, new.inode); |
---|
3996 | 4142 | } |
---|
.. | .. |
---|
4014 | 4160 | brelse(old.dir_bh); |
---|
4015 | 4161 | brelse(old.bh); |
---|
4016 | 4162 | brelse(new.bh); |
---|
| 4163 | + |
---|
4017 | 4164 | return retval; |
---|
4018 | 4165 | } |
---|
4019 | 4166 | |
---|
.. | .. |
---|
4130 | 4277 | ctime = current_time(old.inode); |
---|
4131 | 4278 | old.inode->i_ctime = ctime; |
---|
4132 | 4279 | new.inode->i_ctime = ctime; |
---|
4133 | | - ext4_mark_inode_dirty(handle, old.inode); |
---|
4134 | | - ext4_mark_inode_dirty(handle, new.inode); |
---|
4135 | | - |
---|
| 4280 | + retval = ext4_mark_inode_dirty(handle, old.inode); |
---|
| 4281 | + if (unlikely(retval)) |
---|
| 4282 | + goto end_rename; |
---|
| 4283 | + retval = ext4_mark_inode_dirty(handle, new.inode); |
---|
| 4284 | + if (unlikely(retval)) |
---|
| 4285 | + goto end_rename; |
---|
| 4286 | + ext4_fc_mark_ineligible(new.inode->i_sb, |
---|
| 4287 | + EXT4_FC_REASON_CROSS_RENAME); |
---|
4136 | 4288 | if (old.dir_bh) { |
---|
4137 | 4289 | retval = ext4_rename_dir_finish(handle, &old, new.dir->i_ino); |
---|
4138 | 4290 | if (retval) |
---|