aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/ialloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/ialloc.c')
-rw-r--r--fs/ext4/ialloc.c105
1 files changed, 47 insertions, 58 deletions
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 57f6eef6ccd6..45853e0d1f21 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -222,7 +222,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
222 is_directory = S_ISDIR(inode->i_mode); 222 is_directory = S_ISDIR(inode->i_mode);
223 223
224 /* Do this BEFORE marking the inode not in use or returning an error */ 224 /* Do this BEFORE marking the inode not in use or returning an error */
225 clear_inode(inode); 225 ext4_clear_inode(inode);
226 226
227 es = EXT4_SB(sb)->s_es; 227 es = EXT4_SB(sb)->s_es;
228 if (ino < EXT4_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) { 228 if (ino < EXT4_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
@@ -240,56 +240,49 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
240 if (fatal) 240 if (fatal)
241 goto error_return; 241 goto error_return;
242 242
243 /* Ok, now we can actually update the inode bitmaps.. */ 243 fatal = -ESRCH;
244 cleared = ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group), 244 gdp = ext4_get_group_desc(sb, block_group, &bh2);
245 bit, bitmap_bh->b_data); 245 if (gdp) {
246 if (!cleared)
247 ext4_error(sb, "bit already cleared for inode %lu", ino);
248 else {
249 gdp = ext4_get_group_desc(sb, block_group, &bh2);
250
251 BUFFER_TRACE(bh2, "get_write_access"); 246 BUFFER_TRACE(bh2, "get_write_access");
252 fatal = ext4_journal_get_write_access(handle, bh2); 247 fatal = ext4_journal_get_write_access(handle, bh2);
253 if (fatal) goto error_return; 248 }
254 249 ext4_lock_group(sb, block_group);
255 if (gdp) { 250 cleared = ext4_clear_bit(bit, bitmap_bh->b_data);
256 ext4_lock_group(sb, block_group); 251 if (fatal || !cleared) {
257 count = ext4_free_inodes_count(sb, gdp) + 1; 252 ext4_unlock_group(sb, block_group);
258 ext4_free_inodes_set(sb, gdp, count); 253 goto out;
259 if (is_directory) { 254 }
260 count = ext4_used_dirs_count(sb, gdp) - 1;
261 ext4_used_dirs_set(sb, gdp, count);
262 if (sbi->s_log_groups_per_flex) {
263 ext4_group_t f;
264
265 f = ext4_flex_group(sbi, block_group);
266 atomic_dec(&sbi->s_flex_groups[f].used_dirs);
267 }
268 255
269 } 256 count = ext4_free_inodes_count(sb, gdp) + 1;
270 gdp->bg_checksum = ext4_group_desc_csum(sbi, 257 ext4_free_inodes_set(sb, gdp, count);
271 block_group, gdp); 258 if (is_directory) {
272 ext4_unlock_group(sb, block_group); 259 count = ext4_used_dirs_count(sb, gdp) - 1;
273 percpu_counter_inc(&sbi->s_freeinodes_counter); 260 ext4_used_dirs_set(sb, gdp, count);
274 if (is_directory) 261 percpu_counter_dec(&sbi->s_dirs_counter);
275 percpu_counter_dec(&sbi->s_dirs_counter); 262 }
276 263 gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp);
277 if (sbi->s_log_groups_per_flex) { 264 ext4_unlock_group(sb, block_group);
278 ext4_group_t f; 265
279 266 percpu_counter_inc(&sbi->s_freeinodes_counter);
280 f = ext4_flex_group(sbi, block_group); 267 if (sbi->s_log_groups_per_flex) {
281 atomic_inc(&sbi->s_flex_groups[f].free_inodes); 268 ext4_group_t f = ext4_flex_group(sbi, block_group);
282 } 269
283 } 270 atomic_inc(&sbi->s_flex_groups[f].free_inodes);
284 BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata"); 271 if (is_directory)
285 err = ext4_handle_dirty_metadata(handle, NULL, bh2); 272 atomic_dec(&sbi->s_flex_groups[f].used_dirs);
286 if (!fatal) fatal = err;
287 } 273 }
288 BUFFER_TRACE(bitmap_bh, "call ext4_handle_dirty_metadata"); 274 BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata");
289 err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); 275 fatal = ext4_handle_dirty_metadata(handle, NULL, bh2);
290 if (!fatal) 276out:
291 fatal = err; 277 if (cleared) {
292 sb->s_dirt = 1; 278 BUFFER_TRACE(bitmap_bh, "call ext4_handle_dirty_metadata");
279 err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
280 if (!fatal)
281 fatal = err;
282 ext4_mark_super_dirty(sb);
283 } else
284 ext4_error(sb, "bit already cleared for inode %lu", ino);
285
293error_return: 286error_return:
294 brelse(bitmap_bh); 287 brelse(bitmap_bh);
295 ext4_std_error(sb, fatal); 288 ext4_std_error(sb, fatal);
@@ -499,7 +492,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
499 492
500 if (S_ISDIR(mode) && 493 if (S_ISDIR(mode) &&
501 ((parent == sb->s_root->d_inode) || 494 ((parent == sb->s_root->d_inode) ||
502 (EXT4_I(parent)->i_flags & EXT4_TOPDIR_FL))) { 495 (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) {
503 int best_ndir = inodes_per_group; 496 int best_ndir = inodes_per_group;
504 int ret = -1; 497 int ret = -1;
505 498
@@ -972,23 +965,19 @@ got:
972 percpu_counter_dec(&sbi->s_freeinodes_counter); 965 percpu_counter_dec(&sbi->s_freeinodes_counter);
973 if (S_ISDIR(mode)) 966 if (S_ISDIR(mode))
974 percpu_counter_inc(&sbi->s_dirs_counter); 967 percpu_counter_inc(&sbi->s_dirs_counter);
975 sb->s_dirt = 1; 968 ext4_mark_super_dirty(sb);
976 969
977 if (sbi->s_log_groups_per_flex) { 970 if (sbi->s_log_groups_per_flex) {
978 flex_group = ext4_flex_group(sbi, group); 971 flex_group = ext4_flex_group(sbi, group);
979 atomic_dec(&sbi->s_flex_groups[flex_group].free_inodes); 972 atomic_dec(&sbi->s_flex_groups[flex_group].free_inodes);
980 } 973 }
981 974
982 inode->i_uid = current_fsuid(); 975 if (test_opt(sb, GRPID)) {
983 if (test_opt(sb, GRPID)) 976 inode->i_mode = mode;
984 inode->i_gid = dir->i_gid; 977 inode->i_uid = current_fsuid();
985 else if (dir->i_mode & S_ISGID) {
986 inode->i_gid = dir->i_gid; 978 inode->i_gid = dir->i_gid;
987 if (S_ISDIR(mode))
988 mode |= S_ISGID;
989 } else 979 } else
990 inode->i_gid = current_fsgid(); 980 inode_init_owner(inode, dir, mode);
991 inode->i_mode = mode;
992 981
993 inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb); 982 inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb);
994 /* This is the optimal IO size (for stat), not the fs block size */ 983 /* This is the optimal IO size (for stat), not the fs block size */
@@ -1045,7 +1034,7 @@ got:
1045 if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) { 1034 if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
1046 /* set extent flag only for directory, file and normal symlink*/ 1035 /* set extent flag only for directory, file and normal symlink*/
1047 if (S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) { 1036 if (S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) {
1048 EXT4_I(inode)->i_flags |= EXT4_EXTENTS_FL; 1037 ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS);
1049 ext4_ext_tree_init(handle, inode); 1038 ext4_ext_tree_init(handle, inode);
1050 } 1039 }
1051 } 1040 }