On Sat 02-11-19 16:13:00, Konstantin Khlebnikov wrote: > This helper prints warning if direct I/O write failed to invalidate cache, > and set EIO at inode to warn usersapce about possible data corruption. > See also commit 5a9d929d6e13 ("iomap: report collisions between directio and > buffered writes to userspace"). > > Direct I/O is supported by non-disk filesystems, for example NFS. > Thus generic code needs this even in kernel without CONFIG_BLOCK. > > Signed-off-by: Konstantin Khlebnikov <khlebnikov@xxxxxxxxxxxxxx> Looks good to me. You can add: Reviewed-by: Jan Kara <jack@xxxxxxx> Honza > --- > fs/direct-io.c | 21 --------------------- > include/linux/fs.h | 6 +++++- > mm/filemap.c | 21 +++++++++++++++++++++ > 3 files changed, 26 insertions(+), 22 deletions(-) > > diff --git a/fs/direct-io.c b/fs/direct-io.c > index 9329ced91f1d..0ec4f270139f 100644 > --- a/fs/direct-io.c > +++ b/fs/direct-io.c > @@ -220,27 +220,6 @@ static inline struct page *dio_get_page(struct dio *dio, > return dio->pages[sdio->head]; > } > > -/* > - * Warn about a page cache invalidation failure during a direct io write. > - */ > -void dio_warn_stale_pagecache(struct file *filp) > -{ > - static DEFINE_RATELIMIT_STATE(_rs, 86400 * HZ, DEFAULT_RATELIMIT_BURST); > - char pathname[128]; > - struct inode *inode = file_inode(filp); > - char *path; > - > - errseq_set(&inode->i_mapping->wb_err, -EIO); > - if (__ratelimit(&_rs)) { > - path = file_path(filp, pathname, sizeof(pathname)); > - if (IS_ERR(path)) > - path = "(unknown)"; > - pr_crit("Page cache invalidation failure on direct I/O. Possible data corruption due to collision with buffered I/O!\n"); > - pr_crit("File: %s PID: %d Comm: %.20s\n", path, current->pid, > - current->comm); > - } > -} > - > /* > * dio_complete() - called when all DIO BIO I/O has been completed > * > diff --git a/include/linux/fs.h b/include/linux/fs.h > index e0d909d35763..b4e4560d1c38 100644 > --- a/include/linux/fs.h > +++ b/include/linux/fs.h > @@ -3153,7 +3153,6 @@ enum { > }; > > void dio_end_io(struct bio *bio); > -void dio_warn_stale_pagecache(struct file *filp); > > ssize_t __blockdev_direct_IO(struct kiocb *iocb, struct inode *inode, > struct block_device *bdev, struct iov_iter *iter, > @@ -3198,6 +3197,11 @@ static inline void inode_dio_end(struct inode *inode) > wake_up_bit(&inode->i_state, __I_DIO_WAKEUP); > } > > +/* > + * Warn about a page cache invalidation failure diring a direct I/O write. > + */ > +void dio_warn_stale_pagecache(struct file *filp); > + > extern void inode_set_flags(struct inode *inode, unsigned int flags, > unsigned int mask); > > diff --git a/mm/filemap.c b/mm/filemap.c > index 288e38199068..189b8f318da2 100644 > --- a/mm/filemap.c > +++ b/mm/filemap.c > @@ -3161,6 +3161,27 @@ int pagecache_write_end(struct file *file, struct address_space *mapping, > } > EXPORT_SYMBOL(pagecache_write_end); > > +/* > + * Warn about a page cache invalidation failure during a direct I/O write. > + */ > +void dio_warn_stale_pagecache(struct file *filp) > +{ > + static DEFINE_RATELIMIT_STATE(_rs, 86400 * HZ, DEFAULT_RATELIMIT_BURST); > + char pathname[128]; > + struct inode *inode = file_inode(filp); > + char *path; > + > + errseq_set(&inode->i_mapping->wb_err, -EIO); > + if (__ratelimit(&_rs)) { > + path = file_path(filp, pathname, sizeof(pathname)); > + if (IS_ERR(path)) > + path = "(unknown)"; > + pr_crit("Page cache invalidation failure on direct I/O. Possible data corruption due to collision with buffered I/O!\n"); > + pr_crit("File: %s PID: %d Comm: %.20s\n", path, current->pid, > + current->comm); > + } > +} > + > ssize_t > generic_file_direct_write(struct kiocb *iocb, struct iov_iter *from) > { > -- Jan Kara <jack@xxxxxxxx> SUSE Labs, CR