Skip to content

Commit 79a97f0

Browse files
jankaragregkh
authored andcommitted
udf: Discard preallocation before extending file with a hole
commit 16d0556 upstream. When extending file with a hole, we tried to preserve existing preallocation for the file. However that is not very useful and complicates code because the previous extent may need to be rounded to block boundary as well (which we forgot to do thus causing data corruption for sequence like: xfs_io -f -c "pwrite 0x75e63 11008" -c "truncate 0x7b24b" \ -c "truncate 0xabaa3" -c "pwrite 0xac70b 22954" \ -c "pwrite 0x93a43 11358" -c "pwrite 0xb8e65 52211" file with 512-byte block size. Just discard preallocation before extending file to simplify things and also fix this data corruption. CC: stable@vger.kernel.org Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent d68f50b commit 79a97f0

1 file changed

Lines changed: 18 additions & 28 deletions

File tree

fs/udf/inode.c

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,12 @@ static int udf_get_block(struct inode *inode, sector_t block,
438438
iinfo->i_next_alloc_goal++;
439439
}
440440

441+
/*
442+
* Block beyond EOF and prealloc extents? Just discard preallocation
443+
* as it is not useful and complicates things.
444+
*/
445+
if (((loff_t)block) << inode->i_blkbits > iinfo->i_lenExtents)
446+
udf_discard_prealloc(inode);
441447
udf_clear_extent_cache(inode);
442448
phys = inode_getblk(inode, block, &err, &new);
443449
if (!phys)
@@ -487,8 +493,6 @@ static int udf_do_extend_file(struct inode *inode,
487493
uint32_t add;
488494
int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
489495
struct super_block *sb = inode->i_sb;
490-
struct kernel_lb_addr prealloc_loc = {};
491-
uint32_t prealloc_len = 0;
492496
struct udf_inode_info *iinfo;
493497
int err;
494498

@@ -509,19 +513,6 @@ static int udf_do_extend_file(struct inode *inode,
509513
~(sb->s_blocksize - 1);
510514
}
511515

512-
/* Last extent are just preallocated blocks? */
513-
if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) ==
514-
EXT_NOT_RECORDED_ALLOCATED) {
515-
/* Save the extent so that we can reattach it to the end */
516-
prealloc_loc = last_ext->extLocation;
517-
prealloc_len = last_ext->extLength;
518-
/* Mark the extent as a hole */
519-
last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
520-
(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
521-
last_ext->extLocation.logicalBlockNum = 0;
522-
last_ext->extLocation.partitionReferenceNum = 0;
523-
}
524-
525516
/* Can we merge with the previous extent? */
526517
if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) ==
527518
EXT_NOT_RECORDED_NOT_ALLOCATED) {
@@ -549,7 +540,7 @@ static int udf_do_extend_file(struct inode *inode,
549540
* more extents, we may need to enter possible following
550541
* empty indirect extent.
551542
*/
552-
if (new_block_bytes || prealloc_len)
543+
if (new_block_bytes)
553544
udf_next_aext(inode, last_pos, &tmploc, &tmplen, 0);
554545
}
555546

@@ -583,17 +574,6 @@ static int udf_do_extend_file(struct inode *inode,
583574
}
584575

585576
out:
586-
/* Do we have some preallocated blocks saved? */
587-
if (prealloc_len) {
588-
err = udf_add_aext(inode, last_pos, &prealloc_loc,
589-
prealloc_len, 1);
590-
if (err)
591-
return err;
592-
last_ext->extLocation = prealloc_loc;
593-
last_ext->extLength = prealloc_len;
594-
count++;
595-
}
596-
597577
/* last_pos should point to the last written extent... */
598578
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
599579
last_pos->offset -= sizeof(struct short_ad);
@@ -646,8 +626,17 @@ static int udf_extend_file(struct inode *inode, loff_t newsize)
646626
else
647627
BUG();
648628

629+
/*
630+
* When creating hole in file, just don't bother with preserving
631+
* preallocation. It likely won't be very useful anyway.
632+
*/
633+
udf_discard_prealloc(inode);
634+
649635
etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
650636
within_final_block = (etype != -1);
637+
/* We don't expect extents past EOF... */
638+
WARN_ON_ONCE(etype != -1 &&
639+
elen > ((loff_t)offset + 1) << inode->i_blkbits);
651640

652641
if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) ||
653642
(epos.bh && epos.offset == sizeof(struct allocExtDesc))) {
@@ -776,10 +765,11 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
776765
goto out_free;
777766
}
778767

779-
/* Are we beyond EOF? */
768+
/* Are we beyond EOF and preallocated extent? */
780769
if (etype == -1) {
781770
int ret;
782771
loff_t hole_len;
772+
783773
isBeyondEOF = true;
784774
if (count) {
785775
if (c)

0 commit comments

Comments
 (0)