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: Matthew Wilcox (Oracle) <willy@infradead.org> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>pull/318/merge
parent
bfca5fb4e9
commit
f003a717ae
29
fs/nfs/dir.c
29
fs/nfs/dir.c
|
|
@ -2532,7 +2532,7 @@ EXPORT_SYMBOL_GPL(nfs_unlink);
|
||||||
int nfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
|
int nfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
|
||||||
struct dentry *dentry, const char *symname)
|
struct dentry *dentry, const char *symname)
|
||||||
{
|
{
|
||||||
struct page *page;
|
struct folio *folio;
|
||||||
char *kaddr;
|
char *kaddr;
|
||||||
struct iattr attr;
|
struct iattr attr;
|
||||||
unsigned int pathlen = strlen(symname);
|
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_mode = S_IFLNK | S_IRWXUGO;
|
||||||
attr.ia_valid = ATTR_MODE;
|
attr.ia_valid = ATTR_MODE;
|
||||||
|
|
||||||
page = alloc_page(GFP_USER);
|
folio = folio_alloc(GFP_USER, 0);
|
||||||
if (!page)
|
if (!folio)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
kaddr = page_address(page);
|
kaddr = folio_address(folio);
|
||||||
memcpy(kaddr, symname, pathlen);
|
memcpy(kaddr, symname, pathlen);
|
||||||
if (pathlen < PAGE_SIZE)
|
if (pathlen < PAGE_SIZE)
|
||||||
memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen);
|
memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen);
|
||||||
|
|
||||||
trace_nfs_symlink_enter(dir, dentry);
|
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);
|
trace_nfs_symlink_exit(dir, dentry, error);
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
dfprintk(VFS, "NFS: symlink(%s/%lu, %pd, %s) error %d\n",
|
dfprintk(VFS, "NFS: symlink(%s/%lu, %pd, %s) error %d\n",
|
||||||
dir->i_sb->s_id, dir->i_ino,
|
dir->i_sb->s_id, dir->i_ino,
|
||||||
dentry, symname, error);
|
dentry, symname, error);
|
||||||
d_drop(dentry);
|
d_drop(dentry);
|
||||||
__free_page(page);
|
folio_put(folio);
|
||||||
return error;
|
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.
|
* 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.
|
* READLINK will get the missing page from the server if needed.
|
||||||
*/
|
*/
|
||||||
if (!add_to_page_cache_lru(page, d_inode(dentry)->i_mapping, 0,
|
if (filemap_add_folio(d_inode(dentry)->i_mapping, folio, 0,
|
||||||
GFP_KERNEL)) {
|
GFP_KERNEL) == 0) {
|
||||||
SetPageUptodate(page);
|
folio_mark_uptodate(folio);
|
||||||
unlock_page(page);
|
folio_unlock(folio);
|
||||||
/*
|
}
|
||||||
* 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);
|
|
||||||
|
|
||||||
|
folio_put(folio);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(nfs_symlink);
|
EXPORT_SYMBOL_GPL(nfs_symlink);
|
||||||
|
|
|
||||||
|
|
@ -543,9 +543,10 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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)
|
unsigned int len, struct iattr *sattr)
|
||||||
{
|
{
|
||||||
|
struct page *page = &folio->page;
|
||||||
struct nfs3_createdata *data;
|
struct nfs3_createdata *data;
|
||||||
struct dentry *d_alias;
|
struct dentry *d_alias;
|
||||||
int status = -ENOMEM;
|
int status = -ENOMEM;
|
||||||
|
|
|
||||||
|
|
@ -5036,9 +5036,10 @@ static void nfs4_free_createdata(struct nfs4_createdata *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
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_label *label)
|
struct nfs4_label *label)
|
||||||
{
|
{
|
||||||
|
struct page *page = &folio->page;
|
||||||
struct nfs4_createdata *data;
|
struct nfs4_createdata *data;
|
||||||
int status = -ENAMETOOLONG;
|
int status = -ENAMETOOLONG;
|
||||||
|
|
||||||
|
|
@ -5063,7 +5064,7 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = {
|
struct nfs4_exception exception = {
|
||||||
.interruptible = true,
|
.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);
|
label = nfs4_label_init_security(dir, dentry, sattr, &l);
|
||||||
|
|
||||||
do {
|
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);
|
trace_nfs4_symlink(dir, &dentry->d_name, err);
|
||||||
err = nfs4_handle_exception(NFS_SERVER(dir), err,
|
err = nfs4_handle_exception(NFS_SERVER(dir), err,
|
||||||
&exception);
|
&exception);
|
||||||
|
|
|
||||||
|
|
@ -396,9 +396,10 @@ nfs_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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)
|
unsigned int len, struct iattr *sattr)
|
||||||
{
|
{
|
||||||
|
struct page *page = &folio->page;
|
||||||
struct nfs_fh *fh;
|
struct nfs_fh *fh;
|
||||||
struct nfs_fattr *fattr;
|
struct nfs_fattr *fattr;
|
||||||
struct nfs_symlinkargs arg = {
|
struct nfs_symlinkargs arg = {
|
||||||
|
|
|
||||||
|
|
@ -1772,7 +1772,7 @@ struct nfs_rpc_ops {
|
||||||
void (*rename_rpc_prepare)(struct rpc_task *task, struct nfs_renamedata *);
|
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 (*rename_done) (struct rpc_task *task, struct inode *old_dir, struct inode *new_dir);
|
||||||
int (*link) (struct inode *, struct inode *, const struct qstr *);
|
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 *);
|
unsigned int, struct iattr *);
|
||||||
int (*mkdir) (struct inode *, struct dentry *, struct iattr *);
|
int (*mkdir) (struct inode *, struct dentry *, struct iattr *);
|
||||||
int (*rmdir) (struct inode *, const struct qstr *);
|
int (*rmdir) (struct inode *, const struct qstr *);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue