aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/ext4_jbd2.h2
-rw-r--r--fs/ext4/file.c2
-rw-r--r--fs/ext4/indirect.c43
-rw-r--r--fs/ext4/inode.c30
-rw-r--r--fs/ext4/ioctl.c7
-rw-r--r--fs/ext4/resize.c17
-rw-r--r--fs/ext4/super.c16
7 files changed, 58 insertions, 59 deletions
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index a1ac7e9245ec..75a5309f2231 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -384,7 +384,7 @@ static inline void ext4_update_inode_fsync_trans(handle_t *handle,
384{ 384{
385 struct ext4_inode_info *ei = EXT4_I(inode); 385 struct ext4_inode_info *ei = EXT4_I(inode);
386 386
387 if (ext4_handle_valid(handle)) { 387 if (ext4_handle_valid(handle) && !is_handle_aborted(handle)) {
388 ei->i_sync_tid = handle->h_transaction->t_tid; 388 ei->i_sync_tid = handle->h_transaction->t_tid;
389 if (datasync) 389 if (datasync)
390 ei->i_datasync_tid = handle->h_transaction->t_tid; 390 ei->i_datasync_tid = handle->h_transaction->t_tid;
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 69d65d49837b..98ec11f69cd4 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -125,7 +125,7 @@ ext4_unaligned_aio(struct inode *inode, struct iov_iter *from, loff_t pos)
125 struct super_block *sb = inode->i_sb; 125 struct super_block *sb = inode->i_sb;
126 int blockmask = sb->s_blocksize - 1; 126 int blockmask = sb->s_blocksize - 1;
127 127
128 if (pos >= i_size_read(inode)) 128 if (pos >= ALIGN(i_size_read(inode), sb->s_blocksize))
129 return 0; 129 return 0;
130 130
131 if ((pos | iov_iter_alignment(from)) & blockmask) 131 if ((pos | iov_iter_alignment(from)) & blockmask)
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index c2225f0d31b5..2024d3fa5504 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -1222,6 +1222,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
1222 ext4_lblk_t offsets[4], offsets2[4]; 1222 ext4_lblk_t offsets[4], offsets2[4];
1223 Indirect chain[4], chain2[4]; 1223 Indirect chain[4], chain2[4];
1224 Indirect *partial, *partial2; 1224 Indirect *partial, *partial2;
1225 Indirect *p = NULL, *p2 = NULL;
1225 ext4_lblk_t max_block; 1226 ext4_lblk_t max_block;
1226 __le32 nr = 0, nr2 = 0; 1227 __le32 nr = 0, nr2 = 0;
1227 int n = 0, n2 = 0; 1228 int n = 0, n2 = 0;
@@ -1263,7 +1264,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
1263 } 1264 }
1264 1265
1265 1266
1266 partial = ext4_find_shared(inode, n, offsets, chain, &nr); 1267 partial = p = ext4_find_shared(inode, n, offsets, chain, &nr);
1267 if (nr) { 1268 if (nr) {
1268 if (partial == chain) { 1269 if (partial == chain) {
1269 /* Shared branch grows from the inode */ 1270 /* Shared branch grows from the inode */
@@ -1288,13 +1289,11 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
1288 partial->p + 1, 1289 partial->p + 1,
1289 (__le32 *)partial->bh->b_data+addr_per_block, 1290 (__le32 *)partial->bh->b_data+addr_per_block,
1290 (chain+n-1) - partial); 1291 (chain+n-1) - partial);
1291 BUFFER_TRACE(partial->bh, "call brelse");
1292 brelse(partial->bh);
1293 partial--; 1292 partial--;
1294 } 1293 }
1295 1294
1296end_range: 1295end_range:
1297 partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2); 1296 partial2 = p2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);
1298 if (nr2) { 1297 if (nr2) {
1299 if (partial2 == chain2) { 1298 if (partial2 == chain2) {
1300 /* 1299 /*
@@ -1324,16 +1323,14 @@ end_range:
1324 (__le32 *)partial2->bh->b_data, 1323 (__le32 *)partial2->bh->b_data,
1325 partial2->p, 1324 partial2->p,
1326 (chain2+n2-1) - partial2); 1325 (chain2+n2-1) - partial2);
1327 BUFFER_TRACE(partial2->bh, "call brelse");
1328 brelse(partial2->bh);
1329 partial2--; 1326 partial2--;
1330 } 1327 }
1331 goto do_indirects; 1328 goto do_indirects;
1332 } 1329 }
1333 1330
1334 /* Punch happened within the same level (n == n2) */ 1331 /* Punch happened within the same level (n == n2) */
1335 partial = ext4_find_shared(inode, n, offsets, chain, &nr); 1332 partial = p = ext4_find_shared(inode, n, offsets, chain, &nr);
1336 partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2); 1333 partial2 = p2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);
1337 1334
1338 /* Free top, but only if partial2 isn't its subtree. */ 1335 /* Free top, but only if partial2 isn't its subtree. */
1339 if (nr) { 1336 if (nr) {
@@ -1390,11 +1387,7 @@ end_range:
1390 partial->p + 1, 1387 partial->p + 1,
1391 partial2->p, 1388 partial2->p,
1392 (chain+n-1) - partial); 1389 (chain+n-1) - partial);
1393 BUFFER_TRACE(partial->bh, "call brelse"); 1390 goto cleanup;
1394 brelse(partial->bh);
1395 BUFFER_TRACE(partial2->bh, "call brelse");
1396 brelse(partial2->bh);
1397 return 0;
1398 } 1391 }
1399 1392
1400 /* 1393 /*
@@ -1409,8 +1402,6 @@ end_range:
1409 partial->p + 1, 1402 partial->p + 1,
1410 (__le32 *)partial->bh->b_data+addr_per_block, 1403 (__le32 *)partial->bh->b_data+addr_per_block,
1411 (chain+n-1) - partial); 1404 (chain+n-1) - partial);
1412 BUFFER_TRACE(partial->bh, "call brelse");
1413 brelse(partial->bh);
1414 partial--; 1405 partial--;
1415 } 1406 }
1416 if (partial2 > chain2 && depth2 <= depth) { 1407 if (partial2 > chain2 && depth2 <= depth) {
@@ -1418,11 +1409,21 @@ end_range:
1418 (__le32 *)partial2->bh->b_data, 1409 (__le32 *)partial2->bh->b_data,
1419 partial2->p, 1410 partial2->p,
1420 (chain2+n2-1) - partial2); 1411 (chain2+n2-1) - partial2);
1421 BUFFER_TRACE(partial2->bh, "call brelse");
1422 brelse(partial2->bh);
1423 partial2--; 1412 partial2--;
1424 } 1413 }
1425 } 1414 }
1415
1416cleanup:
1417 while (p && p > chain) {
1418 BUFFER_TRACE(p->bh, "call brelse");
1419 brelse(p->bh);
1420 p--;
1421 }
1422 while (p2 && p2 > chain2) {
1423 BUFFER_TRACE(p2->bh, "call brelse");
1424 brelse(p2->bh);
1425 p2--;
1426 }
1426 return 0; 1427 return 0;
1427 1428
1428do_indirects: 1429do_indirects:
@@ -1430,7 +1431,7 @@ do_indirects:
1430 switch (offsets[0]) { 1431 switch (offsets[0]) {
1431 default: 1432 default:
1432 if (++n >= n2) 1433 if (++n >= n2)
1433 return 0; 1434 break;
1434 nr = i_data[EXT4_IND_BLOCK]; 1435 nr = i_data[EXT4_IND_BLOCK];
1435 if (nr) { 1436 if (nr) {
1436 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 1); 1437 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 1);
@@ -1439,7 +1440,7 @@ do_indirects:
1439 /* fall through */ 1440 /* fall through */
1440 case EXT4_IND_BLOCK: 1441 case EXT4_IND_BLOCK:
1441 if (++n >= n2) 1442 if (++n >= n2)
1442 return 0; 1443 break;
1443 nr = i_data[EXT4_DIND_BLOCK]; 1444 nr = i_data[EXT4_DIND_BLOCK];
1444 if (nr) { 1445 if (nr) {
1445 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 2); 1446 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 2);
@@ -1448,7 +1449,7 @@ do_indirects:
1448 /* fall through */ 1449 /* fall through */
1449 case EXT4_DIND_BLOCK: 1450 case EXT4_DIND_BLOCK:
1450 if (++n >= n2) 1451 if (++n >= n2)
1451 return 0; 1452 break;
1452 nr = i_data[EXT4_TIND_BLOCK]; 1453 nr = i_data[EXT4_TIND_BLOCK];
1453 if (nr) { 1454 if (nr) {
1454 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3); 1455 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3);
@@ -1458,5 +1459,5 @@ do_indirects:
1458 case EXT4_TIND_BLOCK: 1459 case EXT4_TIND_BLOCK:
1459 ; 1460 ;
1460 } 1461 }
1461 return 0; 1462 goto cleanup;
1462} 1463}
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index b54b261ded36..b32a57bc5d5d 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -6080,36 +6080,6 @@ out:
6080 return; 6080 return;
6081} 6081}
6082 6082
6083#if 0
6084/*
6085 * Bind an inode's backing buffer_head into this transaction, to prevent
6086 * it from being flushed to disk early. Unlike
6087 * ext4_reserve_inode_write, this leaves behind no bh reference and
6088 * returns no iloc structure, so the caller needs to repeat the iloc
6089 * lookup to mark the inode dirty later.
6090 */
6091static int ext4_pin_inode(handle_t *handle, struct inode *inode)
6092{
6093 struct ext4_iloc iloc;
6094
6095 int err = 0;
6096 if (handle) {
6097 err = ext4_get_inode_loc(inode, &iloc);
6098 if (!err) {
6099 BUFFER_TRACE(iloc.bh, "get_write_access");
6100 err = jbd2_journal_get_write_access(handle, iloc.bh);
6101 if (!err)
6102 err = ext4_handle_dirty_metadata(handle,
6103 NULL,
6104 iloc.bh);
6105 brelse(iloc.bh);
6106 }
6107 }
6108 ext4_std_error(inode->i_sb, err);
6109 return err;
6110}
6111#endif
6112
6113int ext4_change_inode_journal_flag(struct inode *inode, int val) 6083int ext4_change_inode_journal_flag(struct inode *inode, int val)
6114{ 6084{
6115 journal_t *journal; 6085 journal_t *journal;
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 3c4f8bb59f8a..bab3da4f1e0d 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -1000,6 +1000,13 @@ resizefs_out:
1000 if (!blk_queue_discard(q)) 1000 if (!blk_queue_discard(q))
1001 return -EOPNOTSUPP; 1001 return -EOPNOTSUPP;
1002 1002
1003 /*
1004 * We haven't replayed the journal, so we cannot use our
1005 * block-bitmap-guided storage zapping commands.
1006 */
1007 if (test_opt(sb, NOLOAD) && ext4_has_feature_journal(sb))
1008 return -EROFS;
1009
1003 if (copy_from_user(&range, (struct fstrim_range __user *)arg, 1010 if (copy_from_user(&range, (struct fstrim_range __user *)arg,
1004 sizeof(range))) 1011 sizeof(range)))
1005 return -EFAULT; 1012 return -EFAULT;
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 3d9b18505c0c..e7ae26e36c9c 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -932,11 +932,18 @@ static int add_new_gdb_meta_bg(struct super_block *sb,
932 memcpy(n_group_desc, o_group_desc, 932 memcpy(n_group_desc, o_group_desc,
933 EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *)); 933 EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *));
934 n_group_desc[gdb_num] = gdb_bh; 934 n_group_desc[gdb_num] = gdb_bh;
935
936 BUFFER_TRACE(gdb_bh, "get_write_access");
937 err = ext4_journal_get_write_access(handle, gdb_bh);
938 if (err) {
939 kvfree(n_group_desc);
940 brelse(gdb_bh);
941 return err;
942 }
943
935 EXT4_SB(sb)->s_group_desc = n_group_desc; 944 EXT4_SB(sb)->s_group_desc = n_group_desc;
936 EXT4_SB(sb)->s_gdb_count++; 945 EXT4_SB(sb)->s_gdb_count++;
937 kvfree(o_group_desc); 946 kvfree(o_group_desc);
938 BUFFER_TRACE(gdb_bh, "get_write_access");
939 err = ext4_journal_get_write_access(handle, gdb_bh);
940 return err; 947 return err;
941} 948}
942 949
@@ -2073,6 +2080,10 @@ out:
2073 free_flex_gd(flex_gd); 2080 free_flex_gd(flex_gd);
2074 if (resize_inode != NULL) 2081 if (resize_inode != NULL)
2075 iput(resize_inode); 2082 iput(resize_inode);
2076 ext4_msg(sb, KERN_INFO, "resized filesystem to %llu", n_blocks_count); 2083 if (err)
2084 ext4_warning(sb, "error (%d) occurred during "
2085 "file system resize", err);
2086 ext4_msg(sb, KERN_INFO, "resized filesystem to %llu",
2087 ext4_blocks_count(es));
2077 return err; 2088 return err;
2078} 2089}
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index f5b828bf1299..6ed4eb81e674 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -430,6 +430,12 @@ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
430 spin_unlock(&sbi->s_md_lock); 430 spin_unlock(&sbi->s_md_lock);
431} 431}
432 432
433static bool system_going_down(void)
434{
435 return system_state == SYSTEM_HALT || system_state == SYSTEM_POWER_OFF
436 || system_state == SYSTEM_RESTART;
437}
438
433/* Deal with the reporting of failure conditions on a filesystem such as 439/* Deal with the reporting of failure conditions on a filesystem such as
434 * inconsistencies detected or read IO failures. 440 * inconsistencies detected or read IO failures.
435 * 441 *
@@ -460,7 +466,12 @@ static void ext4_handle_error(struct super_block *sb)
460 if (journal) 466 if (journal)
461 jbd2_journal_abort(journal, -EIO); 467 jbd2_journal_abort(journal, -EIO);
462 } 468 }
463 if (test_opt(sb, ERRORS_RO)) { 469 /*
470 * We force ERRORS_RO behavior when system is rebooting. Otherwise we
471 * could panic during 'reboot -f' as the underlying device got already
472 * disabled.
473 */
474 if (test_opt(sb, ERRORS_RO) || system_going_down()) {
464 ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only"); 475 ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
465 /* 476 /*
466 * Make sure updated value of ->s_mount_flags will be visible 477 * Make sure updated value of ->s_mount_flags will be visible
@@ -468,8 +479,7 @@ static void ext4_handle_error(struct super_block *sb)
468 */ 479 */
469 smp_wmb(); 480 smp_wmb();
470 sb->s_flags |= SB_RDONLY; 481 sb->s_flags |= SB_RDONLY;
471 } 482 } else if (test_opt(sb, ERRORS_PANIC)) {
472 if (test_opt(sb, ERRORS_PANIC)) {
473 if (EXT4_SB(sb)->s_journal && 483 if (EXT4_SB(sb)->s_journal &&
474 !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR)) 484 !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR))
475 return; 485 return;