Skip to content

Commit f008b1d

Browse files
committed
Merge tag 'netfs-prep-20220318' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
Pull netfs updates from David Howells: "Netfs prep for write helpers. Having had a go at implementing write helpers and content encryption support in netfslib, it seems that the netfs_read_{,sub}request structs and the equivalent write request structs were almost the same and so should be merged, thereby requiring only one set of alloc/get/put functions and a common set of tracepoints. Merging the structs also has the advantage that if a bounce buffer is added to the request struct, a read operation can be performed to fill the bounce buffer, the contents of the buffer can be modified and then a write operation can be performed on it to send the data wherever it needs to go using the same request structure all the way through. The I/O handlers would then transparently perform any required crypto. This should make it easier to perform RMW cycles if needed. The potentially common functions and structs, however, by their names all proclaim themselves to be associated with the read side of things. The bulk of these changes alter this in the following ways: - Rename struct netfs_read_{,sub}request to netfs_io_{,sub}request. - Rename some enums, members and flags to make them more appropriate. - Adjust some comments to match. - Drop "read"/"rreq" from the names of common functions. For instance, netfs_get_read_request() becomes netfs_get_request(). - The ->init_rreq() and ->issue_op() methods become ->init_request() and ->issue_read(). I've kept the latter as a read-specific function and in another branch added an ->issue_write() method. The driver source is then reorganised into a number of files: fs/netfs/buffered_read.c Create read reqs to the pagecache fs/netfs/io.c Dispatchers for read and write reqs fs/netfs/main.c Some general miscellaneous bits fs/netfs/objects.c Alloc, get and put functions fs/netfs/stats.c Optional procfs statistics. and future development can be fitted into this scheme, e.g.: fs/netfs/buffered_write.c Modify the pagecache fs/netfs/buffered_flush.c Writeback from the pagecache fs/netfs/direct_read.c DIO read support fs/netfs/direct_write.c DIO write support fs/netfs/unbuffered_write.c Write modifications directly back Beyond the above changes, there are also some changes that affect how things work: - Make fscache_end_operation() generally available. - In the netfs tracing header, generate enums from the symbol -> string mapping tables rather than manually coding them. - Add a struct for filesystems that uses netfslib to put into their inode wrapper structs to hold extra state that netfslib is interested in, such as the fscache cookie. This allows netfslib functions to be set in filesystem operation tables and jumped to directly without having to have a filesystem wrapper. - Add a member to the struct added above to track the remote inode length as that may differ if local modifications are buffered. We may need to supply an appropriate EOF pointer when storing data (in AFS for example). - Pass extra information to netfs_alloc_request() so that the ->init_request() hook can access it and retain information to indicate the origin of the operation. - Make the ->init_request() hook return an error, thereby allowing a filesystem that isn't allowed to cache an inode (ceph or cifs, for example) to skip readahead. - Switch to using refcount_t for subrequests and add tracepoints to log refcount changes for the request and subrequest structs. - Add a function to consolidate dispatching a read request. Similar code is used in three places and another couple are likely to be added in the future" Link: https://lore.kernel.org/all/2639515.1648483225@warthog.procyon.org.uk/ * tag 'netfs-prep-20220318' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs: afs: Maintain netfs_i_context::remote_i_size netfs: Keep track of the actual remote file size netfs: Split some core bits out into their own file netfs: Split fs/netfs/read_helper.c netfs: Rename read_helper.c to io.c netfs: Prepare to split read_helper.c netfs: Add a function to consolidate beginning a read netfs: Add a netfs inode context ceph: Make ceph_init_request() check caps on readahead netfs: Change ->init_request() to return an error code netfs: Refactor arguments for netfs_alloc_read_request netfs: Adjust the netfs_failure tracepoint to indicate non-subreq lines netfs: Trace refcounting on the netfs_io_subrequest struct netfs: Trace refcounting on the netfs_io_request struct netfs: Adjust the netfs_rreq tracepoint slightly netfs: Split netfs_io_* object handling out netfs: Finish off rename of netfs_read_request to netfs_io_request netfs: Rename netfs_read_*request to netfs_io_*request netfs: Generate enums from trace symbol mapping lists fscache: export fscache_end_operation()
2 parents 478f74a + ab487a4 commit f008b1d

35 files changed

+1868
-1628
lines changed

Documentation/filesystems/netfs_library.rst

Lines changed: 92 additions & 48 deletions
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_read_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_read_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_read_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.
@@ -116,7 +165,7 @@ occurs, the request will get partially completed if sufficient data is read.
116165

117166
Additionally, there is::
118167

119-
* void netfs_subreq_terminated(struct netfs_read_subrequest *subreq,
168+
* void netfs_subreq_terminated(struct netfs_io_subrequest *subreq,
120169
ssize_t transferred_or_error,
121170
bool was_async);
122171

@@ -132,15 +181,15 @@ Read Helper Structures
132181
The read helpers make use of a couple of structures to maintain the state of
133182
the read. The first is a structure that manages a read request as a whole::
134183

135-
struct netfs_read_request {
184+
struct netfs_io_request {
136185
struct inode *inode;
137186
struct address_space *mapping;
138187
struct netfs_cache_resources cache_resources;
139188
void *netfs_priv;
140189
loff_t start;
141190
size_t len;
142191
loff_t i_size;
143-
const struct netfs_read_request_ops *netfs_ops;
192+
const struct netfs_request_ops *netfs_ops;
144193
unsigned int debug_id;
145194
...
146195
};
@@ -187,8 +236,8 @@ The above fields are the ones the netfs can use. They are:
187236
The second structure is used to manage individual slices of the overall read
188237
request::
189238

190-
struct netfs_read_subrequest {
191-
struct netfs_read_request *rreq;
239+
struct netfs_io_subrequest {
240+
struct netfs_io_request *rreq;
192241
loff_t start;
193242
size_t len;
194243
size_t transferred;
@@ -244,32 +293,26 @@ Read Helper Operations
244293
The network filesystem must provide the read helpers with a table of operations
245294
through which it can issue requests and negotiate::
246295

247-
struct netfs_read_request_ops {
248-
void (*init_rreq)(struct netfs_read_request *rreq, struct file *file);
249-
bool (*is_cache_enabled)(struct inode *inode);
250-
int (*begin_cache_operation)(struct netfs_read_request *rreq);
251-
void (*expand_readahead)(struct netfs_read_request *rreq);
252-
bool (*clamp_length)(struct netfs_read_subrequest *subreq);
253-
void (*issue_op)(struct netfs_read_subrequest *subreq);
254-
bool (*is_still_valid)(struct netfs_read_request *rreq);
296+
struct netfs_request_ops {
297+
void (*init_request)(struct netfs_io_request *rreq, struct file *file);
298+
int (*begin_cache_operation)(struct netfs_io_request *rreq);
299+
void (*expand_readahead)(struct netfs_io_request *rreq);
300+
bool (*clamp_length)(struct netfs_io_subrequest *subreq);
301+
void (*issue_read)(struct netfs_io_subrequest *subreq);
302+
bool (*is_still_valid)(struct netfs_io_request *rreq);
255303
int (*check_write_begin)(struct file *file, loff_t pos, unsigned len,
256304
struct folio *folio, void **_fsdata);
257-
void (*done)(struct netfs_read_request *rreq);
305+
void (*done)(struct netfs_io_request *rreq);
258306
void (*cleanup)(struct address_space *mapping, void *netfs_priv);
259307
};
260308

261309
The operations are as follows:
262310

263-
* ``init_rreq()``
311+
* ``init_request()``
264312

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
@@ -305,7 +348,7 @@ The operations are as follows:
305348

306349
This should return 0 on success and an error code on error.
307350

308-
* ``issue_op()``
351+
* ``issue_read()``
309352

310353
[Required] The helpers use this to dispatch a subrequest to the server for
311354
reading. In the subrequest, ->start, ->len and ->transferred indicate what
@@ -420,12 +463,12 @@ The network filesystem's ->begin_cache_operation() method is called to set up a
420463
cache and this must call into the cache to do the work. If using fscache, for
421464
example, the cache would call::
422465

423-
int fscache_begin_read_operation(struct netfs_read_request *rreq,
466+
int fscache_begin_read_operation(struct netfs_io_request *rreq,
424467
struct fscache_cookie *cookie);
425468

426469
passing in the request pointer and the cookie corresponding to the file.
427470

428-
The netfs_read_request object contains a place for the cache to hang its
471+
The netfs_io_request object contains a place for the cache to hang its
429472
state::
430473

431474
struct netfs_cache_resources {
@@ -443,7 +486,7 @@ operation table looks like the following::
443486
void (*expand_readahead)(struct netfs_cache_resources *cres,
444487
loff_t *_start, size_t *_len, loff_t i_size);
445488

446-
enum netfs_read_source (*prepare_read)(struct netfs_read_subrequest *subreq,
489+
enum netfs_io_source (*prepare_read)(struct netfs_io_subrequest *subreq,
447490
loff_t i_size);
448491

449492
int (*read)(struct netfs_cache_resources *cres,
@@ -562,4 +605,5 @@ API Function Reference
562605
======================
563606

564607
.. kernel-doc:: include/linux/netfs.h
565-
.. kernel-doc:: fs/netfs/read_helper.c
608+
.. kernel-doc:: fs/netfs/buffered_read.c
609+
.. kernel-doc:: fs/netfs/io.c

fs/9p/cache.c

Lines changed: 4 additions & 6 deletions
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

Lines changed: 1 addition & 3 deletions
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

Lines changed: 8 additions & 5 deletions
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);

0 commit comments

Comments
 (0)