Skip to content

Commit

Permalink
9p: Convert to using the netfs helper lib to do reads and caching
Browse files Browse the repository at this point in the history
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 #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 <[email protected]>
Reviewed-and-tested-by: Dominique Martinet <[email protected]>
cc: [email protected]
cc: [email protected]
Link: https://lore.kernel.org/r/[email protected]/ [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
  • Loading branch information
dhowells committed Oct 13, 2021
1 parent 0074790 commit 504058d
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 335 deletions.
1 change: 1 addition & 0 deletions fs/9p/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
config 9P_FS
tristate "Plan 9 Resource Sharing Support (9P2000)"
depends on INET && NET_9P
select NETFS_SUPPORT
help
If you say Y here, you will get experimental support for
Plan 9 resource sharing via the 9P2000 protocol.
Expand Down
137 changes: 0 additions & 137 deletions fs/9p/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,140 +199,3 @@ void v9fs_cache_inode_reset_cookie(struct inode *inode)

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);
}
99 changes: 4 additions & 95 deletions fs/9p/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@

#ifndef _9P_CACHE_H
#define _9P_CACHE_H
#ifdef CONFIG_9P_FSCACHE
#define FSCACHE_USE_OLD_IO_API

#define FSCACHE_USE_NEW_IO_API
#include <linux/fscache.h>
#include <linux/spinlock.h>

#ifdef CONFIG_9P_FSCACHE

extern struct fscache_netfs v9fs_cache_netfs;
extern const struct fscache_cookie_def v9fs_cache_session_index_def;
Expand All @@ -28,64 +29,6 @@ extern void v9fs_cache_inode_reset_cookie(struct inode *inode);
extern int __v9fs_cache_register(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 */

static inline void v9fs_cache_inode_get_cookie(struct inode *inode)
Expand All @@ -100,39 +43,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 /* _9P_CACHE_H */
9 changes: 9 additions & 0 deletions fs/9p/v9fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,15 @@ static inline struct v9fs_inode *V9FS_I(const struct inode *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);

struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *,
Expand Down
Loading

0 comments on commit 504058d

Please sign in to comment.