aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/indirect.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/indirect.c')
-rw-r--r--fs/ext4/indirect.c86
1 files changed, 42 insertions, 44 deletions
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index e75f840000a0..36b369697a13 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -318,34 +318,24 @@ static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned int blks,
318 * ext4_alloc_block() (normally -ENOSPC). Otherwise we set the chain 318 * ext4_alloc_block() (normally -ENOSPC). Otherwise we set the chain
319 * as described above and return 0. 319 * as described above and return 0.
320 */ 320 */
321static int ext4_alloc_branch(handle_t *handle, struct inode *inode, 321static int ext4_alloc_branch(handle_t *handle,
322 ext4_lblk_t iblock, int indirect_blks, 322 struct ext4_allocation_request *ar,
323 int *blks, ext4_fsblk_t goal, 323 int indirect_blks, ext4_lblk_t *offsets,
324 ext4_lblk_t *offsets, Indirect *branch) 324 Indirect *branch)
325{ 325{
326 struct ext4_allocation_request ar;
327 struct buffer_head * bh; 326 struct buffer_head * bh;
328 ext4_fsblk_t b, new_blocks[4]; 327 ext4_fsblk_t b, new_blocks[4];
329 __le32 *p; 328 __le32 *p;
330 int i, j, err, len = 1; 329 int i, j, err, len = 1;
331 330
332 /*
333 * Set up for the direct block allocation
334 */
335 memset(&ar, 0, sizeof(ar));
336 ar.inode = inode;
337 ar.len = *blks;
338 ar.logical = iblock;
339 if (S_ISREG(inode->i_mode))
340 ar.flags = EXT4_MB_HINT_DATA;
341
342 for (i = 0; i <= indirect_blks; i++) { 331 for (i = 0; i <= indirect_blks; i++) {
343 if (i == indirect_blks) { 332 if (i == indirect_blks) {
344 ar.goal = goal; 333 new_blocks[i] = ext4_mb_new_blocks(handle, ar, &err);
345 new_blocks[i] = ext4_mb_new_blocks(handle, &ar, &err);
346 } else 334 } else
347 goal = new_blocks[i] = ext4_new_meta_blocks(handle, inode, 335 ar->goal = new_blocks[i] = ext4_new_meta_blocks(handle,
348 goal, 0, NULL, &err); 336 ar->inode, ar->goal,
337 ar->flags & EXT4_MB_DELALLOC_RESERVED,
338 NULL, &err);
349 if (err) { 339 if (err) {
350 i--; 340 i--;
351 goto failed; 341 goto failed;
@@ -354,7 +344,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
354 if (i == 0) 344 if (i == 0)
355 continue; 345 continue;
356 346
357 bh = branch[i].bh = sb_getblk(inode->i_sb, new_blocks[i-1]); 347 bh = branch[i].bh = sb_getblk(ar->inode->i_sb, new_blocks[i-1]);
358 if (unlikely(!bh)) { 348 if (unlikely(!bh)) {
359 err = -ENOMEM; 349 err = -ENOMEM;
360 goto failed; 350 goto failed;
@@ -372,7 +362,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
372 b = new_blocks[i]; 362 b = new_blocks[i];
373 363
374 if (i == indirect_blks) 364 if (i == indirect_blks)
375 len = ar.len; 365 len = ar->len;
376 for (j = 0; j < len; j++) 366 for (j = 0; j < len; j++)
377 *p++ = cpu_to_le32(b++); 367 *p++ = cpu_to_le32(b++);
378 368
@@ -381,11 +371,10 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
381 unlock_buffer(bh); 371 unlock_buffer(bh);
382 372
383 BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); 373 BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
384 err = ext4_handle_dirty_metadata(handle, inode, bh); 374 err = ext4_handle_dirty_metadata(handle, ar->inode, bh);
385 if (err) 375 if (err)
386 goto failed; 376 goto failed;
387 } 377 }
388 *blks = ar.len;
389 return 0; 378 return 0;
390failed: 379failed:
391 for (; i >= 0; i--) { 380 for (; i >= 0; i--) {
@@ -396,10 +385,10 @@ failed:
396 * existing before ext4_alloc_branch() was called. 385 * existing before ext4_alloc_branch() was called.
397 */ 386 */
398 if (i > 0 && i != indirect_blks && branch[i].bh) 387 if (i > 0 && i != indirect_blks && branch[i].bh)
399 ext4_forget(handle, 1, inode, branch[i].bh, 388 ext4_forget(handle, 1, ar->inode, branch[i].bh,
400 branch[i].bh->b_blocknr); 389 branch[i].bh->b_blocknr);
401 ext4_free_blocks(handle, inode, NULL, new_blocks[i], 390 ext4_free_blocks(handle, ar->inode, NULL, new_blocks[i],
402 (i == indirect_blks) ? ar.len : 1, 0); 391 (i == indirect_blks) ? ar->len : 1, 0);
403 } 392 }
404 return err; 393 return err;
405} 394}
@@ -419,9 +408,9 @@ failed:
419 * inode (->i_blocks, etc.). In case of success we end up with the full 408 * inode (->i_blocks, etc.). In case of success we end up with the full
420 * chain to new block and return 0. 409 * chain to new block and return 0.
421 */ 410 */
422static int ext4_splice_branch(handle_t *handle, struct inode *inode, 411static int ext4_splice_branch(handle_t *handle,
423 ext4_lblk_t block, Indirect *where, int num, 412 struct ext4_allocation_request *ar,
424 int blks) 413 Indirect *where, int num)
425{ 414{
426 int i; 415 int i;
427 int err = 0; 416 int err = 0;
@@ -446,9 +435,9 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
446 * Update the host buffer_head or inode to point to more just allocated 435 * Update the host buffer_head or inode to point to more just allocated
447 * direct blocks blocks 436 * direct blocks blocks
448 */ 437 */
449 if (num == 0 && blks > 1) { 438 if (num == 0 && ar->len > 1) {
450 current_block = le32_to_cpu(where->key) + 1; 439 current_block = le32_to_cpu(where->key) + 1;
451 for (i = 1; i < blks; i++) 440 for (i = 1; i < ar->len; i++)
452 *(where->p + i) = cpu_to_le32(current_block++); 441 *(where->p + i) = cpu_to_le32(current_block++);
453 } 442 }
454 443
@@ -465,14 +454,14 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
465 */ 454 */
466 jbd_debug(5, "splicing indirect only\n"); 455 jbd_debug(5, "splicing indirect only\n");
467 BUFFER_TRACE(where->bh, "call ext4_handle_dirty_metadata"); 456 BUFFER_TRACE(where->bh, "call ext4_handle_dirty_metadata");
468 err = ext4_handle_dirty_metadata(handle, inode, where->bh); 457 err = ext4_handle_dirty_metadata(handle, ar->inode, where->bh);
469 if (err) 458 if (err)
470 goto err_out; 459 goto err_out;
471 } else { 460 } else {
472 /* 461 /*
473 * OK, we spliced it into the inode itself on a direct block. 462 * OK, we spliced it into the inode itself on a direct block.
474 */ 463 */
475 ext4_mark_inode_dirty(handle, inode); 464 ext4_mark_inode_dirty(handle, ar->inode);
476 jbd_debug(5, "splicing direct\n"); 465 jbd_debug(5, "splicing direct\n");
477 } 466 }
478 return err; 467 return err;
@@ -484,11 +473,11 @@ err_out:
484 * need to revoke the block, which is why we don't 473 * need to revoke the block, which is why we don't
485 * need to set EXT4_FREE_BLOCKS_METADATA. 474 * need to set EXT4_FREE_BLOCKS_METADATA.
486 */ 475 */
487 ext4_free_blocks(handle, inode, where[i].bh, 0, 1, 476 ext4_free_blocks(handle, ar->inode, where[i].bh, 0, 1,
488 EXT4_FREE_BLOCKS_FORGET); 477 EXT4_FREE_BLOCKS_FORGET);
489 } 478 }
490 ext4_free_blocks(handle, inode, NULL, le32_to_cpu(where[num].key), 479 ext4_free_blocks(handle, ar->inode, NULL, le32_to_cpu(where[num].key),
491 blks, 0); 480 ar->len, 0);
492 481
493 return err; 482 return err;
494} 483}
@@ -525,11 +514,11 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
525 struct ext4_map_blocks *map, 514 struct ext4_map_blocks *map,
526 int flags) 515 int flags)
527{ 516{
517 struct ext4_allocation_request ar;
528 int err = -EIO; 518 int err = -EIO;
529 ext4_lblk_t offsets[4]; 519 ext4_lblk_t offsets[4];
530 Indirect chain[4]; 520 Indirect chain[4];
531 Indirect *partial; 521 Indirect *partial;
532 ext4_fsblk_t goal;
533 int indirect_blks; 522 int indirect_blks;
534 int blocks_to_boundary = 0; 523 int blocks_to_boundary = 0;
535 int depth; 524 int depth;
@@ -579,7 +568,16 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
579 return -ENOSPC; 568 return -ENOSPC;
580 } 569 }
581 570
582 goal = ext4_find_goal(inode, map->m_lblk, partial); 571 /* Set up for the direct block allocation */
572 memset(&ar, 0, sizeof(ar));
573 ar.inode = inode;
574 ar.logical = map->m_lblk;
575 if (S_ISREG(inode->i_mode))
576 ar.flags = EXT4_MB_HINT_DATA;
577 if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
578 ar.flags |= EXT4_MB_DELALLOC_RESERVED;
579
580 ar.goal = ext4_find_goal(inode, map->m_lblk, partial);
583 581
584 /* the number of blocks need to allocate for [d,t]indirect blocks */ 582 /* the number of blocks need to allocate for [d,t]indirect blocks */
585 indirect_blks = (chain + depth) - partial - 1; 583 indirect_blks = (chain + depth) - partial - 1;
@@ -588,13 +586,13 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
588 * Next look up the indirect map to count the totoal number of 586 * Next look up the indirect map to count the totoal number of
589 * direct blocks to allocate for this branch. 587 * direct blocks to allocate for this branch.
590 */ 588 */
591 count = ext4_blks_to_allocate(partial, indirect_blks, 589 ar.len = ext4_blks_to_allocate(partial, indirect_blks,
592 map->m_len, blocks_to_boundary); 590 map->m_len, blocks_to_boundary);
591
593 /* 592 /*
594 * Block out ext4_truncate while we alter the tree 593 * Block out ext4_truncate while we alter the tree
595 */ 594 */
596 err = ext4_alloc_branch(handle, inode, map->m_lblk, indirect_blks, 595 err = ext4_alloc_branch(handle, &ar, indirect_blks,
597 &count, goal,
598 offsets + (partial - chain), partial); 596 offsets + (partial - chain), partial);
599 597
600 /* 598 /*
@@ -605,14 +603,14 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
605 * may need to return -EAGAIN upwards in the worst case. --sct 603 * may need to return -EAGAIN upwards in the worst case. --sct
606 */ 604 */
607 if (!err) 605 if (!err)
608 err = ext4_splice_branch(handle, inode, map->m_lblk, 606 err = ext4_splice_branch(handle, &ar, partial, indirect_blks);
609 partial, indirect_blks, count);
610 if (err) 607 if (err)
611 goto cleanup; 608 goto cleanup;
612 609
613 map->m_flags |= EXT4_MAP_NEW; 610 map->m_flags |= EXT4_MAP_NEW;
614 611
615 ext4_update_inode_fsync_trans(handle, inode, 1); 612 ext4_update_inode_fsync_trans(handle, inode, 1);
613 count = ar.len;
616got_it: 614got_it:
617 map->m_flags |= EXT4_MAP_MAPPED; 615 map->m_flags |= EXT4_MAP_MAPPED;
618 map->m_pblk = le32_to_cpu(chain[depth-1].key); 616 map->m_pblk = le32_to_cpu(chain[depth-1].key);