Commit f003a717 authored by Matthew Wilcox (Oracle)'s avatar Matthew Wilcox (Oracle) Committed by Trond Myklebust
Browse files

nfs: Convert nfs_symlink() to use a folio



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: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent bfca5fb4
Loading
Loading
Loading
Loading
+12 −17
Original line number Diff line number Diff line
@@ -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);
+2 −1
Original line number Diff line number Diff line
@@ -543,9 +543,10 @@ nfs3_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name)
}

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;
+4 −3
Original line number Diff line number Diff line
@@ -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 @@ static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
}

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);
+2 −1
Original line number Diff line number Diff line
@@ -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 = {
+1 −1
Original line number Diff line number Diff line
@@ -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 *);