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 <dhowells@redhat.com> Acked-by: Jeff Layton <jlayton@kernel.org> cc: linux-cachefs@redhat.com
Unified · Split
| @@ -7,6 +7,8 @@ Network Filesystem Helper Library · 6 unmodified lines | ||
| 7 | 7 | .. Contents: |
| 8 | 8 | |
| 9 | 9 | - Overview. |
| 10 | + - Per-inode context. | |
| 11 | + - Inode context helper functions. | |
| 10 | 12 | - Buffered read helpers. |
| 11 | 13 | - Read helper functions. |
| 12 | 14 | - Read helper structures. |
| @@ -28,6 +30,69 @@ Note that the library module doesn't link against local caching directly, so · 15 unmodified lines | ||
| 28 | 30 | access must be provided by the netfs. |
| 29 | 31 | |
| 30 | 32 | |
| 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 | + | |
| 31 | 96 | Buffered Read Helpers |
| 32 | 97 | ===================== |
| 33 | 98 | |
| @@ -70,38 +135,22 @@ Read Helper Functions · 36 unmodified lines | ||
| 70 | 135 | |
| 71 | 136 | Three read helpers are provided:: |
| 72 | 137 | |
| 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); | |
| 76 | 139 | 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); | |
| 80 | 141 | int netfs_write_begin(struct file *file, |
| 81 | 142 | struct address_space *mapping, |
| 82 | 143 | loff_t pos, |
| 83 | 144 | unsigned int len, |
| 84 | 145 | unsigned int flags, |
| 85 | 146 | 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); | |
| 92 | 148 | |
| 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. | |
| 98 | 151 | |
| 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 | |
| 105 | 154 | little more complicated as the network filesystem might want to flush |
| 106 | 155 | conflicting writes or track dirty data and needs to put the acquired folio if |
| 107 | 156 | an error occurs after calling the helper. |
| @@ -246,7 +295,6 @@ through which it can issue requests and negotiate:: · 138 unmodified lines | ||
| 246 | 295 | |
| 247 | 296 | struct netfs_request_ops { |
| 248 | 297 | void (*init_request)(struct netfs_io_request *rreq, struct file *file); |
| 249 | − bool (*is_cache_enabled)(struct inode *inode); | |
| 250 | 298 | int (*begin_cache_operation)(struct netfs_io_request *rreq); |
| 251 | 299 | void (*expand_readahead)(struct netfs_io_request *rreq); |
| 252 | 300 | bool (*clamp_length)(struct netfs_io_subrequest *subreq); |
| @@ -265,11 +313,6 @@ The operations are as follows: · 12 unmodified lines | ||
| 265 | 313 | [Optional] This is called to initialise the request structure. It is given |
| 266 | 314 | the file for reference and can modify the ->netfs_priv value. |
| 267 | 315 | |
| 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 | − | |
| 273 | 316 | * ``begin_cache_operation()`` |
| 274 | 317 | |
| 275 | 318 | [Optional] This is called to ask the network filesystem to call into the |
| @@ -49,22 +49,20 @@ int v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses, · 48 unmodified lines | ||
| 49 | 49 | |
| 50 | 50 | void v9fs_cache_inode_get_cookie(struct inode *inode) |
| 51 | 51 | { |
| 52 | − struct v9fs_inode *v9inode; | |
| 52 | + struct v9fs_inode *v9inode = V9FS_I(inode); | |
| 53 | 53 | struct v9fs_session_info *v9ses; |
| 54 | 54 | __le32 version; |
| 55 | 55 | __le64 path; |
| 56 | 56 | |
| 57 | 57 | if (!S_ISREG(inode->i_mode)) |
| 58 | 58 | return; |
| 59 | − | |
| 60 | − v9inode = V9FS_I(inode); | |
| 61 | − if (WARN_ON(v9inode->fscache)) | |
| 59 | + if (WARN_ON(v9fs_inode_cookie(v9inode))) | |
| 62 | 60 | return; |
| 63 | 61 | |
| 64 | 62 | version = cpu_to_le32(v9inode->qid.version); |
| 65 | 63 | path = cpu_to_le64(v9inode->qid.path); |
| 66 | 64 | v9ses = v9fs_inode2v9ses(inode); |
| 67 | − v9inode->fscache = | |
| 65 | + v9inode->netfs_ctx.cache = | |
| 68 | 66 | fscache_acquire_cookie(v9fs_session_cache(v9ses), |
| 69 | 67 | 0, |
| 70 | 68 | &path, sizeof(path), |
| @@ -72,5 +70,5 @@ void v9fs_cache_inode_get_cookie(struct inode *inode) · 1 unmodified line | ||
| 72 | 70 | i_size_read(&v9inode->vfs_inode)); |
| 73 | 71 | |
| 74 | 72 | p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n", |
| 75 | − inode, v9inode->fscache); | |
| 73 | + inode, v9fs_inode_cookie(v9inode)); | |
| 76 | 74 | } |
| @@ -623,9 +623,7 @@ static void v9fs_sysfs_cleanup(void) · 622 unmodified lines | ||
| 623 | 623 | static void v9fs_inode_init_once(void *foo) |
| 624 | 624 | { |
| 625 | 625 | struct v9fs_inode *v9inode = (struct v9fs_inode *)foo; |
| 626 | −#ifdef CONFIG_9P_FSCACHE | |
| 627 | − v9inode->fscache = NULL; | |
| 628 | −#endif | |
| 626 | + | |
| 629 | 627 | memset(&v9inode->qid, 0, sizeof(v9inode->qid)); |
| 630 | 628 | inode_init_once(&v9inode->vfs_inode); |
| 631 | 629 | } |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #define FS_9P_V9FS_H |
| 10 | 10 | |
| 11 | 11 | #include <linux/backing-dev.h> |
| 12 | +#include <linux/netfs.h> | |
| 12 | 13 | |
| 13 | 14 | /** |
| 14 | 15 | * enum p9_session_flags - option flags for each 9P session |
| @@ -108,14 +109,15 @@ struct v9fs_session_info { · 93 unmodified lines | ||
| 108 | 109 | #define V9FS_INO_INVALID_ATTR 0x01 |
| 109 | 110 | |
| 110 | 111 | 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 | + }; | |
| 114 | 117 | struct p9_qid qid; |
| 115 | 118 | unsigned int cache_validity; |
| 116 | 119 | struct p9_fid *writeback_fid; |
| 117 | 120 | struct mutex v_mutex; |
| 118 | − struct inode vfs_inode; | |
| 119 | 121 | }; |
| 120 | 122 | |
| 121 | 123 | 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) · 4 unmodified lines | ||
| 126 | 128 | static inline struct fscache_cookie *v9fs_inode_cookie(struct v9fs_inode *v9inode) |
| 127 | 129 | { |
| 128 | 130 | #ifdef CONFIG_9P_FSCACHE |
| 129 | − return v9inode->fscache; | |
| 131 | + return netfs_i_cookie(&v9inode->vfs_inode); | |
| 130 | 132 | #else |
| 131 | 133 | return NULL; |
| 132 | 134 | #endif |
| @@ -163,6 +165,7 @@ extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses, · 30 unmodified lines | ||
| 163 | 165 | extern const struct inode_operations v9fs_dir_inode_operations_dotl; |
| 164 | 166 | extern const struct inode_operations v9fs_file_inode_operations_dotl; |
| 165 | 167 | extern const struct inode_operations v9fs_symlink_inode_operations_dotl; |
| 168 | +extern const struct netfs_request_ops v9fs_req_ops; | |
| 166 | 169 | extern struct inode *v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, |
| 167 | 170 | struct p9_fid *fid, |
| 168 | 171 | struct super_block *sb, int new); |
| @@ -77,17 +77,6 @@ static void v9fs_req_cleanup(struct address_space *mapping, void *priv) · 76 unmodified lines | ||
| 77 | 77 | p9_client_clunk(fid); |
| 78 | 78 | } |
| 79 | 79 | |
| 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 | − | |
| 91 | 80 | /** |
| 92 | 81 | * v9fs_begin_cache_operation - Begin a cache operation for a read |
| 93 | 82 | * @rreq: The read request |
| @@ -103,36 +92,13 @@ static int v9fs_begin_cache_operation(struct netfs_io_request *rreq) · 9 unmodified lines | ||
| 103 | 92 | #endif |
| 104 | 93 | } |
| 105 | 94 | |
| 106 | −static const struct netfs_request_ops v9fs_req_ops = { | |
| 95 | +const struct netfs_request_ops v9fs_req_ops = { | |
| 107 | 96 | .init_request = v9fs_init_request, |
| 108 | − .is_cache_enabled = v9fs_is_cache_enabled, | |
| 109 | 97 | .begin_cache_operation = v9fs_begin_cache_operation, |
| 110 | 98 | .issue_read = v9fs_issue_read, |
| 111 | 99 | .cleanup = v9fs_req_cleanup, |
| 112 | 100 | }; |
| 113 | 101 | |
| 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 | − | |
| 136 | 102 | /** |
| 137 | 103 | * v9fs_release_page - release the private state associated with a page |
| 138 | 104 | * @page: The page to be released |
| @@ -326,8 +292,7 @@ static int v9fs_write_begin(struct file *filp, struct address_space *mapping, · 187 unmodified lines | ||
| 326 | 292 | * file. We need to do this before we get a lock on the page in case |
| 327 | 293 | * there's more than one writer competing for the same cache block. |
| 328 | 294 | */ |
| 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); | |
| 331 | 296 | if (retval < 0) |
| 332 | 297 | return retval; |
| 333 | 298 | |
| @@ -388,8 +353,8 @@ static int v9fs_set_page_dirty(struct page *page) · 54 unmodified lines | ||
| 388 | 353 | #endif |
| 389 | 354 | |
| 390 | 355 | 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, | |
| 393 | 358 | .set_page_dirty = v9fs_set_page_dirty, |
| 394 | 359 | .writepage = v9fs_vfs_writepage, |
| 395 | 360 | .write_begin = v9fs_write_begin, |
| @@ -231,9 +231,6 @@ struct inode *v9fs_alloc_inode(struct super_block *sb) · 230 unmodified lines | ||
| 231 | 231 | v9inode = kmem_cache_alloc(v9fs_inode_cache, GFP_KERNEL); |
| 232 | 232 | if (!v9inode) |
| 233 | 233 | return NULL; |
| 234 | −#ifdef CONFIG_9P_FSCACHE | |
| 235 | − v9inode->fscache = NULL; | |
| 236 | −#endif | |
| 237 | 234 | v9inode->writeback_fid = NULL; |
| 238 | 235 | v9inode->cache_validity = 0; |
| 239 | 236 | mutex_init(&v9inode->v_mutex); |
| @@ -250,6 +247,14 @@ void v9fs_free_inode(struct inode *inode) · 10 unmodified lines | ||
| 250 | 247 | kmem_cache_free(v9fs_inode_cache, V9FS_I(inode)); |
| 251 | 248 | } |
| 252 | 249 | |
| 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 | + | |
| 253 | 258 | int v9fs_init_inode(struct v9fs_session_info *v9ses, |
| 254 | 259 | struct inode *inode, umode_t mode, dev_t rdev) |
| 255 | 260 | { |
| @@ -338,6 +343,8 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses, · 82 unmodified lines | ||
| 338 | 343 | err = -EINVAL; |
| 339 | 344 | goto error; |
| 340 | 345 | } |
| 346 | + | |
| 347 | + v9fs_set_netfs_context(inode); | |
| 341 | 348 | error: |
| 342 | 349 | return err; |
| 343 | 350 | |
| @@ -76,6 +76,7 @@ struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root) · 75 unmodified lines | ||
| 76 | 76 | /* there shouldn't be an existing inode */ |
| 77 | 77 | BUG_ON(!(inode->i_state & I_NEW)); |
| 78 | 78 | |
| 79 | + netfs_i_context_init(inode, NULL); | |
| 79 | 80 | inode->i_size = 0; |
| 80 | 81 | inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; |
| 81 | 82 | if (root) { |
| @@ -19,13 +19,11 @@ · 18 unmodified lines | ||
| 19 | 19 | #include "internal.h" |
| 20 | 20 | |
| 21 | 21 | static int afs_file_mmap(struct file *file, struct vm_area_struct *vma); |
| 22 | −static int afs_readpage(struct file *file, struct page *page); | |
| 23 | 22 | static int afs_symlink_readpage(struct file *file, struct page *page); |
| 24 | 23 | static void afs_invalidatepage(struct page *page, unsigned int offset, |
| 25 | 24 | unsigned int length); |
| 26 | 25 | static int afs_releasepage(struct page *page, gfp_t gfp_flags); |
| 27 | 26 | |
| 28 | −static void afs_readahead(struct readahead_control *ractl); | |
| 29 | 27 | static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter); |
| 30 | 28 | static void afs_vm_open(struct vm_area_struct *area); |
| 31 | 29 | static void afs_vm_close(struct vm_area_struct *area); |
| @@ -52,8 +50,8 @@ const struct inode_operations afs_file_inode_operations = { · 20 unmodified lines | ||
| 52 | 50 | }; |
| 53 | 51 | |
| 54 | 52 | const struct address_space_operations afs_file_aops = { |
| 55 | − .readpage = afs_readpage, | |
| 56 | − .readahead = afs_readahead, | |
| 53 | + .readpage = netfs_readpage, | |
| 54 | + .readahead = netfs_readahead, | |
| 57 | 55 | .set_page_dirty = afs_set_page_dirty, |
| 58 | 56 | .launder_page = afs_launder_page, |
| 59 | 57 | .releasepage = afs_releasepage, |
| @@ -365,13 +363,6 @@ static int afs_init_request(struct netfs_io_request *rreq, struct file *file) · 305 unmodified lines | ||
| 365 | 363 | return 0; |
| 366 | 364 | } |
| 367 | 365 | |
| 368 | −static bool afs_is_cache_enabled(struct inode *inode) | |
| 369 | −{ | |
| 370 | − struct fscache_cookie *cookie = afs_vnode_cache(AFS_FS_I(inode)); | |
| 371 | − | |
| 372 | − return fscache_cookie_enabled(cookie) && cookie->cache_priv; | |
| 373 | −} | |
| 374 | − | |
| 375 | 366 | static int afs_begin_cache_operation(struct netfs_io_request *rreq) |
| 376 | 367 | { |
| 377 | 368 | #ifdef CONFIG_AFS_FSCACHE |
| @@ -399,25 +390,12 @@ static void afs_priv_cleanup(struct address_space *mapping, void *netfs_priv) · 21 unmodified lines | ||
| 399 | 390 | |
| 400 | 391 | const struct netfs_request_ops afs_req_ops = { |
| 401 | 392 | .init_request = afs_init_request, |
| 402 | − .is_cache_enabled = afs_is_cache_enabled, | |
| 403 | 393 | .begin_cache_operation = afs_begin_cache_operation, |
| 404 | 394 | .check_write_begin = afs_check_write_begin, |
| 405 | 395 | .issue_read = afs_issue_read, |
| 406 | 396 | .cleanup = afs_priv_cleanup, |
| 407 | 397 | }; |
| 408 | 398 | |
| 409 | −static int afs_readpage(struct file *file, struct page *page) | |
| 410 | −{ | |
| 411 | − struct folio *folio = page_folio(page); | |
| 412 | − | |
| 413 | − return netfs_readpage(file, folio, &afs_req_ops, NULL); | |
| 414 | −} | |
| 415 | − | |
| 416 | −static void afs_readahead(struct readahead_control *ractl) | |
| 417 | −{ | |
| 418 | − netfs_readahead(ractl, &afs_req_ops, NULL); | |
| 419 | −} | |
| 420 | − | |
| 421 | 399 | int afs_write_inode(struct inode *inode, struct writeback_control *wbc) |
| 422 | 400 | { |
| 423 | 401 | fscache_unpin_writeback(wbc, afs_vnode_cache(AFS_FS_I(inode))); |
| @@ -53,6 +53,14 @@ static noinline void dump_vnode(struct afs_vnode *vnode, struct afs_vnode *paren · 52 unmodified lines | ||
| 53 | 53 | dump_stack(); |
| 54 | 54 | } |
| 55 | 55 | |
| 56 | +/* | |
| 57 | + * Set parameters for the netfs library | |
| 58 | + */ | |
| 59 | +static void afs_set_netfs_context(struct afs_vnode *vnode) | |
| 60 | +{ | |
| 61 | + netfs_i_context_init(&vnode->vfs_inode, &afs_req_ops); | |
| 62 | +} | |
| 63 | + | |
| 56 | 64 | /* |
| 57 | 65 | * Initialise an inode from the vnode status. |
| 58 | 66 | */ |
| @@ -128,6 +136,7 @@ static int afs_inode_init_from_status(struct afs_operation *op, · 69 unmodified lines | ||
| 128 | 136 | } |
| 129 | 137 | |
| 130 | 138 | afs_set_i_size(vnode, status->size); |
| 139 | + afs_set_netfs_context(vnode); | |
| 131 | 140 | |
| 132 | 141 | vnode->invalid_before = status->data_version; |
| 133 | 142 | inode_set_iversion_raw(&vnode->vfs_inode, status->data_version); |
| @@ -420,7 +429,7 @@ static void afs_get_inode_cache(struct afs_vnode *vnode) · 286 unmodified lines | ||
| 420 | 429 | struct afs_vnode_cache_aux aux; |
| 421 | 430 | |
| 422 | 431 | if (vnode->status.type != AFS_FTYPE_FILE) { |
| 423 | − vnode->cache = NULL; | |
| 432 | + vnode->netfs_ctx.cache = NULL; | |
| 424 | 433 | return; |
| 425 | 434 | } |
| 426 | 435 | |
| @@ -430,12 +439,14 @@ static void afs_get_inode_cache(struct afs_vnode *vnode) · 3 unmodified lines | ||
| 430 | 439 | key.vnode_id_ext[1] = htonl(vnode->fid.vnode_hi); |
| 431 | 440 | afs_set_cache_aux(vnode, &aux); |
| 432 | 441 | |
| 433 | − vnode->cache = fscache_acquire_cookie( | |
| 434 | − vnode->volume->cache, | |
| 435 | − vnode->status.type == AFS_FTYPE_FILE ? 0 : FSCACHE_ADV_SINGLE_CHUNK, | |
| 436 | − &key, sizeof(key), | |
| 437 | − &aux, sizeof(aux), | |
| 438 | − vnode->status.size); | |
| 442 | + afs_vnode_set_cache(vnode, | |
| 443 | + fscache_acquire_cookie( | |
| 444 | + vnode->volume->cache, | |
| 445 | + vnode->status.type == AFS_FTYPE_FILE ? | |
| 446 | + 0 : FSCACHE_ADV_SINGLE_CHUNK, | |
| 447 | + &key, sizeof(key), | |
| 448 | + &aux, sizeof(aux), | |
| 449 | + vnode->status.size)); | |
| 439 | 450 | #endif |
| 440 | 451 | } |
| 441 | 452 | |
| @@ -528,6 +539,7 @@ struct inode *afs_root_iget(struct super_block *sb, struct key *key) · 86 unmodified lines | ||
| 528 | 539 | |
| 529 | 540 | vnode = AFS_FS_I(inode); |
| 530 | 541 | vnode->cb_v_break = as->volume->cb_v_break, |
| 542 | + afs_set_netfs_context(vnode); | |
| 531 | 543 | |
| 532 | 544 | op = afs_alloc_operation(key, as->volume); |
| 533 | 545 | if (IS_ERR(op)) { |
| @@ -786,11 +798,8 @@ void afs_evict_inode(struct inode *inode) · 252 unmodified lines | ||
| 786 | 798 | afs_put_wb_key(wbk); |
| 787 | 799 | } |
| 788 | 800 | |
| 789 | −#ifdef CONFIG_AFS_FSCACHE | |
| 790 | − fscache_relinquish_cookie(vnode->cache, | |
| 801 | + fscache_relinquish_cookie(afs_vnode_cache(vnode), | |
| 791 | 802 | test_bit(AFS_VNODE_DELETED, &vnode->flags)); |
| 792 | − vnode->cache = NULL; | |
| 793 | −#endif | |
| 794 | 803 | |
| 795 | 804 | afs_prune_wb_keys(vnode); |
| 796 | 805 | afs_put_permits(rcu_access_pointer(vnode->permit_cache)); |
| @@ -619,15 +619,16 @@ enum afs_lock_state { · 618 unmodified lines | ||
| 619 | 619 | * leak from one inode to another. |
| 620 | 620 | */ |
| 621 | 621 | struct afs_vnode { |
| 622 | − struct inode vfs_inode; /* the VFS's inode record */ | |
| 622 | + struct { | |
| 623 | + /* These must be contiguous */ | |
| 624 | + struct inode vfs_inode; /* the VFS's inode record */ | |
| 625 | + struct netfs_i_context netfs_ctx; /* Netfslib context */ | |
| 626 | + }; | |
| 623 | 627 | |
| 624 | 628 | struct afs_volume *volume; /* volume on which vnode resides */ |
| 625 | 629 | struct afs_fid fid; /* the file identifier for this inode */ |
| 626 | 630 | struct afs_file_status status; /* AFS status info for this file */ |
| 627 | 631 | afs_dataversion_t invalid_before; /* Child dentries are invalid before this */ |
| 628 | −#ifdef CONFIG_AFS_FSCACHE | |
| 629 | − struct fscache_cookie *cache; /* caching cookie */ | |
| 630 | −#endif | |
| 631 | 632 | struct afs_permits __rcu *permit_cache; /* cache of permits so far obtained */ |
| 632 | 633 | struct mutex io_lock; /* Lock for serialising I/O on this mutex */ |
| 633 | 634 | struct rw_semaphore validate_lock; /* lock for validating this vnode */ |
| @@ -674,12 +675,20 @@ struct afs_vnode { · 40 unmodified lines | ||
| 674 | 675 | static inline struct fscache_cookie *afs_vnode_cache(struct afs_vnode *vnode) |
| 675 | 676 | { |
| 676 | 677 | #ifdef CONFIG_AFS_FSCACHE |
| 677 | − return vnode->cache; | |
| 678 | + return netfs_i_cookie(&vnode->vfs_inode); | |
| 678 | 679 | #else |
| 679 | 680 | return NULL; |
| 680 | 681 | #endif |
| 681 | 682 | } |
| 682 | 683 | |
| 684 | +static inline void afs_vnode_set_cache(struct afs_vnode *vnode, | |
| 685 | + struct fscache_cookie *cookie) | |
| 686 | +{ | |
| 687 | +#ifdef CONFIG_AFS_FSCACHE | |
| 688 | + vnode->netfs_ctx.cache = cookie; | |
| 689 | +#endif | |
| 690 | +} | |
| 691 | + | |
| 683 | 692 | /* |
| 684 | 693 | * cached security record for one user's attempt to access a vnode |
| 685 | 694 | */ |
| @@ -688,13 +688,11 @@ static struct inode *afs_alloc_inode(struct super_block *sb) · 687 unmodified lines | ||
| 688 | 688 | /* Reset anything that shouldn't leak from one inode to the next. */ |
| 689 | 689 | memset(&vnode->fid, 0, sizeof(vnode->fid)); |
| 690 | 690 | memset(&vnode->status, 0, sizeof(vnode->status)); |
| 691 | + afs_vnode_set_cache(vnode, NULL); | |
| 691 | 692 | |
| 692 | 693 | vnode->volume = NULL; |
| 693 | 694 | vnode->lock_key = NULL; |
| 694 | 695 | vnode->permit_cache = NULL; |
| 695 | −#ifdef CONFIG_AFS_FSCACHE | |
| 696 | − vnode->cache = NULL; | |
| 697 | −#endif | |
| 698 | 696 | |
| 699 | 697 | vnode->flags = 1 << AFS_VNODE_UNSET; |
| 700 | 698 | vnode->lock_state = AFS_VNODE_LOCK_NONE; |
| @@ -59,8 +59,7 @@ int afs_write_begin(struct file *file, struct address_space *mapping, · 58 unmodified lines | ||
| 59 | 59 | * file. We need to do this before we get a lock on the page in case |
| 60 | 60 | * there's more than one writer competing for the same cache block. |
| 61 | 61 | */ |
| 62 | − ret = netfs_write_begin(file, mapping, pos, len, flags, &folio, fsdata, | |
| 63 | − &afs_req_ops, NULL); | |
| 62 | + ret = netfs_write_begin(file, mapping, pos, len, flags, &folio, fsdata); | |
| 64 | 63 | if (ret < 0) |
| 65 | 64 | return ret; |
| 66 | 65 | |
| @@ -403,7 +403,7 @@ static void ceph_readahead_cleanup(struct address_space *mapping, void *priv) · 402 unmodified lines | ||
| 403 | 403 | ceph_put_cap_refs(ci, got); |
| 404 | 404 | } |
| 405 | 405 | |
| 406 | −static const struct netfs_request_ops ceph_netfs_read_ops = { | |
| 406 | +const struct netfs_request_ops ceph_netfs_ops = { | |
| 407 | 407 | .init_request = ceph_init_request, |
| 408 | 408 | .begin_cache_operation = ceph_begin_cache_operation, |
| 409 | 409 | .issue_read = ceph_netfs_issue_read, |
| @@ -413,28 +413,6 @@ static const struct netfs_request_ops ceph_netfs_read_ops = { · 3 unmodified lines | ||
| 413 | 413 | .cleanup = ceph_readahead_cleanup, |
| 414 | 414 | }; |
| 415 | 415 | |
| 416 | −/* read a single page, without unlocking it. */ | |
| 417 | −static int ceph_readpage(struct file *file, struct page *subpage) | |
| 418 | −{ | |
| 419 | − struct folio *folio = page_folio(subpage); | |
| 420 | − struct inode *inode = file_inode(file); | |
| 421 | − struct ceph_inode_info *ci = ceph_inode(inode); | |
| 422 | − struct ceph_vino vino = ceph_vino(inode); | |
| 423 | − size_t len = folio_size(folio); | |
| 424 | − u64 off = folio_file_pos(folio); | |
| 425 | − | |
| 426 | − dout("readpage ino %llx.%llx file %p off %llu len %zu folio %p index %lu\n inline %d", | |
| 427 | − vino.ino, vino.snap, file, off, len, folio, folio_index(folio), | |
| 428 | − ci->i_inline_version != CEPH_INLINE_NONE); | |
| 429 | − | |
| 430 | − return netfs_readpage(file, folio, &ceph_netfs_read_ops, NULL); | |
| 431 | −} | |
| 432 | − | |
| 433 | −static void ceph_readahead(struct readahead_control *ractl) | |
| 434 | −{ | |
| 435 | − netfs_readahead(ractl, &ceph_netfs_read_ops, NULL); | |
| 436 | −} | |
| 437 | − | |
| 438 | 416 | #ifdef CONFIG_CEPH_FSCACHE |
| 439 | 417 | static void ceph_set_page_fscache(struct page *page) |
| 440 | 418 | { |
| @@ -1333,8 +1311,7 @@ static int ceph_write_begin(struct file *file, struct address_space *mapping, · 892 unmodified lines | ||
| 1333 | 1311 | struct folio *folio = NULL; |
| 1334 | 1312 | int r; |
| 1335 | 1313 | |
| 1336 | − r = netfs_write_begin(file, inode->i_mapping, pos, len, 0, &folio, NULL, | |
| 1337 | − &ceph_netfs_read_ops, NULL); | |
| 1314 | + r = netfs_write_begin(file, inode->i_mapping, pos, len, 0, &folio, NULL); | |
| 1338 | 1315 | if (r == 0) |
| 1339 | 1316 | folio_wait_fscache(folio); |
| 1340 | 1317 | if (r < 0) { |
| @@ -1388,8 +1365,8 @@ out: · 47 unmodified lines | ||
| 1388 | 1365 | } |
| 1389 | 1366 | |
| 1390 | 1367 | const struct address_space_operations ceph_aops = { |
| 1391 | − .readpage = ceph_readpage, | |
| 1392 | − .readahead = ceph_readahead, | |
| 1368 | + .readpage = netfs_readpage, | |
| 1369 | + .readahead = netfs_readahead, | |
| 1393 | 1370 | .writepage = ceph_writepage, |
| 1394 | 1371 | .writepages = ceph_writepages_start, |
| 1395 | 1372 | .write_begin = ceph_write_begin, |
| @@ -29,26 +29,25 @@ void ceph_fscache_register_inode_cookie(struct inode *inode) · 28 unmodified lines | ||
| 29 | 29 | if (!(inode->i_state & I_NEW)) |
| 30 | 30 | return; |
| 31 | 31 | |
| 32 | − WARN_ON_ONCE(ci->fscache); | |
| 32 | + WARN_ON_ONCE(ci->netfs_ctx.cache); | |
| 33 | 33 | |
| 34 | − ci->fscache = fscache_acquire_cookie(fsc->fscache, 0, | |
| 35 | − &ci->i_vino, sizeof(ci->i_vino), | |
| 36 | − &ci->i_version, sizeof(ci->i_version), | |
| 37 | − i_size_read(inode)); | |
| 34 | + ci->netfs_ctx.cache = | |
| 35 | + fscache_acquire_cookie(fsc->fscache, 0, | |
| 36 | + &ci->i_vino, sizeof(ci->i_vino), | |
| 37 | + &ci->i_version, sizeof(ci->i_version), | |
| 38 | + i_size_read(inode)); | |
| 38 | 39 | } |
| 39 | 40 | |
| 40 | −void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci) | |
| 41 | +void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info *ci) | |
| 41 | 42 | { |
| 42 | − struct fscache_cookie *cookie = ci->fscache; | |
| 43 | − | |
| 44 | − fscache_relinquish_cookie(cookie, false); | |
| 43 | + fscache_relinquish_cookie(ceph_fscache_cookie(ci), false); | |
| 45 | 44 | } |
| 46 | 45 | |
| 47 | 46 | void ceph_fscache_use_cookie(struct inode *inode, bool will_modify) |
| 48 | 47 | { |
| 49 | 48 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 50 | 49 | |
| 51 | − fscache_use_cookie(ci->fscache, will_modify); | |
| 50 | + fscache_use_cookie(ceph_fscache_cookie(ci), will_modify); | |
| 52 | 51 | } |
| 53 | 52 | |
| 54 | 53 | void ceph_fscache_unuse_cookie(struct inode *inode, bool update) |
| @@ -58,9 +57,10 @@ void ceph_fscache_unuse_cookie(struct inode *inode, bool update) · 3 unmodified lines | ||
| 58 | 57 | if (update) { |
| 59 | 58 | loff_t i_size = i_size_read(inode); |
| 60 | 59 | |
| 61 | − fscache_unuse_cookie(ci->fscache, &ci->i_version, &i_size); | |
| 60 | + fscache_unuse_cookie(ceph_fscache_cookie(ci), | |
| 61 | + &ci->i_version, &i_size); | |
| 62 | 62 | } else { |
| 63 | − fscache_unuse_cookie(ci->fscache, NULL, NULL); | |
| 63 | + fscache_unuse_cookie(ceph_fscache_cookie(ci), NULL, NULL); | |
| 64 | 64 | } |
| 65 | 65 | } |
| 66 | 66 | |
| @@ -69,14 +69,14 @@ void ceph_fscache_update(struct inode *inode) · 2 unmodified lines | ||
| 69 | 69 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 70 | 70 | loff_t i_size = i_size_read(inode); |
| 71 | 71 | |
| 72 | − fscache_update_cookie(ci->fscache, &ci->i_version, &i_size); | |
| 72 | + fscache_update_cookie(ceph_fscache_cookie(ci), &ci->i_version, &i_size); | |
| 73 | 73 | } |
| 74 | 74 | |
| 75 | 75 | void ceph_fscache_invalidate(struct inode *inode, bool dio_write) |
| 76 | 76 | { |
| 77 | 77 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 78 | 78 | |
| 79 | − fscache_invalidate(ceph_inode(inode)->fscache, | |
| 79 | + fscache_invalidate(ceph_fscache_cookie(ci), | |
| 80 | 80 | &ci->i_version, i_size_read(inode), |
| 81 | 81 | dio_write ? FSCACHE_INVAL_DIO_WRITE : 0); |
| 82 | 82 | } |
| @@ -26,14 +26,9 @@ void ceph_fscache_unuse_cookie(struct inode *inode, bool update); · 25 unmodified lines | ||
| 26 | 26 | void ceph_fscache_update(struct inode *inode); |
| 27 | 27 | void ceph_fscache_invalidate(struct inode *inode, bool dio_write); |
| 28 | 28 | |
| 29 | −static inline void ceph_fscache_inode_init(struct ceph_inode_info *ci) | |
| 30 | −{ | |
| 31 | − ci->fscache = NULL; | |
| 32 | −} | |
| 33 | − | |
| 34 | 29 | static inline struct fscache_cookie *ceph_fscache_cookie(struct ceph_inode_info *ci) |
| 35 | 30 | { |
| 36 | − return ci->fscache; | |
| 31 | + return netfs_i_cookie(&ci->vfs_inode); | |
| 37 | 32 | } |
| 38 | 33 | |
| 39 | 34 | static inline void ceph_fscache_resize(struct inode *inode, loff_t to) |
| @@ -91,10 +86,6 @@ static inline void ceph_fscache_unregister_fs(struct ceph_fs_client* fsc) · 51 unmodified lines | ||
| 91 | 86 | { |
| 92 | 87 | } |
| 93 | 88 | |
| 94 | −static inline void ceph_fscache_inode_init(struct ceph_inode_info *ci) | |
| 95 | −{ | |
| 96 | −} | |
| 97 | − | |
| 98 | 89 | static inline void ceph_fscache_register_inode_cookie(struct inode *inode) |
| 99 | 90 | { |
| 100 | 91 | } |
| @@ -453,6 +453,9 @@ struct inode *ceph_alloc_inode(struct super_block *sb) · 452 unmodified lines | ||
| 453 | 453 | |
| 454 | 454 | dout("alloc_inode %p\n", &ci->vfs_inode); |
| 455 | 455 | |
| 456 | + /* Set parameters for the netfs library */ | |
| 457 | + netfs_i_context_init(&ci->vfs_inode, &ceph_netfs_ops); | |
| 458 | + | |
| 456 | 459 | spin_lock_init(&ci->i_ceph_lock); |
| 457 | 460 | |
| 458 | 461 | ci->i_version = 0; |
| @@ -538,9 +541,6 @@ struct inode *ceph_alloc_inode(struct super_block *sb) · 79 unmodified lines | ||
| 538 | 541 | INIT_WORK(&ci->i_work, ceph_inode_work); |
| 539 | 542 | ci->i_work_mask = 0; |
| 540 | 543 | memset(&ci->i_btime, '\0', sizeof(ci->i_btime)); |
| 541 | − | |
| 542 | − ceph_fscache_inode_init(ci); | |
| 543 | − | |
| 544 | 544 | return &ci->vfs_inode; |
| 545 | 545 | } |
| 546 | 546 | |
| @@ -17,13 +17,11 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <linux/posix_acl.h> |
| 18 | 18 | #include <linux/refcount.h> |
| 19 | 19 | #include <linux/security.h> |
| 20 | +#include <linux/netfs.h> | |
| 21 | +#include <linux/fscache.h> | |
| 20 | 22 | |
| 21 | 23 | #include <linux/ceph/libceph.h> |
| 22 | 24 | |
| 23 | −#ifdef CONFIG_CEPH_FSCACHE | |
| 24 | −#include <linux/fscache.h> | |
| 25 | −#endif | |
| 26 | − | |
| 27 | 25 | /* large granularity for statfs utilization stats to facilitate |
| 28 | 26 | * large volume sizes on 32-bit machines. */ |
| 29 | 27 | #define CEPH_BLOCK_SHIFT 22 /* 4 MB */ |
| @@ -317,6 +315,11 @@ struct ceph_inode_xattrs_info { · 287 unmodified lines | ||
| 317 | 315 | * Ceph inode. |
| 318 | 316 | */ |
| 319 | 317 | struct ceph_inode_info { |
| 318 | + struct { | |
| 319 | + /* These must be contiguous */ | |
| 320 | + struct inode vfs_inode; | |
| 321 | + struct netfs_i_context netfs_ctx; /* Netfslib context */ | |
| 322 | + }; | |
| 320 | 323 | struct ceph_vino i_vino; /* ceph ino + snap */ |
| 321 | 324 | |
| 322 | 325 | spinlock_t i_ceph_lock; |
| @@ -427,11 +430,6 @@ struct ceph_inode_info { · 104 unmodified lines | ||
| 427 | 430 | |
| 428 | 431 | struct work_struct i_work; |
| 429 | 432 | unsigned long i_work_mask; |
| 430 | − | |
| 431 | −#ifdef CONFIG_CEPH_FSCACHE | |
| 432 | − struct fscache_cookie *fscache; | |
| 433 | −#endif | |
| 434 | − struct inode vfs_inode; /* at end */ | |
| 435 | 433 | }; |
| 436 | 434 | |
| 437 | 435 | static inline struct ceph_inode_info * |
| @@ -1215,6 +1213,7 @@ extern void __ceph_touch_fmode(struct ceph_inode_info *ci, · 777 unmodified lines | ||
| 1215 | 1213 | |
| 1216 | 1214 | /* addr.c */ |
| 1217 | 1215 | extern const struct address_space_operations ceph_aops; |
| 1216 | +extern const struct netfs_request_ops ceph_netfs_ops; | |
| 1218 | 1217 | extern int ceph_mmap(struct file *file, struct vm_area_struct *vma); |
| 1219 | 1218 | extern int ceph_uninline_data(struct file *file); |
| 1220 | 1219 | extern int ceph_pool_perm_check(struct inode *inode, int need); |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/mempool.h> |
| 17 | 17 | #include <linux/workqueue.h> |
| 18 | 18 | #include <linux/utsname.h> |
| 19 | +#include <linux/netfs.h> | |
| 19 | 20 | #include "cifs_fs_sb.h" |
| 20 | 21 | #include "cifsacl.h" |
| 21 | 22 | #include <crypto/internal/hash.h> |
| @@ -1402,6 +1403,11 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file); · 1380 unmodified lines | ||
| 1402 | 1403 | */ |
| 1403 | 1404 | |
| 1404 | 1405 | struct cifsInodeInfo { |
| 1406 | + struct { | |
| 1407 | + /* These must be contiguous */ | |
| 1408 | + struct inode vfs_inode; /* the VFS's inode record */ | |
| 1409 | + struct netfs_i_context netfs_ctx; /* Netfslib context */ | |
| 1410 | + }; | |
| 1405 | 1411 | bool can_cache_brlcks; |
| 1406 | 1412 | struct list_head llist; /* locks helb by this inode */ |
| 1407 | 1413 | /* |
| @@ -1432,10 +1438,6 @@ struct cifsInodeInfo { · 24 unmodified lines | ||
| 1432 | 1438 | u64 uniqueid; /* server inode number */ |
| 1433 | 1439 | u64 createtime; /* creation time on server */ |
| 1434 | 1440 | __u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for this inode */ |
| 1435 | −#ifdef CONFIG_CIFS_FSCACHE | |
| 1436 | − struct fscache_cookie *fscache; | |
| 1437 | −#endif | |
| 1438 | − struct inode vfs_inode; | |
| 1439 | 1441 | struct list_head deferred_closes; /* list of deferred closes */ |
| 1440 | 1442 | spinlock_t deferred_lock; /* protection on deferred list */ |
| 1441 | 1443 | bool lease_granted; /* Flag to indicate whether lease or oplock is granted. */ |
| @@ -103,7 +103,7 @@ void cifs_fscache_get_inode_cookie(struct inode *inode) · 102 unmodified lines | ||
| 103 | 103 | |
| 104 | 104 | cifs_fscache_fill_coherency(&cifsi->vfs_inode, &cd); |
| 105 | 105 | |
| 106 | − cifsi->fscache = | |
| 106 | + cifsi->netfs_ctx.cache = | |
| 107 | 107 | fscache_acquire_cookie(tcon->fscache, 0, |
| 108 | 108 | &cifsi->uniqueid, sizeof(cifsi->uniqueid), |
| 109 | 109 | &cd, sizeof(cd), |
| @@ -126,11 +126,12 @@ void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update) · 16 unmodified lines | ||
| 126 | 126 | void cifs_fscache_release_inode_cookie(struct inode *inode) |
| 127 | 127 | { |
| 128 | 128 | struct cifsInodeInfo *cifsi = CIFS_I(inode); |
| 129 | + struct fscache_cookie *cookie = cifs_inode_cookie(inode); | |
| 129 | 130 | |
| 130 | − if (cifsi->fscache) { | |
| 131 | − cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache); | |
| 132 | − fscache_relinquish_cookie(cifsi->fscache, false); | |
| 133 | − cifsi->fscache = NULL; | |
| 131 | + if (cookie) { | |
| 132 | + cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cookie); | |
| 133 | + fscache_relinquish_cookie(cookie, false); | |
| 134 | + cifsi->netfs_ctx.cache = NULL; | |
| 134 | 135 | } |
| 135 | 136 | } |
| 136 | 137 | |
| @@ -61,7 +61,7 @@ void cifs_fscache_fill_coherency(struct inode *inode, · 60 unmodified lines | ||
| 61 | 61 | |
| 62 | 62 | static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode) |
| 63 | 63 | { |
| 64 | − return CIFS_I(inode)->fscache; | |
| 64 | + return netfs_i_cookie(inode); | |
| 65 | 65 | } |
| 66 | 66 | |
| 67 | 67 | static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags) |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | #include <linux/netfs.h> |
| 9 | +#include <linux/fscache.h> | |
| 9 | 10 | #include <trace/events/netfs.h> |
| 10 | 11 | |
| 11 | 12 | #ifdef pr_fmt |
| @@ -19,8 +20,6 @@ · 7 unmodified lines | ||
| 19 | 20 | */ |
| 20 | 21 | struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, |
| 21 | 22 | struct file *file, |
| 22 | − const struct netfs_request_ops *ops, | |
| 23 | − void *netfs_priv, | |
| 24 | 23 | loff_t start, size_t len, |
| 25 | 24 | enum netfs_io_origin origin); |
| 26 | 25 | void netfs_get_request(struct netfs_io_request *rreq, enum netfs_rreq_ref_trace what); |
| @@ -81,6 +80,21 @@ static inline void netfs_stat_d(atomic_t *stat) · 54 unmodified lines | ||
| 81 | 80 | #define netfs_stat_d(x) do {} while(0) |
| 82 | 81 | #endif |
| 83 | 82 | |
| 83 | +/* | |
| 84 | + * Miscellaneous functions. | |
| 85 | + */ | |
| 86 | +static inline bool netfs_is_cache_enabled(struct netfs_i_context *ctx) | |
| 87 | +{ | |
| 88 | +#if IS_ENABLED(CONFIG_FSCACHE) | |
| 89 | + struct fscache_cookie *cookie = ctx->cache; | |
| 90 | + | |
| 91 | + return fscache_cookie_valid(cookie) && cookie->cache_priv && | |
| 92 | + fscache_cookie_enabled(cookie); | |
| 93 | +#else | |
| 94 | + return false; | |
| 95 | +#endif | |
| 96 | +} | |
| 97 | + | |
| 84 | 98 | /*****************************************************************************/ |
| 85 | 99 | /* |
| 86 | 100 | * debug tracing |
| @@ -13,12 +13,12 @@ · 12 unmodified lines | ||
| 13 | 13 | */ |
| 14 | 14 | struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, |
| 15 | 15 | struct file *file, |
| 16 | − const struct netfs_request_ops *ops, | |
| 17 | − void *netfs_priv, | |
| 18 | 16 | loff_t start, size_t len, |
| 19 | 17 | enum netfs_io_origin origin) |
| 20 | 18 | { |
| 21 | 19 | static atomic_t debug_ids; |
| 20 | + struct inode *inode = file ? file_inode(file) : mapping->host; | |
| 21 | + struct netfs_i_context *ctx = netfs_i_context(inode); | |
| 22 | 22 | struct netfs_io_request *rreq; |
| 23 | 23 | int ret; |
| 24 | 24 | |
| @@ -29,11 +29,10 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, · 4 unmodified lines | ||
| 29 | 29 | rreq->start = start; |
| 30 | 30 | rreq->len = len; |
| 31 | 31 | rreq->origin = origin; |
| 32 | − rreq->netfs_ops = ops; | |
| 33 | − rreq->netfs_priv = netfs_priv; | |
| 32 | + rreq->netfs_ops = ctx->ops; | |
| 34 | 33 | rreq->mapping = mapping; |
| 35 | − rreq->inode = file_inode(file); | |
| 36 | − rreq->i_size = i_size_read(rreq->inode); | |
| 34 | + rreq->inode = inode; | |
| 35 | + rreq->i_size = i_size_read(inode); | |
| 37 | 36 | rreq->debug_id = atomic_inc_return(&debug_ids); |
| 38 | 37 | INIT_LIST_HEAD(&rreq->subrequests); |
| 39 | 38 | INIT_WORK(&rreq->work, netfs_rreq_work); |
| @@ -76,6 +75,7 @@ static void netfs_free_request(struct work_struct *work) · 36 unmodified lines | ||
| 76 | 75 | { |
| 77 | 76 | struct netfs_io_request *rreq = |
| 78 | 77 | container_of(work, struct netfs_io_request, work); |
| 78 | + | |
| 79 | 79 | netfs_clear_subrequests(rreq, false); |
| 80 | 80 | if (rreq->netfs_priv) |
| 81 | 81 | rreq->netfs_ops->cleanup(rreq->mapping, rreq->netfs_priv); |
| @@ -14,7 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/uio.h> |
| 15 | 15 | #include <linux/sched/mm.h> |
| 16 | 16 | #include <linux/task_io_accounting_ops.h> |
| 17 | −#include <linux/netfs.h> | |
| 18 | 17 | #include "internal.h" |
| 19 | 18 | #define CREATE_TRACE_POINTS |
| 20 | 19 | #include <trace/events/netfs.h> |
| @@ -735,8 +734,6 @@ static void netfs_rreq_expand(struct netfs_io_request *rreq, · 714 unmodified lines | ||
| 735 | 734 | /** |
| 736 | 735 | * netfs_readahead - Helper to manage a read request |
| 737 | 736 | * @ractl: The description of the readahead request |
| 738 | − * @ops: The network filesystem's operations for the helper to use | |
| 739 | − * @netfs_priv: Private netfs data to be retained in the request | |
| 740 | 737 | * |
| 741 | 738 | * Fulfil a readahead request by drawing data from the cache if possible, or |
| 742 | 739 | * the netfs if not. Space beyond the EOF is zero-filled. Multiple I/O |
| @@ -744,35 +741,32 @@ static void netfs_rreq_expand(struct netfs_io_request *rreq, · 1 unmodified line | ||
| 744 | 741 | * readahead window can be expanded in either direction to a more convenient |
| 745 | 742 | * alighment for RPC efficiency or to make storage in the cache feasible. |
| 746 | 743 | * |
| 747 | − * The calling netfs must provide a table of operations, only one of which, | |
| 748 | − * issue_op, is mandatory. It may also be passed a private token, which will | |
| 749 | − * be retained in rreq->netfs_priv and will be cleaned up by ops->cleanup(). | |
| 744 | + * The calling netfs must initialise a netfs context contiguous to the vfs | |
| 745 | + * inode before calling this. | |
| 750 | 746 | * |
| 751 | 747 | * This is usable whether or not caching is enabled. |
| 752 | 748 | */ |
| 753 | −void netfs_readahead(struct readahead_control *ractl, | |
| 754 | − const struct netfs_request_ops *ops, | |
| 755 | − void *netfs_priv) | |
| 749 | +void netfs_readahead(struct readahead_control *ractl) | |
| 756 | 750 | { |
| 757 | 751 | struct netfs_io_request *rreq; |
| 752 | + struct netfs_i_context *ctx = netfs_i_context(ractl->mapping->host); | |
| 758 | 753 | unsigned int debug_index = 0; |
| 759 | 754 | int ret; |
| 760 | 755 | |
| 761 | 756 | _enter("%lx,%x", readahead_index(ractl), readahead_count(ractl)); |
| 762 | 757 | |
| 763 | 758 | if (readahead_count(ractl) == 0) |
| 764 | − goto cleanup; | |
| 759 | + return; | |
| 765 | 760 | |
| 766 | 761 | rreq = netfs_alloc_request(ractl->mapping, ractl->file, |
| 767 | − ops, netfs_priv, | |
| 768 | 762 | readahead_pos(ractl), |
| 769 | 763 | readahead_length(ractl), |
| 770 | 764 | NETFS_READAHEAD); |
| 771 | 765 | if (IS_ERR(rreq)) |
| 772 | − goto cleanup; | |
| 766 | + return; | |
| 773 | 767 | |
| 774 | − if (ops->begin_cache_operation) { | |
| 775 | − ret = ops->begin_cache_operation(rreq); | |
| 768 | + if (ctx->ops->begin_cache_operation) { | |
| 769 | + ret = ctx->ops->begin_cache_operation(rreq); | |
| 776 | 770 | if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS) |
| 777 | 771 | goto cleanup_free; |
| 778 | 772 | } |
| @@ -804,42 +798,35 @@ void netfs_readahead(struct readahead_control *ractl, · 25 unmodified lines | ||
| 804 | 798 | cleanup_free: |
| 805 | 799 | netfs_put_request(rreq, false, netfs_rreq_trace_put_failed); |
| 806 | 800 | return; |
| 807 | −cleanup: | |
| 808 | − if (netfs_priv) | |
| 809 | − ops->cleanup(ractl->mapping, netfs_priv); | |
| 810 | − return; | |
| 811 | 801 | } |
| 812 | 802 | EXPORT_SYMBOL(netfs_readahead); |
| 813 | 803 | |
| 814 | 804 | /** |
| 815 | 805 | * netfs_readpage - Helper to manage a readpage request |
| 816 | 806 | * @file: The file to read from |
| 817 | − * @folio: The folio to read | |
| 818 | − * @ops: The network filesystem's operations for the helper to use | |
| 819 | − * @netfs_priv: Private netfs data to be retained in the request | |
| 807 | + * @subpage: A subpage of the folio to read | |
| 820 | 808 | * |
| 821 | 809 | * Fulfil a readpage request by drawing data from the cache if possible, or the |
| 822 | 810 | * netfs if not. Space beyond the EOF is zero-filled. Multiple I/O requests |
| 823 | 811 | * from different sources will get munged together. |
| 824 | 812 | * |
| 825 | − * The calling netfs must provide a table of operations, only one of which, | |
| 826 | − * issue_op, is mandatory. It may also be passed a private token, which will | |
| 827 | − * be retained in rreq->netfs_priv and will be cleaned up by ops->cleanup(). | |
| 813 | + * The calling netfs must initialise a netfs context contiguous to the vfs | |
| 814 | + * inode before calling this. | |
| 828 | 815 | * |
| 829 | 816 | * This is usable whether or not caching is enabled. |
| 830 | 817 | */ |
| 831 | −int netfs_readpage(struct file *file, | |
| 832 | − struct folio *folio, | |
| 833 | − const struct netfs_request_ops *ops, | |
| 834 | − void *netfs_priv) | |
| 818 | +int netfs_readpage(struct file *file, struct page *subpage) | |
| 835 | 819 | { |
| 820 | + struct folio *folio = page_folio(subpage); | |
| 821 | + struct address_space *mapping = folio->mapping; | |
| 836 | 822 | struct netfs_io_request *rreq; |
| 823 | + struct netfs_i_context *ctx = netfs_i_context(mapping->host); | |
| 837 | 824 | unsigned int debug_index = 0; |
| 838 | 825 | int ret; |
| 839 | 826 | |
| 840 | 827 | _enter("%lx", folio_index(folio)); |
| 841 | 828 | |
| 842 | − rreq = netfs_alloc_request(folio->mapping, file, ops, netfs_priv, | |
| 829 | + rreq = netfs_alloc_request(mapping, file, | |
| 843 | 830 | folio_file_pos(folio), folio_size(folio), |
| 844 | 831 | NETFS_READPAGE); |
| 845 | 832 | if (IS_ERR(rreq)) { |
| @@ -847,8 +834,8 @@ int netfs_readpage(struct file *file, · 1 unmodified line | ||
| 847 | 834 | goto alloc_error; |
| 848 | 835 | } |
| 849 | 836 | |
| 850 | − if (ops->begin_cache_operation) { | |
| 851 | − ret = ops->begin_cache_operation(rreq); | |
| 837 | + if (ctx->ops->begin_cache_operation) { | |
| 838 | + ret = ctx->ops->begin_cache_operation(rreq); | |
| 852 | 839 | if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS) { |
| 853 | 840 | folio_unlock(folio); |
| 854 | 841 | goto out; |
| @@ -886,8 +873,6 @@ out: · 31 unmodified lines | ||
| 886 | 873 | netfs_put_request(rreq, false, netfs_rreq_trace_put_hold); |
| 887 | 874 | return ret; |
| 888 | 875 | alloc_error: |
| 889 | − if (netfs_priv) | |
| 890 | − ops->cleanup(folio_file_mapping(folio), netfs_priv); | |
| 891 | 876 | folio_unlock(folio); |
| 892 | 877 | return ret; |
| 893 | 878 | } |
| @@ -898,6 +883,7 @@ EXPORT_SYMBOL(netfs_readpage); · 4 unmodified lines | ||
| 898 | 883 | * @folio: The folio being prepared |
| 899 | 884 | * @pos: starting position for the write |
| 900 | 885 | * @len: length of write |
| 886 | + * @always_fill: T if the folio should always be completely filled/cleared | |
| 901 | 887 | * |
| 902 | 888 | * In some cases, write_begin doesn't need to read at all: |
| 903 | 889 | * - full folio write |
| @@ -907,17 +893,27 @@ EXPORT_SYMBOL(netfs_readpage); · 3 unmodified lines | ||
| 907 | 893 | * If any of these criteria are met, then zero out the unwritten parts |
| 908 | 894 | * of the folio and return true. Otherwise, return false. |
| 909 | 895 | */ |
| 910 | −static bool netfs_skip_folio_read(struct folio *folio, loff_t pos, size_t len) | |
| 896 | +static bool netfs_skip_folio_read(struct folio *folio, loff_t pos, size_t len, | |
| 897 | + bool always_fill) | |
| 911 | 898 | { |
| 912 | 899 | struct inode *inode = folio_inode(folio); |
| 913 | 900 | loff_t i_size = i_size_read(inode); |
| 914 | 901 | size_t offset = offset_in_folio(folio, pos); |
| 902 | + size_t plen = folio_size(folio); | |
| 903 | + | |
| 904 | + if (unlikely(always_fill)) { | |
| 905 | + if (pos - offset + len <= i_size) | |
| 906 | + return false; /* Page entirely before EOF */ | |
| 907 | + zero_user_segment(&folio->page, 0, plen); | |
| 908 | + folio_mark_uptodate(folio); | |
| 909 | + return true; | |
| 910 | + } | |
| 915 | 911 | |
| 916 | 912 | /* Full folio write */ |
| 917 | − if (offset == 0 && len >= folio_size(folio)) | |
| 913 | + if (offset == 0 && len >= plen) | |
| 918 | 914 | return true; |
| 919 | 915 | |
| 920 | − /* pos beyond last folio in the file */ | |
| 916 | + /* Page entirely beyond the end of the file */ | |
| 921 | 917 | if (pos - offset >= i_size) |
| 922 | 918 | goto zero_out; |
| 923 | 919 | |
| @@ -927,7 +923,7 @@ static bool netfs_skip_folio_read(struct folio *folio, loff_t pos, size_t len) · 3 unmodified lines | ||
| 927 | 923 | |
| 928 | 924 | return false; |
| 929 | 925 | zero_out: |
| 930 | − zero_user_segments(&folio->page, 0, offset, offset + len, folio_size(folio)); | |
| 926 | + zero_user_segments(&folio->page, 0, offset, offset + len, plen); | |
| 931 | 927 | return true; |
| 932 | 928 | } |
| 933 | 929 | |
| @@ -940,8 +936,6 @@ zero_out: · 6 unmodified lines | ||
| 940 | 936 | * @aop_flags: AOP_* flags |
| 941 | 937 | * @_folio: Where to put the resultant folio |
| 942 | 938 | * @_fsdata: Place for the netfs to store a cookie |
| 943 | − * @ops: The network filesystem's operations for the helper to use | |
| 944 | − * @netfs_priv: Private netfs data to be retained in the request | |
| 945 | 939 | * |
| 946 | 940 | * Pre-read data for a write-begin request by drawing data from the cache if |
| 947 | 941 | * possible, or the netfs if not. Space beyond the EOF is zero-filled. |
| @@ -960,17 +954,18 @@ zero_out: · 12 unmodified lines | ||
| 960 | 954 | * should go ahead; unlock the folio and return -EAGAIN to cause the folio to |
| 961 | 955 | * be regot; or return an error. |
| 962 | 956 | * |
| 957 | + * The calling netfs must initialise a netfs context contiguous to the vfs | |
| 958 | + * inode before calling this. | |
| 959 | + * | |
| 963 | 960 | * This is usable whether or not caching is enabled. |
| 964 | 961 | */ |
| 965 | 962 | int netfs_write_begin(struct file *file, struct address_space *mapping, |
| 966 | 963 | loff_t pos, unsigned int len, unsigned int aop_flags, |
| 967 | − struct folio **_folio, void **_fsdata, | |
| 968 | − const struct netfs_request_ops *ops, | |
| 969 | − void *netfs_priv) | |
| 964 | + struct folio **_folio, void **_fsdata) | |
| 970 | 965 | { |
| 971 | 966 | struct netfs_io_request *rreq; |
| 967 | + struct netfs_i_context *ctx = netfs_i_context(file_inode(file )); | |
| 972 | 968 | struct folio *folio; |
| 973 | − struct inode *inode = file_inode(file); | |
| 974 | 969 | unsigned int debug_index = 0, fgp_flags; |
| 975 | 970 | pgoff_t index = pos >> PAGE_SHIFT; |
| 976 | 971 | int ret; |
| @@ -986,9 +981,9 @@ retry: · 9 unmodified lines | ||
| 986 | 981 | if (!folio) |
| 987 | 982 | return -ENOMEM; |
| 988 | 983 | |
| 989 | − if (ops->check_write_begin) { | |
| 984 | + if (ctx->ops->check_write_begin) { | |
| 990 | 985 | /* Allow the netfs (eg. ceph) to flush conflicts. */ |
| 991 | − ret = ops->check_write_begin(file, pos, len, folio, _fsdata); | |
| 986 | + ret = ctx->ops->check_write_begin(file, pos, len, folio, _fsdata); | |
| 992 | 987 | if (ret < 0) { |
| 993 | 988 | trace_netfs_failure(NULL, NULL, ret, netfs_fail_check_write_begin); |
| 994 | 989 | if (ret == -EAGAIN) |
| @@ -1004,13 +999,13 @@ retry: · 9 unmodified lines | ||
| 1004 | 999 | * within the cache granule containing the EOF, in which case we need |
| 1005 | 1000 | * to preload the granule. |
| 1006 | 1001 | */ |
| 1007 | − if (!ops->is_cache_enabled(inode) && | |
| 1008 | − netfs_skip_folio_read(folio, pos, len)) { | |
| 1002 | + if (!netfs_is_cache_enabled(ctx) && | |
| 1003 | + netfs_skip_folio_read(folio, pos, len, false)) { | |
| 1009 | 1004 | netfs_stat(&netfs_n_rh_write_zskip); |
| 1010 | 1005 | goto have_folio_no_wait; |
| 1011 | 1006 | } |
| 1012 | 1007 | |
| 1013 | − rreq = netfs_alloc_request(mapping, file, ops, netfs_priv, | |
| 1008 | + rreq = netfs_alloc_request(mapping, file, | |
| 1014 | 1009 | folio_file_pos(folio), folio_size(folio), |
| 1015 | 1010 | NETFS_READ_FOR_WRITE); |
| 1016 | 1011 | if (IS_ERR(rreq)) { |
| @@ -1019,10 +1014,9 @@ retry: · 2 unmodified lines | ||
| 1019 | 1014 | } |
| 1020 | 1015 | rreq->no_unlock_folio = folio_index(folio); |
| 1021 | 1016 | __set_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags); |
| 1022 | − netfs_priv = NULL; | |
| 1023 | 1017 | |
| 1024 | − if (ops->begin_cache_operation) { | |
| 1025 | − ret = ops->begin_cache_operation(rreq); | |
| 1018 | + if (ctx->ops->begin_cache_operation) { | |
| 1019 | + ret = ctx->ops->begin_cache_operation(rreq); | |
| 1026 | 1020 | if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS) |
| 1027 | 1021 | goto error_put; |
| 1028 | 1022 | } |
| @@ -1076,8 +1070,6 @@ have_folio: · 47 unmodified lines | ||
| 1076 | 1070 | if (ret < 0) |
| 1077 | 1071 | goto error; |
| 1078 | 1072 | have_folio_no_wait: |
| 1079 | − if (netfs_priv) | |
| 1080 | − ops->cleanup(mapping, netfs_priv); | |
| 1081 | 1073 | *_folio = folio; |
| 1082 | 1074 | _leave(" = 0"); |
| 1083 | 1075 | return 0; |
| @@ -1087,8 +1079,6 @@ error_put: · 3 unmodified lines | ||
| 1087 | 1079 | error: |
| 1088 | 1080 | folio_unlock(folio); |
| 1089 | 1081 | folio_put(folio); |
| 1090 | − if (netfs_priv) | |
| 1091 | − ops->cleanup(mapping, netfs_priv); | |
| 1092 | 1082 | _leave(" = %d", ret); |
| 1093 | 1083 | return ret; |
| 1094 | 1084 | } |
| @@ -7,7 +7,6 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | #include <linux/export.h> |
| 9 | 9 | #include <linux/seq_file.h> |
| 10 | −#include <linux/netfs.h> | |
| 11 | 10 | #include "internal.h" |
| 12 | 11 | |
| 13 | 12 | atomic_t netfs_n_rh_readahead; |
| @@ -118,6 +118,16 @@ enum netfs_io_source { · 117 unmodified lines | ||
| 118 | 118 | typedef void (*netfs_io_terminated_t)(void *priv, ssize_t transferred_or_error, |
| 119 | 119 | bool was_async); |
| 120 | 120 | |
| 121 | +/* | |
| 122 | + * Per-inode description. This must be directly after the inode struct. | |
| 123 | + */ | |
| 124 | +struct netfs_i_context { | |
| 125 | + const struct netfs_request_ops *ops; | |
| 126 | +#if IS_ENABLED(CONFIG_FSCACHE) | |
| 127 | + struct fscache_cookie *cache; | |
| 128 | +#endif | |
| 129 | +}; | |
| 130 | + | |
| 121 | 131 | /* |
| 122 | 132 | * Resources required to do operations on a cache. |
| 123 | 133 | */ |
| @@ -192,7 +202,6 @@ struct netfs_io_request { · 68 unmodified lines | ||
| 192 | 202 | * Operations the network filesystem can/must provide to the helpers. |
| 193 | 203 | */ |
| 194 | 204 | struct netfs_request_ops { |
| 195 | − bool (*is_cache_enabled)(struct inode *inode); | |
| 196 | 205 | int (*init_request)(struct netfs_io_request *rreq, struct file *file); |
| 197 | 206 | int (*begin_cache_operation)(struct netfs_io_request *rreq); |
| 198 | 207 | void (*expand_readahead)(struct netfs_io_request *rreq); |
| @@ -263,18 +272,11 @@ struct netfs_cache_ops { · 64 unmodified lines | ||
| 263 | 272 | }; |
| 264 | 273 | |
| 265 | 274 | struct readahead_control; |
| 266 | −extern void netfs_readahead(struct readahead_control *, | |
| 267 | − const struct netfs_request_ops *, | |
| 268 | − void *); | |
| 269 | −extern int netfs_readpage(struct file *, | |
| 270 | − struct folio *, | |
| 271 | − const struct netfs_request_ops *, | |
| 272 | − void *); | |
| 275 | +extern void netfs_readahead(struct readahead_control *); | |
| 276 | +extern int netfs_readpage(struct file *, struct page *); | |
| 273 | 277 | extern int netfs_write_begin(struct file *, struct address_space *, |
| 274 | 278 | loff_t, unsigned int, unsigned int, struct folio **, |
| 275 | − void **, | |
| 276 | − const struct netfs_request_ops *, | |
| 277 | − void *); | |
| 279 | + void **); | |
| 278 | 280 | |
| 279 | 281 | extern void netfs_subreq_terminated(struct netfs_io_subrequest *, ssize_t, bool); |
| 280 | 282 | extern void netfs_get_subrequest(struct netfs_io_subrequest *subreq, |
| @@ -283,4 +285,61 @@ extern void netfs_put_subrequest(struct netfs_io_subrequest *subreq, · 2 unmodified lines | ||
| 283 | 285 | bool was_async, enum netfs_sreq_ref_trace what); |
| 284 | 286 | extern void netfs_stats_show(struct seq_file *); |
| 285 | 287 | |
| 288 | +/** | |
| 289 | + * netfs_i_context - Get the netfs inode context from the inode | |
| 290 | + * @inode: The inode to query | |
| 291 | + * | |
| 292 | + * Get the netfs lib inode context from the network filesystem's inode. The | |
| 293 | + * context struct is expected to directly follow on from the VFS inode struct. | |
| 294 | + */ | |
| 295 | +static inline struct netfs_i_context *netfs_i_context(struct inode *inode) | |
| 296 | +{ | |
| 297 | + return (struct netfs_i_context *)(inode + 1); | |
| 298 | +} | |
| 299 | + | |
| 300 | +/** | |
| 301 | + * netfs_inode - Get the netfs inode from the inode context | |
| 302 | + * @ctx: The context to query | |
| 303 | + * | |
| 304 | + * Get the netfs inode from the netfs library's inode context. The VFS inode | |
| 305 | + * is expected to directly precede the context struct. | |
| 306 | + */ | |
| 307 | +static inline struct inode *netfs_inode(struct netfs_i_context *ctx) | |
| 308 | +{ | |
| 309 | + return ((struct inode *)ctx) - 1; | |
| 310 | +} | |
| 311 | + | |
| 312 | +/** | |
| 313 | + * netfs_i_context_init - Initialise a netfs lib context | |
| 314 | + * @inode: The inode with which the context is associated | |
| 315 | + * @ops: The netfs's operations list | |
| 316 | + * | |
| 317 | + * Initialise the netfs library context struct. This is expected to follow on | |
| 318 | + * directly from the VFS inode struct. | |
| 319 | + */ | |
| 320 | +static inline void netfs_i_context_init(struct inode *inode, | |
| 321 | + const struct netfs_request_ops *ops) | |
| 322 | +{ | |
| 323 | + struct netfs_i_context *ctx = netfs_i_context(inode); | |
| 324 | + | |
| 325 | + memset(ctx, 0, sizeof(*ctx)); | |
| 326 | + ctx->ops = ops; | |
| 327 | +} | |
| 328 | + | |
| 329 | +/** | |
| 330 | + * netfs_i_cookie - Get the cache cookie from the inode | |
| 331 | + * @inode: The inode to query | |
| 332 | + * | |
| 333 | + * Get the caching cookie (if enabled) from the network filesystem's inode. | |
| 334 | + */ | |
| 335 | +static inline struct fscache_cookie *netfs_i_cookie(struct inode *inode) | |
| 336 | +{ | |
| 337 | +#if IS_ENABLED(CONFIG_FSCACHE) | |
| 338 | + struct netfs_i_context *ctx = netfs_i_context(inode); | |
| 339 | + return ctx->cache; | |
| 340 | +#else | |
| 341 | + return NULL; | |
| 342 | +#endif | |
| 343 | +} | |
| 344 | + | |
| 286 | 345 | #endif /* _LINUX_NETFS_H */ |