Commit 0127f25b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull NFS client updates from Anna Schumaker:
 "New Features:

   - Convert the readdir path to use folios

   - Convert the NFS fscache code to use netfs

  Bugfixes and Cleanups:

   - Always send a RECLAIM_COMPLETE after establishing a lease

   - Simplify sysctl registrations and other cleanups

   - Handle out-of-order write replies on NFS v3

   - Have sunrpc call_bind_status use standard hard/soft task semantics

   - Other minor cleanups"

* tag 'nfs-for-6.4-1' of git://git.linux-nfs.org/projects/anna/linux-nfs:
  NFSv4.2: Rework scratch handling for READ_PLUS
  NFS: Cleanup unused rpc_clnt variable
  NFS: set varaiable nfs_netfs_debug_id storage-class-specifier to static
  SUNRPC: remove the maximum number of retries in call_bind_status
  NFS: Convert readdir page array functions to use a folio
  NFS: Convert the readdir array-of-pages into an array-of-folios
  NFSv3: handle out-of-order write replies.
  NFS: Remove fscache specific trace points and NFS_INO_FSCACHE bit
  NFS: Remove all NFSIOS_FSCACHE counters due to conversion to netfs API
  NFS: Convert buffered read paths to use netfs when fscache is enabled
  NFS: Configure support for netfs when NFS fscache is configured
  NFS: Rename readpage_async_filler to nfs_read_add_folio
  sunrpc: simplify one-level sysctl registration for debug_table
  sunrpc: move sunrpc_table and proc routines above
  sunrpc: simplify one-level sysctl registration for xs_tunables_table
  sunrpc: simplify one-level sysctl registration for xr_tunables_table
  nfs: simplify two-level sysctl registration for nfs_cb_sysctls
  nfs: simplify two-level sysctl registration for nfs4_cb_sysctls
  lockd: simplify two-level sysctl registration for nlm_sysctls
  NFSv4.1: Always send a RECLAIM_COMPLETE after establishing lease
parents 1e098dec fbd2a05f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -170,6 +170,7 @@ config ROOT_NFS
config NFS_FSCACHE
	bool "Provide NFS client caching support"
	depends on NFS_FS=m && FSCACHE || NFS_FS=y && FSCACHE=y
	select NETFS_SUPPORT
	help
	  Say Y here if you want NFS data to be cached locally on disc through
	  the general filesystem cache manager
+149 −151

File changed.

Preview size limit exceeded, changes collapsed.

+142 −96

File changed.

Preview size limit exceeded, changes collapsed.

+92 −39
Original line number Diff line number Diff line
@@ -34,6 +34,58 @@ struct nfs_fscache_inode_auxdata {
	u64	change_attr;
};

struct nfs_netfs_io_data {
	/*
	 * NFS may split a netfs_io_subrequest into multiple RPCs, each
	 * with their own read completion.  In netfs, we can only call
	 * netfs_subreq_terminated() once for each subrequest.  Use the
	 * refcount here to double as a marker of the last RPC completion,
	 * and only call netfs via netfs_subreq_terminated() once.
	 */
	refcount_t			refcount;
	struct netfs_io_subrequest	*sreq;

	/*
	 * Final disposition of the netfs_io_subrequest, sent in
	 * netfs_subreq_terminated()
	 */
	atomic64_t	transferred;
	int		error;
};

static inline void nfs_netfs_get(struct nfs_netfs_io_data *netfs)
{
	refcount_inc(&netfs->refcount);
}

static inline void nfs_netfs_put(struct nfs_netfs_io_data *netfs)
{
	ssize_t final_len;

	/* Only the last RPC completion should call netfs_subreq_terminated() */
	if (!refcount_dec_and_test(&netfs->refcount))
		return;

	/*
	 * The NFS pageio interface may read a complete page, even when netfs
	 * only asked for a partial page.  Specifically, this may be seen when
	 * one thread is truncating a file while another one is reading the last
	 * page of the file.
	 * Correct the final length here to be no larger than the netfs subrequest
	 * length, and thus avoid netfs's "Subreq overread" warning message.
	 */
	final_len = min_t(s64, netfs->sreq->len, atomic64_read(&netfs->transferred));
	netfs_subreq_terminated(netfs->sreq, netfs->error ?: final_len, false);
	kfree(netfs);
}
static inline void nfs_netfs_inode_init(struct nfs_inode *nfsi)
{
	netfs_inode_init(&nfsi->netfs, &nfs_netfs_ops);
}
extern void nfs_netfs_initiate_read(struct nfs_pgio_header *hdr);
extern void nfs_netfs_read_completion(struct nfs_pgio_header *hdr);
extern int nfs_netfs_folio_unlock(struct folio *folio);

/*
 * fscache.c
 */
@@ -44,9 +96,8 @@ extern void nfs_fscache_init_inode(struct inode *);
extern void nfs_fscache_clear_inode(struct inode *);
extern void nfs_fscache_open_file(struct inode *, struct file *);
extern void nfs_fscache_release_file(struct inode *, struct file *);

extern int __nfs_fscache_read_page(struct inode *, struct page *);
extern void __nfs_fscache_write_page(struct inode *, struct page *);
extern int nfs_netfs_readahead(struct readahead_control *ractl);
extern int nfs_netfs_read_folio(struct file *file, struct folio *folio);

static inline bool nfs_fscache_release_folio(struct folio *folio, gfp_t gfp)
{
@@ -54,34 +105,11 @@ static inline bool nfs_fscache_release_folio(struct folio *folio, gfp_t gfp)
		if (current_is_kswapd() || !(gfp & __GFP_FS))
			return false;
		folio_wait_fscache(folio);
		fscache_note_page_release(nfs_i_fscache(folio->mapping->host));
		nfs_inc_fscache_stats(folio->mapping->host,
				      NFSIOS_FSCACHE_PAGES_UNCACHED);
	}
	fscache_note_page_release(netfs_i_cookie(netfs_inode(folio->mapping->host)));
	return true;
}

/*
 * Retrieve a page from an inode data storage object.
 */
static inline int nfs_fscache_read_page(struct inode *inode, struct page *page)
{
	if (nfs_i_fscache(inode))
		return __nfs_fscache_read_page(inode, page);
	return -ENOBUFS;
}

/*
 * Store a page newly fetched from the server in an inode data storage object
 * in the cache.
 */
static inline void nfs_fscache_write_page(struct inode *inode,
					   struct page *page)
{
	if (nfs_i_fscache(inode))
		__nfs_fscache_write_page(inode, page);
}

static inline void nfs_fscache_update_auxdata(struct nfs_fscache_inode_auxdata *auxdata,
					      struct inode *inode)
{
@@ -101,13 +129,10 @@ static inline void nfs_fscache_update_auxdata(struct nfs_fscache_inode_auxdata *
static inline void nfs_fscache_invalidate(struct inode *inode, int flags)
{
	struct nfs_fscache_inode_auxdata auxdata;
	struct nfs_inode *nfsi = NFS_I(inode);
	struct fscache_cookie *cookie =  netfs_i_cookie(&NFS_I(inode)->netfs);

	if (nfsi->fscache) {
	nfs_fscache_update_auxdata(&auxdata, inode);
		fscache_invalidate(nfsi->fscache, &auxdata,
				   i_size_read(inode), flags);
	}
	fscache_invalidate(cookie, &auxdata, i_size_read(inode), flags);
}

/*
@@ -120,7 +145,28 @@ static inline const char *nfs_server_fscache_state(struct nfs_server *server)
	return "no ";
}

static inline void nfs_netfs_set_pgio_header(struct nfs_pgio_header *hdr,
					     struct nfs_pageio_descriptor *desc)
{
	hdr->netfs = desc->pg_netfs;
}
static inline void nfs_netfs_set_pageio_descriptor(struct nfs_pageio_descriptor *desc,
						   struct nfs_pgio_header *hdr)
{
	desc->pg_netfs = hdr->netfs;
}
static inline void nfs_netfs_reset_pageio_descriptor(struct nfs_pageio_descriptor *desc)
{
	desc->pg_netfs = NULL;
}
#else /* CONFIG_NFS_FSCACHE */
static inline void nfs_netfs_inode_init(struct nfs_inode *nfsi) {}
static inline void nfs_netfs_initiate_read(struct nfs_pgio_header *hdr) {}
static inline void nfs_netfs_read_completion(struct nfs_pgio_header *hdr) {}
static inline int nfs_netfs_folio_unlock(struct folio *folio)
{
	return 1;
}
static inline void nfs_fscache_release_super_cookie(struct super_block *sb) {}

static inline void nfs_fscache_init_inode(struct inode *inode) {}
@@ -128,22 +174,29 @@ static inline void nfs_fscache_clear_inode(struct inode *inode) {}
static inline void nfs_fscache_open_file(struct inode *inode,
					 struct file *filp) {}
static inline void nfs_fscache_release_file(struct inode *inode, struct file *file) {}

static inline bool nfs_fscache_release_folio(struct folio *folio, gfp_t gfp)
static inline int nfs_netfs_readahead(struct readahead_control *ractl)
{
	return true; /* may release folio */
	return -ENOBUFS;
}
static inline int nfs_fscache_read_page(struct inode *inode, struct page *page)
static inline int nfs_netfs_read_folio(struct file *file, struct folio *folio)
{
	return -ENOBUFS;
}
static inline void nfs_fscache_write_page(struct inode *inode, struct page *page) {}

static inline bool nfs_fscache_release_folio(struct folio *folio, gfp_t gfp)
{
	return true; /* may release folio */
}
static inline void nfs_fscache_invalidate(struct inode *inode, int flags) {}

static inline const char *nfs_server_fscache_state(struct nfs_server *server)
{
	return "no ";
}

static inline void nfs_netfs_set_pgio_header(struct nfs_pgio_header *hdr,
					     struct nfs_pageio_descriptor *desc) {}
static inline void nfs_netfs_set_pageio_descriptor(struct nfs_pageio_descriptor *desc,
						   struct nfs_pgio_header *hdr) {}
static inline void nfs_netfs_reset_pageio_descriptor(struct nfs_pageio_descriptor *desc) {}
#endif /* CONFIG_NFS_FSCACHE */
#endif /* _NFS_FSCACHE_H */
+99 −15

File changed.

Preview size limit exceeded, changes collapsed.

Loading