diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/Kconfig | 4 | ||||
-rw-r--r-- | fs/nfs/dir.c | 28 | ||||
-rw-r--r-- | fs/nfs/direct.c | 23 | ||||
-rw-r--r-- | fs/nfs/file.c | 69 | ||||
-rw-r--r-- | fs/nfs/fs_context.c | 2 | ||||
-rw-r--r-- | fs/nfs/fscache.h | 14 | ||||
-rw-r--r-- | fs/nfs/inode.c | 1 | ||||
-rw-r--r-- | fs/nfs/internal.h | 10 | ||||
-rw-r--r-- | fs/nfs/nfs42xattr.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4file.c | 6 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 14 | ||||
-rw-r--r-- | fs/nfs/read.c | 3 | ||||
-rw-r--r-- | fs/nfs/symlink.c | 16 | ||||
-rw-r--r-- | fs/nfs/unlink.c | 1 |
14 files changed, 106 insertions, 87 deletions
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 47a53b3362b6..14a72224b657 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig @@ -4,10 +4,6 @@ config NFS_FS depends on INET && FILE_LOCKING && MULTIUSER select LOCKD select SUNRPC - select CRYPTO - select CRYPTO_HASH - select XXHASH - select CRYPTO_XXHASH select NFS_ACL_SUPPORT if NFS_V3_ACL help Choose Y here if you want to access files residing on other diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index bac4cf1a308e..a8ecdd527662 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -39,7 +39,7 @@ #include <linux/sched.h> #include <linux/kmemleak.h> #include <linux/xattr.h> -#include <linux/xxhash.h> +#include <linux/hash.h> #include "delegation.h" #include "iostat.h" @@ -55,7 +55,7 @@ static int nfs_closedir(struct inode *, struct file *); static int nfs_readdir(struct file *, struct dir_context *); static int nfs_fsync_dir(struct file *, loff_t, loff_t, int); static loff_t nfs_llseek_dir(struct file *, loff_t, int); -static void nfs_readdir_clear_array(struct page*); +static void nfs_readdir_free_folio(struct folio *); const struct file_operations nfs_dir_operations = { .llseek = nfs_llseek_dir, @@ -67,7 +67,7 @@ const struct file_operations nfs_dir_operations = { }; const struct address_space_operations nfs_dir_aops = { - .freepage = nfs_readdir_clear_array, + .free_folio = nfs_readdir_free_folio, }; #define NFS_INIT_DTSIZE PAGE_SIZE @@ -228,6 +228,11 @@ static void nfs_readdir_clear_array(struct page *page) kunmap_atomic(array); } +static void nfs_readdir_free_folio(struct folio *folio) +{ + nfs_readdir_clear_array(&folio->page); +} + static void nfs_readdir_page_reinit_array(struct page *page, u64 last_cookie, u64 change_attr) { @@ -350,10 +355,7 @@ out: * of directory cookies. Content is addressed by the value of the * cookie index of the first readdir entry in a page. * - * The xxhash algorithm is chosen because it is fast, and is supposed - * to result in a decent flat distribution of hashes. - * - * We then select only the first 18 bits to avoid issues with excessive + * We select only the first 18 bits to avoid issues with excessive * memory use for the page cache XArray. 18 bits should allow the caching * of 262144 pages of sequences of readdir entries. Since each page holds * 127 readdir entries for a typical 64-bit system, that works out to a @@ -363,7 +365,7 @@ static pgoff_t nfs_readdir_page_cookie_hash(u64 cookie) { if (cookie == 0) return 0; - return xxhash(&cookie, sizeof(cookie), 0) & NFS_READDIR_COOKIE_MASK; + return hash_64(cookie, 18); } static bool nfs_readdir_page_validate(struct page *page, u64 last_cookie, @@ -1991,16 +1993,6 @@ const struct dentry_operations nfs4_dentry_operations = { }; EXPORT_SYMBOL_GPL(nfs4_dentry_operations); -static fmode_t flags_to_mode(int flags) -{ - fmode_t res = (__force fmode_t)flags & FMODE_EXEC; - if ((flags & O_ACCMODE) != O_WRONLY) - res |= FMODE_READ; - if ((flags & O_ACCMODE) != O_RDONLY) - res |= FMODE_WRITE; - return res; -} - static struct nfs_open_context *create_nfs_open_context(struct dentry *dentry, int open_flags, struct file *filp) { return alloc_nfs_open_context(dentry, flags_to_mode(open_flags), filp); diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 11c566d8769f..4eb2a8380a28 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -153,28 +153,25 @@ nfs_direct_count_bytes(struct nfs_direct_req *dreq, } /** - * nfs_direct_IO - NFS address space operation for direct I/O + * nfs_swap_rw - NFS address space operation for swap I/O * @iocb: target I/O control block * @iter: I/O buffer * - * The presence of this routine in the address space ops vector means - * the NFS client supports direct I/O. However, for most direct IO, we - * shunt off direct read and write requests before the VFS gets them, - * so this method is only ever called for swap. + * Perform IO to the swap-file. This is much like direct IO. */ -ssize_t nfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) +int nfs_swap_rw(struct kiocb *iocb, struct iov_iter *iter) { - struct inode *inode = iocb->ki_filp->f_mapping->host; - - /* we only support swap file calling nfs_direct_IO */ - if (!IS_SWAPFILE(inode)) - return 0; + ssize_t ret; VM_BUG_ON(iov_iter_count(iter) != PAGE_SIZE); if (iov_iter_rw(iter) == READ) - return nfs_file_direct_read(iocb, iter, true); - return nfs_file_direct_write(iocb, iter, true); + ret = nfs_file_direct_read(iocb, iter, true); + else + ret = nfs_file_direct_write(iocb, iter, true); + if (ret < 0) + return ret; + return 0; } static void nfs_direct_release_pages(struct page **pages, unsigned int npages) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 150b7fa8f0a7..6f5425e89ca6 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -69,6 +69,8 @@ nfs_file_open(struct inode *inode, struct file *filp) return res; res = nfs_open(inode, filp); + if (res == 0) + filp->f_mode |= FMODE_CAN_ODIRECT; return res; } @@ -313,7 +315,7 @@ static bool nfs_want_read_modify_write(struct file *file, struct page *page, * increment the page use counts until he is done with the page. */ static int nfs_write_begin(struct file *file, struct address_space *mapping, - loff_t pos, unsigned len, unsigned flags, + loff_t pos, unsigned len, struct page **pagep, void **fsdata) { int ret; @@ -325,7 +327,7 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping, file, mapping->host->i_ino, len, (long long) pos); start: - page = grab_cache_page_write_begin(mapping, index, flags); + page = grab_cache_page_write_begin(mapping, index); if (!page) return -ENOMEM; *pagep = page; @@ -337,7 +339,7 @@ start: } else if (!once_thru && nfs_want_read_modify_write(file, page, pos, len)) { once_thru = 1; - ret = nfs_readpage(file, page); + ret = nfs_read_folio(file, page_folio(page)); put_page(page); if (!ret) goto start; @@ -415,34 +417,31 @@ static void nfs_invalidate_folio(struct folio *folio, size_t offset, } /* - * Attempt to release the private state associated with a page - * - Called if either PG_private or PG_fscache is set on the page - * - Caller holds page lock - * - Return true (may release page) or false (may not) + * Attempt to release the private state associated with a folio + * - Called if either private or fscache flags are set on the folio + * - Caller holds folio lock + * - Return true (may release folio) or false (may not) */ -static int nfs_release_page(struct page *page, gfp_t gfp) +static bool nfs_release_folio(struct folio *folio, gfp_t gfp) { - dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); + dfprintk(PAGECACHE, "NFS: release_folio(%p)\n", folio); - /* If PagePrivate() is set, then the page is not freeable */ - if (PagePrivate(page)) - return 0; - return nfs_fscache_release_page(page, gfp); + /* If the private flag is set, then the folio is not freeable */ + if (folio_test_private(folio)) + return false; + return nfs_fscache_release_folio(folio, gfp); } -static void nfs_check_dirty_writeback(struct page *page, +static void nfs_check_dirty_writeback(struct folio *folio, bool *dirty, bool *writeback) { struct nfs_inode *nfsi; - struct address_space *mapping = page_file_mapping(page); - - if (!mapping || PageSwapCache(page)) - return; + struct address_space *mapping = folio->mapping; /* - * Check if an unstable page is currently being committed and - * if so, have the VM treat it as if the page is under writeback - * so it will not block due to pages that will shortly be freeable. + * Check if an unstable folio is currently being committed and + * if so, have the VM treat it as if the folio is under writeback + * so it will not block due to folios that will shortly be freeable. */ nfsi = NFS_I(mapping->host); if (atomic_read(&nfsi->commit_info.rpcs_out)) { @@ -451,11 +450,11 @@ static void nfs_check_dirty_writeback(struct page *page, } /* - * If PagePrivate() is set, then the page is not freeable and as the - * inode is not being committed, it's not going to be cleaned in the - * near future so treat it as dirty + * If the private flag is set, then the folio is not freeable + * and as the inode is not being committed, it's not going to + * be cleaned in the near future so treat it as dirty */ - if (PagePrivate(page)) + if (folio_test_private(folio)) *dirty = true; } @@ -483,6 +482,7 @@ static int nfs_swap_activate(struct swap_info_struct *sis, struct file *file, { unsigned long blocks; long long isize; + int ret; struct inode *inode = file_inode(file); struct rpc_clnt *clnt = NFS_CLIENT(inode); struct nfs_client *cl = NFS_SERVER(inode)->nfs_client; @@ -496,13 +496,22 @@ static int nfs_swap_activate(struct swap_info_struct *sis, struct file *file, return -EINVAL; } - *span = sis->pages; + ret = rpc_clnt_swap_activate(clnt); + if (ret) + return ret; + ret = add_swap_extent(sis, 0, sis->max, 0); + if (ret < 0) { + rpc_clnt_swap_deactivate(clnt); + return ret; + } + *span = sis->pages; if (cl->rpc_ops->enable_swap) cl->rpc_ops->enable_swap(inode); - return rpc_clnt_swap_activate(clnt); + sis->flags |= SWP_FS_OPS; + return ret; } static void nfs_swap_deactivate(struct file *file) @@ -517,7 +526,7 @@ static void nfs_swap_deactivate(struct file *file) } const struct address_space_operations nfs_file_aops = { - .readpage = nfs_readpage, + .read_folio = nfs_read_folio, .readahead = nfs_readahead, .dirty_folio = filemap_dirty_folio, .writepage = nfs_writepage, @@ -525,8 +534,7 @@ const struct address_space_operations nfs_file_aops = { .write_begin = nfs_write_begin, .write_end = nfs_write_end, .invalidate_folio = nfs_invalidate_folio, - .releasepage = nfs_release_page, - .direct_IO = nfs_direct_IO, + .release_folio = nfs_release_folio, #ifdef CONFIG_MIGRATION .migratepage = nfs_migrate_page, #endif @@ -535,6 +543,7 @@ const struct address_space_operations nfs_file_aops = { .error_remove_page = generic_error_remove_page, .swap_activate = nfs_swap_activate, .swap_deactivate = nfs_swap_deactivate, + .swap_rw = nfs_swap_rw, }; /* diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c index e2d59bb5e6bb..9a16897e8dc6 100644 --- a/fs/nfs/fs_context.c +++ b/fs/nfs/fs_context.c @@ -517,7 +517,7 @@ static int nfs_fs_context_parse_param(struct fs_context *fc, if (result.negated) ctx->flags &= ~NFS_MOUNT_SOFTREVAL; else - ctx->flags &= NFS_MOUNT_SOFTREVAL; + ctx->flags |= NFS_MOUNT_SOFTREVAL; break; case Opt_posix: if (result.negated) diff --git a/fs/nfs/fscache.h b/fs/nfs/fscache.h index 4e980cc04779..2a37af880978 100644 --- a/fs/nfs/fscache.h +++ b/fs/nfs/fscache.h @@ -48,14 +48,14 @@ 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 *); -static inline int nfs_fscache_release_page(struct page *page, gfp_t gfp) +static inline bool nfs_fscache_release_folio(struct folio *folio, gfp_t gfp) { - if (PageFsCache(page)) { + if (folio_test_fscache(folio)) { if (current_is_kswapd() || !(gfp & __GFP_FS)) return false; - wait_on_page_fscache(page); - fscache_note_page_release(nfs_i_fscache(page->mapping->host)); - nfs_inc_fscache_stats(page->mapping->host, + 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); } return true; @@ -129,9 +129,9 @@ 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 int nfs_fscache_release_page(struct page *page, gfp_t gfp) +static inline bool nfs_fscache_release_folio(struct folio *folio, gfp_t gfp) { - return 1; /* True: may release page */ + return true; /* may release folio */ } static inline int nfs_fscache_read_page(struct inode *inode, struct page *page) { diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 7eb3b08d702f..b4e46b0ffa2d 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1180,7 +1180,6 @@ int nfs_open(struct inode *inode, struct file *filp) nfs_fscache_open_file(inode, filp); return 0; } -EXPORT_SYMBOL_GPL(nfs_open); /* * This function is called whenever some part of NFS notices that diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 57b0497105c8..7eefa16ed381 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -42,6 +42,16 @@ static inline bool nfs_lookup_is_soft_revalidate(const struct dentry *dentry) return true; } +static inline fmode_t flags_to_mode(int flags) +{ + fmode_t res = (__force fmode_t)flags & FMODE_EXEC; + if ((flags & O_ACCMODE) != O_WRONLY) + res |= FMODE_READ; + if ((flags & O_ACCMODE) != O_RDONLY) + res |= FMODE_WRITE; + return res; +} + /* * Note: RFC 1813 doesn't limit the number of auth flavors that * a server can return, so make something up. diff --git a/fs/nfs/nfs42xattr.c b/fs/nfs/nfs42xattr.c index ad3405c64b9e..e7b34f7e0614 100644 --- a/fs/nfs/nfs42xattr.c +++ b/fs/nfs/nfs42xattr.c @@ -997,7 +997,7 @@ int __init nfs4_xattr_cache_init(void) nfs4_xattr_cache_cachep = kmem_cache_create("nfs4_xattr_cache_cache", sizeof(struct nfs4_xattr_cache), 0, - (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD|SLAB_ACCOUNT), + (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD), nfs4_xattr_cache_init_once); if (nfs4_xattr_cache_cachep == NULL) return -ENOMEM; diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index d258933cf8c8..7b861e4f0533 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -32,6 +32,7 @@ nfs4_file_open(struct inode *inode, struct file *filp) struct dentry *parent = NULL; struct inode *dir; unsigned openflags = filp->f_flags; + fmode_t f_mode; struct iattr attr; int err; @@ -50,8 +51,9 @@ nfs4_file_open(struct inode *inode, struct file *filp) if (err) return err; + f_mode = filp->f_mode; if ((openflags & O_ACCMODE) == 3) - return nfs_open(inode, filp); + f_mode |= flags_to_mode(openflags); /* We can't create new files here */ openflags &= ~(O_CREAT|O_EXCL); @@ -59,7 +61,7 @@ nfs4_file_open(struct inode *inode, struct file *filp) parent = dget_parent(dentry); dir = d_inode(parent); - ctx = alloc_nfs_open_context(file_dentry(filp), filp->f_mode, filp); + ctx = alloc_nfs_open_context(file_dentry(filp), f_mode, filp); err = PTR_ERR(ctx); if (IS_ERR(ctx)) goto out; diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index e3f5b380cefe..a79f66432bd3 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -363,6 +363,14 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent kunmap_atomic(start); } +static void nfs4_fattr_set_prechange(struct nfs_fattr *fattr, u64 version) +{ + if (!(fattr->valid & NFS_ATTR_FATTR_PRECHANGE)) { + fattr->pre_change_attr = version; + fattr->valid |= NFS_ATTR_FATTR_PRECHANGE; + } +} + static void nfs4_test_and_free_stateid(struct nfs_server *server, nfs4_stateid *stateid, const struct cred *cred) @@ -6553,7 +6561,9 @@ static void nfs4_delegreturn_release(void *calldata) pnfs_roc_release(&data->lr.arg, &data->lr.res, data->res.lr_ret); if (inode) { - nfs_post_op_update_inode_force_wcc(inode, &data->fattr); + nfs4_fattr_set_prechange(&data->fattr, + inode_peek_iversion_raw(inode)); + nfs_refresh_inode(inode, &data->fattr); nfs_iput_and_deactive(inode); } kfree(calldata); @@ -9615,6 +9625,8 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout) nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0, 0); task = rpc_run_task(&task_setup_data); + if (IS_ERR(task)) + return ERR_CAST(task); status = rpc_wait_for_completion_task(task); if (status != 0) diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 5e7657374bc3..5a9b043662e9 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -333,8 +333,9 @@ out: * - The error flag is set for this page. This happens only when a * previous async read operation failed. */ -int nfs_readpage(struct file *file, struct page *page) +int nfs_read_folio(struct file *file, struct folio *folio) { + struct page *page = &folio->page; struct nfs_readdesc desc; struct inode *inode = page_file_mapping(page)->host; int ret; diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c index 25ba299fdac2..0e27a2e4e68b 100644 --- a/fs/nfs/symlink.c +++ b/fs/nfs/symlink.c @@ -26,21 +26,21 @@ * and straight-forward than readdir caching. */ -static int nfs_symlink_filler(void *data, struct page *page) +static int nfs_symlink_filler(struct file *file, struct folio *folio) { - struct inode *inode = data; + struct inode *inode = folio->mapping->host; int error; - error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE); + error = NFS_PROTO(inode)->readlink(inode, &folio->page, 0, PAGE_SIZE); if (error < 0) goto error; - SetPageUptodate(page); - unlock_page(page); + folio_mark_uptodate(folio); + folio_unlock(folio); return 0; error: - SetPageError(page); - unlock_page(page); + folio_set_error(folio); + folio_unlock(folio); return -EIO; } @@ -67,7 +67,7 @@ static const char *nfs_get_link(struct dentry *dentry, if (err) return err; page = read_cache_page(&inode->i_data, 0, nfs_symlink_filler, - inode); + NULL); if (IS_ERR(page)) return ERR_CAST(page); } diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 5fa11e1aca4c..6f325e10056c 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c @@ -347,6 +347,7 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir, data = kzalloc(sizeof(*data), GFP_KERNEL); if (data == NULL) return ERR_PTR(-ENOMEM); + task_setup_data.task = &data->task; task_setup_data.callback_data = data; data->cred = get_current_cred(); |