aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/ext4.h
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2009-01-05 22:19:52 -0500
committerTheodore Ts'o <tytso@mit.edu>2009-01-05 22:19:52 -0500
commit5d1b1b3f492f8696ea18950a454a141381b0f926 (patch)
treee6277cd3e01c074403b9da7390de1daa6b9f248f /fs/ext4/ext4.h
parentb7be019e80da4db96d283734d55366014509911c (diff)
ext4: fix BUG when calling ext4_error with locked block group
The mballoc code likes to call ext4_error while it is holding locked block groups. This can causes a scheduling in atomic context BUG. We can't just unlock the block group and relock it after/if ext4_error returns since that might result in race conditions in the case where the filesystem is set to continue after finding errors. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/ext4.h')
-rw-r--r--fs/ext4/ext4.h47
1 files changed, 47 insertions, 0 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 8152b5603f0a..f0b1db6acf85 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1126,6 +1126,9 @@ extern void ext4_abort(struct super_block *, const char *, const char *, ...)
1126 __attribute__ ((format (printf, 3, 4))); 1126 __attribute__ ((format (printf, 3, 4)));
1127extern void ext4_warning(struct super_block *, const char *, const char *, ...) 1127extern void ext4_warning(struct super_block *, const char *, const char *, ...)
1128 __attribute__ ((format (printf, 3, 4))); 1128 __attribute__ ((format (printf, 3, 4)));
1129extern void ext4_grp_locked_error(struct super_block *, ext4_group_t,
1130 const char *, const char *, ...)
1131 __attribute__ ((format (printf, 4, 5)));
1129extern void ext4_update_dynamic_rev(struct super_block *sb); 1132extern void ext4_update_dynamic_rev(struct super_block *sb);
1130extern int ext4_update_compat_feature(handle_t *handle, struct super_block *sb, 1133extern int ext4_update_compat_feature(handle_t *handle, struct super_block *sb,
1131 __u32 compat); 1134 __u32 compat);
@@ -1249,6 +1252,50 @@ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize)
1249 return ; 1252 return ;
1250} 1253}
1251 1254
1255struct ext4_group_info {
1256 unsigned long bb_state;
1257 struct rb_root bb_free_root;
1258 unsigned short bb_first_free;
1259 unsigned short bb_free;
1260 unsigned short bb_fragments;
1261 struct list_head bb_prealloc_list;
1262#ifdef DOUBLE_CHECK
1263 void *bb_bitmap;
1264#endif
1265 struct rw_semaphore alloc_sem;
1266 unsigned short bb_counters[];
1267};
1268
1269#define EXT4_GROUP_INFO_NEED_INIT_BIT 0
1270#define EXT4_GROUP_INFO_LOCKED_BIT 1
1271
1272#define EXT4_MB_GRP_NEED_INIT(grp) \
1273 (test_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &((grp)->bb_state)))
1274
1275static inline void ext4_lock_group(struct super_block *sb, ext4_group_t group)
1276{
1277 struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
1278
1279 bit_spin_lock(EXT4_GROUP_INFO_LOCKED_BIT, &(grinfo->bb_state));
1280}
1281
1282static inline void ext4_unlock_group(struct super_block *sb,
1283 ext4_group_t group)
1284{
1285 struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
1286
1287 bit_spin_unlock(EXT4_GROUP_INFO_LOCKED_BIT, &(grinfo->bb_state));
1288}
1289
1290static inline int ext4_is_group_locked(struct super_block *sb,
1291 ext4_group_t group)
1292{
1293 struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
1294
1295 return bit_spin_is_locked(EXT4_GROUP_INFO_LOCKED_BIT,
1296 &(grinfo->bb_state));
1297}
1298
1252/* 1299/*
1253 * Inodes and files operations 1300 * Inodes and files operations
1254 */ 1301 */