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
This commit is contained in:
@@ -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)
|
|||||||
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 @@ no_delete:
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 @@ add:
|
|||||||
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 @@ add:
|
|||||||
(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 @@ add:
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_part_map *map = &sbi->s_partmaps[p_index];
|
||||||
|
sector_t vat_block;
|
||||||
|
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)
|
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_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];
|
||||||
struct kernel_lb_addr ino;
|
|
||||||
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)
|
|||||||
"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;
|
||||||
|
Reference in New Issue
Block a user