Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d7bdb996 authored by Sougata Santra's avatar Sougata Santra Committed by Linus Torvalds
Browse files

fs/hfsplus/extents.c: fix concurrent acess of alloc_blocks



Concurrent access to alloc_blocks in hfsplus_inode_info() is protected
by extents_lock mutex.  This patch fixes two instances where
alloc_blocks modification was not protected with this lock.

This fixes possible allocation bitmap corruption in race conditions
while extending and truncating files.

[akpm@linux-foundation.org: take extents_lock before taking a copy of ->alloc_blocks]
[akpm@linux-foundation.org: remove now-unused label `out']
Signed-off-by: default avatarSougata Santra <sougata@tuxera.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Cc: Vyacheslav Dubeyko <slava@dubeyko.com>
Cc: Alexey Khoroshilov <khoroshilov@ispras.ru>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent abfeb724
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -496,11 +496,13 @@ int hfsplus_file_extend(struct inode *inode)
			goto insert_extent;
	}
out:
	mutex_unlock(&hip->extents_lock);
	if (!res) {
		hip->alloc_blocks += len;
		mutex_unlock(&hip->extents_lock);
		hfsplus_mark_inode_dirty(inode, HFSPLUS_I_ALLOC_DIRTY);
		return 0;
	}
	mutex_unlock(&hip->extents_lock);
	return res;

insert_extent:
@@ -554,11 +556,13 @@ void hfsplus_file_truncate(struct inode *inode)

	blk_cnt = (inode->i_size + HFSPLUS_SB(sb)->alloc_blksz - 1) >>
			HFSPLUS_SB(sb)->alloc_blksz_shift;

	mutex_lock(&hip->extents_lock);

	alloc_cnt = hip->alloc_blocks;
	if (blk_cnt == alloc_cnt)
		goto out;
		goto out_unlock;

	mutex_lock(&hip->extents_lock);
	res = hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd);
	if (res) {
		mutex_unlock(&hip->extents_lock);
@@ -590,10 +594,10 @@ void hfsplus_file_truncate(struct inode *inode)
		hfs_brec_remove(&fd);
	}
	hfs_find_exit(&fd);
	mutex_unlock(&hip->extents_lock);

	hip->alloc_blocks = blk_cnt;
out:
out_unlock:
	mutex_unlock(&hip->extents_lock);
	hip->phys_size = inode->i_size;
	hip->fs_blocks = (inode->i_size + sb->s_blocksize - 1) >>
		sb->s_blocksize_bits;