General improvements: * Remove unused datawriteback. * Check nr_files before accesing members in files[0]. * Remove excess {} in oneliner if condition. * Check lack of journal early. * Remove and add some newlines and spaces to improve readability. * Add err3 to fix error handling in blkdev_issue_flush error path.
Make similar changes like in mainstream in ext4_sync_file: * Replace J_ASSERT to ASSERT similar to [1]. * Remove inode_lock as it's not needed after [2]. * Force commit only for non-regular files, similar to [3] + [4]. * Use ext4_fc_commit instead of jbd2_complete_transaction as in [5]. * Track writeback errors in ext4_sync_files as in [6]. * Replace mapping->nrpages with equivalent mapping_needs_writeback() helper. 837c23fbc1b8 ("ext4: use ASSERT() to replace J_ASSERT()") [1] 92e6222dfb85 ("ext4: remove i_mutex from ext4_file_sync()") [2] e360c6ed7274 ("ext4: Drop special handling of journalled data from ext4_sync_file()") [3] 1077b2d53ef5 ("ext4: fix fsync for non-directories") [4] aa75f4d3daae ("ext4: main fast-commit commit path") [5] 95cb67138746 ("ext4: track writeback errors using the generic trackinginfrastructure") [6] https://virtuozzo.atlassian.net/browse/VSTOR-107255 Fixes: c266e3fb67ca ("ext4: add mfsync support") Signed-off-by: Pavel Tikhomirov <ptikhomi...@virtuozzo.com> Feature: ext4: optimized sync of a set of files - mfsync() --- v2: use mapping_needs_writeback helper --- fs/ext4/fsync.c | 51 +++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c index 9819848c17a3..e0b0e0d0295c 100644 --- a/fs/ext4/fsync.c +++ b/fs/ext4/fsync.c @@ -180,25 +180,30 @@ int ext4_sync_files(struct file **files, unsigned int *flags, unsigned int nr_fi { struct super_block *sb; journal_t *journal; - int err = 0, err2 = 0, i = 0, j = 0; - int force_commit = 0, datawriteback = 0; + int err = 0, err2 = 0, err3 = 0; + int i = 0, j = 0; + int force_commit = 0; tid_t commit_tid = 0; int need_barrier = 0; int ret; + if (!nr_files) + return 0; sb = files[0]->f_mapping->host->i_sb; + ret = ext4_emergency_state(sb); if (unlikely(ret)) return ret; - J_ASSERT(ext4_journal_current_handle() == NULL); - if (!nr_files) + ASSERT(ext4_journal_current_handle() == NULL); + + if (sb_rdonly(sb)) return 0; journal = EXT4_SB(sb)->s_journal; - if (sb_rdonly(sb)) { - return 0; - } + if (!journal) + return -ENOTSUPP; + for (i = 0; i < nr_files; i++) { struct address_space * mapping = files[i]->f_mapping; struct inode *inode = mapping->host; @@ -207,13 +212,13 @@ int ext4_sync_files(struct file **files, unsigned int *flags, unsigned int nr_fi err = -EINVAL; goto out; } - if (!mapping->nrpages) + + if (!mapping_needs_writeback(mapping)) continue; err = filemap_fdatawrite(mapping); if (err) break; - } /* * Even if the above returned error, the pages may be @@ -225,32 +230,27 @@ int ext4_sync_files(struct file **files, unsigned int *flags, unsigned int nr_fi goto out; for (j = 0; j < i; j++) { - struct address_space * mapping = files[j]->f_mapping; + struct address_space *mapping = files[j]->f_mapping; struct inode *inode = mapping->host; struct ext4_inode_info *ei = EXT4_I(inode); unsigned int datasync = flags[j]; tid_t tid; - if (mapping->nrpages) { + if (mapping_needs_writeback(mapping)) err2 = filemap_fdatawait(mapping); if (!err || err2 == -EIO) err = err2; } - inode_lock_shared(inode); - force_commit |= ext4_should_journal_data(inode); - datawriteback |= ext4_should_writeback_data(inode); + force_commit |= !S_ISREG(inode->i_mode); tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid; - inode_unlock_shared(inode); trace_ext4_sync_files_iterate(files[j]->f_path.dentry, tid, datasync); if (j == 0 || !tid_geq(commit_tid, tid)) commit_tid = tid; } /* Ext4 specific stuff starts here */ - if (!journal) { - return -ENOTSUPP; - } else if (force_commit) { + if (force_commit) { /* data=journal: * filemap_fdatawrite won't do anything (the buffers are clean). * ext4_force_commit will write the file data into the journal and @@ -271,17 +271,26 @@ int ext4_sync_files(struct file **files, unsigned int *flags, unsigned int nr_fi !jbd2_trans_will_send_data_barrier(journal, commit_tid)) need_barrier = true; - err2 = jbd2_complete_transaction(journal, commit_tid); + err2 = ext4_fc_commit(journal, commit_tid); /* Even if we had to wait for commit completion, it does not * mean a flush has been issued after data demanded by this * fsync were written back. Commit could be in state after * it is already done, but not yet in state where we should * not wait. */ - if (need_barrier) - err2 = blkdev_issue_flush(sb->s_bdev); + if (need_barrier) { + err3 = blkdev_issue_flush(sb->s_bdev); + if (!err2 || err3 == -EIO) + err2 = err3; + } } out: + for (i = 0; i < nr_files; i++) { + err3 = file_check_and_advance_wb_err(files[i]); + if (!err2 || err3 == -EIO) + err2 = err3; + } + trace_ext4_sync_files_exit(files[0]->f_path.dentry, commit_tid, need_barrier); if (!err || err2 == -EIO) err = err2; -- 2.50.1 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel