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

Commit 7fcc99f4 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Christoph Hellwig
Browse files

hfsplus: add missing extent locking in hfsplus_write_inode



Most of the extent handling code already does proper SMP locking, but
hfsplus_write_inode was calling into hfsplus_ext_write_extent without
taking the extents_lock.  Fix this by splitting hfsplus_ext_write_extent
into an internal helper that expects the lock, and a public interface
that first acquires it.

Also add a few locking asserts and document the locking rules in
hfsplus_fs.h.

Signed-off-by: default avatarChristoph Hellwig <hch@tuxera.com>
parent 89755dca
Loading
Loading
Loading
Loading
+13 −2
Original line number Diff line number Diff line
@@ -88,6 +88,8 @@ static void __hfsplus_ext_write_extent(struct inode *inode, struct hfs_find_data
	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
	int res;

	WARN_ON(!mutex_is_locked(&hip->extents_lock));

	hfsplus_ext_build_key(fd->search_key, inode->i_ino, hip->cached_start,
			      HFSPLUS_IS_RSRC(inode) ?
				HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA);
@@ -108,7 +110,7 @@ static void __hfsplus_ext_write_extent(struct inode *inode, struct hfs_find_data
	}
}

void hfsplus_ext_write_extent(struct inode *inode)
static void hfsplus_ext_write_extent_locked(struct inode *inode)
{
	if (HFSPLUS_I(inode)->flags & HFSPLUS_FLG_EXT_DIRTY) {
		struct hfs_find_data fd;
@@ -119,6 +121,13 @@ void hfsplus_ext_write_extent(struct inode *inode)
	}
}

void hfsplus_ext_write_extent(struct inode *inode)
{
	mutex_lock(&HFSPLUS_I(inode)->extents_lock);
	hfsplus_ext_write_extent_locked(inode);
	mutex_unlock(&HFSPLUS_I(inode)->extents_lock);
}

static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd,
					    struct hfsplus_extent *extent,
					    u32 cnid, u32 block, u8 type)
@@ -144,6 +153,8 @@ static inline int __hfsplus_ext_cache_extent(struct hfs_find_data *fd, struct in
	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
	int res;

	WARN_ON(!mutex_is_locked(&hip->extents_lock));

	if (hip->flags & HFSPLUS_FLG_EXT_DIRTY)
		__hfsplus_ext_write_extent(inode, fd);

@@ -433,7 +444,7 @@ out:

insert_extent:
	dprint(DBG_EXTENT, "insert new extent\n");
	hfsplus_ext_write_extent(inode);
	hfsplus_ext_write_extent_locked(inode);

	memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
	hip->cached_extents[0].start_block = cpu_to_be32(start);
+21 −13
Original line number Diff line number Diff line
@@ -158,28 +158,36 @@ struct hfsplus_sb_info {


struct hfsplus_inode_info {
	struct mutex extents_lock;
	u32 clump_blocks, alloc_blocks;
	sector_t fs_blocks;
	/* Allocation extents from catalog record or volume header */
	hfsplus_extent_rec first_extents;
	u32 first_blocks;
	hfsplus_extent_rec cached_extents;
	u32 cached_start, cached_blocks;
	atomic_t opencnt;

	struct inode *rsrc_inode;
	/*
	 * Extent allocation information, protected by extents_lock.
	 */
	u32 first_blocks;
	u32 clump_blocks;
	u32 alloc_blocks;
	u32 cached_start;
	u32 cached_blocks;
	hfsplus_extent_rec first_extents;
	hfsplus_extent_rec cached_extents;
	unsigned long flags;
	struct mutex extents_lock;

	/*
	 * Immutable data.
	 */
	struct inode *rsrc_inode;
	__be32 create_date;
	/* Device number in hfsplus_permissions in catalog */
	u32 dev;
	/* BSD system and user file flags */
	u8 rootflags;
	u8 userflags;

	/*
	 * Protected by i_mutex.
	 */
	sector_t fs_blocks;
	u8 rootflags, userflags;	/* BSD system and user file flags */
	struct list_head open_dir_list;
	loff_t phys_size;

	struct inode vfs_inode;
};