aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf/inode.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2010-01-08 10:46:29 -0500
committerJan Kara <jack@suse.cz>2010-03-09 11:15:17 -0500
commitaae917cd188f397e9223001d9f6c0adfb339fd64 (patch)
tree7185f5f0b984145c1511ae657487e68504f185a7 /fs/udf/inode.c
parent57d54889cd00db2752994b389ba714138652e60c (diff)
udf: Fix unalloc space handling in udf_update_inode
Writing of inode holding unallocated space info was broken because we first cleared the buffer and after that checked whether it contains a tag meaning the block holds unallocated space information. Fix the problem by checking appropriate in memory flag instead. Also cleanup the function a bit along the way - most importantly lock buffer when modifying its contents, check for buffer_write_io_error instead of !buffer_uptodate, etc.. Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/udf/inode.c')
-rw-r--r--fs/udf/inode.c28
1 files changed, 14 insertions, 14 deletions
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index b57ab0402d89..a792a884b49c 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1412,16 +1412,16 @@ static int udf_update_inode(struct inode *inode, int do_sync)
1412 udf_get_lb_pblock(inode->i_sb, 1412 udf_get_lb_pblock(inode->i_sb,
1413 &iinfo->i_location, 0)); 1413 &iinfo->i_location, 0));
1414 if (!bh) { 1414 if (!bh) {
1415 udf_debug("bread failure\n"); 1415 udf_debug("getblk failure\n");
1416 return -EIO; 1416 return -ENOMEM;
1417 } 1417 }
1418 1418
1419 memset(bh->b_data, 0x00, inode->i_sb->s_blocksize); 1419 lock_buffer(bh);
1420 1420 memset(bh->b_data, 0, inode->i_sb->s_blocksize);
1421 fe = (struct fileEntry *)bh->b_data; 1421 fe = (struct fileEntry *)bh->b_data;
1422 efe = (struct extendedFileEntry *)bh->b_data; 1422 efe = (struct extendedFileEntry *)bh->b_data;
1423 1423
1424 if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_USE)) { 1424 if (iinfo->i_use) {
1425 struct unallocSpaceEntry *use = 1425 struct unallocSpaceEntry *use =
1426 (struct unallocSpaceEntry *)bh->b_data; 1426 (struct unallocSpaceEntry *)bh->b_data;
1427 1427
@@ -1429,20 +1429,18 @@ static int udf_update_inode(struct inode *inode, int do_sync)
1429 memcpy(bh->b_data + sizeof(struct unallocSpaceEntry), 1429 memcpy(bh->b_data + sizeof(struct unallocSpaceEntry),
1430 iinfo->i_ext.i_data, inode->i_sb->s_blocksize - 1430 iinfo->i_ext.i_data, inode->i_sb->s_blocksize -
1431 sizeof(struct unallocSpaceEntry)); 1431 sizeof(struct unallocSpaceEntry));
1432 use->descTag.tagIdent = cpu_to_le16(TAG_IDENT_USE);
1433 use->descTag.tagLocation =
1434 cpu_to_le32(iinfo->i_location.logicalBlockNum);
1432 crclen = sizeof(struct unallocSpaceEntry) + 1435 crclen = sizeof(struct unallocSpaceEntry) +
1433 iinfo->i_lenAlloc - sizeof(struct tag); 1436 iinfo->i_lenAlloc - sizeof(struct tag);
1434 use->descTag.tagLocation = cpu_to_le32(
1435 iinfo->i_location.
1436 logicalBlockNum);
1437 use->descTag.descCRCLength = cpu_to_le16(crclen); 1437 use->descTag.descCRCLength = cpu_to_le16(crclen);
1438 use->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)use + 1438 use->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)use +
1439 sizeof(struct tag), 1439 sizeof(struct tag),
1440 crclen)); 1440 crclen));
1441 use->descTag.tagChecksum = udf_tag_checksum(&use->descTag); 1441 use->descTag.tagChecksum = udf_tag_checksum(&use->descTag);
1442 1442
1443 mark_buffer_dirty(bh); 1443 goto out;
1444 brelse(bh);
1445 return err;
1446 } 1444 }
1447 1445
1448 if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET)) 1446 if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET))
@@ -1597,18 +1595,20 @@ static int udf_update_inode(struct inode *inode, int do_sync)
1597 fe->descTag.tagSerialNum = cpu_to_le16(sbi->s_serial_number); 1595 fe->descTag.tagSerialNum = cpu_to_le16(sbi->s_serial_number);
1598 fe->descTag.tagLocation = cpu_to_le32( 1596 fe->descTag.tagLocation = cpu_to_le32(
1599 iinfo->i_location.logicalBlockNum); 1597 iinfo->i_location.logicalBlockNum);
1600 crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc - 1598 crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc - sizeof(struct tag);
1601 sizeof(struct tag);
1602 fe->descTag.descCRCLength = cpu_to_le16(crclen); 1599 fe->descTag.descCRCLength = cpu_to_le16(crclen);
1603 fe->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)fe + sizeof(struct tag), 1600 fe->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)fe + sizeof(struct tag),
1604 crclen)); 1601 crclen));
1605 fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag); 1602 fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag);
1606 1603
1604out:
1605 unlock_buffer(bh);
1606
1607 /* write the data blocks */ 1607 /* write the data blocks */
1608 mark_buffer_dirty(bh); 1608 mark_buffer_dirty(bh);
1609 if (do_sync) { 1609 if (do_sync) {
1610 sync_dirty_buffer(bh); 1610 sync_dirty_buffer(bh);
1611 if (buffer_req(bh) && !buffer_uptodate(bh)) { 1611 if (buffer_write_io_error(bh)) {
1612 printk(KERN_WARNING "IO error syncing udf inode " 1612 printk(KERN_WARNING "IO error syncing udf inode "
1613 "[%s:%08lx]\n", inode->i_sb->s_id, 1613 "[%s:%08lx]\n", inode->i_sb->s_id,
1614 inode->i_ino); 1614 inode->i_ino);