aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf/inode.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2007-05-08 03:35:21 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:15:21 -0400
commit31170b6ad4ebe6c43c1cc3b8112274cf59474de0 (patch)
tree25e19a70a323f18757c60a658d930b63e8e45124 /fs/udf/inode.c
parent948b9b2c967c3bec6136b2dbb9e1c12f62e03efa (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/inode.c')
-rw-r--r--fs/udf/inode.c192
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 */
360int 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 }
436out:
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
359static struct buffer_head * inode_getblk(struct inode * inode, sector_t block, 455static 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