diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-14 15:50:25 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-14 15:50:25 -0500 |
| commit | 3ea6b3d0e6d0ffd91c0f8cadeb69b7133c038b32 (patch) | |
| tree | 5d5920258fc8e3bafd16fddf5fb92f9ec0bb3cc1 | |
| parent | 75b08038ceb62f3bd8935346679920f97c3cf9f6 (diff) | |
| parent | 2c948b3f86e5f0327e2e57858600af6e6f0ae29a (diff) | |
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
| -rw-r--r-- | fs/udf/balloc.c | 2 | ||||
| -rw-r--r-- | fs/udf/file.c | 1 | ||||
| -rw-r--r-- | fs/udf/inode.c | 24 | ||||
| -rw-r--r-- | fs/udf/namei.c | 38 | ||||
| -rw-r--r-- | fs/udf/super.c | 32 |
5 files changed, 66 insertions, 31 deletions
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index 1e068535b58b..82372e332f08 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c | |||
| @@ -440,7 +440,7 @@ static void udf_table_free_blocks(struct super_block *sb, | |||
| 440 | (bloc->logicalBlockNum + count) > | 440 | (bloc->logicalBlockNum + count) > |
| 441 | partmap->s_partition_len) { | 441 | partmap->s_partition_len) { |
| 442 | udf_debug("%d < %d || %d + %d > %d\n", | 442 | udf_debug("%d < %d || %d + %d > %d\n", |
| 443 | bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count, | 443 | bloc->logicalBlockNum, 0, bloc->logicalBlockNum, count, |
| 444 | partmap->s_partition_len); | 444 | partmap->s_partition_len); |
| 445 | goto error_return; | 445 | goto error_return; |
| 446 | } | 446 | } |
diff --git a/fs/udf/file.c b/fs/udf/file.c index b80cbd78833c..f311d509b6a3 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c | |||
| @@ -196,6 +196,7 @@ static int udf_release_file(struct inode *inode, struct file *filp) | |||
| 196 | mutex_lock(&inode->i_mutex); | 196 | mutex_lock(&inode->i_mutex); |
| 197 | lock_kernel(); | 197 | lock_kernel(); |
| 198 | udf_discard_prealloc(inode); | 198 | udf_discard_prealloc(inode); |
| 199 | udf_truncate_tail_extent(inode); | ||
| 199 | unlock_kernel(); | 200 | unlock_kernel(); |
| 200 | mutex_unlock(&inode->i_mutex); | 201 | mutex_unlock(&inode->i_mutex); |
| 201 | } | 202 | } |
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 6d24c2c63f93..f90231eb2916 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
| @@ -97,15 +97,17 @@ no_delete: | |||
| 97 | */ | 97 | */ |
| 98 | void udf_clear_inode(struct inode *inode) | 98 | void udf_clear_inode(struct inode *inode) |
| 99 | { | 99 | { |
| 100 | struct udf_inode_info *iinfo; | 100 | struct udf_inode_info *iinfo = UDF_I(inode); |
| 101 | if (!(inode->i_sb->s_flags & MS_RDONLY)) { | 101 | |
| 102 | lock_kernel(); | 102 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && |
| 103 | udf_truncate_tail_extent(inode); | 103 | inode->i_size != iinfo->i_lenExtents) { |
| 104 | unlock_kernel(); | 104 | printk(KERN_WARNING "UDF-fs (%s): Inode %lu (mode %o) has " |
| 105 | write_inode_now(inode, 0); | 105 | "inode size %llu different from extent lenght %llu. " |
| 106 | invalidate_inode_buffers(inode); | 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); | ||
| 107 | } | 110 | } |
| 108 | iinfo = UDF_I(inode); | ||
| 109 | kfree(iinfo->i_ext.i_data); | 111 | kfree(iinfo->i_ext.i_data); |
| 110 | iinfo->i_ext.i_data = NULL; | 112 | iinfo->i_ext.i_data = NULL; |
| 111 | } | 113 | } |
| @@ -198,7 +200,6 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block, | |||
| 198 | int newblock; | 200 | int newblock; |
| 199 | struct buffer_head *dbh = NULL; | 201 | struct buffer_head *dbh = NULL; |
| 200 | struct kernel_lb_addr eloc; | 202 | struct kernel_lb_addr eloc; |
| 201 | uint32_t elen; | ||
| 202 | uint8_t alloctype; | 203 | uint8_t alloctype; |
| 203 | struct extent_position epos; | 204 | struct extent_position epos; |
| 204 | 205 | ||
| @@ -273,12 +274,11 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block, | |||
| 273 | eloc.logicalBlockNum = *block; | 274 | eloc.logicalBlockNum = *block; |
| 274 | eloc.partitionReferenceNum = | 275 | eloc.partitionReferenceNum = |
| 275 | iinfo->i_location.partitionReferenceNum; | 276 | iinfo->i_location.partitionReferenceNum; |
| 276 | elen = inode->i_sb->s_blocksize; | 277 | iinfo->i_lenExtents = inode->i_size; |
| 277 | iinfo->i_lenExtents = elen; | ||
| 278 | epos.bh = NULL; | 278 | epos.bh = NULL; |
| 279 | epos.block = iinfo->i_location; | 279 | epos.block = iinfo->i_location; |
| 280 | epos.offset = udf_file_entry_alloc_offset(inode); | 280 | 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); |
| 282 | /* UniqueID stuff */ | 282 | /* UniqueID stuff */ |
| 283 | 283 | ||
| 284 | brelse(epos.bh); | 284 | brelse(epos.bh); |
diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 21dad8c608f9..cd2115060fdc 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c | |||
| @@ -408,15 +408,6 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, | |||
| 408 | } | 408 | } |
| 409 | 409 | ||
| 410 | add: | 410 | 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 | } | ||
| 420 | f_pos += nfidlen; | 411 | f_pos += nfidlen; |
| 421 | 412 | ||
| 422 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB && | 413 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB && |
| @@ -439,6 +430,7 @@ add: | |||
| 439 | udf_current_aext(dir, &epos, &eloc, &elen, 1); | 430 | udf_current_aext(dir, &epos, &eloc, &elen, 1); |
| 440 | } | 431 | } |
| 441 | 432 | ||
| 433 | /* Entry fits into current block? */ | ||
| 442 | if (sb->s_blocksize - fibh->eoffset >= nfidlen) { | 434 | if (sb->s_blocksize - fibh->eoffset >= nfidlen) { |
| 443 | fibh->soffset = fibh->eoffset; | 435 | fibh->soffset = fibh->eoffset; |
| 444 | fibh->eoffset += nfidlen; | 436 | fibh->eoffset += nfidlen; |
| @@ -462,6 +454,16 @@ add: | |||
| 462 | (fibh->sbh->b_data + fibh->soffset); | 454 | (fibh->sbh->b_data + fibh->soffset); |
| 463 | } | 455 | } |
| 464 | } else { | 456 | } 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 | |||
| 465 | fibh->soffset = fibh->eoffset - sb->s_blocksize; | 467 | fibh->soffset = fibh->eoffset - sb->s_blocksize; |
| 466 | fibh->eoffset += nfidlen - sb->s_blocksize; | 468 | fibh->eoffset += nfidlen - sb->s_blocksize; |
| 467 | if (fibh->sbh != fibh->ebh) { | 469 | if (fibh->sbh != fibh->ebh) { |
| @@ -508,6 +510,20 @@ add: | |||
| 508 | dir->i_size += nfidlen; | 510 | dir->i_size += nfidlen; |
| 509 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) | 511 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) |
| 510 | dinfo->i_lenAlloc += nfidlen; | 512 | 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 | |||
| 511 | mark_inode_dirty(dir); | 527 | mark_inode_dirty(dir); |
| 512 | goto out_ok; | 528 | goto out_ok; |
| 513 | } else { | 529 | } else { |
| @@ -922,7 +938,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, | |||
| 922 | block = udf_get_pblock(inode->i_sb, block, | 938 | block = udf_get_pblock(inode->i_sb, block, |
| 923 | iinfo->i_location.partitionReferenceNum, | 939 | iinfo->i_location.partitionReferenceNum, |
| 924 | 0); | 940 | 0); |
| 925 | epos.bh = udf_tread(inode->i_sb, block); | 941 | epos.bh = udf_tgetblk(inode->i_sb, block); |
| 926 | lock_buffer(epos.bh); | 942 | lock_buffer(epos.bh); |
| 927 | memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize); | 943 | memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize); |
| 928 | set_buffer_uptodate(epos.bh); | 944 | set_buffer_uptodate(epos.bh); |
| @@ -999,6 +1015,8 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, | |||
| 999 | inode->i_size = elen; | 1015 | inode->i_size = elen; |
| 1000 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) | 1016 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) |
| 1001 | iinfo->i_lenAlloc = inode->i_size; | 1017 | iinfo->i_lenAlloc = inode->i_size; |
| 1018 | else | ||
| 1019 | udf_truncate_tail_extent(inode); | ||
| 1002 | mark_inode_dirty(inode); | 1020 | mark_inode_dirty(inode); |
| 1003 | 1021 | ||
| 1004 | fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); | 1022 | fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); |
diff --git a/fs/udf/super.c b/fs/udf/super.c index 9d1b8c2e6c45..1e4543cbcd27 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
| @@ -1078,21 +1078,39 @@ static int udf_fill_partdesc_info(struct super_block *sb, | |||
| 1078 | return 0; | 1078 | return 0; |
| 1079 | } | 1079 | } |
| 1080 | 1080 | ||
| 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) | ||
| 1082 | { | 1083 | { |
| 1083 | struct udf_sb_info *sbi = UDF_SB(sb); | 1084 | struct udf_sb_info *sbi = UDF_SB(sb); |
| 1084 | struct udf_part_map *map = &sbi->s_partmaps[p_index]; | 1085 | struct udf_part_map *map = &sbi->s_partmaps[p_index]; |
| 1086 | sector_t vat_block; | ||
| 1085 | struct kernel_lb_addr ino; | 1087 | 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]; | ||
| 1086 | struct buffer_head *bh = NULL; | 1107 | struct buffer_head *bh = NULL; |
| 1087 | struct udf_inode_info *vati; | 1108 | struct udf_inode_info *vati; |
| 1088 | uint32_t pos; | 1109 | uint32_t pos; |
| 1089 | struct virtualAllocationTable20 *vat20; | 1110 | struct virtualAllocationTable20 *vat20; |
| 1090 | sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits; | 1111 | sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits; |
| 1091 | 1112 | ||
| 1092 | /* VAT file entry is in the last recorded block */ | 1113 | udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_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); | ||
| 1096 | if (!sbi->s_vat_inode && | 1114 | if (!sbi->s_vat_inode && |
| 1097 | sbi->s_last_block != blocks - 1) { | 1115 | sbi->s_last_block != blocks - 1) { |
| 1098 | printk(KERN_NOTICE "UDF-fs: Failed to read VAT inode from the" | 1116 | 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 | "block of the device (%lu).\n", | 1118 | "block of the device (%lu).\n", |
| 1101 | (unsigned long)sbi->s_last_block, | 1119 | (unsigned long)sbi->s_last_block, |
| 1102 | (unsigned long)blocks - 1); | 1120 | (unsigned long)blocks - 1); |
| 1103 | ino.partitionReferenceNum = type1_index; | 1121 | udf_find_vat_block(sb, p_index, type1_index, blocks - 1); |
| 1104 | ino.logicalBlockNum = blocks - 1 - map->s_partition_root; | ||
| 1105 | sbi->s_vat_inode = udf_iget(sb, &ino); | ||
| 1106 | } | 1122 | } |
| 1107 | if (!sbi->s_vat_inode) | 1123 | if (!sbi->s_vat_inode) |
| 1108 | return 1; | 1124 | return 1; |
