Commit 3ea6b3d0 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 75b08038 2c948b3f
...@@ -440,7 +440,7 @@ static void udf_table_free_blocks(struct super_block *sb, ...@@ -440,7 +440,7 @@ static void udf_table_free_blocks(struct super_block *sb,
(bloc->logicalBlockNum + count) > (bloc->logicalBlockNum + count) >
partmap->s_partition_len) { partmap->s_partition_len) {
udf_debug("%d < %d || %d + %d > %d\n", udf_debug("%d < %d || %d + %d > %d\n",
bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count, bloc->logicalBlockNum, 0, bloc->logicalBlockNum, count,
partmap->s_partition_len); partmap->s_partition_len);
goto error_return; goto error_return;
} }
......
...@@ -196,6 +196,7 @@ static int udf_release_file(struct inode *inode, struct file *filp) ...@@ -196,6 +196,7 @@ static int udf_release_file(struct inode *inode, struct file *filp)
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
lock_kernel(); lock_kernel();
udf_discard_prealloc(inode); udf_discard_prealloc(inode);
udf_truncate_tail_extent(inode);
unlock_kernel(); unlock_kernel();
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
} }
......
...@@ -97,15 +97,17 @@ void udf_delete_inode(struct inode *inode) ...@@ -97,15 +97,17 @@ void udf_delete_inode(struct inode *inode)
*/ */
void udf_clear_inode(struct inode *inode) void udf_clear_inode(struct inode *inode)
{ {
struct udf_inode_info *iinfo; struct udf_inode_info *iinfo = UDF_I(inode);
if (!(inode->i_sb->s_flags & MS_RDONLY)) {
lock_kernel(); if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB &&
udf_truncate_tail_extent(inode); inode->i_size != iinfo->i_lenExtents) {
unlock_kernel(); printk(KERN_WARNING "UDF-fs (%s): Inode %lu (mode %o) has "
write_inode_now(inode, 0); "inode size %llu different from extent lenght %llu. "
invalidate_inode_buffers(inode); "Filesystem need not be standards compliant.\n",
inode->i_sb->s_id, inode->i_ino, inode->i_mode,
(unsigned long long)inode->i_size,
(unsigned long long)iinfo->i_lenExtents);
} }
iinfo = UDF_I(inode);
kfree(iinfo->i_ext.i_data); kfree(iinfo->i_ext.i_data);
iinfo->i_ext.i_data = NULL; iinfo->i_ext.i_data = NULL;
} }
...@@ -198,7 +200,6 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block, ...@@ -198,7 +200,6 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block,
int newblock; int newblock;
struct buffer_head *dbh = NULL; struct buffer_head *dbh = NULL;
struct kernel_lb_addr eloc; struct kernel_lb_addr eloc;
uint32_t elen;
uint8_t alloctype; uint8_t alloctype;
struct extent_position epos; struct extent_position epos;
...@@ -273,12 +274,11 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block, ...@@ -273,12 +274,11 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block,
eloc.logicalBlockNum = *block; eloc.logicalBlockNum = *block;
eloc.partitionReferenceNum = eloc.partitionReferenceNum =
iinfo->i_location.partitionReferenceNum; iinfo->i_location.partitionReferenceNum;
elen = inode->i_sb->s_blocksize; iinfo->i_lenExtents = inode->i_size;
iinfo->i_lenExtents = elen;
epos.bh = NULL; epos.bh = NULL;
epos.block = iinfo->i_location; epos.block = iinfo->i_location;
epos.offset = udf_file_entry_alloc_offset(inode); epos.offset = udf_file_entry_alloc_offset(inode);
udf_add_aext(inode, &epos, &eloc, elen, 0); udf_add_aext(inode, &epos, &eloc, inode->i_size, 0);
/* UniqueID stuff */ /* UniqueID stuff */
brelse(epos.bh); brelse(epos.bh);
......
...@@ -408,15 +408,6 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, ...@@ -408,15 +408,6 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
} }
add: add:
/* Is there any extent whose size we need to round up? */
if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && elen) {
elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1);
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
epos.offset -= sizeof(struct short_ad);
else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
epos.offset -= sizeof(struct long_ad);
udf_write_aext(dir, &epos, &eloc, elen, 1);
}
f_pos += nfidlen; f_pos += nfidlen;
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB && if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB &&
...@@ -439,6 +430,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, ...@@ -439,6 +430,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
udf_current_aext(dir, &epos, &eloc, &elen, 1); udf_current_aext(dir, &epos, &eloc, &elen, 1);
} }
/* Entry fits into current block? */
if (sb->s_blocksize - fibh->eoffset >= nfidlen) { if (sb->s_blocksize - fibh->eoffset >= nfidlen) {
fibh->soffset = fibh->eoffset; fibh->soffset = fibh->eoffset;
fibh->eoffset += nfidlen; fibh->eoffset += nfidlen;
...@@ -462,6 +454,16 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, ...@@ -462,6 +454,16 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
(fibh->sbh->b_data + fibh->soffset); (fibh->sbh->b_data + fibh->soffset);
} }
} else { } else {
/* Round up last extent in the file */
elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1);
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
epos.offset -= sizeof(struct short_ad);
else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
epos.offset -= sizeof(struct long_ad);
udf_write_aext(dir, &epos, &eloc, elen, 1);
dinfo->i_lenExtents = (dinfo->i_lenExtents + sb->s_blocksize
- 1) & ~(sb->s_blocksize - 1);
fibh->soffset = fibh->eoffset - sb->s_blocksize; fibh->soffset = fibh->eoffset - sb->s_blocksize;
fibh->eoffset += nfidlen - sb->s_blocksize; fibh->eoffset += nfidlen - sb->s_blocksize;
if (fibh->sbh != fibh->ebh) { if (fibh->sbh != fibh->ebh) {
...@@ -508,6 +510,20 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, ...@@ -508,6 +510,20 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
dir->i_size += nfidlen; dir->i_size += nfidlen;
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
dinfo->i_lenAlloc += nfidlen; dinfo->i_lenAlloc += nfidlen;
else {
/* Find the last extent and truncate it to proper size */
while (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
(EXT_RECORDED_ALLOCATED >> 30))
;
elen -= dinfo->i_lenExtents - dir->i_size;
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
epos.offset -= sizeof(struct short_ad);
else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
epos.offset -= sizeof(struct long_ad);
udf_write_aext(dir, &epos, &eloc, elen, 1);
dinfo->i_lenExtents = dir->i_size;
}
mark_inode_dirty(dir); mark_inode_dirty(dir);
goto out_ok; goto out_ok;
} else { } else {
...@@ -922,7 +938,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, ...@@ -922,7 +938,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
block = udf_get_pblock(inode->i_sb, block, block = udf_get_pblock(inode->i_sb, block,
iinfo->i_location.partitionReferenceNum, iinfo->i_location.partitionReferenceNum,
0); 0);
epos.bh = udf_tread(inode->i_sb, block); epos.bh = udf_tgetblk(inode->i_sb, block);
lock_buffer(epos.bh); lock_buffer(epos.bh);
memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize); memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize);
set_buffer_uptodate(epos.bh); set_buffer_uptodate(epos.bh);
...@@ -999,6 +1015,8 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, ...@@ -999,6 +1015,8 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
inode->i_size = elen; inode->i_size = elen;
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
iinfo->i_lenAlloc = inode->i_size; iinfo->i_lenAlloc = inode->i_size;
else
udf_truncate_tail_extent(inode);
mark_inode_dirty(inode); mark_inode_dirty(inode);
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
......
...@@ -1078,21 +1078,39 @@ static int udf_fill_partdesc_info(struct super_block *sb, ...@@ -1078,21 +1078,39 @@ static int udf_fill_partdesc_info(struct super_block *sb,
return 0; return 0;
} }
static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) static void udf_find_vat_block(struct super_block *sb, int p_index,
int type1_index, sector_t start_block)
{ {
struct udf_sb_info *sbi = UDF_SB(sb); struct udf_sb_info *sbi = UDF_SB(sb);
struct udf_part_map *map = &sbi->s_partmaps[p_index]; struct udf_part_map *map = &sbi->s_partmaps[p_index];
sector_t vat_block;
struct kernel_lb_addr ino; struct kernel_lb_addr ino;
/*
* VAT file entry is in the last recorded block. Some broken disks have
* it a few blocks before so try a bit harder...
*/
ino.partitionReferenceNum = type1_index;
for (vat_block = start_block;
vat_block >= map->s_partition_root &&
vat_block >= start_block - 3 &&
!sbi->s_vat_inode; vat_block--) {
ino.logicalBlockNum = vat_block - map->s_partition_root;
sbi->s_vat_inode = udf_iget(sb, &ino);
}
}
static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
{
struct udf_sb_info *sbi = UDF_SB(sb);
struct udf_part_map *map = &sbi->s_partmaps[p_index];
struct buffer_head *bh = NULL; struct buffer_head *bh = NULL;
struct udf_inode_info *vati; struct udf_inode_info *vati;
uint32_t pos; uint32_t pos;
struct virtualAllocationTable20 *vat20; struct virtualAllocationTable20 *vat20;
sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits; sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits;
/* VAT file entry is in the last recorded block */ udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_block);
ino.partitionReferenceNum = type1_index;
ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root;
sbi->s_vat_inode = udf_iget(sb, &ino);
if (!sbi->s_vat_inode && if (!sbi->s_vat_inode &&
sbi->s_last_block != blocks - 1) { sbi->s_last_block != blocks - 1) {
printk(KERN_NOTICE "UDF-fs: Failed to read VAT inode from the" printk(KERN_NOTICE "UDF-fs: Failed to read VAT inode from the"
...@@ -1100,9 +1118,7 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) ...@@ -1100,9 +1118,7 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
"block of the device (%lu).\n", "block of the device (%lu).\n",
(unsigned long)sbi->s_last_block, (unsigned long)sbi->s_last_block,
(unsigned long)blocks - 1); (unsigned long)blocks - 1);
ino.partitionReferenceNum = type1_index; udf_find_vat_block(sb, p_index, type1_index, blocks - 1);
ino.logicalBlockNum = blocks - 1 - map->s_partition_root;
sbi->s_vat_inode = udf_iget(sb, &ino);
} }
if (!sbi->s_vat_inode) if (!sbi->s_vat_inode)
return 1; return 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment