Skip to content

Commit bc899ee

Browse files
committed
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 { /* These must be contiguous */ struct inode vfs_inode; struct netfs_i_context netfs_ctx; }; }; The netfs_i_context struct so far contains a single field for the network filesystem to use - the cache cookie: struct netfs_i_context { ... struct fscache_cookie *cache; }; 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. Changes ======= ver #4) - Fix netfs_is_cache_enabled() to check cookie->cache_priv to see if a cache is present[3]. - Fix netfs_skip_folio_read() to zero out all of the page, not just some of it[3]. ver #3) - Split out the bit to move ceph cap-getting on readahead into ceph_init_request()[1]. - Stick in a comment to the netfs inode structs indicating the contiguity requirements[2]. ver #2) - Adjust documentation to match. - Use "#if IS_ENABLED()" in netfs_i_cookie(), not "#ifdef". - Move the cap check from ceph_readahead() to ceph_init_request() to be called from netfslib. - Remove ceph_readahead() and use netfs_readahead() directly instead. Signed-off-by: David Howells <[email protected]> Acked-by: Jeff Layton <[email protected]> cc: [email protected] Link: https://lore.kernel.org/r/[email protected]/ [1] Link: https://lore.kernel.org/r/[email protected]/ [2] Link: https://lore.kernel.org/r/[email protected]/ [3] Link: https://lore.kernel.org/r/164622984545.3564931.15691742939278418580.stgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678213320.1200972.16807551936267647470.stgit@warthog.procyon.org.uk/ # v2 Link: https://lore.kernel.org/r/164692909854.2099075.9535537286264248057.stgit@warthog.procyon.org.uk/ # v3 Link: https://lore.kernel.org/r/[email protected]/ # v4
1 parent a5c9dc4 commit bc899ee

25 files changed

+318
-278
lines changed

Documentation/filesystems/netfs_library.rst

+72-29
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Network Filesystem Helper Library
77
.. Contents:
88
99
- Overview.
10+
- Per-inode context.
11+
- Inode context helper functions.
1012
- Buffered read helpers.
1113
- Read helper functions.
1214
- Read helper structures.
@@ -28,6 +30,69 @@ Note that the library module doesn't link against local caching directly, so
2830
access must be provided by the netfs.
2931

3032

33+
Per-Inode Context
34+
=================
35+
36+
The network filesystem helper library needs a place to store a bit of state for
37+
its use on each netfs inode it is helping to manage. To this end, a context
38+
structure is defined::
39+
40+
struct netfs_i_context {
41+
const struct netfs_request_ops *ops;
42+
struct fscache_cookie *cache;
43+
};
44+
45+
A network filesystem that wants to use netfs lib must place one of these
46+
directly after the VFS ``struct inode`` it allocates, usually as part of its
47+
own struct. This can be done in a way similar to the following::
48+
49+
struct my_inode {
50+
struct {
51+
/* These must be contiguous */
52+
struct inode vfs_inode;
53+
struct netfs_i_context netfs_ctx;
54+
};
55+
...
56+
};
57+
58+
This allows netfslib to find its state by simple offset from the inode pointer,
59+
thereby allowing the netfslib helper functions to be pointed to directly by the
60+
VFS/VM operation tables.
61+
62+
The structure contains the following fields:
63+
64+
* ``ops``
65+
66+
The set of operations provided by the network filesystem to netfslib.
67+
68+
* ``cache``
69+
70+
Local caching cookie, or NULL if no caching is enabled. This field does not
71+
exist if fscache is disabled.
72+
73+
74+
Inode Context Helper Functions
75+
------------------------------
76+
77+
To help deal with the per-inode context, a number helper functions are
78+
provided. Firstly, a function to perform basic initialisation on a context and
79+
set the operations table pointer::
80+
81+
void netfs_i_context_init(struct inode *inode,
82+
const struct netfs_request_ops *ops);
83+
84+
then two functions to cast between the VFS inode structure and the netfs
85+
context::
86+
87+
struct netfs_i_context *netfs_i_context(struct inode *inode);
88+
struct inode *netfs_inode(struct netfs_i_context *ctx);
89+
90+
and finally, a function to get the cache cookie pointer from the context
91+
attached to an inode (or NULL if fscache is disabled)::
92+
93+
struct fscache_cookie *netfs_i_cookie(struct inode *inode);
94+
95+
3196
Buffered Read Helpers
3297
=====================
3398

@@ -70,38 +135,22 @@ Read Helper Functions
70135

71136
Three read helpers are provided::
72137

73-
void netfs_readahead(struct readahead_control *ractl,
74-
const struct netfs_request_ops *ops,
75-
void *netfs_priv);
138+
void netfs_readahead(struct readahead_control *ractl);
76139
int netfs_readpage(struct file *file,
77-
struct folio *folio,
78-
const struct netfs_request_ops *ops,
79-
void *netfs_priv);
140+
struct page *page);
80141
int netfs_write_begin(struct file *file,
81142
struct address_space *mapping,
82143
loff_t pos,
83144
unsigned int len,
84145
unsigned int flags,
85146
struct folio **_folio,
86-
void **_fsdata,
87-
const struct netfs_request_ops *ops,
88-
void *netfs_priv);
89-
90-
Each corresponds to a VM operation, with the addition of a couple of parameters
91-
for the use of the read helpers:
147+
void **_fsdata);
92148

93-
* ``ops``
94-
95-
A table of operations through which the helpers can talk to the filesystem.
96-
97-
* ``netfs_priv``
149+
Each corresponds to a VM address space operation. These operations use the
150+
state in the per-inode context.
98151

99-
Filesystem private data (can be NULL).
100-
101-
Both of these values will be stored into the read request structure.
102-
103-
For ->readahead() and ->readpage(), the network filesystem should just jump
104-
into the corresponding read helper; whereas for ->write_begin(), it may be a
152+
For ->readahead() and ->readpage(), the network filesystem just point directly
153+
at the corresponding read helper; whereas for ->write_begin(), it may be a
105154
little more complicated as the network filesystem might want to flush
106155
conflicting writes or track dirty data and needs to put the acquired folio if
107156
an error occurs after calling the helper.
@@ -246,7 +295,6 @@ through which it can issue requests and negotiate::
246295

247296
struct netfs_request_ops {
248297
void (*init_request)(struct netfs_io_request *rreq, struct file *file);
249-
bool (*is_cache_enabled)(struct inode *inode);
250298
int (*begin_cache_operation)(struct netfs_io_request *rreq);
251299
void (*expand_readahead)(struct netfs_io_request *rreq);
252300
bool (*clamp_length)(struct netfs_io_subrequest *subreq);
@@ -265,11 +313,6 @@ The operations are as follows:
265313
[Optional] This is called to initialise the request structure. It is given
266314
the file for reference and can modify the ->netfs_priv value.
267315

268-
* ``is_cache_enabled()``
269-
270-
[Required] This is called by netfs_write_begin() to ask if the file is being
271-
cached. It should return true if it is being cached and false otherwise.
272-
273316
* ``begin_cache_operation()``
274317

275318
[Optional] This is called to ask the network filesystem to call into the

fs/9p/cache.c

+4-6
Original file line numberDiff line numberDiff line change
@@ -49,28 +49,26 @@ int v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses,
4949

5050
void v9fs_cache_inode_get_cookie(struct inode *inode)
5151
{
52-
struct v9fs_inode *v9inode;
52+
struct v9fs_inode *v9inode = V9FS_I(inode);
5353
struct v9fs_session_info *v9ses;
5454
__le32 version;
5555
__le64 path;
5656

5757
if (!S_ISREG(inode->i_mode))
5858
return;
59-
60-
v9inode = V9FS_I(inode);
61-
if (WARN_ON(v9inode->fscache))
59+
if (WARN_ON(v9fs_inode_cookie(v9inode)))
6260
return;
6361

6462
version = cpu_to_le32(v9inode->qid.version);
6563
path = cpu_to_le64(v9inode->qid.path);
6664
v9ses = v9fs_inode2v9ses(inode);
67-
v9inode->fscache =
65+
v9inode->netfs_ctx.cache =
6866
fscache_acquire_cookie(v9fs_session_cache(v9ses),
6967
0,
7068
&path, sizeof(path),
7169
&version, sizeof(version),
7270
i_size_read(&v9inode->vfs_inode));
7371

7472
p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n",
75-
inode, v9inode->fscache);
73+
inode, v9fs_inode_cookie(v9inode));
7674
}

fs/9p/v9fs.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -623,9 +623,7 @@ static void v9fs_sysfs_cleanup(void)
623623
static void v9fs_inode_init_once(void *foo)
624624
{
625625
struct v9fs_inode *v9inode = (struct v9fs_inode *)foo;
626-
#ifdef CONFIG_9P_FSCACHE
627-
v9inode->fscache = NULL;
628-
#endif
626+
629627
memset(&v9inode->qid, 0, sizeof(v9inode->qid));
630628
inode_init_once(&v9inode->vfs_inode);
631629
}

fs/9p/v9fs.h

+8-5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#define FS_9P_V9FS_H
1010

1111
#include <linux/backing-dev.h>
12+
#include <linux/netfs.h>
1213

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

110111
struct v9fs_inode {
111-
#ifdef CONFIG_9P_FSCACHE
112-
struct fscache_cookie *fscache;
113-
#endif
112+
struct {
113+
/* These must be contiguous */
114+
struct inode vfs_inode; /* the VFS's inode record */
115+
struct netfs_i_context netfs_ctx; /* Netfslib context */
116+
};
114117
struct p9_qid qid;
115118
unsigned int cache_validity;
116119
struct p9_fid *writeback_fid;
117120
struct mutex v_mutex;
118-
struct inode vfs_inode;
119121
};
120122

121123
static inline struct v9fs_inode *V9FS_I(const struct inode *inode)
@@ -126,7 +128,7 @@ static inline struct v9fs_inode *V9FS_I(const struct inode *inode)
126128
static inline struct fscache_cookie *v9fs_inode_cookie(struct v9fs_inode *v9inode)
127129
{
128130
#ifdef CONFIG_9P_FSCACHE
129-
return v9inode->fscache;
131+
return netfs_i_cookie(&v9inode->vfs_inode);
130132
#else
131133
return NULL;
132134
#endif
@@ -163,6 +165,7 @@ extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses,
163165
extern const struct inode_operations v9fs_dir_inode_operations_dotl;
164166
extern const struct inode_operations v9fs_file_inode_operations_dotl;
165167
extern const struct inode_operations v9fs_symlink_inode_operations_dotl;
168+
extern const struct netfs_request_ops v9fs_req_ops;
166169
extern struct inode *v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses,
167170
struct p9_fid *fid,
168171
struct super_block *sb, int new);

fs/9p/vfs_addr.c

+4-39
Original file line numberDiff line numberDiff line change
@@ -77,17 +77,6 @@ static void v9fs_req_cleanup(struct address_space *mapping, void *priv)
7777
p9_client_clunk(fid);
7878
}
7979

80-
/**
81-
* v9fs_is_cache_enabled - Determine if caching is enabled for an inode
82-
* @inode: The inode to check
83-
*/
84-
static bool v9fs_is_cache_enabled(struct inode *inode)
85-
{
86-
struct fscache_cookie *cookie = v9fs_inode_cookie(V9FS_I(inode));
87-
88-
return fscache_cookie_enabled(cookie) && cookie->cache_priv;
89-
}
90-
9180
/**
9281
* v9fs_begin_cache_operation - Begin a cache operation for a read
9382
* @rreq: The read request
@@ -103,36 +92,13 @@ static int v9fs_begin_cache_operation(struct netfs_io_request *rreq)
10392
#endif
10493
}
10594

106-
static const struct netfs_request_ops v9fs_req_ops = {
95+
const struct netfs_request_ops v9fs_req_ops = {
10796
.init_request = v9fs_init_request,
108-
.is_cache_enabled = v9fs_is_cache_enabled,
10997
.begin_cache_operation = v9fs_begin_cache_operation,
11098
.issue_read = v9fs_issue_read,
11199
.cleanup = v9fs_req_cleanup,
112100
};
113101

114-
/**
115-
* v9fs_vfs_readpage - read an entire page in from 9P
116-
* @file: file being read
117-
* @page: structure to page
118-
*
119-
*/
120-
static int v9fs_vfs_readpage(struct file *file, struct page *page)
121-
{
122-
struct folio *folio = page_folio(page);
123-
124-
return netfs_readpage(file, folio, &v9fs_req_ops, NULL);
125-
}
126-
127-
/**
128-
* v9fs_vfs_readahead - read a set of pages from 9P
129-
* @ractl: The readahead parameters
130-
*/
131-
static void v9fs_vfs_readahead(struct readahead_control *ractl)
132-
{
133-
netfs_readahead(ractl, &v9fs_req_ops, NULL);
134-
}
135-
136102
/**
137103
* v9fs_release_page - release the private state associated with a page
138104
* @page: The page to be released
@@ -326,8 +292,7 @@ static int v9fs_write_begin(struct file *filp, struct address_space *mapping,
326292
* file. We need to do this before we get a lock on the page in case
327293
* there's more than one writer competing for the same cache block.
328294
*/
329-
retval = netfs_write_begin(filp, mapping, pos, len, flags, &folio, fsdata,
330-
&v9fs_req_ops, NULL);
295+
retval = netfs_write_begin(filp, mapping, pos, len, flags, &folio, fsdata);
331296
if (retval < 0)
332297
return retval;
333298

@@ -388,8 +353,8 @@ static int v9fs_set_page_dirty(struct page *page)
388353
#endif
389354

390355
const struct address_space_operations v9fs_addr_operations = {
391-
.readpage = v9fs_vfs_readpage,
392-
.readahead = v9fs_vfs_readahead,
356+
.readpage = netfs_readpage,
357+
.readahead = netfs_readahead,
393358
.set_page_dirty = v9fs_set_page_dirty,
394359
.writepage = v9fs_vfs_writepage,
395360
.write_begin = v9fs_write_begin,

fs/9p/vfs_inode.c

+10-3
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,6 @@ struct inode *v9fs_alloc_inode(struct super_block *sb)
231231
v9inode = kmem_cache_alloc(v9fs_inode_cache, GFP_KERNEL);
232232
if (!v9inode)
233233
return NULL;
234-
#ifdef CONFIG_9P_FSCACHE
235-
v9inode->fscache = NULL;
236-
#endif
237234
v9inode->writeback_fid = NULL;
238235
v9inode->cache_validity = 0;
239236
mutex_init(&v9inode->v_mutex);
@@ -250,6 +247,14 @@ void v9fs_free_inode(struct inode *inode)
250247
kmem_cache_free(v9fs_inode_cache, V9FS_I(inode));
251248
}
252249

250+
/*
251+
* Set parameters for the netfs library
252+
*/
253+
static void v9fs_set_netfs_context(struct inode *inode)
254+
{
255+
netfs_i_context_init(inode, &v9fs_req_ops);
256+
}
257+
253258
int v9fs_init_inode(struct v9fs_session_info *v9ses,
254259
struct inode *inode, umode_t mode, dev_t rdev)
255260
{
@@ -338,6 +343,8 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses,
338343
err = -EINVAL;
339344
goto error;
340345
}
346+
347+
v9fs_set_netfs_context(inode);
341348
error:
342349
return err;
343350

fs/afs/dynroot.c

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root)
7676
/* there shouldn't be an existing inode */
7777
BUG_ON(!(inode->i_state & I_NEW));
7878

79+
netfs_i_context_init(inode, NULL);
7980
inode->i_size = 0;
8081
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
8182
if (root) {

0 commit comments

Comments
 (0)