Skip to content

Commit

Permalink
udf: Fix unalloc space handling in udf_update_inode
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jan Kara committed Mar 9, 2010
1 parent 57d5488 commit aae917c
Showing 1 changed file with 14 additions and 14 deletions.
28 changes: 14 additions & 14 deletions fs/udf/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1412,37 +1412,35 @@ static int udf_update_inode(struct inode *inode, int do_sync)
udf_get_lb_pblock(inode->i_sb,
&iinfo->i_location, 0));
if (!bh) {
udf_debug("bread failure\n");
return -EIO;
udf_debug("getblk failure\n");
return -ENOMEM;
}

memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);

lock_buffer(bh);
memset(bh->b_data, 0, inode->i_sb->s_blocksize);
fe = (struct fileEntry *)bh->b_data;
efe = (struct extendedFileEntry *)bh->b_data;

if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_USE)) {
if (iinfo->i_use) {
struct unallocSpaceEntry *use =
(struct unallocSpaceEntry *)bh->b_data;

use->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc);
memcpy(bh->b_data + sizeof(struct unallocSpaceEntry),
iinfo->i_ext.i_data, inode->i_sb->s_blocksize -
sizeof(struct unallocSpaceEntry));
use->descTag.tagIdent = cpu_to_le16(TAG_IDENT_USE);
use->descTag.tagLocation =
cpu_to_le32(iinfo->i_location.logicalBlockNum);
crclen = sizeof(struct unallocSpaceEntry) +
iinfo->i_lenAlloc - sizeof(struct tag);
use->descTag.tagLocation = cpu_to_le32(
iinfo->i_location.
logicalBlockNum);
use->descTag.descCRCLength = cpu_to_le16(crclen);
use->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)use +
sizeof(struct tag),
crclen));
use->descTag.tagChecksum = udf_tag_checksum(&use->descTag);

mark_buffer_dirty(bh);
brelse(bh);
return err;
goto out;
}

if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET))
Expand Down Expand Up @@ -1597,18 +1595,20 @@ static int udf_update_inode(struct inode *inode, int do_sync)
fe->descTag.tagSerialNum = cpu_to_le16(sbi->s_serial_number);
fe->descTag.tagLocation = cpu_to_le32(
iinfo->i_location.logicalBlockNum);
crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc -
sizeof(struct tag);
crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc - sizeof(struct tag);
fe->descTag.descCRCLength = cpu_to_le16(crclen);
fe->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)fe + sizeof(struct tag),
crclen));
fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag);

out:
unlock_buffer(bh);

/* write the data blocks */
mark_buffer_dirty(bh);
if (do_sync) {
sync_dirty_buffer(bh);
if (buffer_req(bh) && !buffer_uptodate(bh)) {
if (buffer_write_io_error(bh)) {
printk(KERN_WARNING "IO error syncing udf inode "
"[%s:%08lx]\n", inode->i_sb->s_id,
inode->i_ino);
Expand Down

0 comments on commit aae917c

Please sign in to comment.