diff options
Diffstat (limited to 'fs/udf/inode.c')
-rw-r--r-- | fs/udf/inode.c | 192 |
1 files changed, 157 insertions, 35 deletions
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 2171bcfeec20..c8461551e108 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
@@ -356,9 +356,106 @@ udf_getblk(struct inode *inode, long block, int create, int *err) | |||
356 | return NULL; | 356 | return NULL; |
357 | } | 357 | } |
358 | 358 | ||
359 | /* Extend the file by 'blocks' blocks, return the number of extents added */ | ||
360 | int udf_extend_file(struct inode *inode, struct extent_position *last_pos, | ||
361 | kernel_long_ad *last_ext, sector_t blocks) | ||
362 | { | ||
363 | sector_t add; | ||
364 | int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK); | ||
365 | struct super_block *sb = inode->i_sb; | ||
366 | kernel_lb_addr prealloc_loc = {0, 0}; | ||
367 | int prealloc_len = 0; | ||
368 | |||
369 | /* The previous extent is fake and we should not extend by anything | ||
370 | * - there's nothing to do... */ | ||
371 | if (!blocks && fake) | ||
372 | return 0; | ||
373 | /* Round the last extent up to a multiple of block size */ | ||
374 | if (last_ext->extLength & (sb->s_blocksize - 1)) { | ||
375 | last_ext->extLength = | ||
376 | (last_ext->extLength & UDF_EXTENT_FLAG_MASK) | | ||
377 | (((last_ext->extLength & UDF_EXTENT_LENGTH_MASK) + | ||
378 | sb->s_blocksize - 1) & ~(sb->s_blocksize - 1)); | ||
379 | UDF_I_LENEXTENTS(inode) = | ||
380 | (UDF_I_LENEXTENTS(inode) + sb->s_blocksize - 1) & | ||
381 | ~(sb->s_blocksize - 1); | ||
382 | } | ||
383 | /* Last extent are just preallocated blocks? */ | ||
384 | if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == EXT_NOT_RECORDED_ALLOCATED) { | ||
385 | /* Save the extent so that we can reattach it to the end */ | ||
386 | prealloc_loc = last_ext->extLocation; | ||
387 | prealloc_len = last_ext->extLength; | ||
388 | /* Mark the extent as a hole */ | ||
389 | last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | | ||
390 | (last_ext->extLength & UDF_EXTENT_LENGTH_MASK); | ||
391 | last_ext->extLocation.logicalBlockNum = 0; | ||
392 | last_ext->extLocation.partitionReferenceNum = 0; | ||
393 | } | ||
394 | /* Can we merge with the previous extent? */ | ||
395 | if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == EXT_NOT_RECORDED_NOT_ALLOCATED) { | ||
396 | add = ((1<<30) - sb->s_blocksize - (last_ext->extLength & | ||
397 | UDF_EXTENT_LENGTH_MASK)) >> sb->s_blocksize_bits; | ||
398 | if (add > blocks) | ||
399 | add = blocks; | ||
400 | blocks -= add; | ||
401 | last_ext->extLength += add << sb->s_blocksize_bits; | ||
402 | } | ||
403 | |||
404 | if (fake) { | ||
405 | udf_add_aext(inode, last_pos, last_ext->extLocation, | ||
406 | last_ext->extLength, 1); | ||
407 | count++; | ||
408 | } | ||
409 | else | ||
410 | udf_write_aext(inode, last_pos, last_ext->extLocation, last_ext->extLength, 1); | ||
411 | /* Managed to do everything necessary? */ | ||
412 | if (!blocks) | ||
413 | goto out; | ||
414 | |||
415 | /* All further extents will be NOT_RECORDED_NOT_ALLOCATED */ | ||
416 | last_ext->extLocation.logicalBlockNum = 0; | ||
417 | last_ext->extLocation.partitionReferenceNum = 0; | ||
418 | add = (1 << (30-sb->s_blocksize_bits)) - 1; | ||
419 | last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | (add << sb->s_blocksize_bits); | ||
420 | /* Create enough extents to cover the whole hole */ | ||
421 | while (blocks > add) { | ||
422 | blocks -= add; | ||
423 | if (udf_add_aext(inode, last_pos, last_ext->extLocation, | ||
424 | last_ext->extLength, 1) == -1) | ||
425 | return -1; | ||
426 | count++; | ||
427 | } | ||
428 | if (blocks) { | ||
429 | last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | | ||
430 | (blocks << sb->s_blocksize_bits); | ||
431 | if (udf_add_aext(inode, last_pos, last_ext->extLocation, | ||
432 | last_ext->extLength, 1) == -1) | ||
433 | return -1; | ||
434 | count++; | ||
435 | } | ||
436 | out: | ||
437 | /* Do we have some preallocated blocks saved? */ | ||
438 | if (prealloc_len) { | ||
439 | if (udf_add_aext(inode, last_pos, prealloc_loc, prealloc_len, 1) == -1) | ||
440 | return -1; | ||
441 | last_ext->extLocation = prealloc_loc; | ||
442 | last_ext->extLength = prealloc_len; | ||
443 | count++; | ||
444 | } | ||
445 | /* last_pos should point to the last written extent... */ | ||
446 | if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT) | ||
447 | last_pos->offset -= sizeof(short_ad); | ||
448 | else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG) | ||
449 | last_pos->offset -= sizeof(long_ad); | ||
450 | else | ||
451 | return -1; | ||
452 | return count; | ||
453 | } | ||
454 | |||
359 | static struct buffer_head * inode_getblk(struct inode * inode, sector_t block, | 455 | static struct buffer_head * inode_getblk(struct inode * inode, sector_t block, |
360 | int *err, long *phys, int *new) | 456 | int *err, long *phys, int *new) |
361 | { | 457 | { |
458 | static sector_t last_block; | ||
362 | struct buffer_head *result = NULL; | 459 | struct buffer_head *result = NULL; |
363 | kernel_long_ad laarr[EXTENT_MERGE_SIZE]; | 460 | kernel_long_ad laarr[EXTENT_MERGE_SIZE]; |
364 | struct extent_position prev_epos, cur_epos, next_epos; | 461 | struct extent_position prev_epos, cur_epos, next_epos; |
@@ -371,7 +468,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block, | |||
371 | sector_t offset = 0; | 468 | sector_t offset = 0; |
372 | int8_t etype; | 469 | int8_t etype; |
373 | int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum; | 470 | int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum; |
374 | char lastblock = 0; | 471 | int lastblock = 0; |
375 | 472 | ||
376 | prev_epos.offset = udf_file_entry_alloc_offset(inode); | 473 | prev_epos.offset = udf_file_entry_alloc_offset(inode); |
377 | prev_epos.block = UDF_I_LOCATION(inode); | 474 | prev_epos.block = UDF_I_LOCATION(inode); |
@@ -423,6 +520,8 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block, | |||
423 | 520 | ||
424 | b_off -= lbcount; | 521 | b_off -= lbcount; |
425 | offset = b_off >> inode->i_sb->s_blocksize_bits; | 522 | offset = b_off >> inode->i_sb->s_blocksize_bits; |
523 | /* Move into indirect extent if we are at a pointer to it */ | ||
524 | udf_next_aext(inode, &prev_epos, &eloc, &elen, 0); | ||
426 | 525 | ||
427 | /* if the extent is allocated and recorded, return the block | 526 | /* if the extent is allocated and recorded, return the block |
428 | if the extent is not a multiple of the blocksize, round up */ | 527 | if the extent is not a multiple of the blocksize, round up */ |
@@ -444,43 +543,66 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block, | |||
444 | return NULL; | 543 | return NULL; |
445 | } | 544 | } |
446 | 545 | ||
546 | last_block = block; | ||
547 | /* Are we beyond EOF? */ | ||
447 | if (etype == -1) | 548 | if (etype == -1) |
448 | { | 549 | { |
449 | endnum = startnum = ((count > 1) ? 1 : count); | 550 | int ret; |
450 | if (laarr[c].extLength & (inode->i_sb->s_blocksize - 1)) | 551 | |
451 | { | 552 | if (count) { |
452 | laarr[c].extLength = | 553 | if (c) |
453 | (laarr[c].extLength & UDF_EXTENT_FLAG_MASK) | | 554 | laarr[0] = laarr[1]; |
454 | (((laarr[c].extLength & UDF_EXTENT_LENGTH_MASK) + | 555 | startnum = 1; |
455 | inode->i_sb->s_blocksize - 1) & | 556 | } |
456 | ~(inode->i_sb->s_blocksize - 1)); | 557 | else { |
457 | UDF_I_LENEXTENTS(inode) = | 558 | /* Create a fake extent when there's not one */ |
458 | (UDF_I_LENEXTENTS(inode) + inode->i_sb->s_blocksize - 1) & | 559 | memset(&laarr[0].extLocation, 0x00, sizeof(kernel_lb_addr)); |
459 | ~(inode->i_sb->s_blocksize - 1); | 560 | laarr[0].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED; |
561 | /* Will udf_extend_file() create real extent from a fake one? */ | ||
562 | startnum = (offset > 0); | ||
563 | } | ||
564 | /* Create extents for the hole between EOF and offset */ | ||
565 | ret = udf_extend_file(inode, &prev_epos, laarr, offset); | ||
566 | if (ret == -1) { | ||
567 | brelse(prev_epos.bh); | ||
568 | brelse(cur_epos.bh); | ||
569 | brelse(next_epos.bh); | ||
570 | /* We don't really know the error here so we just make | ||
571 | * something up */ | ||
572 | *err = -ENOSPC; | ||
573 | return NULL; | ||
460 | } | 574 | } |
461 | c = !c; | 575 | c = 0; |
462 | laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | | 576 | offset = 0; |
463 | ((offset + 1) << inode->i_sb->s_blocksize_bits); | 577 | count += ret; |
464 | memset(&laarr[c].extLocation, 0x00, sizeof(kernel_lb_addr)); | 578 | /* We are not covered by a preallocated extent? */ |
465 | count ++; | 579 | if ((laarr[0].extLength & UDF_EXTENT_FLAG_MASK) != EXT_NOT_RECORDED_ALLOCATED) { |
466 | endnum ++; | 580 | /* Is there any real extent? - otherwise we overwrite |
581 | * the fake one... */ | ||
582 | if (count) | ||
583 | c = !c; | ||
584 | laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | | ||
585 | inode->i_sb->s_blocksize; | ||
586 | memset(&laarr[c].extLocation, 0x00, sizeof(kernel_lb_addr)); | ||
587 | count ++; | ||
588 | endnum ++; | ||
589 | } | ||
590 | endnum = c+1; | ||
467 | lastblock = 1; | 591 | lastblock = 1; |
468 | } | 592 | } |
469 | else | 593 | else { |
470 | endnum = startnum = ((count > 2) ? 2 : count); | 594 | endnum = startnum = ((count > 2) ? 2 : count); |
471 | 595 | ||
472 | /* if the current extent is in position 0, swap it with the previous */ | 596 | /* if the current extent is in position 0, swap it with the previous */ |
473 | if (!c && count != 1) | 597 | if (!c && count != 1) |
474 | { | 598 | { |
475 | laarr[2] = laarr[0]; | 599 | laarr[2] = laarr[0]; |
476 | laarr[0] = laarr[1]; | 600 | laarr[0] = laarr[1]; |
477 | laarr[1] = laarr[2]; | 601 | laarr[1] = laarr[2]; |
478 | c = 1; | 602 | c = 1; |
479 | } | 603 | } |
480 | 604 | ||
481 | /* if the current block is located in a extent, read the next extent */ | 605 | /* if the current block is located in an extent, read the next extent */ |
482 | if (etype != -1) | ||
483 | { | ||
484 | if ((etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 0)) != -1) | 606 | if ((etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 0)) != -1) |
485 | { | 607 | { |
486 | laarr[c+1].extLength = (etype << 30) | elen; | 608 | laarr[c+1].extLength = (etype << 30) | elen; |
@@ -489,11 +611,10 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block, | |||
489 | startnum ++; | 611 | startnum ++; |
490 | endnum ++; | 612 | endnum ++; |
491 | } | 613 | } |
492 | else | 614 | else { |
493 | lastblock = 1; | 615 | lastblock = 1; |
616 | } | ||
494 | } | 617 | } |
495 | brelse(cur_epos.bh); | ||
496 | brelse(next_epos.bh); | ||
497 | 618 | ||
498 | /* if the current extent is not recorded but allocated, get the | 619 | /* if the current extent is not recorded but allocated, get the |
499 | block in the extent corresponding to the requested block */ | 620 | block in the extent corresponding to the requested block */ |
@@ -534,8 +655,8 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block, | |||
534 | udf_merge_extents(inode, laarr, &endnum); | 655 | udf_merge_extents(inode, laarr, &endnum); |
535 | 656 | ||
536 | /* write back the new extents, inserting new extents if the new number | 657 | /* write back the new extents, inserting new extents if the new number |
537 | of extents is greater than the old number, and deleting extents if | 658 | of extents is greater than the old number, and deleting extents if |
538 | the new number of extents is less than the old number */ | 659 | the new number of extents is less than the old number */ |
539 | udf_update_extents(inode, laarr, startnum, endnum, &prev_epos); | 660 | udf_update_extents(inode, laarr, startnum, endnum, &prev_epos); |
540 | 661 | ||
541 | brelse(prev_epos.bh); | 662 | brelse(prev_epos.bh); |
@@ -991,6 +1112,7 @@ __udf_read_inode(struct inode *inode) | |||
991 | return; | 1112 | return; |
992 | } | 1113 | } |
993 | udf_fill_inode(inode, bh); | 1114 | udf_fill_inode(inode, bh); |
1115 | |||
994 | brelse(bh); | 1116 | brelse(bh); |
995 | } | 1117 | } |
996 | 1118 | ||