Skip to content
Permalink
Browse files
netfs: Add a netfs inode context
Add a netfs_i_context struct that should be included in the network
filesystem's own inode struct wrapper, directly after the VFS's inode
struct, e.g.:

	struct my_inode {
		struct {
			struct inode		vfs_inode;
			struct netfs_i_context	netfs_ctx;
		};
	};

The netfs_i_context struct contains two fields for the network filesystem
to use:

	struct netfs_i_context {
		...
		struct fscache_cookie	*cache;
		unsigned long		flags;
	#define NETFS_ICTX_NEW_CONTENT	0
	};

There's a pointer to the cache cookie and a flag to indicate that the
content in the file is locally generated and entirely new (ie. the file was
just created locally or was truncated to nothing).

Three functions are provided to help with this:

 (1) void netfs_i_context_init(struct inode *inode,
			       const struct netfs_request_ops *ops);

     Initialise the netfs context and set the operations.

 (2) struct netfs_i_context *netfs_i_context(struct inode *inode);

     Find the netfs context from the VFS inode.

 (3) struct inode *netfs_inode(struct netfs_i_context *ctx);

     Find the VFS inode from the netfs context.

Signed-off-by: David Howells <dhowells@redhat.com>
  • Loading branch information
dhowells committed Jan 20, 2022
1 parent 44b3b1b commit 5dcff5ed720e69e0ffec5ade8d8a0df96d0b0369
Show file tree
Hide file tree
Showing 25 changed files with 287 additions and 272 deletions.
@@ -49,28 +49,26 @@ int v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses,

void v9fs_cache_inode_get_cookie(struct inode *inode)
{
struct v9fs_inode *v9inode;
struct v9fs_inode *v9inode = V9FS_I(inode);
struct v9fs_session_info *v9ses;
__le32 version;
__le64 path;

if (!S_ISREG(inode->i_mode))
return;

v9inode = V9FS_I(inode);
if (WARN_ON(v9inode->fscache))
if (WARN_ON(v9fs_inode_cookie(v9inode)))
return;

version = cpu_to_le32(v9inode->qid.version);
path = cpu_to_le64(v9inode->qid.path);
v9ses = v9fs_inode2v9ses(inode);
v9inode->fscache =
v9inode->netfs_ctx.cache =
fscache_acquire_cookie(v9fs_session_cache(v9ses),
0,
&path, sizeof(path),
&version, sizeof(version),
i_size_read(&v9inode->vfs_inode));

p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n",
inode, v9inode->fscache);
inode, v9fs_inode_cookie(v9inode));
}
@@ -623,9 +623,7 @@ static void v9fs_sysfs_cleanup(void)
static void v9fs_inode_init_once(void *foo)
{
struct v9fs_inode *v9inode = (struct v9fs_inode *)foo;
#ifdef CONFIG_9P_FSCACHE
v9inode->fscache = NULL;
#endif

memset(&v9inode->qid, 0, sizeof(v9inode->qid));
inode_init_once(&v9inode->vfs_inode);
}
@@ -9,6 +9,7 @@
#define FS_9P_V9FS_H

#include <linux/backing-dev.h>
#include <linux/netfs.h>

/**
* enum p9_session_flags - option flags for each 9P session
@@ -108,14 +109,14 @@ struct v9fs_session_info {
#define V9FS_INO_INVALID_ATTR 0x01

struct v9fs_inode {
#ifdef CONFIG_9P_FSCACHE
struct fscache_cookie *fscache;
#endif
struct {
struct inode vfs_inode; /* the VFS's inode record */
struct netfs_i_context netfs_ctx; /* Netfslib context */
};
struct p9_qid qid;
unsigned int cache_validity;
struct p9_fid *writeback_fid;
struct mutex v_mutex;
struct inode vfs_inode;
};

static inline struct v9fs_inode *V9FS_I(const struct inode *inode)
@@ -126,7 +127,7 @@ static inline struct v9fs_inode *V9FS_I(const struct inode *inode)
static inline struct fscache_cookie *v9fs_inode_cookie(struct v9fs_inode *v9inode)
{
#ifdef CONFIG_9P_FSCACHE
return v9inode->fscache;
return netfs_i_cookie(&v9inode->vfs_inode);
#else
return NULL;
#endif
@@ -163,6 +164,7 @@ extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses,
extern const struct inode_operations v9fs_dir_inode_operations_dotl;
extern const struct inode_operations v9fs_file_inode_operations_dotl;
extern const struct inode_operations v9fs_symlink_inode_operations_dotl;
extern const struct netfs_request_ops v9fs_req_ops;
extern struct inode *v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses,
struct p9_fid *fid,
struct super_block *sb, int new);
@@ -71,17 +71,6 @@ static void v9fs_req_cleanup(struct address_space *mapping, void *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) && cookie->cache_priv;
}

/**
* v9fs_begin_cache_operation - Begin a cache operation for a read
* @rreq: The read request
@@ -97,36 +86,13 @@ static int v9fs_begin_cache_operation(struct netfs_read_request *rreq)
#endif
}

static const struct netfs_read_request_ops v9fs_req_ops = {
const struct netfs_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
* @file: file being read
* @page: structure to page
*
*/
static int v9fs_vfs_readpage(struct file *file, struct page *page)
{
struct folio *folio = page_folio(page);

return netfs_readpage(file, folio, &v9fs_req_ops, NULL);
}

/**
* v9fs_vfs_readahead - read a set of pages from 9P
* @ractl: The readahead parameters
*/
static void v9fs_vfs_readahead(struct readahead_control *ractl)
{
netfs_readahead(ractl, &v9fs_req_ops, NULL);
}

/**
* v9fs_release_page - release the private state associated with a page
* @page: The page to be released
@@ -320,8 +286,7 @@ static int v9fs_write_begin(struct file *filp, struct address_space *mapping,
* 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, &folio, fsdata,
&v9fs_req_ops, NULL);
retval = netfs_write_begin(filp, mapping, pos, len, flags, &folio, fsdata);
if (retval < 0)
return retval;

@@ -382,8 +347,8 @@ static int v9fs_set_page_dirty(struct page *page)
#endif

const struct address_space_operations v9fs_addr_operations = {
.readpage = v9fs_vfs_readpage,
.readahead = v9fs_vfs_readahead,
.readpage = netfs_readpage,
.readahead = netfs_readahead,
.set_page_dirty = v9fs_set_page_dirty,
.writepage = v9fs_vfs_writepage,
.write_begin = v9fs_write_begin,
@@ -231,9 +231,6 @@ struct inode *v9fs_alloc_inode(struct super_block *sb)
v9inode = kmem_cache_alloc(v9fs_inode_cache, GFP_KERNEL);
if (!v9inode)
return NULL;
#ifdef CONFIG_9P_FSCACHE
v9inode->fscache = NULL;
#endif
v9inode->writeback_fid = NULL;
v9inode->cache_validity = 0;
mutex_init(&v9inode->v_mutex);
@@ -250,6 +247,17 @@ void v9fs_free_inode(struct inode *inode)
kmem_cache_free(v9fs_inode_cache, V9FS_I(inode));
}

/*
* Set parameters for the netfs library
*/
static void v9fs_set_netfs_context(struct inode *inode)
{
struct netfs_i_context *ctx = netfs_i_context(inode);

netfs_i_context_init(inode, &v9fs_req_ops);
ctx->wsize = 1024 * 1024;
}

int v9fs_init_inode(struct v9fs_session_info *v9ses,
struct inode *inode, umode_t mode, dev_t rdev)
{
@@ -338,6 +346,8 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses,
err = -EINVAL;
goto error;
}

v9fs_set_netfs_context(inode);
error:
return err;

@@ -75,7 +75,7 @@ void __afs_break_callback(struct afs_vnode *vnode, enum afs_cb_break_reason reas
{
_enter("");

clear_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
clear_bit(NETFS_ICTX_NEW_CONTENT, &netfs_i_context(&vnode->vfs_inode)->flags);
if (test_and_clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) {
vnode->cb_break++;
vnode->cb_v_break = vnode->volume->cb_v_break;
@@ -1279,7 +1279,7 @@ static void afs_vnode_new_inode(struct afs_operation *op)
}

vnode = AFS_FS_I(inode);
set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
set_bit(NETFS_ICTX_NEW_CONTENT, &netfs_i_context(&vnode->vfs_inode)->flags);
if (!op->error)
afs_cache_permit(vnode, op->key, vnode->cb_break, &vp->scb);
d_instantiate(op->dentry, inode);
@@ -76,6 +76,7 @@ struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root)
/* there shouldn't be an existing inode */
BUG_ON(!(inode->i_state & I_NEW));

netfs_i_context_init(inode, NULL);
inode->i_size = 0;
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
if (root) {
@@ -19,13 +19,11 @@
#include "internal.h"

static int afs_file_mmap(struct file *file, struct vm_area_struct *vma);
static int afs_readpage(struct file *file, struct page *page);
static int afs_symlink_readpage(struct file *file, struct page *page);
static void afs_invalidatepage(struct page *page, unsigned int offset,
unsigned int length);
static int afs_releasepage(struct page *page, gfp_t gfp_flags);

static void afs_readahead(struct readahead_control *ractl);
static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter);
static void afs_vm_open(struct vm_area_struct *area);
static void afs_vm_close(struct vm_area_struct *area);
@@ -52,8 +50,8 @@ const struct inode_operations afs_file_inode_operations = {
};

const struct address_space_operations afs_file_aops = {
.readpage = afs_readpage,
.readahead = afs_readahead,
.readpage = netfs_readpage,
.readahead = netfs_readahead,
.set_page_dirty = afs_set_page_dirty,
.launder_page = afs_launder_page,
.releasepage = afs_releasepage,
@@ -158,7 +156,8 @@ int afs_open(struct inode *inode, struct file *file)
}

if (file->f_flags & O_TRUNC)
set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
set_bit(NETFS_ICTX_NEW_CONTENT,
&netfs_i_context(&vnode->vfs_inode)->flags);

fscache_use_cookie(afs_vnode_cache(vnode), file->f_mode & FMODE_WRITE);

@@ -360,13 +359,6 @@ static void afs_init_rreq(struct netfs_read_request *rreq, struct file *file)
rreq->netfs_priv = key_get(afs_file_key(file));
}

static bool afs_is_cache_enabled(struct inode *inode)
{
struct fscache_cookie *cookie = afs_vnode_cache(AFS_FS_I(inode));

return fscache_cookie_enabled(cookie) && cookie->cache_priv;
}

static int afs_begin_cache_operation(struct netfs_read_request *rreq)
{
#ifdef CONFIG_AFS_FSCACHE
@@ -392,27 +384,14 @@ static void afs_priv_cleanup(struct address_space *mapping, void *netfs_priv)
key_put(netfs_priv);
}

const struct netfs_read_request_ops afs_req_ops = {
const struct netfs_request_ops afs_req_ops = {
.init_rreq = afs_init_rreq,
.is_cache_enabled = afs_is_cache_enabled,
.begin_cache_operation = afs_begin_cache_operation,
.check_write_begin = afs_check_write_begin,
.issue_op = afs_req_issue_op,
.cleanup = afs_priv_cleanup,
};

static int afs_readpage(struct file *file, struct page *page)
{
struct folio *folio = page_folio(page);

return netfs_readpage(file, folio, &afs_req_ops, NULL);
}

static void afs_readahead(struct readahead_control *ractl)
{
netfs_readahead(ractl, &afs_req_ops, NULL);
}

int afs_write_inode(struct inode *inode, struct writeback_control *wbc)
{
fscache_unpin_writeback(wbc, afs_vnode_cache(AFS_FS_I(inode)));
@@ -53,6 +53,19 @@ static noinline void dump_vnode(struct afs_vnode *vnode, struct afs_vnode *paren
dump_stack();
}

/*
* Set parameters for the netfs library
*/
static void afs_set_netfs_context(struct afs_vnode *vnode)
{
struct netfs_i_context *ctx = netfs_i_context(&vnode->vfs_inode);

netfs_i_context_init(&vnode->vfs_inode, &afs_req_ops);
ctx->wsize = 16*1024*1024; // 0x33333;
//ctx->min_bshift = ilog2(0x10000);
//ctx->obj_bshift = ilog2(0x40000);
}

/*
* Initialise an inode from the vnode status.
*/
@@ -128,6 +141,7 @@ static int afs_inode_init_from_status(struct afs_operation *op,
}

afs_set_i_size(vnode, status->size);
afs_set_netfs_context(vnode);

vnode->invalid_before = status->data_version;
inode_set_iversion_raw(&vnode->vfs_inode, status->data_version);
@@ -420,7 +434,7 @@ static void afs_get_inode_cache(struct afs_vnode *vnode)
struct afs_vnode_cache_aux aux;

if (vnode->status.type != AFS_FTYPE_FILE) {
vnode->cache = NULL;
vnode->netfs_ctx.cache = NULL;
return;
}

@@ -430,12 +444,14 @@ static void afs_get_inode_cache(struct afs_vnode *vnode)
key.vnode_id_ext[1] = htonl(vnode->fid.vnode_hi);
afs_set_cache_aux(vnode, &aux);

vnode->cache = fscache_acquire_cookie(
vnode->volume->cache,
vnode->status.type == AFS_FTYPE_FILE ? 0 : FSCACHE_ADV_SINGLE_CHUNK,
&key, sizeof(key),
&aux, sizeof(aux),
vnode->status.size);
afs_vnode_set_cache(vnode,
fscache_acquire_cookie(
vnode->volume->cache,
vnode->status.type == AFS_FTYPE_FILE ?
0 : FSCACHE_ADV_SINGLE_CHUNK,
&key, sizeof(key),
&aux, sizeof(aux),
vnode->status.size));
#endif
}

@@ -528,6 +544,7 @@ struct inode *afs_root_iget(struct super_block *sb, struct key *key)

vnode = AFS_FS_I(inode);
vnode->cb_v_break = as->volume->cb_v_break,
afs_set_netfs_context(vnode);

op = afs_alloc_operation(key, as->volume);
if (IS_ERR(op)) {
@@ -786,11 +803,8 @@ void afs_evict_inode(struct inode *inode)
afs_put_wb_key(wbk);
}

#ifdef CONFIG_AFS_FSCACHE
fscache_relinquish_cookie(vnode->cache,
fscache_relinquish_cookie(afs_vnode_cache(vnode),
test_bit(AFS_VNODE_DELETED, &vnode->flags));
vnode->cache = NULL;
#endif

afs_prune_wb_keys(vnode);
afs_put_permits(rcu_access_pointer(vnode->permit_cache));

0 comments on commit 5dcff5e

Please sign in to comment.