mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	9p: Convert to using the netfs helper lib to do reads and caching
Convert the 9p filesystem to use the netfs helper lib to handle readpage, readahead and write_begin, converting those into a common issue_op for the filesystem itself to handle. The netfs helper lib also handles reading from fscache if a cache is available, and interleaving reads from both sources. This change also switches from the old fscache I/O API to the new one, meaning that fscache no longer keeps track of netfs pages and instead does async DIO between the backing files and the 9p file pagecache. As a part of this change, the handling of PG_fscache changes. It now just means that the cache has a write I/O operation in progress on a page (PG_locked is used for a read I/O op). Note that this is a cut-down version of the fscache rewrite and does not change any of the cookie and cache coherency handling. Changes ======= ver #4: - Rebase on top of folios. - Don't use wait_on_page_bit_killable(). ver #3: - v9fs_req_issue_op() needs to terminate the subrequest. - v9fs_write_end() needs to call SetPageUptodate() a bit more often. - It's not CONFIG_{AFS,V9FS}_FSCACHE[1] - v9fs_init_rreq() should take a ref on the p9_fid and the cleanup should drop it [from Dominique Martinet]. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-and-tested-by: Dominique Martinet <asmadeus@codewreck.org> cc: v9fs-developer@lists.sourceforge.net cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/YUm+xucHxED+1MJp@codewreck.org/ [1] Link: https://lore.kernel.org/r/163162772646.438332.16323773205855053535.stgit@warthog.procyon.org.uk/ # rfc Link: https://lore.kernel.org/r/163189109885.2509237.7153668924503399173.stgit@warthog.procyon.org.uk/ # rfc v2 Link: https://lore.kernel.org/r/163363943896.1980952.1226527304649419689.stgit@warthog.procyon.org.uk/ # v3 Link: https://lore.kernel.org/r/163551662876.1877519.14706391695553204156.stgit@warthog.procyon.org.uk/ # v4 Link: https://lore.kernel.org/r/163584179557.4023316.11089762304657644342.stgit@warthog.procyon.org.uk # rebase on folio Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
This commit is contained in:
		
							parent
							
								
									0dc54bd4d6
								
							
						
					
					
						commit
						eb497943fa
					
				
					 6 changed files with 128 additions and 340 deletions
				
			
		| 
						 | 
					@ -2,6 +2,7 @@
 | 
				
			||||||
config 9P_FS
 | 
					config 9P_FS
 | 
				
			||||||
	tristate "Plan 9 Resource Sharing Support (9P2000)"
 | 
						tristate "Plan 9 Resource Sharing Support (9P2000)"
 | 
				
			||||||
	depends on INET && NET_9P
 | 
						depends on INET && NET_9P
 | 
				
			||||||
 | 
						select NETFS_SUPPORT
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  If you say Y here, you will get experimental support for
 | 
						  If you say Y here, you will get experimental support for
 | 
				
			||||||
	  Plan 9 resource sharing via the 9P2000 protocol.
 | 
						  Plan 9 resource sharing via the 9P2000 protocol.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										137
									
								
								fs/9p/cache.c
									
									
									
									
									
								
							
							
						
						
									
										137
									
								
								fs/9p/cache.c
									
									
									
									
									
								
							| 
						 | 
					@ -199,140 +199,3 @@ void v9fs_cache_inode_reset_cookie(struct inode *inode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_unlock(&v9inode->fscache_lock);
 | 
						mutex_unlock(&v9inode->fscache_lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
int __v9fs_fscache_release_page(struct page *page, gfp_t gfp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct inode *inode = page->mapping->host;
 | 
					 | 
				
			||||||
	struct v9fs_inode *v9inode = V9FS_I(inode);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	BUG_ON(!v9inode->fscache);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return fscache_maybe_release_page(v9inode->fscache, page, gfp);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void __v9fs_fscache_invalidate_page(struct page *page)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct inode *inode = page->mapping->host;
 | 
					 | 
				
			||||||
	struct v9fs_inode *v9inode = V9FS_I(inode);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	BUG_ON(!v9inode->fscache);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (PageFsCache(page)) {
 | 
					 | 
				
			||||||
		fscache_wait_on_page_write(v9inode->fscache, page);
 | 
					 | 
				
			||||||
		BUG_ON(!PageLocked(page));
 | 
					 | 
				
			||||||
		fscache_uncache_page(v9inode->fscache, page);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void v9fs_vfs_readpage_complete(struct page *page, void *data,
 | 
					 | 
				
			||||||
				       int error)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (!error)
 | 
					 | 
				
			||||||
		SetPageUptodate(page);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	unlock_page(page);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * __v9fs_readpage_from_fscache - read a page from cache
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Returns 0 if the pages are in cache and a BIO is submitted,
 | 
					 | 
				
			||||||
 * 1 if the pages are not in cache and -error otherwise.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int __v9fs_readpage_from_fscache(struct inode *inode, struct page *page)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
	const struct v9fs_inode *v9inode = V9FS_I(inode);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page);
 | 
					 | 
				
			||||||
	if (!v9inode->fscache)
 | 
					 | 
				
			||||||
		return -ENOBUFS;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = fscache_read_or_alloc_page(v9inode->fscache,
 | 
					 | 
				
			||||||
					 page,
 | 
					 | 
				
			||||||
					 v9fs_vfs_readpage_complete,
 | 
					 | 
				
			||||||
					 NULL,
 | 
					 | 
				
			||||||
					 GFP_KERNEL);
 | 
					 | 
				
			||||||
	switch (ret) {
 | 
					 | 
				
			||||||
	case -ENOBUFS:
 | 
					 | 
				
			||||||
	case -ENODATA:
 | 
					 | 
				
			||||||
		p9_debug(P9_DEBUG_FSC, "page/inode not in cache %d\n", ret);
 | 
					 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
	case 0:
 | 
					 | 
				
			||||||
		p9_debug(P9_DEBUG_FSC, "BIO submitted\n");
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		p9_debug(P9_DEBUG_FSC, "ret %d\n", ret);
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * __v9fs_readpages_from_fscache - read multiple pages from cache
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Returns 0 if the pages are in cache and a BIO is submitted,
 | 
					 | 
				
			||||||
 * 1 if the pages are not in cache and -error otherwise.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int __v9fs_readpages_from_fscache(struct inode *inode,
 | 
					 | 
				
			||||||
				  struct address_space *mapping,
 | 
					 | 
				
			||||||
				  struct list_head *pages,
 | 
					 | 
				
			||||||
				  unsigned *nr_pages)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
	const struct v9fs_inode *v9inode = V9FS_I(inode);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	p9_debug(P9_DEBUG_FSC, "inode %p pages %u\n", inode, *nr_pages);
 | 
					 | 
				
			||||||
	if (!v9inode->fscache)
 | 
					 | 
				
			||||||
		return -ENOBUFS;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = fscache_read_or_alloc_pages(v9inode->fscache,
 | 
					 | 
				
			||||||
					  mapping, pages, nr_pages,
 | 
					 | 
				
			||||||
					  v9fs_vfs_readpage_complete,
 | 
					 | 
				
			||||||
					  NULL,
 | 
					 | 
				
			||||||
					  mapping_gfp_mask(mapping));
 | 
					 | 
				
			||||||
	switch (ret) {
 | 
					 | 
				
			||||||
	case -ENOBUFS:
 | 
					 | 
				
			||||||
	case -ENODATA:
 | 
					 | 
				
			||||||
		p9_debug(P9_DEBUG_FSC, "pages/inodes not in cache %d\n", ret);
 | 
					 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
	case 0:
 | 
					 | 
				
			||||||
		BUG_ON(!list_empty(pages));
 | 
					 | 
				
			||||||
		BUG_ON(*nr_pages != 0);
 | 
					 | 
				
			||||||
		p9_debug(P9_DEBUG_FSC, "BIO submitted\n");
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		p9_debug(P9_DEBUG_FSC, "ret %d\n", ret);
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * __v9fs_readpage_to_fscache - write a page to the cache
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
	const struct v9fs_inode *v9inode = V9FS_I(inode);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page);
 | 
					 | 
				
			||||||
	ret = fscache_write_page(v9inode->fscache, page,
 | 
					 | 
				
			||||||
				 i_size_read(&v9inode->vfs_inode), GFP_KERNEL);
 | 
					 | 
				
			||||||
	p9_debug(P9_DEBUG_FSC, "ret =  %d\n", ret);
 | 
					 | 
				
			||||||
	if (ret != 0)
 | 
					 | 
				
			||||||
		v9fs_uncache_page(inode, page);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * wait for a page to complete writing to the cache
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void __v9fs_fscache_wait_on_page_write(struct inode *inode, struct page *page)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	const struct v9fs_inode *v9inode = V9FS_I(inode);
 | 
					 | 
				
			||||||
	p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page);
 | 
					 | 
				
			||||||
	if (PageFsCache(page))
 | 
					 | 
				
			||||||
		fscache_wait_on_page_write(v9inode->fscache, page);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,9 +7,10 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef _9P_CACHE_H
 | 
					#ifndef _9P_CACHE_H
 | 
				
			||||||
#define _9P_CACHE_H
 | 
					#define _9P_CACHE_H
 | 
				
			||||||
#ifdef CONFIG_9P_FSCACHE
 | 
					#define FSCACHE_USE_NEW_IO_API
 | 
				
			||||||
#include <linux/fscache.h>
 | 
					#include <linux/fscache.h>
 | 
				
			||||||
#include <linux/spinlock.h>
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_9P_FSCACHE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern struct fscache_netfs v9fs_cache_netfs;
 | 
					extern struct fscache_netfs v9fs_cache_netfs;
 | 
				
			||||||
extern const struct fscache_cookie_def v9fs_cache_session_index_def;
 | 
					extern const struct fscache_cookie_def v9fs_cache_session_index_def;
 | 
				
			||||||
| 
						 | 
					@ -27,64 +28,6 @@ extern void v9fs_cache_inode_reset_cookie(struct inode *inode);
 | 
				
			||||||
extern int __v9fs_cache_register(void);
 | 
					extern int __v9fs_cache_register(void);
 | 
				
			||||||
extern void __v9fs_cache_unregister(void);
 | 
					extern void __v9fs_cache_unregister(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int __v9fs_fscache_release_page(struct page *page, gfp_t gfp);
 | 
					 | 
				
			||||||
extern void __v9fs_fscache_invalidate_page(struct page *page);
 | 
					 | 
				
			||||||
extern int __v9fs_readpage_from_fscache(struct inode *inode,
 | 
					 | 
				
			||||||
					struct page *page);
 | 
					 | 
				
			||||||
extern int __v9fs_readpages_from_fscache(struct inode *inode,
 | 
					 | 
				
			||||||
					 struct address_space *mapping,
 | 
					 | 
				
			||||||
					 struct list_head *pages,
 | 
					 | 
				
			||||||
					 unsigned *nr_pages);
 | 
					 | 
				
			||||||
extern void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page);
 | 
					 | 
				
			||||||
extern void __v9fs_fscache_wait_on_page_write(struct inode *inode,
 | 
					 | 
				
			||||||
					      struct page *page);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline int v9fs_fscache_release_page(struct page *page,
 | 
					 | 
				
			||||||
					    gfp_t gfp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return __v9fs_fscache_release_page(page, gfp);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void v9fs_fscache_invalidate_page(struct page *page)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	__v9fs_fscache_invalidate_page(page);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline int v9fs_readpage_from_fscache(struct inode *inode,
 | 
					 | 
				
			||||||
					     struct page *page)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return __v9fs_readpage_from_fscache(inode, page);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline int v9fs_readpages_from_fscache(struct inode *inode,
 | 
					 | 
				
			||||||
					      struct address_space *mapping,
 | 
					 | 
				
			||||||
					      struct list_head *pages,
 | 
					 | 
				
			||||||
					      unsigned *nr_pages)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return __v9fs_readpages_from_fscache(inode, mapping, pages,
 | 
					 | 
				
			||||||
					     nr_pages);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void v9fs_readpage_to_fscache(struct inode *inode,
 | 
					 | 
				
			||||||
					    struct page *page)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (PageFsCache(page))
 | 
					 | 
				
			||||||
		__v9fs_readpage_to_fscache(inode, page);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void v9fs_uncache_page(struct inode *inode, struct page *page)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct v9fs_inode *v9inode = V9FS_I(inode);
 | 
					 | 
				
			||||||
	fscache_uncache_page(v9inode->fscache, page);
 | 
					 | 
				
			||||||
	BUG_ON(PageFsCache(page));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void v9fs_fscache_wait_on_page_write(struct inode *inode,
 | 
					 | 
				
			||||||
						   struct page *page)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return __v9fs_fscache_wait_on_page_write(inode, page);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#else /* CONFIG_9P_FSCACHE */
 | 
					#else /* CONFIG_9P_FSCACHE */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void v9fs_cache_inode_get_cookie(struct inode *inode)
 | 
					static inline void v9fs_cache_inode_get_cookie(struct inode *inode)
 | 
				
			||||||
| 
						 | 
					@ -99,39 +42,5 @@ static inline void v9fs_cache_inode_set_cookie(struct inode *inode, struct file
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int v9fs_fscache_release_page(struct page *page,
 | 
					 | 
				
			||||||
					    gfp_t gfp) {
 | 
					 | 
				
			||||||
	return 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void v9fs_fscache_invalidate_page(struct page *page) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline int v9fs_readpage_from_fscache(struct inode *inode,
 | 
					 | 
				
			||||||
					     struct page *page)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return -ENOBUFS;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline int v9fs_readpages_from_fscache(struct inode *inode,
 | 
					 | 
				
			||||||
					      struct address_space *mapping,
 | 
					 | 
				
			||||||
					      struct list_head *pages,
 | 
					 | 
				
			||||||
					      unsigned *nr_pages)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return -ENOBUFS;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void v9fs_readpage_to_fscache(struct inode *inode,
 | 
					 | 
				
			||||||
					    struct page *page)
 | 
					 | 
				
			||||||
{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void v9fs_uncache_page(struct inode *inode, struct page *page)
 | 
					 | 
				
			||||||
{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void v9fs_fscache_wait_on_page_write(struct inode *inode,
 | 
					 | 
				
			||||||
						   struct page *page)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /* CONFIG_9P_FSCACHE */
 | 
					#endif /* CONFIG_9P_FSCACHE */
 | 
				
			||||||
#endif /* _9P_CACHE_H */
 | 
					#endif /* _9P_CACHE_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -124,6 +124,15 @@ static inline struct v9fs_inode *V9FS_I(const struct inode *inode)
 | 
				
			||||||
	return container_of(inode, struct v9fs_inode, vfs_inode);
 | 
						return container_of(inode, struct v9fs_inode, vfs_inode);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct fscache_cookie *v9fs_inode_cookie(struct v9fs_inode *v9inode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifdef CONFIG_9P_FSCACHE
 | 
				
			||||||
 | 
						return v9inode->fscache;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int v9fs_show_options(struct seq_file *m, struct dentry *root);
 | 
					extern int v9fs_show_options(struct seq_file *m, struct dentry *root);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *,
 | 
					struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										207
									
								
								fs/9p/vfs_addr.c
									
									
									
									
									
								
							
							
						
						
									
										207
									
								
								fs/9p/vfs_addr.c
									
									
									
									
									
								
							| 
						 | 
					@ -19,7 +19,7 @@
 | 
				
			||||||
#include <linux/idr.h>
 | 
					#include <linux/idr.h>
 | 
				
			||||||
#include <linux/sched.h>
 | 
					#include <linux/sched.h>
 | 
				
			||||||
#include <linux/uio.h>
 | 
					#include <linux/uio.h>
 | 
				
			||||||
#include <linux/bvec.h>
 | 
					#include <linux/netfs.h>
 | 
				
			||||||
#include <net/9p/9p.h>
 | 
					#include <net/9p/9p.h>
 | 
				
			||||||
#include <net/9p/client.h>
 | 
					#include <net/9p/client.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,88 +29,97 @@
 | 
				
			||||||
#include "fid.h"
 | 
					#include "fid.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * v9fs_fid_readpage - read an entire page in from 9P
 | 
					 * v9fs_req_issue_op - Issue a read from 9P
 | 
				
			||||||
 * @data: Opaque pointer to the fid being read
 | 
					 * @subreq: The read to make
 | 
				
			||||||
 * @page: structure to page
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int v9fs_fid_readpage(void *data, struct page *page)
 | 
					static void v9fs_req_issue_op(struct netfs_read_subrequest *subreq)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct p9_fid *fid = data;
 | 
						struct netfs_read_request *rreq = subreq->rreq;
 | 
				
			||||||
	struct inode *inode = page->mapping->host;
 | 
						struct p9_fid *fid = rreq->netfs_priv;
 | 
				
			||||||
	struct bio_vec bvec = {.bv_page = page, .bv_len = PAGE_SIZE};
 | 
					 | 
				
			||||||
	struct iov_iter to;
 | 
						struct iov_iter to;
 | 
				
			||||||
	int retval, err;
 | 
						loff_t pos = subreq->start + subreq->transferred;
 | 
				
			||||||
 | 
						size_t len = subreq->len   - subreq->transferred;
 | 
				
			||||||
 | 
						int total, err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	p9_debug(P9_DEBUG_VFS, "\n");
 | 
						iov_iter_xarray(&to, READ, &rreq->mapping->i_pages, pos, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	BUG_ON(!PageLocked(page));
 | 
						total = p9_client_read(fid, pos, &to, &err);
 | 
				
			||||||
 | 
						netfs_subreq_terminated(subreq, err ?: total, false);
 | 
				
			||||||
	retval = v9fs_readpage_from_fscache(inode, page);
 | 
					 | 
				
			||||||
	if (retval == 0)
 | 
					 | 
				
			||||||
		return retval;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	iov_iter_bvec(&to, READ, &bvec, 1, PAGE_SIZE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	retval = p9_client_read(fid, page_offset(page), &to, &err);
 | 
					 | 
				
			||||||
	if (err) {
 | 
					 | 
				
			||||||
		v9fs_uncache_page(inode, page);
 | 
					 | 
				
			||||||
		retval = err;
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	zero_user(page, retval, PAGE_SIZE - retval);
 | 
					 | 
				
			||||||
	flush_dcache_page(page);
 | 
					 | 
				
			||||||
	SetPageUptodate(page);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	v9fs_readpage_to_fscache(inode, page);
 | 
					 | 
				
			||||||
	retval = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
done:
 | 
					 | 
				
			||||||
	unlock_page(page);
 | 
					 | 
				
			||||||
	return retval;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * v9fs_init_rreq - Initialise a read request
 | 
				
			||||||
 | 
					 * @rreq: The read request
 | 
				
			||||||
 | 
					 * @file: The file being read from
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void v9fs_init_rreq(struct netfs_read_request *rreq, struct file *file)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct p9_fid *fid = file->private_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						refcount_inc(&fid->count);
 | 
				
			||||||
 | 
						rreq->netfs_priv = fid;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * v9fs_req_cleanup - Cleanup request initialized by v9fs_init_rreq
 | 
				
			||||||
 | 
					 * @mapping: unused mapping of request to cleanup
 | 
				
			||||||
 | 
					 * @priv: private data to cleanup, a fid, guaranted non-null.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void v9fs_req_cleanup(struct address_space *mapping, void *priv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct p9_fid *fid = priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p9_client_clunk(fid);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * v9fs_is_cache_enabled - Determine if caching is enabled for an inode
 | 
				
			||||||
 | 
					 * @inode: The inode to check
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static bool v9fs_is_cache_enabled(struct inode *inode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct fscache_cookie *cookie = v9fs_inode_cookie(V9FS_I(inode));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return fscache_cookie_enabled(cookie) && !hlist_empty(&cookie->backing_objects);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * v9fs_begin_cache_operation - Begin a cache operation for a read
 | 
				
			||||||
 | 
					 * @rreq: The read request
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int v9fs_begin_cache_operation(struct netfs_read_request *rreq)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct fscache_cookie *cookie = v9fs_inode_cookie(V9FS_I(rreq->inode));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return fscache_begin_read_operation(rreq, cookie);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct netfs_read_request_ops v9fs_req_ops = {
 | 
				
			||||||
 | 
						.init_rreq		= v9fs_init_rreq,
 | 
				
			||||||
 | 
						.is_cache_enabled	= v9fs_is_cache_enabled,
 | 
				
			||||||
 | 
						.begin_cache_operation	= v9fs_begin_cache_operation,
 | 
				
			||||||
 | 
						.issue_op		= v9fs_req_issue_op,
 | 
				
			||||||
 | 
						.cleanup		= v9fs_req_cleanup,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * v9fs_vfs_readpage - read an entire page in from 9P
 | 
					 * v9fs_vfs_readpage - read an entire page in from 9P
 | 
				
			||||||
 *
 | 
					 * @file: file being read
 | 
				
			||||||
 * @filp: file being read
 | 
					 | 
				
			||||||
 * @page: structure to page
 | 
					 * @page: structure to page
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					static int v9fs_vfs_readpage(struct file *file, struct page *page)
 | 
				
			||||||
static int v9fs_vfs_readpage(struct file *filp, struct page *page)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return v9fs_fid_readpage(filp->private_data, page);
 | 
						return netfs_readpage(file, page, &v9fs_req_ops, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * v9fs_vfs_readpages - read a set of pages from 9P
 | 
					 * v9fs_vfs_readahead - read a set of pages from 9P
 | 
				
			||||||
 *
 | 
					 * @ractl: The readahead parameters
 | 
				
			||||||
 * @filp: file being read
 | 
					 | 
				
			||||||
 * @mapping: the address space
 | 
					 | 
				
			||||||
 * @pages: list of pages to read
 | 
					 | 
				
			||||||
 * @nr_pages: count of pages to read
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					static void v9fs_vfs_readahead(struct readahead_control *ractl)
 | 
				
			||||||
static int v9fs_vfs_readpages(struct file *filp, struct address_space *mapping,
 | 
					 | 
				
			||||||
			     struct list_head *pages, unsigned nr_pages)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret = 0;
 | 
						netfs_readahead(ractl, &v9fs_req_ops, NULL);
 | 
				
			||||||
	struct inode *inode;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	inode = mapping->host;
 | 
					 | 
				
			||||||
	p9_debug(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, filp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = v9fs_readpages_from_fscache(inode, mapping, pages, &nr_pages);
 | 
					 | 
				
			||||||
	if (ret == 0)
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = read_cache_pages(mapping, pages, v9fs_fid_readpage,
 | 
					 | 
				
			||||||
			filp->private_data);
 | 
					 | 
				
			||||||
	p9_debug(P9_DEBUG_VFS, "  = %d\n", ret);
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -125,7 +134,14 @@ static int v9fs_release_page(struct page *page, gfp_t gfp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (PagePrivate(page))
 | 
						if (PagePrivate(page))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	return v9fs_fscache_release_page(page, gfp);
 | 
					#ifdef CONFIG_9P_FSCACHE
 | 
				
			||||||
 | 
						if (PageFsCache(page)) {
 | 
				
			||||||
 | 
							if (!(gfp & __GFP_DIRECT_RECLAIM) || !(gfp & __GFP_FS))
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							wait_on_page_fscache(page);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -138,21 +154,16 @@ static int v9fs_release_page(struct page *page, gfp_t gfp)
 | 
				
			||||||
static void v9fs_invalidate_page(struct page *page, unsigned int offset,
 | 
					static void v9fs_invalidate_page(struct page *page, unsigned int offset,
 | 
				
			||||||
				 unsigned int length)
 | 
									 unsigned int length)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/*
 | 
						wait_on_page_fscache(page);
 | 
				
			||||||
	 * If called with zero offset, we should release
 | 
					 | 
				
			||||||
	 * the private state assocated with the page
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	if (offset == 0 && length == PAGE_SIZE)
 | 
					 | 
				
			||||||
		v9fs_fscache_invalidate_page(page);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int v9fs_vfs_writepage_locked(struct page *page)
 | 
					static int v9fs_vfs_writepage_locked(struct page *page)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct inode *inode = page->mapping->host;
 | 
						struct inode *inode = page->mapping->host;
 | 
				
			||||||
	struct v9fs_inode *v9inode = V9FS_I(inode);
 | 
						struct v9fs_inode *v9inode = V9FS_I(inode);
 | 
				
			||||||
 | 
						loff_t start = page_offset(page);
 | 
				
			||||||
	loff_t size = i_size_read(inode);
 | 
						loff_t size = i_size_read(inode);
 | 
				
			||||||
	struct iov_iter from;
 | 
						struct iov_iter from;
 | 
				
			||||||
	struct bio_vec bvec;
 | 
					 | 
				
			||||||
	int err, len;
 | 
						int err, len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (page->index == size >> PAGE_SHIFT)
 | 
						if (page->index == size >> PAGE_SHIFT)
 | 
				
			||||||
| 
						 | 
					@ -160,17 +171,14 @@ static int v9fs_vfs_writepage_locked(struct page *page)
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		len = PAGE_SIZE;
 | 
							len = PAGE_SIZE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bvec.bv_page = page;
 | 
						iov_iter_xarray(&from, WRITE, &page->mapping->i_pages, start, len);
 | 
				
			||||||
	bvec.bv_offset = 0;
 | 
					 | 
				
			||||||
	bvec.bv_len = len;
 | 
					 | 
				
			||||||
	iov_iter_bvec(&from, WRITE, &bvec, 1, len);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* We should have writeback_fid always set */
 | 
						/* We should have writeback_fid always set */
 | 
				
			||||||
	BUG_ON(!v9inode->writeback_fid);
 | 
						BUG_ON(!v9inode->writeback_fid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	set_page_writeback(page);
 | 
						set_page_writeback(page);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	p9_client_write(v9inode->writeback_fid, page_offset(page), &from, &err);
 | 
						p9_client_write(v9inode->writeback_fid, start, &from, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	end_page_writeback(page);
 | 
						end_page_writeback(page);
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
| 
						 | 
					@ -208,14 +216,13 @@ static int v9fs_vfs_writepage(struct page *page, struct writeback_control *wbc)
 | 
				
			||||||
static int v9fs_launder_page(struct page *page)
 | 
					static int v9fs_launder_page(struct page *page)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int retval;
 | 
						int retval;
 | 
				
			||||||
	struct inode *inode = page->mapping->host;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	v9fs_fscache_wait_on_page_write(inode, page);
 | 
					 | 
				
			||||||
	if (clear_page_dirty_for_io(page)) {
 | 
						if (clear_page_dirty_for_io(page)) {
 | 
				
			||||||
		retval = v9fs_vfs_writepage_locked(page);
 | 
							retval = v9fs_vfs_writepage_locked(page);
 | 
				
			||||||
		if (retval)
 | 
							if (retval)
 | 
				
			||||||
			return retval;
 | 
								return retval;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						wait_on_page_fscache(page);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -260,35 +267,24 @@ static int v9fs_write_begin(struct file *filp, struct address_space *mapping,
 | 
				
			||||||
			    loff_t pos, unsigned len, unsigned flags,
 | 
								    loff_t pos, unsigned len, unsigned flags,
 | 
				
			||||||
			    struct page **pagep, void **fsdata)
 | 
								    struct page **pagep, void **fsdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int retval = 0;
 | 
						int retval;
 | 
				
			||||||
	struct page *page;
 | 
						struct page *page;
 | 
				
			||||||
	struct v9fs_inode *v9inode;
 | 
						struct v9fs_inode *v9inode = V9FS_I(mapping->host);
 | 
				
			||||||
	pgoff_t index = pos >> PAGE_SHIFT;
 | 
					 | 
				
			||||||
	struct inode *inode = mapping->host;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	p9_debug(P9_DEBUG_VFS, "filp %p, mapping %p\n", filp, mapping);
 | 
						p9_debug(P9_DEBUG_VFS, "filp %p, mapping %p\n", filp, mapping);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	v9inode = V9FS_I(inode);
 | 
					 | 
				
			||||||
start:
 | 
					 | 
				
			||||||
	page = grab_cache_page_write_begin(mapping, index, flags);
 | 
					 | 
				
			||||||
	if (!page) {
 | 
					 | 
				
			||||||
		retval = -ENOMEM;
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	BUG_ON(!v9inode->writeback_fid);
 | 
						BUG_ON(!v9inode->writeback_fid);
 | 
				
			||||||
	if (PageUptodate(page))
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (len == PAGE_SIZE)
 | 
						/* Prefetch area to be written into the cache if we're caching this
 | 
				
			||||||
		goto out;
 | 
						 * file.  We need to do this before we get a lock on the page in case
 | 
				
			||||||
 | 
						 * there's more than one writer competing for the same cache block.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						retval = netfs_write_begin(filp, mapping, pos, len, flags, &page, fsdata,
 | 
				
			||||||
 | 
									   &v9fs_req_ops, NULL);
 | 
				
			||||||
 | 
						if (retval < 0)
 | 
				
			||||||
 | 
							return retval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = v9fs_fid_readpage(v9inode->writeback_fid, page);
 | 
						*pagep = find_subpage(page, pos / PAGE_SIZE);
 | 
				
			||||||
	put_page(page);
 | 
					 | 
				
			||||||
	if (!retval)
 | 
					 | 
				
			||||||
		goto start;
 | 
					 | 
				
			||||||
out:
 | 
					 | 
				
			||||||
	*pagep = page;
 | 
					 | 
				
			||||||
	return retval;
 | 
						return retval;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -305,10 +301,11 @@ static int v9fs_write_end(struct file *filp, struct address_space *mapping,
 | 
				
			||||||
		if (unlikely(copied < len)) {
 | 
							if (unlikely(copied < len)) {
 | 
				
			||||||
			copied = 0;
 | 
								copied = 0;
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		} else if (len == PAGE_SIZE) {
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		SetPageUptodate(page);
 | 
							SetPageUptodate(page);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	}
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * No need to use i_size_read() here, the i_size
 | 
						 * No need to use i_size_read() here, the i_size
 | 
				
			||||||
	 * cannot change under us because we hold the i_mutex.
 | 
						 * cannot change under us because we hold the i_mutex.
 | 
				
			||||||
| 
						 | 
					@ -328,7 +325,7 @@ static int v9fs_write_end(struct file *filp, struct address_space *mapping,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const struct address_space_operations v9fs_addr_operations = {
 | 
					const struct address_space_operations v9fs_addr_operations = {
 | 
				
			||||||
	.readpage = v9fs_vfs_readpage,
 | 
						.readpage = v9fs_vfs_readpage,
 | 
				
			||||||
	.readpages = v9fs_vfs_readpages,
 | 
						.readahead = v9fs_vfs_readahead,
 | 
				
			||||||
	.set_page_dirty = __set_page_dirty_nobuffers,
 | 
						.set_page_dirty = __set_page_dirty_nobuffers,
 | 
				
			||||||
	.writepage = v9fs_vfs_writepage,
 | 
						.writepage = v9fs_vfs_writepage,
 | 
				
			||||||
	.write_begin = v9fs_write_begin,
 | 
						.write_begin = v9fs_write_begin,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -537,14 +537,23 @@ v9fs_vm_page_mkwrite(struct vm_fault *vmf)
 | 
				
			||||||
	p9_debug(P9_DEBUG_VFS, "page %p fid %lx\n",
 | 
						p9_debug(P9_DEBUG_VFS, "page %p fid %lx\n",
 | 
				
			||||||
		 page, (unsigned long)filp->private_data);
 | 
							 page, (unsigned long)filp->private_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v9inode = V9FS_I(inode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Wait for the page to be written to the cache before we allow it to
 | 
				
			||||||
 | 
						 * be modified.  We then assume the entire page will need writing back.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					#ifdef CONFIG_9P_FSCACHE
 | 
				
			||||||
 | 
						if (PageFsCache(page) &&
 | 
				
			||||||
 | 
						    wait_on_page_fscache_killable(page) < 0)
 | 
				
			||||||
 | 
							return VM_FAULT_RETRY;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Update file times before taking page lock */
 | 
						/* Update file times before taking page lock */
 | 
				
			||||||
	file_update_time(filp);
 | 
						file_update_time(filp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	v9inode = V9FS_I(inode);
 | 
					 | 
				
			||||||
	/* make sure the cache has finished storing the page */
 | 
					 | 
				
			||||||
	v9fs_fscache_wait_on_page_write(inode, page);
 | 
					 | 
				
			||||||
	BUG_ON(!v9inode->writeback_fid);
 | 
						BUG_ON(!v9inode->writeback_fid);
 | 
				
			||||||
	lock_page(page);
 | 
						if (lock_page_killable(page) < 0)
 | 
				
			||||||
 | 
							return VM_FAULT_RETRY;
 | 
				
			||||||
	if (page->mapping != inode->i_mapping)
 | 
						if (page->mapping != inode->i_mapping)
 | 
				
			||||||
		goto out_unlock;
 | 
							goto out_unlock;
 | 
				
			||||||
	wait_for_stable_page(page);
 | 
						wait_for_stable_page(page);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue