| .. | .. |
|---|
| 32 | 32 | newext.ee_block = cpu_to_le32(lb->first_block); |
|---|
| 33 | 33 | newext.ee_len = cpu_to_le16(lb->last_block - lb->first_block + 1); |
|---|
| 34 | 34 | ext4_ext_store_pblock(&newext, lb->first_pblock); |
|---|
| 35 | | - /* Locking only for convinience since we are operating on temp inode */ |
|---|
| 35 | + /* Locking only for convenience since we are operating on temp inode */ |
|---|
| 36 | 36 | down_write(&EXT4_I(inode)->i_data_sem); |
|---|
| 37 | 37 | path = ext4_find_extent(inode, lb->first_block, NULL, 0); |
|---|
| 38 | 38 | if (IS_ERR(path)) { |
|---|
| .. | .. |
|---|
| 43 | 43 | |
|---|
| 44 | 44 | /* |
|---|
| 45 | 45 | * Calculate the credit needed to inserting this extent |
|---|
| 46 | | - * Since we are doing this in loop we may accumalate extra |
|---|
| 47 | | - * credit. But below we try to not accumalate too much |
|---|
| 46 | + * Since we are doing this in loop we may accumulate extra |
|---|
| 47 | + * credit. But below we try to not accumulate too much |
|---|
| 48 | 48 | * of them by restarting the journal. |
|---|
| 49 | 49 | */ |
|---|
| 50 | 50 | needed = ext4_ext_calc_credits_for_single_extent(inode, |
|---|
| 51 | 51 | lb->last_block - lb->first_block + 1, path); |
|---|
| 52 | 52 | |
|---|
| 53 | | - /* |
|---|
| 54 | | - * Make sure the credit we accumalated is not really high |
|---|
| 55 | | - */ |
|---|
| 56 | | - if (needed && ext4_handle_has_enough_credits(handle, |
|---|
| 57 | | - EXT4_RESERVE_TRANS_BLOCKS)) { |
|---|
| 58 | | - up_write((&EXT4_I(inode)->i_data_sem)); |
|---|
| 59 | | - retval = ext4_journal_restart(handle, needed); |
|---|
| 60 | | - down_write((&EXT4_I(inode)->i_data_sem)); |
|---|
| 61 | | - if (retval) |
|---|
| 62 | | - goto err_out; |
|---|
| 63 | | - } else if (needed) { |
|---|
| 64 | | - retval = ext4_journal_extend(handle, needed); |
|---|
| 65 | | - if (retval) { |
|---|
| 66 | | - /* |
|---|
| 67 | | - * IF not able to extend the journal restart the journal |
|---|
| 68 | | - */ |
|---|
| 69 | | - up_write((&EXT4_I(inode)->i_data_sem)); |
|---|
| 70 | | - retval = ext4_journal_restart(handle, needed); |
|---|
| 71 | | - down_write((&EXT4_I(inode)->i_data_sem)); |
|---|
| 72 | | - if (retval) |
|---|
| 73 | | - goto err_out; |
|---|
| 74 | | - } |
|---|
| 75 | | - } |
|---|
| 53 | + retval = ext4_datasem_ensure_credits(handle, inode, needed, needed, 0); |
|---|
| 54 | + if (retval < 0) |
|---|
| 55 | + goto err_out; |
|---|
| 76 | 56 | retval = ext4_ext_insert_extent(handle, inode, &path, &newext, 0); |
|---|
| 77 | 57 | err_out: |
|---|
| 78 | 58 | up_write((&EXT4_I(inode)->i_data_sem)); |
|---|
| .. | .. |
|---|
| 196 | 176 | |
|---|
| 197 | 177 | } |
|---|
| 198 | 178 | |
|---|
| 199 | | -static int extend_credit_for_blkdel(handle_t *handle, struct inode *inode) |
|---|
| 200 | | -{ |
|---|
| 201 | | - int retval = 0, needed; |
|---|
| 202 | | - |
|---|
| 203 | | - if (ext4_handle_has_enough_credits(handle, EXT4_RESERVE_TRANS_BLOCKS+1)) |
|---|
| 204 | | - return 0; |
|---|
| 205 | | - /* |
|---|
| 206 | | - * We are freeing a blocks. During this we touch |
|---|
| 207 | | - * superblock, group descriptor and block bitmap. |
|---|
| 208 | | - * So allocate a credit of 3. We may update |
|---|
| 209 | | - * quota (user and group). |
|---|
| 210 | | - */ |
|---|
| 211 | | - needed = 3 + EXT4_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb); |
|---|
| 212 | | - |
|---|
| 213 | | - if (ext4_journal_extend(handle, needed) != 0) |
|---|
| 214 | | - retval = ext4_journal_restart(handle, needed); |
|---|
| 215 | | - |
|---|
| 216 | | - return retval; |
|---|
| 217 | | -} |
|---|
| 218 | | - |
|---|
| 219 | 179 | static int free_dind_blocks(handle_t *handle, |
|---|
| 220 | 180 | struct inode *inode, __le32 i_data) |
|---|
| 221 | 181 | { |
|---|
| 222 | 182 | int i; |
|---|
| 223 | 183 | __le32 *tmp_idata; |
|---|
| 224 | 184 | struct buffer_head *bh; |
|---|
| 185 | + struct super_block *sb = inode->i_sb; |
|---|
| 225 | 186 | unsigned long max_entries = inode->i_sb->s_blocksize >> 2; |
|---|
| 187 | + int err; |
|---|
| 226 | 188 | |
|---|
| 227 | | - bh = ext4_sb_bread(inode->i_sb, le32_to_cpu(i_data), 0); |
|---|
| 189 | + bh = ext4_sb_bread(sb, le32_to_cpu(i_data), 0); |
|---|
| 228 | 190 | if (IS_ERR(bh)) |
|---|
| 229 | 191 | return PTR_ERR(bh); |
|---|
| 230 | 192 | |
|---|
| 231 | 193 | tmp_idata = (__le32 *)bh->b_data; |
|---|
| 232 | 194 | for (i = 0; i < max_entries; i++) { |
|---|
| 233 | 195 | if (tmp_idata[i]) { |
|---|
| 234 | | - extend_credit_for_blkdel(handle, inode); |
|---|
| 196 | + err = ext4_journal_ensure_credits(handle, |
|---|
| 197 | + EXT4_RESERVE_TRANS_BLOCKS, |
|---|
| 198 | + ext4_free_metadata_revoke_credits(sb, 1)); |
|---|
| 199 | + if (err < 0) { |
|---|
| 200 | + put_bh(bh); |
|---|
| 201 | + return err; |
|---|
| 202 | + } |
|---|
| 235 | 203 | ext4_free_blocks(handle, inode, NULL, |
|---|
| 236 | 204 | le32_to_cpu(tmp_idata[i]), 1, |
|---|
| 237 | 205 | EXT4_FREE_BLOCKS_METADATA | |
|---|
| .. | .. |
|---|
| 239 | 207 | } |
|---|
| 240 | 208 | } |
|---|
| 241 | 209 | put_bh(bh); |
|---|
| 242 | | - extend_credit_for_blkdel(handle, inode); |
|---|
| 210 | + err = ext4_journal_ensure_credits(handle, EXT4_RESERVE_TRANS_BLOCKS, |
|---|
| 211 | + ext4_free_metadata_revoke_credits(sb, 1)); |
|---|
| 212 | + if (err < 0) |
|---|
| 213 | + return err; |
|---|
| 243 | 214 | ext4_free_blocks(handle, inode, NULL, le32_to_cpu(i_data), 1, |
|---|
| 244 | 215 | EXT4_FREE_BLOCKS_METADATA | |
|---|
| 245 | 216 | EXT4_FREE_BLOCKS_FORGET); |
|---|
| .. | .. |
|---|
| 270 | 241 | } |
|---|
| 271 | 242 | } |
|---|
| 272 | 243 | put_bh(bh); |
|---|
| 273 | | - extend_credit_for_blkdel(handle, inode); |
|---|
| 244 | + retval = ext4_journal_ensure_credits(handle, EXT4_RESERVE_TRANS_BLOCKS, |
|---|
| 245 | + ext4_free_metadata_revoke_credits(inode->i_sb, 1)); |
|---|
| 246 | + if (retval < 0) |
|---|
| 247 | + return retval; |
|---|
| 274 | 248 | ext4_free_blocks(handle, inode, NULL, le32_to_cpu(i_data), 1, |
|---|
| 275 | 249 | EXT4_FREE_BLOCKS_METADATA | |
|---|
| 276 | 250 | EXT4_FREE_BLOCKS_FORGET); |
|---|
| .. | .. |
|---|
| 283 | 257 | |
|---|
| 284 | 258 | /* ei->i_data[EXT4_IND_BLOCK] */ |
|---|
| 285 | 259 | if (i_data[0]) { |
|---|
| 286 | | - extend_credit_for_blkdel(handle, inode); |
|---|
| 260 | + retval = ext4_journal_ensure_credits(handle, |
|---|
| 261 | + EXT4_RESERVE_TRANS_BLOCKS, |
|---|
| 262 | + ext4_free_metadata_revoke_credits(inode->i_sb, 1)); |
|---|
| 263 | + if (retval < 0) |
|---|
| 264 | + return retval; |
|---|
| 287 | 265 | ext4_free_blocks(handle, inode, NULL, |
|---|
| 288 | 266 | le32_to_cpu(i_data[0]), 1, |
|---|
| 289 | 267 | EXT4_FREE_BLOCKS_METADATA | |
|---|
| .. | .. |
|---|
| 309 | 287 | static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode, |
|---|
| 310 | 288 | struct inode *tmp_inode) |
|---|
| 311 | 289 | { |
|---|
| 312 | | - int retval; |
|---|
| 290 | + int retval, retval2 = 0; |
|---|
| 313 | 291 | __le32 i_data[3]; |
|---|
| 314 | 292 | struct ext4_inode_info *ei = EXT4_I(inode); |
|---|
| 315 | 293 | struct ext4_inode_info *tmp_ei = EXT4_I(tmp_inode); |
|---|
| .. | .. |
|---|
| 318 | 296 | * One credit accounted for writing the |
|---|
| 319 | 297 | * i_data field of the original inode |
|---|
| 320 | 298 | */ |
|---|
| 321 | | - retval = ext4_journal_extend(handle, 1); |
|---|
| 322 | | - if (retval) { |
|---|
| 323 | | - retval = ext4_journal_restart(handle, 1); |
|---|
| 324 | | - if (retval) |
|---|
| 325 | | - goto err_out; |
|---|
| 326 | | - } |
|---|
| 299 | + retval = ext4_journal_ensure_credits(handle, 1, 0); |
|---|
| 300 | + if (retval < 0) |
|---|
| 301 | + goto err_out; |
|---|
| 327 | 302 | |
|---|
| 328 | 303 | i_data[0] = ei->i_data[EXT4_IND_BLOCK]; |
|---|
| 329 | 304 | i_data[1] = ei->i_data[EXT4_DIND_BLOCK]; |
|---|
| .. | .. |
|---|
| 367 | 342 | * i_blocks when freeing the indirect meta-data blocks |
|---|
| 368 | 343 | */ |
|---|
| 369 | 344 | retval = free_ind_block(handle, inode, i_data); |
|---|
| 370 | | - ext4_mark_inode_dirty(handle, inode); |
|---|
| 345 | + retval2 = ext4_mark_inode_dirty(handle, inode); |
|---|
| 346 | + if (unlikely(retval2 && !retval)) |
|---|
| 347 | + retval = retval2; |
|---|
| 371 | 348 | |
|---|
| 372 | 349 | err_out: |
|---|
| 373 | 350 | return retval; |
|---|
| .. | .. |
|---|
| 391 | 368 | ix = EXT_FIRST_INDEX(eh); |
|---|
| 392 | 369 | for (i = 0; i < le16_to_cpu(eh->eh_entries); i++, ix++) { |
|---|
| 393 | 370 | retval = free_ext_idx(handle, inode, ix); |
|---|
| 394 | | - if (retval) |
|---|
| 395 | | - break; |
|---|
| 371 | + if (retval) { |
|---|
| 372 | + put_bh(bh); |
|---|
| 373 | + return retval; |
|---|
| 374 | + } |
|---|
| 396 | 375 | } |
|---|
| 397 | 376 | } |
|---|
| 398 | 377 | put_bh(bh); |
|---|
| 399 | | - extend_credit_for_blkdel(handle, inode); |
|---|
| 378 | + retval = ext4_journal_ensure_credits(handle, EXT4_RESERVE_TRANS_BLOCKS, |
|---|
| 379 | + ext4_free_metadata_revoke_credits(inode->i_sb, 1)); |
|---|
| 380 | + if (retval < 0) |
|---|
| 381 | + return retval; |
|---|
| 400 | 382 | ext4_free_blocks(handle, inode, NULL, block, 1, |
|---|
| 401 | 383 | EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); |
|---|
| 402 | | - return retval; |
|---|
| 384 | + return 0; |
|---|
| 403 | 385 | } |
|---|
| 404 | 386 | |
|---|
| 405 | 387 | /* |
|---|
| .. | .. |
|---|
| 435 | 417 | struct inode *tmp_inode = NULL; |
|---|
| 436 | 418 | struct migrate_struct lb; |
|---|
| 437 | 419 | unsigned long max_entries; |
|---|
| 438 | | - __u32 goal; |
|---|
| 420 | + __u32 goal, tmp_csum_seed; |
|---|
| 439 | 421 | uid_t owner[2]; |
|---|
| 440 | 422 | |
|---|
| 441 | 423 | /* |
|---|
| .. | .. |
|---|
| 443 | 425 | * already is extent-based, error out. |
|---|
| 444 | 426 | */ |
|---|
| 445 | 427 | if (!ext4_has_feature_extents(inode->i_sb) || |
|---|
| 446 | | - (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) |
|---|
| 428 | + ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) || |
|---|
| 429 | + ext4_has_inline_data(inode)) |
|---|
| 447 | 430 | return -EINVAL; |
|---|
| 448 | 431 | |
|---|
| 449 | 432 | if (S_ISLNK(inode->i_mode) && inode->i_blocks == 0) |
|---|
| .. | .. |
|---|
| 483 | 466 | * the migration. |
|---|
| 484 | 467 | */ |
|---|
| 485 | 468 | ei = EXT4_I(inode); |
|---|
| 469 | + tmp_csum_seed = EXT4_I(tmp_inode)->i_csum_seed; |
|---|
| 486 | 470 | EXT4_I(tmp_inode)->i_csum_seed = ei->i_csum_seed; |
|---|
| 487 | 471 | i_size_write(tmp_inode, i_size_read(inode)); |
|---|
| 488 | 472 | /* |
|---|
| .. | .. |
|---|
| 537 | 521 | if (i_data[EXT4_IND_BLOCK]) { |
|---|
| 538 | 522 | retval = update_ind_extent_range(handle, tmp_inode, |
|---|
| 539 | 523 | le32_to_cpu(i_data[EXT4_IND_BLOCK]), &lb); |
|---|
| 540 | | - if (retval) |
|---|
| 541 | | - goto err_out; |
|---|
| 524 | + if (retval) |
|---|
| 525 | + goto err_out; |
|---|
| 542 | 526 | } else |
|---|
| 543 | 527 | lb.curr_block += max_entries; |
|---|
| 544 | 528 | if (i_data[EXT4_DIND_BLOCK]) { |
|---|
| 545 | 529 | retval = update_dind_extent_range(handle, tmp_inode, |
|---|
| 546 | 530 | le32_to_cpu(i_data[EXT4_DIND_BLOCK]), &lb); |
|---|
| 547 | | - if (retval) |
|---|
| 548 | | - goto err_out; |
|---|
| 531 | + if (retval) |
|---|
| 532 | + goto err_out; |
|---|
| 549 | 533 | } else |
|---|
| 550 | 534 | lb.curr_block += max_entries * max_entries; |
|---|
| 551 | 535 | if (i_data[EXT4_TIND_BLOCK]) { |
|---|
| 552 | 536 | retval = update_tind_extent_range(handle, tmp_inode, |
|---|
| 553 | 537 | le32_to_cpu(i_data[EXT4_TIND_BLOCK]), &lb); |
|---|
| 554 | | - if (retval) |
|---|
| 555 | | - goto err_out; |
|---|
| 538 | + if (retval) |
|---|
| 539 | + goto err_out; |
|---|
| 556 | 540 | } |
|---|
| 557 | 541 | /* |
|---|
| 558 | 542 | * Build the last extent |
|---|
| .. | .. |
|---|
| 576 | 560 | } |
|---|
| 577 | 561 | |
|---|
| 578 | 562 | /* We mark the tmp_inode dirty via ext4_ext_tree_init. */ |
|---|
| 579 | | - if (ext4_journal_extend(handle, 1) != 0) |
|---|
| 580 | | - ext4_journal_restart(handle, 1); |
|---|
| 581 | | - |
|---|
| 563 | + retval = ext4_journal_ensure_credits(handle, 1, 0); |
|---|
| 564 | + if (retval < 0) |
|---|
| 565 | + goto out_stop; |
|---|
| 582 | 566 | /* |
|---|
| 583 | 567 | * Mark the tmp_inode as of size zero |
|---|
| 584 | 568 | */ |
|---|
| .. | .. |
|---|
| 593 | 577 | * the inode is not visible to user space. |
|---|
| 594 | 578 | */ |
|---|
| 595 | 579 | tmp_inode->i_blocks = 0; |
|---|
| 580 | + EXT4_I(tmp_inode)->i_csum_seed = tmp_csum_seed; |
|---|
| 596 | 581 | |
|---|
| 597 | 582 | /* Reset the extent details */ |
|---|
| 598 | 583 | ext4_ext_tree_init(handle, tmp_inode); |
|---|
| 584 | +out_stop: |
|---|
| 599 | 585 | ext4_journal_stop(handle); |
|---|
| 600 | 586 | out_tmp_inode: |
|---|
| 601 | 587 | unlock_new_inode(tmp_inode); |
|---|
| .. | .. |
|---|
| 619 | 605 | ext4_lblk_t start, end; |
|---|
| 620 | 606 | ext4_fsblk_t blk; |
|---|
| 621 | 607 | handle_t *handle; |
|---|
| 622 | | - int ret; |
|---|
| 608 | + int ret, ret2 = 0; |
|---|
| 623 | 609 | |
|---|
| 624 | 610 | if (!ext4_has_feature_extents(inode->i_sb) || |
|---|
| 625 | 611 | (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) |
|---|
| .. | .. |
|---|
| 673 | 659 | memset(ei->i_data, 0, sizeof(ei->i_data)); |
|---|
| 674 | 660 | for (i = start; i <= end; i++) |
|---|
| 675 | 661 | ei->i_data[i] = cpu_to_le32(blk++); |
|---|
| 676 | | - ext4_mark_inode_dirty(handle, inode); |
|---|
| 662 | + ret2 = ext4_mark_inode_dirty(handle, inode); |
|---|
| 663 | + if (unlikely(ret2 && !ret)) |
|---|
| 664 | + ret = ret2; |
|---|
| 677 | 665 | errout: |
|---|
| 678 | 666 | ext4_journal_stop(handle); |
|---|
| 679 | 667 | up_write(&EXT4_I(inode)->i_data_sem); |
|---|