]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
hfsplus: add missing extent locking in hfsplus_write_inode
authorChristoph Hellwig <hch@tuxera.com>
Fri, 1 Oct 2010 03:46:31 +0000 (05:46 +0200)
committerChristoph Hellwig <hch@lst.de>
Fri, 1 Oct 2010 03:46:31 +0000 (05:46 +0200)
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>
fs/hfsplus/extents.c
fs/hfsplus/hfsplus_fs.h

index b1017eaa4fdc8dfbdcb3e442bf40c2e5cb96b241..0c9cb1820a523fae02c6bf2f37e6fbdc5c5dceeb 100644 (file)
@@ -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);
index c521d44f0747bb1a67cc4bb93bdfd662550b088a..c007cc201279a4df4505ad94c118f9124c6d3824 100644 (file)
@@ -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;
 };