mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 17:30:02 +00:00
![David Howells](/assets/img/avatar_default.png)
Currently, the cifs I/O paths hand lists of pages from the VM interface routines at the top all the way through the intervening layers to the socket interface at the bottom. This is a problem, however, for interfacing with netfslib which passes an iterator through to the ->issue_read() method (and will pass an iterator through to the ->issue_write() method in future). Netfslib takes over bounce buffering for direct I/O, async I/O and encrypted content, so cifs doesn't need to do that. Netfslib also converts IOVEC-type iterators into BVEC-type iterators if necessary. Further, cifs needs foliating - and folios may come in a variety of sizes, so a page list pointing to an array of heterogeneous pages may cause problems in places such as where crypto is done. Change the cifs I/O paths to hand iov_iter iterators all the way through instead. Notes: (1) Some old routines are #if'd out to be removed in a follow up patch so as to avoid confusing diff, thereby making the diff output easier to follow. I've removed functions that don't overlap with anything added. (2) struct smb_rqst loses rq_pages, rq_offset, rq_npages, rq_pagesz and rq_tailsz which describe the pages forming the buffer; instead there's an rq_iter describing the source buffer and an rq_buffer which is used to hold the buffer for encryption. (3) struct cifs_readdata and cifs_writedata are similarly modified to smb_rqst. The ->read_into_pages() and ->copy_into_pages() are then replaced with passing the iterator directly to the socket. The iterators are stored in these structs so that they are persistent and don't get deallocated when the function returns (unlike if they were stack variables). (4) Buffered writeback is overhauled, borrowing the code from the afs filesystem to gather up contiguous runs of folios. The XARRAY-type iterator is then used to refer directly to the pagecache and can be passed to the socket to transmit data directly from there. This includes: cifs_extend_writeback() cifs_write_back_from_locked_folio() cifs_writepages_region() cifs_writepages() (5) Pages are converted to folios. (6) Direct I/O uses netfs_extract_user_iter() to create a BVEC-type iterator from an IOBUF/UBUF-type source iterator. (7) smb2_get_aead_req() uses netfs_extract_iter_to_sg() to extract page fragments from the iterator into the scatterlists that the crypto layer prefers. (8) smb2_init_transform_rq() attached pages to smb_rqst::rq_buffer, an xarray, to use as a bounce buffer for encryption. An XARRAY-type iterator can then be used to pass the bounce buffer to lower layers. Signed-off-by: David Howells <dhowells@redhat.com> cc: Steve French <sfrench@samba.org> cc: Shyam Prasad N <nspmangalore@gmail.com> cc: Rohith Surabattula <rohiths.msft@gmail.com> cc: Paulo Alcantara <pc@cjr.nz> cc: Jeff Layton <jlayton@kernel.org> cc: linux-cifs@vger.kernel.org Link: https://lore.kernel.org/r/164311907995.2806745.400147335497304099.stgit@warthog.procyon.org.uk/ # rfc Link: https://lore.kernel.org/r/164928620163.457102.11602306234438271112.stgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/165211420279.3154751.15923591172438186144.stgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/165348880385.2106726.3220789453472800240.stgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/165364827111.3334034.934805882842932881.stgit@warthog.procyon.org.uk/ # v3 Link: https://lore.kernel.org/r/166126396180.708021.271013668175370826.stgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/166697259595.61150.5982032408321852414.stgit@warthog.procyon.org.uk/ # rfc Link: https://lore.kernel.org/r/166732031756.3186319.12528413619888902872.stgit@warthog.procyon.org.uk/ # rfc Signed-off-by: Steve French <stfrench@microsoft.com>
148 lines
4.3 KiB
C
148 lines
4.3 KiB
C
/* SPDX-License-Identifier: LGPL-2.1 */
|
|
/*
|
|
* CIFS filesystem cache interface definitions
|
|
*
|
|
* Copyright (c) 2010 Novell, Inc.
|
|
* Authors(s): Suresh Jayaraman (sjayaraman@suse.de>
|
|
*
|
|
*/
|
|
#ifndef _CIFS_FSCACHE_H
|
|
#define _CIFS_FSCACHE_H
|
|
|
|
#include <linux/swap.h>
|
|
#include <linux/fscache.h>
|
|
|
|
#include "cifsglob.h"
|
|
|
|
/*
|
|
* Coherency data attached to CIFS volume within the cache
|
|
*/
|
|
struct cifs_fscache_volume_coherency_data {
|
|
__le64 resource_id; /* unique server resource id */
|
|
__le64 vol_create_time;
|
|
__le32 vol_serial_number;
|
|
} __packed;
|
|
|
|
/*
|
|
* Coherency data attached to CIFS inode within the cache.
|
|
*/
|
|
struct cifs_fscache_inode_coherency_data {
|
|
__le64 last_write_time_sec;
|
|
__le64 last_change_time_sec;
|
|
__le32 last_write_time_nsec;
|
|
__le32 last_change_time_nsec;
|
|
};
|
|
|
|
#ifdef CONFIG_CIFS_FSCACHE
|
|
|
|
/*
|
|
* fscache.c
|
|
*/
|
|
extern int cifs_fscache_get_super_cookie(struct cifs_tcon *);
|
|
extern void cifs_fscache_release_super_cookie(struct cifs_tcon *);
|
|
|
|
extern void cifs_fscache_get_inode_cookie(struct inode *inode);
|
|
extern void cifs_fscache_release_inode_cookie(struct inode *);
|
|
extern void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update);
|
|
|
|
static inline
|
|
void cifs_fscache_fill_coherency(struct inode *inode,
|
|
struct cifs_fscache_inode_coherency_data *cd)
|
|
{
|
|
struct cifsInodeInfo *cifsi = CIFS_I(inode);
|
|
|
|
memset(cd, 0, sizeof(*cd));
|
|
cd->last_write_time_sec = cpu_to_le64(cifsi->netfs.inode.i_mtime.tv_sec);
|
|
cd->last_write_time_nsec = cpu_to_le32(cifsi->netfs.inode.i_mtime.tv_nsec);
|
|
cd->last_change_time_sec = cpu_to_le64(cifsi->netfs.inode.i_ctime.tv_sec);
|
|
cd->last_change_time_nsec = cpu_to_le32(cifsi->netfs.inode.i_ctime.tv_nsec);
|
|
}
|
|
|
|
|
|
static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode)
|
|
{
|
|
return netfs_i_cookie(&CIFS_I(inode)->netfs);
|
|
}
|
|
|
|
static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags)
|
|
{
|
|
struct cifs_fscache_inode_coherency_data cd;
|
|
|
|
cifs_fscache_fill_coherency(inode, &cd);
|
|
fscache_invalidate(cifs_inode_cookie(inode), &cd,
|
|
i_size_read(inode), flags);
|
|
}
|
|
|
|
extern int __cifs_fscache_query_occupancy(struct inode *inode,
|
|
pgoff_t first, unsigned int nr_pages,
|
|
pgoff_t *_data_first,
|
|
unsigned int *_data_nr_pages);
|
|
|
|
static inline int cifs_fscache_query_occupancy(struct inode *inode,
|
|
pgoff_t first, unsigned int nr_pages,
|
|
pgoff_t *_data_first,
|
|
unsigned int *_data_nr_pages)
|
|
{
|
|
if (!cifs_inode_cookie(inode))
|
|
return -ENOBUFS;
|
|
return __cifs_fscache_query_occupancy(inode, first, nr_pages,
|
|
_data_first, _data_nr_pages);
|
|
}
|
|
|
|
extern int __cifs_readpage_from_fscache(struct inode *pinode, struct page *ppage);
|
|
extern void __cifs_readahead_to_fscache(struct inode *pinode, loff_t pos, size_t len);
|
|
|
|
|
|
static inline int cifs_readpage_from_fscache(struct inode *inode,
|
|
struct page *page)
|
|
{
|
|
if (cifs_inode_cookie(inode))
|
|
return __cifs_readpage_from_fscache(inode, page);
|
|
return -ENOBUFS;
|
|
}
|
|
|
|
static inline void cifs_readahead_to_fscache(struct inode *inode,
|
|
loff_t pos, size_t len)
|
|
{
|
|
if (cifs_inode_cookie(inode))
|
|
__cifs_readahead_to_fscache(inode, pos, len);
|
|
}
|
|
|
|
#else /* CONFIG_CIFS_FSCACHE */
|
|
static inline
|
|
void cifs_fscache_fill_coherency(struct inode *inode,
|
|
struct cifs_fscache_inode_coherency_data *cd)
|
|
{
|
|
}
|
|
|
|
static inline int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) { return 0; }
|
|
static inline void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) {}
|
|
|
|
static inline void cifs_fscache_get_inode_cookie(struct inode *inode) {}
|
|
static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {}
|
|
static inline void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update) {}
|
|
static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode) { return NULL; }
|
|
static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags) {}
|
|
|
|
static inline int cifs_fscache_query_occupancy(struct inode *inode,
|
|
pgoff_t first, unsigned int nr_pages,
|
|
pgoff_t *_data_first,
|
|
unsigned int *_data_nr_pages)
|
|
{
|
|
*_data_first = ULONG_MAX;
|
|
*_data_nr_pages = 0;
|
|
return -ENOBUFS;
|
|
}
|
|
|
|
static inline int
|
|
cifs_readpage_from_fscache(struct inode *inode, struct page *page)
|
|
{
|
|
return -ENOBUFS;
|
|
}
|
|
|
|
static inline
|
|
void cifs_readahead_to_fscache(struct inode *inode, loff_t pos, size_t len) {}
|
|
|
|
#endif /* CONFIG_CIFS_FSCACHE */
|
|
|
|
#endif /* _CIFS_FSCACHE_H */
|