cifs: Rough, incomplete conversion to new fscache API
Subsystems (3)
PATCH 1/1 cifs: Rough, incomplete conversion to new fscache API
Hi Steve,
Here's a rough, but incomplete, conversion of cifs to use the new fscache API, but I've about hit the limit of what I can manage to do. It's built on top of my fscache-iter branch:
https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=fscache-iter
Notes:
(*) I've replaced some code to discard data by reading into a big buffer with
code that uses the ITER_DISCARD iterator instead. See cifs_discard_from_socket().
(*) I've tried to make the ordinary read use an ITER_XARRAY iterator and read
into that directly from the socket, rather than looping through a bunch of pages. This will handle THPs and partial pages for you. However, under some circumstances, readpages_fill_pages() would then be reading from an iterator to an iterator, it appears. Possibly the source iterator can be got rid of, but the code is quite complex.
(*) There's a new function, cifs_req_issue_op(), which the netfs helpers use
to issue a read on part of a request. This looks at current->tgid, but might be running on a workqueue, so needs to get the tgid from somewhere else if not CIFS_MOUNT_RWPIDFORWARD.
(*) cifs_readpage(), cifs_readahead() and cifs_write_begin() now go through
the helpers. cifs_readpages() is obsolete and is removed.
(*) At the completion of a read, netfs_subreq_terminated() is called. As a
future optimisation, we can add a function to do incremental advancement of the pages, unlocking them as we go. The issue is, however, that we have to coordinate with writing larger page lumps to the cache.
(*) The clause in cifs_write_begin() about optimising away a read when we
have an oplock needs dealing with, but I'm not sure how to fit it in.
(*) cifs_writepages() needs to call fscache_write_to_cache() to write to the
cache.
(*) cifs_write_inode() needs to call fscache_unpin_writeback().
David
---
fs/cifs/Kconfig +1 -1
@@ -206,7 +206,7 @@ config CIFS_SMB_DIRECT config CIFS_FSCACHE bool "Provide CIFS client caching support" - depends on CIFS=m && FSCACHE_OLD || CIFS=y && FSCACHE_OLD=y + depends on CIFS=m || CIFS=y help Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data to be cached locally on disk through the general filesystem cache
fs/cifs/cache.c +0 -95
98 lines not on this page · raw message
fs/cifs/cifsfs.c +2 -0
@@ -372,6 +372,8 @@ static void cifs_evict_inode(struct inode *inode) {truncate_inode_pages_final (&inode->i_data); +if (inode->i_state &I_PINNING_FSCACHE_WB ) +cifs_fscache_unuse_inode_cookie (inode, true);clear_inode (inode);cifs_fscache_release_inode_cookie (inode); }
fs/cifs/cifsglob.h +2 -0
@@ -1367,6 +1367,7 @@ struct cifs_readdata;/* asynchronous read support */ struct cifs_readdata { +struct netfs_read_subrequest *subreq;struct kref refcount;struct list_head list;struct completion done;
@@ -1385,6 +1386,7 @@ struct cifs_readdata {int (*copy_into_pages)(struct TCP_Server_Info *server,struct cifs_readdata *rdata,struct iov_iter *iter); +struct iov_iter iter;struct kvec iov[2 ];struct TCP_Server_Info *server;#ifdef CONFIG_CIFS_SMB_DIRECT
fs/cifs/cifsproto.h +5 -0
@@ -230,10 +230,15 @@ extern unsigned int setup_special_user_owner_ACE(struct cifs_ace *pace);extern void dequeue_mid (struct mid_q_entry *mid,bool malformed);extern int cifs_read_from_socket (struct TCP_Server_Info *server,char *buf,unsigned int to_read); +extern ssize_t cifs_discard_from_socket (struct TCP_Server_Info *server, +size_t to_read);extern int cifs_read_page_from_socket (struct TCP_Server_Info *server,struct page *page,unsigned int page_offset,unsigned int to_read); +extern int cifs_read_iter_from_socket (struct TCP_Server_Info *server, +struct iov_iter *iter, +unsigned int to_read);extern int cifs_setup_cifs_sb (struct smb_vol *pvolume_info,struct cifs_sb_info *cifs_sb);extern int cifs_match_super (struct super_block *,void *);
fs/cifs/cifssmb.c +14 -6
@@ -36,6 +36,7 @@#include <linux/swap.h> #include <linux/task_io_accounting_ops.h> #include <linux/uaccess.h> +#include <linux/netfs.h> #include "cifspdu.h" #include "cifsglob.h" #include "cifsacl.h"
@@ -1445,15 +1446,15 @@ int cifs_discard_remaining_data(struct TCP_Server_Info *server) {unsigned int rfclen = server->pdu_size; -int remaining = rfclen + server->vals->header_preamble_size - +size_t remaining = rfclen + server->vals->header_preamble_size - server->total_read;while (remaining >0 ) { -int length; +ssize_t length; - length =cifs_read_from_socket (server, server->bigbuf, - min_t(unsigned int, remaining, - CIFSMaxBufSize +MAX_HEADER_SIZE (server))); + length =cifs_discard_from_socket (server, +min_t (size_t, remaining, + CIFSMaxBufSize +MAX_HEADER_SIZE (server)));if (length <0 )return length; server->total_read += length;
@@ -1664,7 +1665,14 @@ cifs_readv_callback(struct mid_q_entry *mid) rdata->result = -EIO ; } -queue_work (cifsiod_wq, &rdata->work); +if (rdata->subreq) { +netfs_subreq_terminated (rdata->subreq, + (rdata->result ==0 || rdata->result == -EAGAIN ) ? + rdata->got_bytes : rdata->result); +kref_put (&rdata->refcount, cifs_readdata_release); + }else { +queue_work (cifsiod_wq, &rdata->work); + }DeleteMidQEntry (mid);add_credits (server, &credits,0 ); }
fs/cifs/connect.c +25 -0
@@ -754,6 +754,15 @@ cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,return cifs_readv_from_socket (server, &smb_msg); } +ssize_t +cifs_discard_from_socket (struct TCP_Server_Info *server,size_t to_read) +{ +struct msghdr smb_msg; +iov_iter_discard (&smb_msg.msg_iter,READ , to_read); + +return cifs_readv_from_socket (server, &smb_msg); +} +int cifs_read_page_from_socket (struct TCP_Server_Info *server,struct page *page,unsigned int page_offset,unsigned int to_read)
@@ -765,6 +774,22 @@ cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,return cifs_readv_from_socket (server, &smb_msg); } +int +cifs_read_iter_from_socket (struct TCP_Server_Info *server,struct iov_iter *iter, +unsigned int to_read) +{ +struct msghdr smb_msg; +int ret; + + smb_msg.msg_iter = *iter; +if (smb_msg.msg_iter.count > to_read) + smb_msg.msg_iter.count = to_read; + ret =cifs_readv_from_socket (server, &smb_msg); +if (ret >0 ) +iov_iter_advance (iter, ret); +return ret; +} +static bool is_smb_response (struct TCP_Server_Info *server,unsigned char type) {
fs/cifs/file.c +199 -417
778 lines not on this page · raw message
fs/cifs/fscache.c +52 -204
307 lines not on this page · raw message
fs/cifs/fscache.h +21 -89
140 lines not on this page · raw message
fs/cifs/inode.c +11 -7
@@ -1316,10 +1316,7 @@ cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) inode->i_flags |=S_NOATIME |S_NOCMTIME ;if (inode->i_state &I_NEW ) { inode->i_ino = hash; -#ifdef CONFIG_CIFS_FSCACHE -/* initialize per-inode cache cookie pointer */ -CIFS_I (inode)->fscache =NULL ; -#endif +cifs_fscache_get_inode_cookie (inode);unlock_new_inode (inode); } }
@@ -2213,6 +2210,8 @@ cifs_inode_needs_reval(struct inode *inode)int cifs_invalidate_mapping (struct inode *inode) { +struct cifs_fscache_inode_auxdata auxdata; +struct cifsInodeInfo *cifsi =CIFS_I (inode);int rc =0 ;if (inode->i_mapping && inode->i_mapping->nrpages !=0 ) {
@@ -2222,7 +2221,8 @@ cifs_invalidate_mapping(struct inode *inode) __func__, inode); } -cifs_fscache_reset_inode_cookie (inode); +cifs_fscache_fill_auxdata (&cifsi->vfs_inode, &auxdata); +fscache_invalidate (cifs_inode_cookie (inode), &auxdata,i_size_read (inode),0 );return rc; }
@@ -2704,8 +2704,10 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) goto out;if ((attrs->ia_valid &ATTR_SIZE ) && - attrs->ia_size !=i_size_read (inode)) + attrs->ia_size !=i_size_read (inode)) {truncate_setsize (inode, attrs->ia_size); +fscache_resize_cookie (cifs_inode_cookie (inode), attrs->ia_size); + }setattr_copy (inode, attrs);mark_inode_dirty (inode);
@@ -2894,8 +2896,10 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) goto cifs_setattr_exit;if ((attrs->ia_valid &ATTR_SIZE ) && - attrs->ia_size !=i_size_read (inode)) + attrs->ia_size !=i_size_read (inode)) {truncate_setsize (inode, attrs->ia_size); +fscache_resize_cookie (cifs_inode_cookie (inode), attrs->ia_size); + }setattr_copy (inode, attrs);mark_inode_dirty (inode);
fs/cifs/smb2pdu.c +9 -1
@@ -36,6 +36,7 @@#include <linux/uuid.h> #include <linux/pagemap.h> #include <linux/xattr.h> +#include <linux/netfs.h> #include "smb2pdu.h" #include "cifsglob.h" #include "cifsacl.h"
@@ -3975,7 +3976,14 @@ smb2_readv_callback(struct mid_q_entry *mid) tcon->tid, tcon->ses->Suid, rdata->offset, rdata->got_bytes); -queue_work (cifsiod_wq, &rdata->work); +if (rdata->subreq) { +netfs_subreq_terminated (rdata->subreq, + (rdata->result ==0 || rdata->result == -EAGAIN ) ? + rdata->got_bytes : rdata->result); +kref_put (&rdata->refcount, cifs_readdata_release); + }else { +queue_work (cifsiod_wq, &rdata->work); + }DeleteMidQEntry (mid);add_credits (server, &credits,0 ); }