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 /fs/udf | |
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>
Diffstat (limited to 'fs/udf')
-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; |