Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+66 -31
+1 -1
fs/udf/balloc.c
··· 440 440 (bloc->logicalBlockNum + count) > 441 441 partmap->s_partition_len) { 442 442 udf_debug("%d < %d || %d + %d > %d\n", 443 - bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count, 443 + bloc->logicalBlockNum, 0, bloc->logicalBlockNum, count, 444 444 partmap->s_partition_len); 445 445 goto error_return; 446 446 }
+1
fs/udf/file.c
··· 196 196 mutex_lock(&inode->i_mutex); 197 197 lock_kernel(); 198 198 udf_discard_prealloc(inode); 199 + udf_truncate_tail_extent(inode); 199 200 unlock_kernel(); 200 201 mutex_unlock(&inode->i_mutex); 201 202 }
+12 -12
fs/udf/inode.c
··· 97 97 */ 98 98 void udf_clear_inode(struct inode *inode) 99 99 { 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); 107 110 } 108 - iinfo = UDF_I(inode); 109 111 kfree(iinfo->i_ext.i_data); 110 112 iinfo->i_ext.i_data = NULL; 111 113 } ··· 200 198 int newblock; 201 199 struct buffer_head *dbh = NULL; 202 200 struct kernel_lb_addr eloc; 203 - uint32_t elen; 204 201 uint8_t alloctype; 205 202 struct extent_position epos; 206 203 ··· 274 273 eloc.logicalBlockNum = *block; 275 274 eloc.partitionReferenceNum = 276 275 iinfo->i_location.partitionReferenceNum; 277 - elen = inode->i_sb->s_blocksize; 278 - iinfo->i_lenExtents = elen; 276 + iinfo->i_lenExtents = inode->i_size; 279 277 epos.bh = NULL; 280 278 epos.block = iinfo->i_location; 281 279 epos.offset = udf_file_entry_alloc_offset(inode); 282 - udf_add_aext(inode, &epos, &eloc, elen, 0); 280 + udf_add_aext(inode, &epos, &eloc, inode->i_size, 0); 283 281 /* UniqueID stuff */ 284 282 285 283 brelse(epos.bh);
+28 -10
fs/udf/namei.c
··· 408 408 } 409 409 410 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 411 f_pos += nfidlen; 421 412 422 413 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB && ··· 430 439 udf_current_aext(dir, &epos, &eloc, &elen, 1); 431 440 } 432 441 442 + /* Entry fits into current block? */ 433 443 if (sb->s_blocksize - fibh->eoffset >= nfidlen) { 434 444 fibh->soffset = fibh->eoffset; 435 445 fibh->eoffset += nfidlen; ··· 454 462 (fibh->sbh->b_data + fibh->soffset); 455 463 } 456 464 } else { 465 + /* Round up last extent in the file */ 466 + elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1); 467 + if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) 468 + epos.offset -= sizeof(struct short_ad); 469 + else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) 470 + epos.offset -= sizeof(struct long_ad); 471 + udf_write_aext(dir, &epos, &eloc, elen, 1); 472 + dinfo->i_lenExtents = (dinfo->i_lenExtents + sb->s_blocksize 473 + - 1) & ~(sb->s_blocksize - 1); 474 + 457 475 fibh->soffset = fibh->eoffset - sb->s_blocksize; 458 476 fibh->eoffset += nfidlen - sb->s_blocksize; 459 477 if (fibh->sbh != fibh->ebh) { ··· 510 508 dir->i_size += nfidlen; 511 509 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) 512 510 dinfo->i_lenAlloc += nfidlen; 511 + else { 512 + /* Find the last extent and truncate it to proper size */ 513 + while (udf_next_aext(dir, &epos, &eloc, &elen, 1) == 514 + (EXT_RECORDED_ALLOCATED >> 30)) 515 + ; 516 + elen -= dinfo->i_lenExtents - dir->i_size; 517 + if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) 518 + epos.offset -= sizeof(struct short_ad); 519 + else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) 520 + epos.offset -= sizeof(struct long_ad); 521 + udf_write_aext(dir, &epos, &eloc, elen, 1); 522 + dinfo->i_lenExtents = dir->i_size; 523 + } 524 + 513 525 mark_inode_dirty(dir); 514 526 goto out_ok; 515 527 } else { ··· 938 922 block = udf_get_pblock(inode->i_sb, block, 939 923 iinfo->i_location.partitionReferenceNum, 940 924 0); 941 - epos.bh = udf_tread(inode->i_sb, block); 925 + epos.bh = udf_tgetblk(inode->i_sb, block); 942 926 lock_buffer(epos.bh); 943 927 memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize); 944 928 set_buffer_uptodate(epos.bh); ··· 1015 999 inode->i_size = elen; 1016 1000 if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) 1017 1001 iinfo->i_lenAlloc = inode->i_size; 1002 + else 1003 + udf_truncate_tail_extent(inode); 1018 1004 mark_inode_dirty(inode); 1019 1005 1020 1006 fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
+24 -8
fs/udf/super.c
··· 1078 1078 return 0; 1079 1079 } 1080 1080 1081 + static void udf_find_vat_block(struct super_block *sb, int p_index, 1082 + int type1_index, sector_t start_block) 1083 + { 1084 + struct udf_sb_info *sbi = UDF_SB(sb); 1085 + struct udf_part_map *map = &sbi->s_partmaps[p_index]; 1086 + sector_t vat_block; 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 + 1081 1103 static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) 1082 1104 { 1083 1105 struct udf_sb_info *sbi = UDF_SB(sb); 1084 1106 struct udf_part_map *map = &sbi->s_partmaps[p_index]; 1085 - struct kernel_lb_addr ino; 1086 1107 struct buffer_head *bh = NULL; 1087 1108 struct udf_inode_info *vati; 1088 1109 uint32_t pos; 1089 1110 struct virtualAllocationTable20 *vat20; 1090 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 */ 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); 1096 1114 if (!sbi->s_vat_inode && 1097 1115 sbi->s_last_block != blocks - 1) { 1098 1116 printk(KERN_NOTICE "UDF-fs: Failed to read VAT inode from the" ··· 1118 1100 "block of the device (%lu).\n", 1119 1101 (unsigned long)sbi->s_last_block, 1120 1102 (unsigned long)blocks - 1); 1121 - ino.partitionReferenceNum = type1_index; 1122 - ino.logicalBlockNum = blocks - 1 - map->s_partition_root; 1123 - sbi->s_vat_inode = udf_iget(sb, &ino); 1103 + udf_find_vat_block(sb, p_index, type1_index, blocks - 1); 1124 1104 } 1125 1105 if (!sbi->s_vat_inode) 1126 1106 return 1;