diff options
| author | Jan Kara <jack@suse.cz> | 2007-05-08 03:35:21 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 14:15:21 -0400 |
| commit | 31170b6ad4ebe6c43c1cc3b8112274cf59474de0 (patch) | |
| tree | 25e19a70a323f18757c60a658d930b63e8e45124 | |
| parent | 948b9b2c967c3bec6136b2dbb9e1c12f62e03efa (diff) | |
udf: support files larger than 1G
Make UDF work correctly for files larger than 1GB. As no extent can be
longer than (1<<30)-blocksize bytes, we have to create several extents if a
big hole is being created. As a side-effect, we now don't discard
preallocated blocks when creating a hole.
Signed-off-by: Jan Kara <jack@suse.cz>
Acked-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | fs/udf/inode.c | 192 | ||||
| -rw-r--r-- | fs/udf/super.c | 2 | ||||
| -rw-r--r-- | fs/udf/truncate.c | 68 |
3 files changed, 180 insertions, 82 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 | ||
diff --git a/fs/udf/super.c b/fs/udf/super.c index 9f516d4baf9d..a92daaba6c4c 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
| @@ -1661,7 +1661,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
| 1661 | iput(inode); | 1661 | iput(inode); |
| 1662 | goto error_out; | 1662 | goto error_out; |
| 1663 | } | 1663 | } |
| 1664 | sb->s_maxbytes = 1<<30; | 1664 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
| 1665 | return 0; | 1665 | return 0; |
| 1666 | 1666 | ||
| 1667 | error_out: | 1667 | error_out: |
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c index 0e328cdc9a45..77975ae291a5 100644 --- a/fs/udf/truncate.c +++ b/fs/udf/truncate.c | |||
| @@ -130,7 +130,8 @@ void udf_truncate_extents(struct inode * inode) | |||
| 130 | kernel_lb_addr eloc, neloc = { 0, 0 }; | 130 | kernel_lb_addr eloc, neloc = { 0, 0 }; |
| 131 | uint32_t elen, nelen = 0, indirect_ext_len = 0, lenalloc; | 131 | uint32_t elen, nelen = 0, indirect_ext_len = 0, lenalloc; |
| 132 | int8_t etype; | 132 | int8_t etype; |
| 133 | sector_t first_block = inode->i_size >> inode->i_sb->s_blocksize_bits, offset; | 133 | struct super_block *sb = inode->i_sb; |
| 134 | sector_t first_block = inode->i_size >> sb->s_blocksize_bits, offset; | ||
| 134 | loff_t byte_offset; | 135 | loff_t byte_offset; |
| 135 | int adsize; | 136 | int adsize; |
| 136 | 137 | ||
| @@ -142,7 +143,7 @@ void udf_truncate_extents(struct inode * inode) | |||
| 142 | BUG(); | 143 | BUG(); |
| 143 | 144 | ||
| 144 | etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset); | 145 | etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset); |
| 145 | byte_offset = (offset << inode->i_sb->s_blocksize_bits) + (inode->i_size & (inode->i_sb->s_blocksize-1)); | 146 | byte_offset = (offset << sb->s_blocksize_bits) + (inode->i_size & (sb->s_blocksize-1)); |
| 146 | if (etype != -1) | 147 | if (etype != -1) |
| 147 | { | 148 | { |
| 148 | epos.offset -= adsize; | 149 | epos.offset -= adsize; |
| @@ -169,7 +170,7 @@ void udf_truncate_extents(struct inode * inode) | |||
| 169 | * indirect extent - free it too */ | 170 | * indirect extent - free it too */ |
| 170 | if (!epos.bh) | 171 | if (!epos.bh) |
| 171 | BUG(); | 172 | BUG(); |
| 172 | udf_free_blocks(inode->i_sb, inode, epos.block, 0, indirect_ext_len); | 173 | udf_free_blocks(sb, inode, epos.block, 0, indirect_ext_len); |
| 173 | } | 174 | } |
| 174 | else | 175 | else |
| 175 | { | 176 | { |
| @@ -182,7 +183,7 @@ void udf_truncate_extents(struct inode * inode) | |||
| 182 | { | 183 | { |
| 183 | struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data); | 184 | struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data); |
| 184 | aed->lengthAllocDescs = cpu_to_le32(lenalloc); | 185 | aed->lengthAllocDescs = cpu_to_le32(lenalloc); |
| 185 | if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) | 186 | if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(sb) >= 0x0201) |
| 186 | udf_update_tag(epos.bh->b_data, lenalloc + | 187 | udf_update_tag(epos.bh->b_data, lenalloc + |
| 187 | sizeof(struct allocExtDesc)); | 188 | sizeof(struct allocExtDesc)); |
| 188 | else | 189 | else |
| @@ -193,11 +194,11 @@ void udf_truncate_extents(struct inode * inode) | |||
| 193 | brelse(epos.bh); | 194 | brelse(epos.bh); |
| 194 | epos.offset = sizeof(struct allocExtDesc); | 195 | epos.offset = sizeof(struct allocExtDesc); |
| 195 | epos.block = eloc; | 196 | epos.block = eloc; |
| 196 | epos.bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, eloc, 0)); | 197 | epos.bh = udf_tread(sb, udf_get_lb_pblock(sb, eloc, 0)); |
| 197 | if (elen) | 198 | if (elen) |
| 198 | indirect_ext_len = (elen + | 199 | indirect_ext_len = (elen + |
| 199 | inode->i_sb->s_blocksize - 1) >> | 200 | sb->s_blocksize - 1) >> |
| 200 | inode->i_sb->s_blocksize_bits; | 201 | sb->s_blocksize_bits; |
| 201 | else | 202 | else |
| 202 | indirect_ext_len = 1; | 203 | indirect_ext_len = 1; |
| 203 | } | 204 | } |
| @@ -212,7 +213,7 @@ void udf_truncate_extents(struct inode * inode) | |||
| 212 | { | 213 | { |
| 213 | if (!epos.bh) | 214 | if (!epos.bh) |
| 214 | BUG(); | 215 | BUG(); |
| 215 | udf_free_blocks(inode->i_sb, inode, epos.block, 0, indirect_ext_len); | 216 | udf_free_blocks(sb, inode, epos.block, 0, indirect_ext_len); |
| 216 | } | 217 | } |
| 217 | else | 218 | else |
| 218 | { | 219 | { |
| @@ -225,7 +226,7 @@ void udf_truncate_extents(struct inode * inode) | |||
| 225 | { | 226 | { |
| 226 | struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data); | 227 | struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data); |
| 227 | aed->lengthAllocDescs = cpu_to_le32(lenalloc); | 228 | aed->lengthAllocDescs = cpu_to_le32(lenalloc); |
| 228 | if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) | 229 | if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(sb) >= 0x0201) |
| 229 | udf_update_tag(epos.bh->b_data, lenalloc + | 230 | udf_update_tag(epos.bh->b_data, lenalloc + |
| 230 | sizeof(struct allocExtDesc)); | 231 | sizeof(struct allocExtDesc)); |
| 231 | else | 232 | else |
| @@ -238,53 +239,28 @@ void udf_truncate_extents(struct inode * inode) | |||
| 238 | { | 239 | { |
| 239 | if (byte_offset) | 240 | if (byte_offset) |
| 240 | { | 241 | { |
| 242 | kernel_long_ad extent; | ||
| 243 | |||
| 241 | /* | 244 | /* |
| 242 | * OK, there is not extent covering inode->i_size and | 245 | * OK, there is not extent covering inode->i_size and |
| 243 | * no extent above inode->i_size => truncate is | 246 | * no extent above inode->i_size => truncate is |
| 244 | * extending the file by 'offset'. | 247 | * extending the file by 'offset' blocks. |
| 245 | */ | 248 | */ |
| 246 | if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) || | 249 | if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) || |
| 247 | (epos.bh && epos.offset == sizeof(struct allocExtDesc))) { | 250 | (epos.bh && epos.offset == sizeof(struct allocExtDesc))) { |
| 248 | /* File has no extents at all! */ | 251 | /* File has no extents at all or has empty last |
| 249 | memset(&eloc, 0x00, sizeof(kernel_lb_addr)); | 252 | * indirect extent! Create a fake extent... */ |
| 250 | elen = EXT_NOT_RECORDED_NOT_ALLOCATED | byte_offset; | 253 | extent.extLocation.logicalBlockNum = 0; |
| 251 | udf_add_aext(inode, &epos, eloc, elen, 1); | 254 | extent.extLocation.partitionReferenceNum = 0; |
| 255 | extent.extLength = EXT_NOT_RECORDED_NOT_ALLOCATED; | ||
| 252 | } | 256 | } |
| 253 | else { | 257 | else { |
| 254 | epos.offset -= adsize; | 258 | epos.offset -= adsize; |
| 255 | etype = udf_next_aext(inode, &epos, &eloc, &elen, 1); | 259 | etype = udf_next_aext(inode, &epos, |
| 256 | 260 | &extent.extLocation, &extent.extLength, 0); | |
| 257 | if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) | 261 | extent.extLength |= etype << 30; |
| 258 | { | ||
| 259 | epos.offset -= adsize; | ||
| 260 | elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + byte_offset); | ||
| 261 | udf_write_aext(inode, &epos, eloc, elen, 0); | ||
| 262 | } | ||
| 263 | else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) | ||
| 264 | { | ||
| 265 | kernel_lb_addr neloc = { 0, 0 }; | ||
| 266 | epos.offset -= adsize; | ||
| 267 | nelen = EXT_NOT_RECORDED_NOT_ALLOCATED | | ||
| 268 | ((elen + byte_offset + inode->i_sb->s_blocksize - 1) & | ||
| 269 | ~(inode->i_sb->s_blocksize - 1)); | ||
| 270 | udf_write_aext(inode, &epos, neloc, nelen, 1); | ||
| 271 | udf_add_aext(inode, &epos, eloc, (etype << 30) | elen, 1); | ||
| 272 | } | ||
| 273 | else | ||
| 274 | { | ||
| 275 | if (elen & (inode->i_sb->s_blocksize - 1)) | ||
| 276 | { | ||
| 277 | epos.offset -= adsize; | ||
| 278 | elen = EXT_RECORDED_ALLOCATED | | ||
| 279 | ((elen + inode->i_sb->s_blocksize - 1) & | ||
| 280 | ~(inode->i_sb->s_blocksize - 1)); | ||
| 281 | udf_write_aext(inode, &epos, eloc, elen, 1); | ||
| 282 | } | ||
| 283 | memset(&eloc, 0x00, sizeof(kernel_lb_addr)); | ||
| 284 | elen = EXT_NOT_RECORDED_NOT_ALLOCATED | byte_offset; | ||
| 285 | udf_add_aext(inode, &epos, eloc, elen, 1); | ||
| 286 | } | ||
| 287 | } | 262 | } |
| 263 | udf_extend_file(inode, &epos, &extent, offset+((inode->i_size & (sb->s_blocksize-1)) != 0)); | ||
| 288 | } | 264 | } |
| 289 | } | 265 | } |
| 290 | UDF_I_LENEXTENTS(inode) = inode->i_size; | 266 | UDF_I_LENEXTENTS(inode) = inode->i_size; |
