diff options
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 55 |
1 files changed, 40 insertions, 15 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 006b7a2070bf..d0dc0e3463db 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1340,6 +1340,9 @@ retry_journal: | |||
1340 | } | 1340 | } |
1341 | 1341 | ||
1342 | if (ret) { | 1342 | if (ret) { |
1343 | bool extended = (pos + len > inode->i_size) && | ||
1344 | !ext4_verity_in_progress(inode); | ||
1345 | |||
1343 | unlock_page(page); | 1346 | unlock_page(page); |
1344 | /* | 1347 | /* |
1345 | * __block_write_begin may have instantiated a few blocks | 1348 | * __block_write_begin may have instantiated a few blocks |
@@ -1349,11 +1352,11 @@ retry_journal: | |||
1349 | * Add inode to orphan list in case we crash before | 1352 | * Add inode to orphan list in case we crash before |
1350 | * truncate finishes | 1353 | * truncate finishes |
1351 | */ | 1354 | */ |
1352 | if (pos + len > inode->i_size && ext4_can_truncate(inode)) | 1355 | if (extended && ext4_can_truncate(inode)) |
1353 | ext4_orphan_add(handle, inode); | 1356 | ext4_orphan_add(handle, inode); |
1354 | 1357 | ||
1355 | ext4_journal_stop(handle); | 1358 | ext4_journal_stop(handle); |
1356 | if (pos + len > inode->i_size) { | 1359 | if (extended) { |
1357 | ext4_truncate_failed_write(inode); | 1360 | ext4_truncate_failed_write(inode); |
1358 | /* | 1361 | /* |
1359 | * If truncate failed early the inode might | 1362 | * If truncate failed early the inode might |
@@ -1406,6 +1409,7 @@ static int ext4_write_end(struct file *file, | |||
1406 | int ret = 0, ret2; | 1409 | int ret = 0, ret2; |
1407 | int i_size_changed = 0; | 1410 | int i_size_changed = 0; |
1408 | int inline_data = ext4_has_inline_data(inode); | 1411 | int inline_data = ext4_has_inline_data(inode); |
1412 | bool verity = ext4_verity_in_progress(inode); | ||
1409 | 1413 | ||
1410 | trace_ext4_write_end(inode, pos, len, copied); | 1414 | trace_ext4_write_end(inode, pos, len, copied); |
1411 | if (inline_data) { | 1415 | if (inline_data) { |
@@ -1423,12 +1427,16 @@ static int ext4_write_end(struct file *file, | |||
1423 | /* | 1427 | /* |
1424 | * it's important to update i_size while still holding page lock: | 1428 | * it's important to update i_size while still holding page lock: |
1425 | * page writeout could otherwise come in and zero beyond i_size. | 1429 | * page writeout could otherwise come in and zero beyond i_size. |
1430 | * | ||
1431 | * If FS_IOC_ENABLE_VERITY is running on this inode, then Merkle tree | ||
1432 | * blocks are being written past EOF, so skip the i_size update. | ||
1426 | */ | 1433 | */ |
1427 | i_size_changed = ext4_update_inode_size(inode, pos + copied); | 1434 | if (!verity) |
1435 | i_size_changed = ext4_update_inode_size(inode, pos + copied); | ||
1428 | unlock_page(page); | 1436 | unlock_page(page); |
1429 | put_page(page); | 1437 | put_page(page); |
1430 | 1438 | ||
1431 | if (old_size < pos) | 1439 | if (old_size < pos && !verity) |
1432 | pagecache_isize_extended(inode, old_size, pos); | 1440 | pagecache_isize_extended(inode, old_size, pos); |
1433 | /* | 1441 | /* |
1434 | * Don't mark the inode dirty under page lock. First, it unnecessarily | 1442 | * Don't mark the inode dirty under page lock. First, it unnecessarily |
@@ -1439,7 +1447,7 @@ static int ext4_write_end(struct file *file, | |||
1439 | if (i_size_changed || inline_data) | 1447 | if (i_size_changed || inline_data) |
1440 | ext4_mark_inode_dirty(handle, inode); | 1448 | ext4_mark_inode_dirty(handle, inode); |
1441 | 1449 | ||
1442 | if (pos + len > inode->i_size && ext4_can_truncate(inode)) | 1450 | if (pos + len > inode->i_size && !verity && ext4_can_truncate(inode)) |
1443 | /* if we have allocated more blocks and copied | 1451 | /* if we have allocated more blocks and copied |
1444 | * less. We will have blocks allocated outside | 1452 | * less. We will have blocks allocated outside |
1445 | * inode->i_size. So truncate them | 1453 | * inode->i_size. So truncate them |
@@ -1450,7 +1458,7 @@ errout: | |||
1450 | if (!ret) | 1458 | if (!ret) |
1451 | ret = ret2; | 1459 | ret = ret2; |
1452 | 1460 | ||
1453 | if (pos + len > inode->i_size) { | 1461 | if (pos + len > inode->i_size && !verity) { |
1454 | ext4_truncate_failed_write(inode); | 1462 | ext4_truncate_failed_write(inode); |
1455 | /* | 1463 | /* |
1456 | * If truncate failed early the inode might still be | 1464 | * If truncate failed early the inode might still be |
@@ -1511,6 +1519,7 @@ static int ext4_journalled_write_end(struct file *file, | |||
1511 | unsigned from, to; | 1519 | unsigned from, to; |
1512 | int size_changed = 0; | 1520 | int size_changed = 0; |
1513 | int inline_data = ext4_has_inline_data(inode); | 1521 | int inline_data = ext4_has_inline_data(inode); |
1522 | bool verity = ext4_verity_in_progress(inode); | ||
1514 | 1523 | ||
1515 | trace_ext4_journalled_write_end(inode, pos, len, copied); | 1524 | trace_ext4_journalled_write_end(inode, pos, len, copied); |
1516 | from = pos & (PAGE_SIZE - 1); | 1525 | from = pos & (PAGE_SIZE - 1); |
@@ -1540,13 +1549,14 @@ static int ext4_journalled_write_end(struct file *file, | |||
1540 | if (!partial) | 1549 | if (!partial) |
1541 | SetPageUptodate(page); | 1550 | SetPageUptodate(page); |
1542 | } | 1551 | } |
1543 | size_changed = ext4_update_inode_size(inode, pos + copied); | 1552 | if (!verity) |
1553 | size_changed = ext4_update_inode_size(inode, pos + copied); | ||
1544 | ext4_set_inode_state(inode, EXT4_STATE_JDATA); | 1554 | ext4_set_inode_state(inode, EXT4_STATE_JDATA); |
1545 | EXT4_I(inode)->i_datasync_tid = handle->h_transaction->t_tid; | 1555 | EXT4_I(inode)->i_datasync_tid = handle->h_transaction->t_tid; |
1546 | unlock_page(page); | 1556 | unlock_page(page); |
1547 | put_page(page); | 1557 | put_page(page); |
1548 | 1558 | ||
1549 | if (old_size < pos) | 1559 | if (old_size < pos && !verity) |
1550 | pagecache_isize_extended(inode, old_size, pos); | 1560 | pagecache_isize_extended(inode, old_size, pos); |
1551 | 1561 | ||
1552 | if (size_changed || inline_data) { | 1562 | if (size_changed || inline_data) { |
@@ -1555,7 +1565,7 @@ static int ext4_journalled_write_end(struct file *file, | |||
1555 | ret = ret2; | 1565 | ret = ret2; |
1556 | } | 1566 | } |
1557 | 1567 | ||
1558 | if (pos + len > inode->i_size && ext4_can_truncate(inode)) | 1568 | if (pos + len > inode->i_size && !verity && ext4_can_truncate(inode)) |
1559 | /* if we have allocated more blocks and copied | 1569 | /* if we have allocated more blocks and copied |
1560 | * less. We will have blocks allocated outside | 1570 | * less. We will have blocks allocated outside |
1561 | * inode->i_size. So truncate them | 1571 | * inode->i_size. So truncate them |
@@ -1566,7 +1576,7 @@ errout: | |||
1566 | ret2 = ext4_journal_stop(handle); | 1576 | ret2 = ext4_journal_stop(handle); |
1567 | if (!ret) | 1577 | if (!ret) |
1568 | ret = ret2; | 1578 | ret = ret2; |
1569 | if (pos + len > inode->i_size) { | 1579 | if (pos + len > inode->i_size && !verity) { |
1570 | ext4_truncate_failed_write(inode); | 1580 | ext4_truncate_failed_write(inode); |
1571 | /* | 1581 | /* |
1572 | * If truncate failed early the inode might still be | 1582 | * If truncate failed early the inode might still be |
@@ -2162,7 +2172,8 @@ static int ext4_writepage(struct page *page, | |||
2162 | 2172 | ||
2163 | trace_ext4_writepage(page); | 2173 | trace_ext4_writepage(page); |
2164 | size = i_size_read(inode); | 2174 | size = i_size_read(inode); |
2165 | if (page->index == size >> PAGE_SHIFT) | 2175 | if (page->index == size >> PAGE_SHIFT && |
2176 | !ext4_verity_in_progress(inode)) | ||
2166 | len = size & ~PAGE_MASK; | 2177 | len = size & ~PAGE_MASK; |
2167 | else | 2178 | else |
2168 | len = PAGE_SIZE; | 2179 | len = PAGE_SIZE; |
@@ -2246,7 +2257,8 @@ static int mpage_submit_page(struct mpage_da_data *mpd, struct page *page) | |||
2246 | * after page tables are updated. | 2257 | * after page tables are updated. |
2247 | */ | 2258 | */ |
2248 | size = i_size_read(mpd->inode); | 2259 | size = i_size_read(mpd->inode); |
2249 | if (page->index == size >> PAGE_SHIFT) | 2260 | if (page->index == size >> PAGE_SHIFT && |
2261 | !ext4_verity_in_progress(mpd->inode)) | ||
2250 | len = size & ~PAGE_MASK; | 2262 | len = size & ~PAGE_MASK; |
2251 | else | 2263 | else |
2252 | len = PAGE_SIZE; | 2264 | len = PAGE_SIZE; |
@@ -2345,6 +2357,9 @@ static int mpage_process_page_bufs(struct mpage_da_data *mpd, | |||
2345 | ext4_lblk_t blocks = (i_size_read(inode) + i_blocksize(inode) - 1) | 2357 | ext4_lblk_t blocks = (i_size_read(inode) + i_blocksize(inode) - 1) |
2346 | >> inode->i_blkbits; | 2358 | >> inode->i_blkbits; |
2347 | 2359 | ||
2360 | if (ext4_verity_in_progress(inode)) | ||
2361 | blocks = EXT_MAX_BLOCKS; | ||
2362 | |||
2348 | do { | 2363 | do { |
2349 | BUG_ON(buffer_locked(bh)); | 2364 | BUG_ON(buffer_locked(bh)); |
2350 | 2365 | ||
@@ -3061,8 +3076,8 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, | |||
3061 | 3076 | ||
3062 | index = pos >> PAGE_SHIFT; | 3077 | index = pos >> PAGE_SHIFT; |
3063 | 3078 | ||
3064 | if (ext4_nonda_switch(inode->i_sb) || | 3079 | if (ext4_nonda_switch(inode->i_sb) || S_ISLNK(inode->i_mode) || |
3065 | S_ISLNK(inode->i_mode)) { | 3080 | ext4_verity_in_progress(inode)) { |
3066 | *fsdata = (void *)FALL_BACK_TO_NONDELALLOC; | 3081 | *fsdata = (void *)FALL_BACK_TO_NONDELALLOC; |
3067 | return ext4_write_begin(file, mapping, pos, | 3082 | return ext4_write_begin(file, mapping, pos, |
3068 | len, flags, pagep, fsdata); | 3083 | len, flags, pagep, fsdata); |
@@ -3897,6 +3912,8 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter) | |||
3897 | if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) | 3912 | if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) |
3898 | return 0; | 3913 | return 0; |
3899 | #endif | 3914 | #endif |
3915 | if (fsverity_active(inode)) | ||
3916 | return 0; | ||
3900 | 3917 | ||
3901 | /* | 3918 | /* |
3902 | * If we are doing data journalling we don't support O_DIRECT | 3919 | * If we are doing data journalling we don't support O_DIRECT |
@@ -4736,6 +4753,8 @@ static bool ext4_should_use_dax(struct inode *inode) | |||
4736 | return false; | 4753 | return false; |
4737 | if (ext4_test_inode_flag(inode, EXT4_INODE_ENCRYPT)) | 4754 | if (ext4_test_inode_flag(inode, EXT4_INODE_ENCRYPT)) |
4738 | return false; | 4755 | return false; |
4756 | if (ext4_test_inode_flag(inode, EXT4_INODE_VERITY)) | ||
4757 | return false; | ||
4739 | return true; | 4758 | return true; |
4740 | } | 4759 | } |
4741 | 4760 | ||
@@ -4760,9 +4779,11 @@ void ext4_set_inode_flags(struct inode *inode) | |||
4760 | new_fl |= S_ENCRYPTED; | 4779 | new_fl |= S_ENCRYPTED; |
4761 | if (flags & EXT4_CASEFOLD_FL) | 4780 | if (flags & EXT4_CASEFOLD_FL) |
4762 | new_fl |= S_CASEFOLD; | 4781 | new_fl |= S_CASEFOLD; |
4782 | if (flags & EXT4_VERITY_FL) | ||
4783 | new_fl |= S_VERITY; | ||
4763 | inode_set_flags(inode, new_fl, | 4784 | inode_set_flags(inode, new_fl, |
4764 | S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|S_DAX| | 4785 | S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|S_DAX| |
4765 | S_ENCRYPTED|S_CASEFOLD); | 4786 | S_ENCRYPTED|S_CASEFOLD|S_VERITY); |
4766 | } | 4787 | } |
4767 | 4788 | ||
4768 | static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode, | 4789 | static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode, |
@@ -5552,6 +5573,10 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) | |||
5552 | if (error) | 5573 | if (error) |
5553 | return error; | 5574 | return error; |
5554 | 5575 | ||
5576 | error = fsverity_prepare_setattr(dentry, attr); | ||
5577 | if (error) | ||
5578 | return error; | ||
5579 | |||
5555 | if (is_quota_modification(inode, attr)) { | 5580 | if (is_quota_modification(inode, attr)) { |
5556 | error = dquot_initialize(inode); | 5581 | error = dquot_initialize(inode); |
5557 | if (error) | 5582 | if (error) |