diff options
Diffstat (limited to 'fs/btrfs/file.c')
| -rw-r--r-- | fs/btrfs/file.c | 23 | 
1 files changed, 22 insertions, 1 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index ee34497500e1..7ff577005d0f 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -16,6 +16,7 @@  #include <linux/btrfs.h>  #include <linux/uio.h>  #include <linux/iversion.h> +#include <linux/fsverity.h>  #include "ctree.h"  #include "disk-io.h"  #include "transaction.h" @@ -1340,7 +1341,18 @@ static int prepare_uptodate_page(struct inode *inode,  			unlock_page(page);  			return -EIO;  		} -		if (page->mapping != inode->i_mapping) { + +		/* +		 * Since btrfs_readpage() will unlock the page before it +		 * returns, there is a window where btrfs_releasepage() can be +		 * called to release the page.  Here we check both inode +		 * mapping and PagePrivate() to make sure the page was not +		 * released. +		 * +		 * The private flag check is essential for subpage as we need +		 * to store extra bitmap using page->private. +		 */ +		if (page->mapping != inode->i_mapping || !PagePrivate(page)) {  			unlock_page(page);  			return -EAGAIN;  		} @@ -3604,7 +3616,13 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int whence)  static int btrfs_file_open(struct inode *inode, struct file *filp)  { +	int ret; +  	filp->f_mode |= FMODE_NOWAIT | FMODE_BUF_RASYNC; + +	ret = fsverity_file_open(inode, filp); +	if (ret) +		return ret;  	return generic_file_open(inode, filp);  } @@ -3633,6 +3651,9 @@ static ssize_t btrfs_direct_read(struct kiocb *iocb, struct iov_iter *to)  	struct inode *inode = file_inode(iocb->ki_filp);  	ssize_t ret; +	if (fsverity_active(inode)) +		return 0; +  	if (check_direct_read(btrfs_sb(inode->i_sb), to, iocb->ki_pos))  		return 0;  | 
