| .. | .. |
|---|
| 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) |
|---|