aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfsplus
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@tuxera.com>2010-09-30 23:46:31 -0400
committerChristoph Hellwig <hch@lst.de>2010-09-30 23:46:31 -0400
commit7fcc99f4f2ddb1c39abc05fbb9b32f05b03c7f8f (patch)
treeb07045981f17d855f89f1ef59579e330d8ffce20 /fs/hfsplus
parent89755dcace09b44b3aa024bf302d9b19b4c24cad (diff)
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>
Diffstat (limited to 'fs/hfsplus')
-rw-r--r--fs/hfsplus/extents.c15
-rw-r--r--fs/hfsplus/hfsplus_fs.h34
2 files changed, 34 insertions, 15 deletions
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index b1017eaa4fdc..0c9cb1820a52 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -88,6 +88,8 @@ static void __hfsplus_ext_write_extent(struct inode *inode, struct hfs_find_data
88 struct hfsplus_inode_info *hip = HFSPLUS_I(inode); 88 struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
89 int res; 89 int res;
90 90
91 WARN_ON(!mutex_is_locked(&hip->extents_lock));
92
91 hfsplus_ext_build_key(fd->search_key, inode->i_ino, hip->cached_start, 93 hfsplus_ext_build_key(fd->search_key, inode->i_ino, hip->cached_start,
92 HFSPLUS_IS_RSRC(inode) ? 94 HFSPLUS_IS_RSRC(inode) ?
93 HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA); 95 HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA);
@@ -108,7 +110,7 @@ static void __hfsplus_ext_write_extent(struct inode *inode, struct hfs_find_data
108 } 110 }
109} 111}
110 112
111void hfsplus_ext_write_extent(struct inode *inode) 113static void hfsplus_ext_write_extent_locked(struct inode *inode)
112{ 114{
113 if (HFSPLUS_I(inode)->flags & HFSPLUS_FLG_EXT_DIRTY) { 115 if (HFSPLUS_I(inode)->flags & HFSPLUS_FLG_EXT_DIRTY) {
114 struct hfs_find_data fd; 116 struct hfs_find_data fd;
@@ -119,6 +121,13 @@ void hfsplus_ext_write_extent(struct inode *inode)
119 } 121 }
120} 122}
121 123
124void hfsplus_ext_write_extent(struct inode *inode)
125{
126 mutex_lock(&HFSPLUS_I(inode)->extents_lock);
127 hfsplus_ext_write_extent_locked(inode);
128 mutex_unlock(&HFSPLUS_I(inode)->extents_lock);
129}
130
122static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd, 131static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd,
123 struct hfsplus_extent *extent, 132 struct hfsplus_extent *extent,
124 u32 cnid, u32 block, u8 type) 133 u32 cnid, u32 block, u8 type)
@@ -144,6 +153,8 @@ static inline int __hfsplus_ext_cache_extent(struct hfs_find_data *fd, struct in
144 struct hfsplus_inode_info *hip = HFSPLUS_I(inode); 153 struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
145 int res; 154 int res;
146 155
156 WARN_ON(!mutex_is_locked(&hip->extents_lock));
157
147 if (hip->flags & HFSPLUS_FLG_EXT_DIRTY) 158 if (hip->flags & HFSPLUS_FLG_EXT_DIRTY)
148 __hfsplus_ext_write_extent(inode, fd); 159 __hfsplus_ext_write_extent(inode, fd);
149 160
@@ -433,7 +444,7 @@ out:
433 444
434insert_extent: 445insert_extent:
435 dprint(DBG_EXTENT, "insert new extent\n"); 446 dprint(DBG_EXTENT, "insert new extent\n");
436 hfsplus_ext_write_extent(inode); 447 hfsplus_ext_write_extent_locked(inode);
437 448
438 memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec)); 449 memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
439 hip->cached_extents[0].start_block = cpu_to_be32(start); 450 hip->cached_extents[0].start_block = cpu_to_be32(start);
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index c521d44f0747..c007cc201279 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -158,28 +158,36 @@ struct hfsplus_sb_info {
158 158
159 159
160struct hfsplus_inode_info { 160struct hfsplus_inode_info {
161 struct mutex extents_lock;
162 u32 clump_blocks, alloc_blocks;
163 sector_t fs_blocks;
164 /* Allocation extents from catalog record or volume header */
165 hfsplus_extent_rec first_extents;
166 u32 first_blocks;
167 hfsplus_extent_rec cached_extents;
168 u32 cached_start, cached_blocks;
169 atomic_t opencnt; 161 atomic_t opencnt;
170 162
171 struct inode *rsrc_inode; 163 /*
164 * Extent allocation information, protected by extents_lock.
165 */
166 u32 first_blocks;
167 u32 clump_blocks;
168 u32 alloc_blocks;
169 u32 cached_start;
170 u32 cached_blocks;
171 hfsplus_extent_rec first_extents;
172 hfsplus_extent_rec cached_extents;
172 unsigned long flags; 173 unsigned long flags;
174 struct mutex extents_lock;
173 175
176 /*
177 * Immutable data.
178 */
179 struct inode *rsrc_inode;
174 __be32 create_date; 180 __be32 create_date;
175 /* Device number in hfsplus_permissions in catalog */
176 u32 dev; 181 u32 dev;
177 /* BSD system and user file flags */
178 u8 rootflags;
179 u8 userflags;
180 182
183 /*
184 * Protected by i_mutex.
185 */
186 sector_t fs_blocks;
187 u8 rootflags, userflags; /* BSD system and user file flags */
181 struct list_head open_dir_list; 188 struct list_head open_dir_list;
182 loff_t phys_size; 189 loff_t phys_size;
190
183 struct inode vfs_inode; 191 struct inode vfs_inode;
184}; 192};
185 193