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: Christoph Hellwig <hch@tuxera.com>
This commit is contained in:
parent
89755dcace
commit
7fcc99f4f2
2 changed files with 34 additions and 15 deletions
|
@ -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);
|
struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
WARN_ON(!mutex_is_locked(&hip->extents_lock));
|
||||||
|
|
||||||
hfsplus_ext_build_key(fd->search_key, inode->i_ino, hip->cached_start,
|
hfsplus_ext_build_key(fd->search_key, inode->i_ino, hip->cached_start,
|
||||||
HFSPLUS_IS_RSRC(inode) ?
|
HFSPLUS_IS_RSRC(inode) ?
|
||||||
HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA);
|
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) {
|
if (HFSPLUS_I(inode)->flags & HFSPLUS_FLG_EXT_DIRTY) {
|
||||||
struct hfs_find_data fd;
|
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,
|
static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd,
|
||||||
struct hfsplus_extent *extent,
|
struct hfsplus_extent *extent,
|
||||||
u32 cnid, u32 block, u8 type)
|
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);
|
struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
WARN_ON(!mutex_is_locked(&hip->extents_lock));
|
||||||
|
|
||||||
if (hip->flags & HFSPLUS_FLG_EXT_DIRTY)
|
if (hip->flags & HFSPLUS_FLG_EXT_DIRTY)
|
||||||
__hfsplus_ext_write_extent(inode, fd);
|
__hfsplus_ext_write_extent(inode, fd);
|
||||||
|
|
||||||
|
@ -433,7 +444,7 @@ out:
|
||||||
|
|
||||||
insert_extent:
|
insert_extent:
|
||||||
dprint(DBG_EXTENT, "insert new extent\n");
|
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));
|
memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
|
||||||
hip->cached_extents[0].start_block = cpu_to_be32(start);
|
hip->cached_extents[0].start_block = cpu_to_be32(start);
|
||||||
|
|
|
@ -158,28 +158,36 @@ struct hfsplus_sb_info {
|
||||||
|
|
||||||
|
|
||||||
struct hfsplus_inode_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;
|
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;
|
unsigned long flags;
|
||||||
|
struct mutex extents_lock;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Immutable data.
|
||||||
|
*/
|
||||||
|
struct inode *rsrc_inode;
|
||||||
__be32 create_date;
|
__be32 create_date;
|
||||||
/* Device number in hfsplus_permissions in catalog */
|
|
||||||
u32 dev;
|
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;
|
struct list_head open_dir_list;
|
||||||
loff_t phys_size;
|
loff_t phys_size;
|
||||||
|
|
||||||
struct inode vfs_inode;
|
struct inode vfs_inode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue