Skip to content

Commit a97b520

Browse files
committed
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: fix data corruption regression by reverting commit 6de9843 ext4: Allow indirect-block file to grow the file size to max file size ext4: allow an active handle to be started when freezing ext4: sync the directory inode in ext4_sync_parent() ext4: init timer earlier to avoid a kernel panic in __save_error_info jbd2: fix potential memory leak on transaction commit ext4: fix a double free in ext4_register_li_request ext4: fix credits computing for indirect mapped files ext4: remove unnecessary [cm]time update of quota file jbd2: move bdget out of critical section
2 parents 18770c7 + c820563 commit a97b520

File tree

6 files changed

+102
-35
lines changed

6 files changed

+102
-35
lines changed

fs/ext4/ext4_jbd2.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@
8686

8787
#ifdef CONFIG_QUOTA
8888
/* Amount of blocks needed for quota update - we know that the structure was
89-
* allocated so we need to update only inode+data */
90-
#define EXT4_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 2 : 0)
89+
* allocated so we need to update only data block */
90+
#define EXT4_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 1 : 0)
9191
/* Amount of blocks needed for quota insert/delete - we do some block writes
9292
* but inode, sb and group updates are done only once */
9393
#define EXT4_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\

fs/ext4/fsync.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,11 @@ extern int ext4_flush_completed_IO(struct inode *inode)
125125
* the parent directory's parent as well, and so on recursively, if
126126
* they are also freshly created.
127127
*/
128-
static void ext4_sync_parent(struct inode *inode)
128+
static int ext4_sync_parent(struct inode *inode)
129129
{
130+
struct writeback_control wbc;
130131
struct dentry *dentry = NULL;
132+
int ret = 0;
131133

132134
while (inode && ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) {
133135
ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY);
@@ -136,8 +138,17 @@ static void ext4_sync_parent(struct inode *inode)
136138
if (!dentry || !dentry->d_parent || !dentry->d_parent->d_inode)
137139
break;
138140
inode = dentry->d_parent->d_inode;
139-
sync_mapping_buffers(inode->i_mapping);
141+
ret = sync_mapping_buffers(inode->i_mapping);
142+
if (ret)
143+
break;
144+
memset(&wbc, 0, sizeof(wbc));
145+
wbc.sync_mode = WB_SYNC_ALL;
146+
wbc.nr_to_write = 0; /* only write out the inode */
147+
ret = sync_inode(inode, &wbc);
148+
if (ret)
149+
break;
140150
}
151+
return ret;
141152
}
142153

143154
/*
@@ -176,7 +187,7 @@ int ext4_sync_file(struct file *file, int datasync)
176187
if (!journal) {
177188
ret = generic_file_fsync(file, datasync);
178189
if (!ret && !list_empty(&inode->i_dentry))
179-
ext4_sync_parent(inode);
190+
ret = ext4_sync_parent(inode);
180191
goto out;
181192
}
182193

fs/ext4/inode.c

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2502,6 +2502,7 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
25022502
* for partial write.
25032503
*/
25042504
set_buffer_new(bh);
2505+
set_buffer_mapped(bh);
25052506
}
25062507
return 0;
25072508
}
@@ -4429,8 +4430,8 @@ void ext4_truncate(struct inode *inode)
44294430
Indirect chain[4];
44304431
Indirect *partial;
44314432
__le32 nr = 0;
4432-
int n;
4433-
ext4_lblk_t last_block;
4433+
int n = 0;
4434+
ext4_lblk_t last_block, max_block;
44344435
unsigned blocksize = inode->i_sb->s_blocksize;
44354436

44364437
trace_ext4_truncate_enter(inode);
@@ -4455,14 +4456,18 @@ void ext4_truncate(struct inode *inode)
44554456

44564457
last_block = (inode->i_size + blocksize-1)
44574458
>> EXT4_BLOCK_SIZE_BITS(inode->i_sb);
4459+
max_block = (EXT4_SB(inode->i_sb)->s_bitmap_maxbytes + blocksize-1)
4460+
>> EXT4_BLOCK_SIZE_BITS(inode->i_sb);
44584461

44594462
if (inode->i_size & (blocksize - 1))
44604463
if (ext4_block_truncate_page(handle, mapping, inode->i_size))
44614464
goto out_stop;
44624465

4463-
n = ext4_block_to_path(inode, last_block, offsets, NULL);
4464-
if (n == 0)
4465-
goto out_stop; /* error */
4466+
if (last_block != max_block) {
4467+
n = ext4_block_to_path(inode, last_block, offsets, NULL);
4468+
if (n == 0)
4469+
goto out_stop; /* error */
4470+
}
44664471

44674472
/*
44684473
* OK. This truncate is going to happen. We add the inode to the
@@ -4493,7 +4498,13 @@ void ext4_truncate(struct inode *inode)
44934498
*/
44944499
ei->i_disksize = inode->i_size;
44954500

4496-
if (n == 1) { /* direct blocks */
4501+
if (last_block == max_block) {
4502+
/*
4503+
* It is unnecessary to free any data blocks if last_block is
4504+
* equal to the indirect block limit.
4505+
*/
4506+
goto out_unlock;
4507+
} else if (n == 1) { /* direct blocks */
44974508
ext4_free_data(handle, inode, NULL, i_data+offsets[0],
44984509
i_data + EXT4_NDIR_BLOCKS);
44994510
goto do_indirects;
@@ -4553,6 +4564,7 @@ void ext4_truncate(struct inode *inode)
45534564
;
45544565
}
45554566

4567+
out_unlock:
45564568
up_write(&ei->i_data_sem);
45574569
inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
45584570
ext4_mark_inode_dirty(handle, inode);
@@ -5398,13 +5410,12 @@ static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks,
53985410
/* if nrblocks are contiguous */
53995411
if (chunk) {
54005412
/*
5401-
* With N contiguous data blocks, it need at most
5402-
* N/EXT4_ADDR_PER_BLOCK(inode->i_sb) indirect blocks
5403-
* 2 dindirect blocks
5404-
* 1 tindirect block
5413+
* With N contiguous data blocks, we need at most
5414+
* N/EXT4_ADDR_PER_BLOCK(inode->i_sb) + 1 indirect blocks,
5415+
* 2 dindirect blocks, and 1 tindirect block
54055416
*/
5406-
indirects = nrblocks / EXT4_ADDR_PER_BLOCK(inode->i_sb);
5407-
return indirects + 3;
5417+
return DIV_ROUND_UP(nrblocks,
5418+
EXT4_ADDR_PER_BLOCK(inode->i_sb)) + 4;
54085419
}
54095420
/*
54105421
* if nrblocks are not contiguous, worse case, each block touch

fs/ext4/super.c

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -242,27 +242,44 @@ static void ext4_put_nojournal(handle_t *handle)
242242
* journal_end calls result in the superblock being marked dirty, so
243243
* that sync() will call the filesystem's write_super callback if
244244
* appropriate.
245+
*
246+
* To avoid j_barrier hold in userspace when a user calls freeze(),
247+
* ext4 prevents a new handle from being started by s_frozen, which
248+
* is in an upper layer.
245249
*/
246250
handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
247251
{
248252
journal_t *journal;
253+
handle_t *handle;
249254

250255
if (sb->s_flags & MS_RDONLY)
251256
return ERR_PTR(-EROFS);
252257

253-
vfs_check_frozen(sb, SB_FREEZE_TRANS);
254-
/* Special case here: if the journal has aborted behind our
255-
* backs (eg. EIO in the commit thread), then we still need to
256-
* take the FS itself readonly cleanly. */
257258
journal = EXT4_SB(sb)->s_journal;
258-
if (journal) {
259-
if (is_journal_aborted(journal)) {
260-
ext4_abort(sb, "Detected aborted journal");
261-
return ERR_PTR(-EROFS);
262-
}
263-
return jbd2_journal_start(journal, nblocks);
259+
handle = ext4_journal_current_handle();
260+
261+
/*
262+
* If a handle has been started, it should be allowed to
263+
* finish, otherwise deadlock could happen between freeze
264+
* and others(e.g. truncate) due to the restart of the
265+
* journal handle if the filesystem is forzen and active
266+
* handles are not stopped.
267+
*/
268+
if (!handle)
269+
vfs_check_frozen(sb, SB_FREEZE_TRANS);
270+
271+
if (!journal)
272+
return ext4_get_nojournal();
273+
/*
274+
* Special case here: if the journal has aborted behind our
275+
* backs (eg. EIO in the commit thread), then we still need to
276+
* take the FS itself readonly cleanly.
277+
*/
278+
if (is_journal_aborted(journal)) {
279+
ext4_abort(sb, "Detected aborted journal");
280+
return ERR_PTR(-EROFS);
264281
}
265-
return ext4_get_nojournal();
282+
return jbd2_journal_start(journal, nblocks);
266283
}
267284

268285
/*
@@ -2975,6 +2992,12 @@ static int ext4_register_li_request(struct super_block *sb,
29752992
mutex_unlock(&ext4_li_info->li_list_mtx);
29762993

29772994
sbi->s_li_request = elr;
2995+
/*
2996+
* set elr to NULL here since it has been inserted to
2997+
* the request_list and the removal and free of it is
2998+
* handled by ext4_clear_request_list from now on.
2999+
*/
3000+
elr = NULL;
29783001

29793002
if (!(ext4_li_info->li_state & EXT4_LAZYINIT_RUNNING)) {
29803003
ret = ext4_run_lazyinit_thread();
@@ -3385,6 +3408,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
33853408
get_random_bytes(&sbi->s_next_generation, sizeof(u32));
33863409
spin_lock_init(&sbi->s_next_gen_lock);
33873410

3411+
init_timer(&sbi->s_err_report);
3412+
sbi->s_err_report.function = print_daily_error_info;
3413+
sbi->s_err_report.data = (unsigned long) sb;
3414+
33883415
err = percpu_counter_init(&sbi->s_freeblocks_counter,
33893416
ext4_count_free_blocks(sb));
33903417
if (!err) {
@@ -3646,9 +3673,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
36463673
"Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
36473674
*sbi->s_es->s_mount_opts ? "; " : "", orig_data);
36483675

3649-
init_timer(&sbi->s_err_report);
3650-
sbi->s_err_report.function = print_daily_error_info;
3651-
sbi->s_err_report.data = (unsigned long) sb;
36523676
if (es->s_error_count)
36533677
mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */
36543678

@@ -3672,6 +3696,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
36723696
sbi->s_journal = NULL;
36733697
}
36743698
failed_mount3:
3699+
del_timer(&sbi->s_err_report);
36753700
if (sbi->s_flex_groups) {
36763701
if (is_vmalloc_addr(sbi->s_flex_groups))
36773702
vfree(sbi->s_flex_groups);
@@ -4138,6 +4163,11 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
41384163
/*
41394164
* LVM calls this function before a (read-only) snapshot is created. This
41404165
* gives us a chance to flush the journal completely and mark the fs clean.
4166+
*
4167+
* Note that only this function cannot bring a filesystem to be in a clean
4168+
* state independently, because ext4 prevents a new handle from being started
4169+
* by @sb->s_frozen, which stays in an upper layer. It thus needs help from
4170+
* the upper layer.
41414171
*/
41424172
static int ext4_freeze(struct super_block *sb)
41434173
{
@@ -4614,11 +4644,24 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
46144644

46154645
static int ext4_quota_off(struct super_block *sb, int type)
46164646
{
4647+
struct inode *inode = sb_dqopt(sb)->files[type];
4648+
handle_t *handle;
4649+
46174650
/* Force all delayed allocation blocks to be allocated.
46184651
* Caller already holds s_umount sem */
46194652
if (test_opt(sb, DELALLOC))
46204653
sync_filesystem(sb);
46214654

4655+
/* Update modification times of quota files when userspace can
4656+
* start looking at them */
4657+
handle = ext4_journal_start(inode, 1);
4658+
if (IS_ERR(handle))
4659+
goto out;
4660+
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
4661+
ext4_mark_inode_dirty(handle, inode);
4662+
ext4_journal_stop(handle);
4663+
4664+
out:
46224665
return dquot_quota_off(sb, type);
46234666
}
46244667

@@ -4714,9 +4757,8 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
47144757
if (inode->i_size < off + len) {
47154758
i_size_write(inode, off + len);
47164759
EXT4_I(inode)->i_disksize = inode->i_size;
4760+
ext4_mark_inode_dirty(handle, inode);
47174761
}
4718-
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
4719-
ext4_mark_inode_dirty(handle, inode);
47204762
mutex_unlock(&inode->i_mutex);
47214763
return len;
47224764
}

fs/jbd2/commit.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ static int journal_submit_commit_record(journal_t *journal,
105105
int ret;
106106
struct timespec now = current_kernel_time();
107107

108+
*cbh = NULL;
109+
108110
if (is_journal_aborted(journal))
109111
return 0;
110112

@@ -806,7 +808,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
806808
if (err)
807809
__jbd2_journal_abort_hard(journal);
808810
}
809-
if (!err && !is_journal_aborted(journal))
811+
if (cbh)
810812
err = journal_wait_on_commit_record(journal, cbh);
811813
if (JBD2_HAS_INCOMPAT_FEATURE(journal,
812814
JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT) &&

fs/jbd2/journal.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2413,10 +2413,12 @@ const char *jbd2_dev_to_name(dev_t device)
24132413
new_dev = kmalloc(sizeof(struct devname_cache), GFP_KERNEL);
24142414
if (!new_dev)
24152415
return "NODEV-ALLOCFAILURE"; /* Something non-NULL */
2416+
bd = bdget(device);
24162417
spin_lock(&devname_cache_lock);
24172418
if (devcache[i]) {
24182419
if (devcache[i]->device == device) {
24192420
kfree(new_dev);
2421+
bdput(bd);
24202422
ret = devcache[i]->devname;
24212423
spin_unlock(&devname_cache_lock);
24222424
return ret;
@@ -2425,7 +2427,6 @@ const char *jbd2_dev_to_name(dev_t device)
24252427
}
24262428
devcache[i] = new_dev;
24272429
devcache[i]->device = device;
2428-
bd = bdget(device);
24292430
if (bd) {
24302431
bdevname(bd, devcache[i]->devname);
24312432
bdput(bd);

0 commit comments

Comments
 (0)