nfs: Convert nfs_symlink() to use a folio
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Fri, 15 Sep 2023 17:33:33 +0000 (18:33 +0100)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Wed, 1 Nov 2023 19:40:44 +0000 (15:40 -0400)
Use the folio APIs, saving about four calls to compound_head().
Convert back to a page in each of the individual protocol implementations.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/dir.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4proc.c
fs/nfs/proc.c
include/linux/nfs_xdr.h

index e6a51fd94fea876630c2ea8349256ba09ebadb4d..13dffe4201e6e98fd1d6f3bb649cc6baaa89e17a 100644 (file)
@@ -2532,7 +2532,7 @@ EXPORT_SYMBOL_GPL(nfs_unlink);
 int nfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
                struct dentry *dentry, const char *symname)
 {
-       struct page *page;
+       struct folio *folio;
        char *kaddr;
        struct iattr attr;
        unsigned int pathlen = strlen(symname);
@@ -2547,24 +2547,24 @@ int nfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
        attr.ia_mode = S_IFLNK | S_IRWXUGO;
        attr.ia_valid = ATTR_MODE;
 
-       page = alloc_page(GFP_USER);
-       if (!page)
+       folio = folio_alloc(GFP_USER, 0);
+       if (!folio)
                return -ENOMEM;
 
-       kaddr = page_address(page);
+       kaddr = folio_address(folio);
        memcpy(kaddr, symname, pathlen);
        if (pathlen < PAGE_SIZE)
                memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen);
 
        trace_nfs_symlink_enter(dir, dentry);
-       error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr);
+       error = NFS_PROTO(dir)->symlink(dir, dentry, folio, pathlen, &attr);
        trace_nfs_symlink_exit(dir, dentry, error);
        if (error != 0) {
                dfprintk(VFS, "NFS: symlink(%s/%lu, %pd, %s) error %d\n",
                        dir->i_sb->s_id, dir->i_ino,
                        dentry, symname, error);
                d_drop(dentry);
-               __free_page(page);
+               folio_put(folio);
                return error;
        }
 
@@ -2574,18 +2574,13 @@ int nfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
         * No big deal if we can't add this page to the page cache here.
         * READLINK will get the missing page from the server if needed.
         */
-       if (!add_to_page_cache_lru(page, d_inode(dentry)->i_mapping, 0,
-                                                       GFP_KERNEL)) {
-               SetPageUptodate(page);
-               unlock_page(page);
-               /*
-                * add_to_page_cache_lru() grabs an extra page refcount.
-                * Drop it here to avoid leaking this page later.
-                */
-               put_page(page);
-       } else
-               __free_page(page);
+       if (filemap_add_folio(d_inode(dentry)->i_mapping, folio, 0,
+                                                       GFP_KERNEL) == 0) {
+               folio_mark_uptodate(folio);
+               folio_unlock(folio);
+       }
 
+       folio_put(folio);
        return 0;
 }
 EXPORT_SYMBOL_GPL(nfs_symlink);
index 4bf208a0a8e9948de4131e8e9e9fb6d21db3a5fc..2de66e4e8280a801b647dfe10c577e69192e236c 100644 (file)
@@ -543,9 +543,10 @@ out:
 }
 
 static int
-nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
+nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct folio *folio,
                  unsigned int len, struct iattr *sattr)
 {
+       struct page *page = &folio->page;
        struct nfs3_createdata *data;
        struct dentry *d_alias;
        int status = -ENOMEM;
index b36193edc3ba8f9b5b1ef589b4f757d099129be1..e7e80c67d82b123595e7c293971ee80ecbb7c8f7 100644 (file)
@@ -5036,9 +5036,10 @@ static void nfs4_free_createdata(struct nfs4_createdata *data)
 }
 
 static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
-               struct page *page, unsigned int len, struct iattr *sattr,
+               struct folio *folio, unsigned int len, struct iattr *sattr,
                struct nfs4_label *label)
 {
+       struct page *page = &folio->page;
        struct nfs4_createdata *data;
        int status = -ENAMETOOLONG;
 
@@ -5063,7 +5064,7 @@ out:
 }
 
 static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
-               struct page *page, unsigned int len, struct iattr *sattr)
+               struct folio *folio, unsigned int len, struct iattr *sattr)
 {
        struct nfs4_exception exception = {
                .interruptible = true,
@@ -5074,7 +5075,7 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
        label = nfs4_label_init_security(dir, dentry, sattr, &l);
 
        do {
-               err = _nfs4_proc_symlink(dir, dentry, page, len, sattr, label);
+               err = _nfs4_proc_symlink(dir, dentry, folio, len, sattr, label);
                trace_nfs4_symlink(dir, &dentry->d_name, err);
                err = nfs4_handle_exception(NFS_SERVER(dir), err,
                                &exception);
index e3570c656b0f9b27cd4caa08c4ab67350ae13cd3..ad3a321ae997f593184f7d970f95778e83a636e3 100644 (file)
@@ -396,9 +396,10 @@ nfs_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name)
 }
 
 static int
-nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
+nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct folio *folio,
                 unsigned int len, struct iattr *sattr)
 {
+       struct page *page = &folio->page;
        struct nfs_fh *fh;
        struct nfs_fattr *fattr;
        struct nfs_symlinkargs  arg = {
index 12bbb5c636646e7a9318613669385400749c94d2..539b57fbf3ce397ae80bbe186547f77100830d1b 100644 (file)
@@ -1772,7 +1772,7 @@ struct nfs_rpc_ops {
        void    (*rename_rpc_prepare)(struct rpc_task *task, struct nfs_renamedata *);
        int     (*rename_done) (struct rpc_task *task, struct inode *old_dir, struct inode *new_dir);
        int     (*link)    (struct inode *, struct inode *, const struct qstr *);
-       int     (*symlink) (struct inode *, struct dentry *, struct page *,
+       int     (*symlink) (struct inode *, struct dentry *, struct folio *,
                            unsigned int, struct iattr *);
        int     (*mkdir)   (struct inode *, struct dentry *, struct iattr *);
        int     (*rmdir)   (struct inode *, const struct qstr *);