Skip to content

Commit

Permalink
fs/direct-io.c: keep dio_warn_stale_pagecache() when CONFIG_BLOCK=n
Browse files Browse the repository at this point in the history
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 5a9d929 ("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.

Link: http://lkml.kernel.org/r/157270038074.4812.7980855544557488880.stgit@buzz
Signed-off-by: Konstantin Khlebnikov <[email protected]>
Reviewed-by: Andrew Morton <[email protected]>
Reviewed-by: Jan Kara <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Alexander Viro <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
koct9i authored and torvalds committed Dec 1, 2019
1 parent 80c1fe9 commit a92853b
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 22 deletions.
21 changes: 0 additions & 21 deletions fs/direct-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down
6 changes: 5 additions & 1 deletion include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -3149,7 +3149,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,
Expand Down Expand Up @@ -3194,6 +3193,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);

Expand Down
21 changes: 21 additions & 0 deletions mm/filemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down

0 comments on commit a92853b

Please sign in to comment.