Skip to content

Commit 3ea6b3d

Browse files
committed
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-udf-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-udf-2.6: udf: Avoid IO in udf_clear_inode udf: Try harder when looking for VAT inode udf: Fix compilation with UDFFS_DEBUG enabled
2 parents 75b0803 + 2c948b3 commit 3ea6b3d

File tree

5 files changed

+66
-31
lines changed

5 files changed

+66
-31
lines changed

fs/udf/balloc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ static void udf_table_free_blocks(struct super_block *sb,
440440
(bloc->logicalBlockNum + count) >
441441
partmap->s_partition_len) {
442442
udf_debug("%d < %d || %d + %d > %d\n",
443-
bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count,
443+
bloc->logicalBlockNum, 0, bloc->logicalBlockNum, count,
444444
partmap->s_partition_len);
445445
goto error_return;
446446
}

fs/udf/file.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ static int udf_release_file(struct inode *inode, struct file *filp)
196196
mutex_lock(&inode->i_mutex);
197197
lock_kernel();
198198
udf_discard_prealloc(inode);
199+
udf_truncate_tail_extent(inode);
199200
unlock_kernel();
200201
mutex_unlock(&inode->i_mutex);
201202
}

fs/udf/inode.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,17 @@ void udf_delete_inode(struct inode *inode)
9797
*/
9898
void udf_clear_inode(struct inode *inode)
9999
{
100-
struct udf_inode_info *iinfo;
101-
if (!(inode->i_sb->s_flags & MS_RDONLY)) {
102-
lock_kernel();
103-
udf_truncate_tail_extent(inode);
104-
unlock_kernel();
105-
write_inode_now(inode, 0);
106-
invalidate_inode_buffers(inode);
100+
struct udf_inode_info *iinfo = UDF_I(inode);
101+
102+
if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB &&
103+
inode->i_size != iinfo->i_lenExtents) {
104+
printk(KERN_WARNING "UDF-fs (%s): Inode %lu (mode %o) has "
105+
"inode size %llu different from extent lenght %llu. "
106+
"Filesystem need not be standards compliant.\n",
107+
inode->i_sb->s_id, inode->i_ino, inode->i_mode,
108+
(unsigned long long)inode->i_size,
109+
(unsigned long long)iinfo->i_lenExtents);
107110
}
108-
iinfo = UDF_I(inode);
109111
kfree(iinfo->i_ext.i_data);
110112
iinfo->i_ext.i_data = NULL;
111113
}
@@ -198,7 +200,6 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block,
198200
int newblock;
199201
struct buffer_head *dbh = NULL;
200202
struct kernel_lb_addr eloc;
201-
uint32_t elen;
202203
uint8_t alloctype;
203204
struct extent_position epos;
204205

@@ -273,12 +274,11 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block,
273274
eloc.logicalBlockNum = *block;
274275
eloc.partitionReferenceNum =
275276
iinfo->i_location.partitionReferenceNum;
276-
elen = inode->i_sb->s_blocksize;
277-
iinfo->i_lenExtents = elen;
277+
iinfo->i_lenExtents = inode->i_size;
278278
epos.bh = NULL;
279279
epos.block = iinfo->i_location;
280280
epos.offset = udf_file_entry_alloc_offset(inode);
281-
udf_add_aext(inode, &epos, &eloc, elen, 0);
281+
udf_add_aext(inode, &epos, &eloc, inode->i_size, 0);
282282
/* UniqueID stuff */
283283

284284
brelse(epos.bh);

fs/udf/namei.c

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -408,15 +408,6 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
408408
}
409409

410410
add:
411-
/* Is there any extent whose size we need to round up? */
412-
if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && elen) {
413-
elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1);
414-
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
415-
epos.offset -= sizeof(struct short_ad);
416-
else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
417-
epos.offset -= sizeof(struct long_ad);
418-
udf_write_aext(dir, &epos, &eloc, elen, 1);
419-
}
420411
f_pos += nfidlen;
421412

422413
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB &&
@@ -439,6 +430,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
439430
udf_current_aext(dir, &epos, &eloc, &elen, 1);
440431
}
441432

433+
/* Entry fits into current block? */
442434
if (sb->s_blocksize - fibh->eoffset >= nfidlen) {
443435
fibh->soffset = fibh->eoffset;
444436
fibh->eoffset += nfidlen;
@@ -462,6 +454,16 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
462454
(fibh->sbh->b_data + fibh->soffset);
463455
}
464456
} else {
457+
/* Round up last extent in the file */
458+
elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1);
459+
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
460+
epos.offset -= sizeof(struct short_ad);
461+
else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
462+
epos.offset -= sizeof(struct long_ad);
463+
udf_write_aext(dir, &epos, &eloc, elen, 1);
464+
dinfo->i_lenExtents = (dinfo->i_lenExtents + sb->s_blocksize
465+
- 1) & ~(sb->s_blocksize - 1);
466+
465467
fibh->soffset = fibh->eoffset - sb->s_blocksize;
466468
fibh->eoffset += nfidlen - sb->s_blocksize;
467469
if (fibh->sbh != fibh->ebh) {
@@ -508,6 +510,20 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
508510
dir->i_size += nfidlen;
509511
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
510512
dinfo->i_lenAlloc += nfidlen;
513+
else {
514+
/* Find the last extent and truncate it to proper size */
515+
while (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
516+
(EXT_RECORDED_ALLOCATED >> 30))
517+
;
518+
elen -= dinfo->i_lenExtents - dir->i_size;
519+
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
520+
epos.offset -= sizeof(struct short_ad);
521+
else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
522+
epos.offset -= sizeof(struct long_ad);
523+
udf_write_aext(dir, &epos, &eloc, elen, 1);
524+
dinfo->i_lenExtents = dir->i_size;
525+
}
526+
511527
mark_inode_dirty(dir);
512528
goto out_ok;
513529
} else {
@@ -922,7 +938,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
922938
block = udf_get_pblock(inode->i_sb, block,
923939
iinfo->i_location.partitionReferenceNum,
924940
0);
925-
epos.bh = udf_tread(inode->i_sb, block);
941+
epos.bh = udf_tgetblk(inode->i_sb, block);
926942
lock_buffer(epos.bh);
927943
memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize);
928944
set_buffer_uptodate(epos.bh);
@@ -999,6 +1015,8 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
9991015
inode->i_size = elen;
10001016
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
10011017
iinfo->i_lenAlloc = inode->i_size;
1018+
else
1019+
udf_truncate_tail_extent(inode);
10021020
mark_inode_dirty(inode);
10031021

10041022
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);

fs/udf/super.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,31 +1078,47 @@ static int udf_fill_partdesc_info(struct super_block *sb,
10781078
return 0;
10791079
}
10801080

1081-
static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
1081+
static void udf_find_vat_block(struct super_block *sb, int p_index,
1082+
int type1_index, sector_t start_block)
10821083
{
10831084
struct udf_sb_info *sbi = UDF_SB(sb);
10841085
struct udf_part_map *map = &sbi->s_partmaps[p_index];
1086+
sector_t vat_block;
10851087
struct kernel_lb_addr ino;
1088+
1089+
/*
1090+
* VAT file entry is in the last recorded block. Some broken disks have
1091+
* it a few blocks before so try a bit harder...
1092+
*/
1093+
ino.partitionReferenceNum = type1_index;
1094+
for (vat_block = start_block;
1095+
vat_block >= map->s_partition_root &&
1096+
vat_block >= start_block - 3 &&
1097+
!sbi->s_vat_inode; vat_block--) {
1098+
ino.logicalBlockNum = vat_block - map->s_partition_root;
1099+
sbi->s_vat_inode = udf_iget(sb, &ino);
1100+
}
1101+
}
1102+
1103+
static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
1104+
{
1105+
struct udf_sb_info *sbi = UDF_SB(sb);
1106+
struct udf_part_map *map = &sbi->s_partmaps[p_index];
10861107
struct buffer_head *bh = NULL;
10871108
struct udf_inode_info *vati;
10881109
uint32_t pos;
10891110
struct virtualAllocationTable20 *vat20;
10901111
sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits;
10911112

1092-
/* VAT file entry is in the last recorded block */
1093-
ino.partitionReferenceNum = type1_index;
1094-
ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root;
1095-
sbi->s_vat_inode = udf_iget(sb, &ino);
1113+
udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_block);
10961114
if (!sbi->s_vat_inode &&
10971115
sbi->s_last_block != blocks - 1) {
10981116
printk(KERN_NOTICE "UDF-fs: Failed to read VAT inode from the"
10991117
" last recorded block (%lu), retrying with the last "
11001118
"block of the device (%lu).\n",
11011119
(unsigned long)sbi->s_last_block,
11021120
(unsigned long)blocks - 1);
1103-
ino.partitionReferenceNum = type1_index;
1104-
ino.logicalBlockNum = blocks - 1 - map->s_partition_root;
1105-
sbi->s_vat_inode = udf_iget(sb, &ino);
1121+
udf_find_vat_block(sb, p_index, type1_index, blocks - 1);
11061122
}
11071123
if (!sbi->s_vat_inode)
11081124
return 1;

0 commit comments

Comments
 (0)