Skip to content

Commit 6984aef

Browse files
zhangyi089tytso
authored andcommitted
ext4: factor out write end code of inline file
Now that the inline_data file write end procedure are falled into the common write end functions, it is not clear. Factor them out and do some cleanup. This patch also drop ext4_da_write_inline_data_end() and switch to use ext4_write_inline_data_end() instead because we also need to do the same error processing if we failed to write data into inline entry. Signed-off-by: Zhang Yi <[email protected]> Reviewed-by: Jan Kara <[email protected]> Signed-off-by: Theodore Ts'o <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 55ce2f6 commit 6984aef

File tree

3 files changed

+84
-109
lines changed

3 files changed

+84
-109
lines changed

fs/ext4/ext4.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3533,9 +3533,6 @@ extern int ext4_da_write_inline_data_begin(struct address_space *mapping,
35333533
unsigned flags,
35343534
struct page **pagep,
35353535
void **fsdata);
3536-
extern int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
3537-
unsigned len, unsigned copied,
3538-
struct page *page);
35393536
extern int ext4_try_add_inline_entry(handle_t *handle,
35403537
struct ext4_filename *fname,
35413538
struct inode *dir, struct inode *inode);

fs/ext4/inline.c

Lines changed: 61 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -729,34 +729,76 @@ int ext4_try_to_write_inline_data(struct address_space *mapping,
729729
int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
730730
unsigned copied, struct page *page)
731731
{
732-
int ret, no_expand;
732+
handle_t *handle = ext4_journal_current_handle();
733+
int no_expand;
733734
void *kaddr;
734735
struct ext4_iloc iloc;
736+
int ret = 0, ret2;
735737

736738
if (unlikely(copied < len) && !PageUptodate(page))
737-
return 0;
739+
copied = 0;
738740

739-
ret = ext4_get_inode_loc(inode, &iloc);
740-
if (ret) {
741-
ext4_std_error(inode->i_sb, ret);
742-
return ret;
743-
}
741+
if (likely(copied)) {
742+
ret = ext4_get_inode_loc(inode, &iloc);
743+
if (ret) {
744+
unlock_page(page);
745+
put_page(page);
746+
ext4_std_error(inode->i_sb, ret);
747+
goto out;
748+
}
749+
ext4_write_lock_xattr(inode, &no_expand);
750+
BUG_ON(!ext4_has_inline_data(inode));
744751

745-
ext4_write_lock_xattr(inode, &no_expand);
746-
BUG_ON(!ext4_has_inline_data(inode));
752+
kaddr = kmap_atomic(page);
753+
ext4_write_inline_data(inode, &iloc, kaddr, pos, copied);
754+
kunmap_atomic(kaddr);
755+
SetPageUptodate(page);
756+
/* clear page dirty so that writepages wouldn't work for us. */
757+
ClearPageDirty(page);
747758

748-
kaddr = kmap_atomic(page);
749-
ext4_write_inline_data(inode, &iloc, kaddr, pos, copied);
750-
kunmap_atomic(kaddr);
751-
SetPageUptodate(page);
752-
/* clear page dirty so that writepages wouldn't work for us. */
753-
ClearPageDirty(page);
759+
ext4_write_unlock_xattr(inode, &no_expand);
760+
brelse(iloc.bh);
754761

755-
ext4_write_unlock_xattr(inode, &no_expand);
756-
brelse(iloc.bh);
757-
mark_inode_dirty(inode);
762+
/*
763+
* It's important to update i_size while still holding page
764+
* lock: page writeout could otherwise come in and zero
765+
* beyond i_size.
766+
*/
767+
ext4_update_inode_size(inode, pos + copied);
768+
}
769+
unlock_page(page);
770+
put_page(page);
771+
772+
/*
773+
* Don't mark the inode dirty under page lock. First, it unnecessarily
774+
* makes the holding time of page lock longer. Second, it forces lock
775+
* ordering of page lock and transaction start for journaling
776+
* filesystems.
777+
*/
778+
if (likely(copied))
779+
mark_inode_dirty(inode);
780+
out:
781+
/*
782+
* If we didn't copy as much data as expected, we need to trim back
783+
* size of xattr containing inline data.
784+
*/
785+
if (pos + len > inode->i_size && ext4_can_truncate(inode))
786+
ext4_orphan_add(handle, inode);
758787

759-
return copied;
788+
ret2 = ext4_journal_stop(handle);
789+
if (!ret)
790+
ret = ret2;
791+
if (pos + len > inode->i_size) {
792+
ext4_truncate_failed_write(inode);
793+
/*
794+
* If truncate failed early the inode might still be
795+
* on the orphan list; we need to make sure the inode
796+
* is removed from the orphan list in that case.
797+
*/
798+
if (inode->i_nlink)
799+
ext4_orphan_del(NULL, inode);
800+
}
801+
return ret ? ret : copied;
760802
}
761803

762804
struct buffer_head *
@@ -937,43 +979,6 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
937979
return ret;
938980
}
939981

940-
int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
941-
unsigned len, unsigned copied,
942-
struct page *page)
943-
{
944-
int ret;
945-
946-
ret = ext4_write_inline_data_end(inode, pos, len, copied, page);
947-
if (ret < 0) {
948-
unlock_page(page);
949-
put_page(page);
950-
return ret;
951-
}
952-
copied = ret;
953-
954-
/*
955-
* No need to use i_size_read() here, the i_size
956-
* cannot change under us because we hold i_mutex.
957-
*
958-
* But it's important to update i_size while still holding page lock:
959-
* page writeout could otherwise come in and zero beyond i_size.
960-
*/
961-
if (pos+copied > inode->i_size)
962-
i_size_write(inode, pos+copied);
963-
unlock_page(page);
964-
put_page(page);
965-
966-
/*
967-
* Don't mark the inode dirty under page lock. First, it unnecessarily
968-
* makes the holding time of page lock longer. Second, it forces lock
969-
* ordering of page lock and transaction start for journaling
970-
* filesystems.
971-
*/
972-
mark_inode_dirty(inode);
973-
974-
return copied;
975-
}
976-
977982
#ifdef INLINE_DIR_DEBUG
978983
void ext4_show_inline_dir(struct inode *dir, struct buffer_head *bh,
979984
void *inline_start, int inline_size)

fs/ext4/inode.c

Lines changed: 23 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,23 +1282,14 @@ static int ext4_write_end(struct file *file,
12821282
loff_t old_size = inode->i_size;
12831283
int ret = 0, ret2;
12841284
int i_size_changed = 0;
1285-
int inline_data = ext4_has_inline_data(inode);
12861285
bool verity = ext4_verity_in_progress(inode);
12871286

12881287
trace_ext4_write_end(inode, pos, len, copied);
1289-
if (inline_data) {
1290-
ret = ext4_write_inline_data_end(inode, pos, len,
1291-
copied, page);
1292-
if (ret < 0) {
1293-
unlock_page(page);
1294-
put_page(page);
1295-
goto errout;
1296-
}
1297-
copied = ret;
1298-
ret = 0;
1299-
} else
1300-
copied = block_write_end(file, mapping, pos,
1301-
len, copied, page, fsdata);
1288+
1289+
if (ext4_has_inline_data(inode))
1290+
return ext4_write_inline_data_end(inode, pos, len, copied, page);
1291+
1292+
copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
13021293
/*
13031294
* it's important to update i_size while still holding page lock:
13041295
* page writeout could otherwise come in and zero beyond i_size.
@@ -1319,10 +1310,9 @@ static int ext4_write_end(struct file *file,
13191310
* ordering of page lock and transaction start for journaling
13201311
* filesystems.
13211312
*/
1322-
if (i_size_changed || inline_data)
1313+
if (i_size_changed)
13231314
ret = ext4_mark_inode_dirty(handle, inode);
13241315

1325-
errout:
13261316
if (pos + len > inode->i_size && !verity && ext4_can_truncate(inode))
13271317
/* if we have allocated more blocks and copied
13281318
* less. We will have blocks allocated outside
@@ -1394,7 +1384,6 @@ static int ext4_journalled_write_end(struct file *file,
13941384
int partial = 0;
13951385
unsigned from, to;
13961386
int size_changed = 0;
1397-
int inline_data = ext4_has_inline_data(inode);
13981387
bool verity = ext4_verity_in_progress(inode);
13991388

14001389
trace_ext4_journalled_write_end(inode, pos, len, copied);
@@ -1403,17 +1392,10 @@ static int ext4_journalled_write_end(struct file *file,
14031392

14041393
BUG_ON(!ext4_handle_valid(handle));
14051394

1406-
if (inline_data) {
1407-
ret = ext4_write_inline_data_end(inode, pos, len,
1408-
copied, page);
1409-
if (ret < 0) {
1410-
unlock_page(page);
1411-
put_page(page);
1412-
goto errout;
1413-
}
1414-
copied = ret;
1415-
ret = 0;
1416-
} else if (unlikely(copied < len) && !PageUptodate(page)) {
1395+
if (ext4_has_inline_data(inode))
1396+
return ext4_write_inline_data_end(inode, pos, len, copied, page);
1397+
1398+
if (unlikely(copied < len) && !PageUptodate(page)) {
14171399
copied = 0;
14181400
ext4_journalled_zero_new_buffers(handle, page, from, to);
14191401
} else {
@@ -1436,13 +1418,12 @@ static int ext4_journalled_write_end(struct file *file,
14361418
if (old_size < pos && !verity)
14371419
pagecache_isize_extended(inode, old_size, pos);
14381420

1439-
if (size_changed || inline_data) {
1421+
if (size_changed) {
14401422
ret2 = ext4_mark_inode_dirty(handle, inode);
14411423
if (!ret)
14421424
ret = ret2;
14431425
}
14441426

1445-
errout:
14461427
if (pos + len > inode->i_size && !verity && ext4_can_truncate(inode))
14471428
/* if we have allocated more blocks and copied
14481429
* less. We will have blocks allocated outside
@@ -3072,7 +3053,7 @@ static int ext4_da_write_end(struct file *file,
30723053
struct page *page, void *fsdata)
30733054
{
30743055
struct inode *inode = mapping->host;
3075-
int ret = 0, ret2;
3056+
int ret;
30763057
handle_t *handle = ext4_journal_current_handle();
30773058
loff_t new_i_size;
30783059
unsigned long start, end;
@@ -3083,6 +3064,12 @@ static int ext4_da_write_end(struct file *file,
30833064
len, copied, page, fsdata);
30843065

30853066
trace_ext4_da_write_end(inode, pos, len, copied);
3067+
3068+
if (write_mode != CONVERT_INLINE_DATA &&
3069+
ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA) &&
3070+
ext4_has_inline_data(inode))
3071+
return ext4_write_inline_data_end(inode, pos, len, copied, page);
3072+
30863073
start = pos & (PAGE_SIZE - 1);
30873074
end = start + copied - 1;
30883075

@@ -3102,26 +3089,12 @@ static int ext4_da_write_end(struct file *file,
31023089
* ext4_da_write_inline_data_end().
31033090
*/
31043091
new_i_size = pos + copied;
3105-
if (copied && new_i_size > inode->i_size) {
3106-
if (ext4_has_inline_data(inode) ||
3107-
ext4_da_should_update_i_disksize(page, end))
3108-
ext4_update_i_disksize(inode, new_i_size);
3109-
}
3110-
3111-
if (write_mode != CONVERT_INLINE_DATA &&
3112-
ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA) &&
3113-
ext4_has_inline_data(inode))
3114-
ret = ext4_da_write_inline_data_end(inode, pos, len, copied,
3115-
page);
3116-
else
3117-
ret = generic_write_end(file, mapping, pos, len, copied,
3118-
page, fsdata);
3119-
3120-
copied = ret;
3121-
ret2 = ext4_journal_stop(handle);
3122-
if (unlikely(ret2 && !ret))
3123-
ret = ret2;
3092+
if (copied && new_i_size > inode->i_size &&
3093+
ext4_da_should_update_i_disksize(page, end))
3094+
ext4_update_i_disksize(inode, new_i_size);
31243095

3096+
copied = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
3097+
ret = ext4_journal_stop(handle);
31253098
return ret ? ret : copied;
31263099
}
31273100

0 commit comments

Comments
 (0)