Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 94a6d753 authored by Chuck Lever's avatar Chuck Lever Committed by Trond Myklebust
Browse files

NFS: Use cached page as buffer for NFS symlink requests



Now that we have a copy of the symlink path in the page cache, we can pass
a struct page down to the XDR routines instead of a string buffer.

Test plan:
Connectathon, all NFS versions.

Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 873101b3
Loading
Loading
Loading
Loading
+1 −7
Original line number Diff line number Diff line
@@ -1464,10 +1464,6 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym
	char *kaddr;
	struct iattr attr;
	unsigned int pathlen = strlen(symname);
	struct qstr qsymname = {
		.name	= symname,
		.len	= pathlen,
	};
	int error;

	dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id,
@@ -1493,10 +1489,8 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym
		memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen);
	kunmap_atomic(kaddr, KM_USER0);

	/* XXX: eventually this will pass in {page, pathlen},
	 *	instead of qsymname; need XDR changes for that */
	nfs_begin_data_update(dir);
	error = NFS_PROTO(dir)->symlink(dir, dentry, &qsymname, &attr);
	error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr);
	nfs_end_data_update(dir);
	if (error != 0) {
		dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n",
+18 −3
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@
#define NFS_createargs_sz	(NFS_diropargs_sz+NFS_sattr_sz)
#define NFS_renameargs_sz	(NFS_diropargs_sz+NFS_diropargs_sz)
#define NFS_linkargs_sz		(NFS_fhandle_sz+NFS_diropargs_sz)
#define NFS_symlinkargs_sz	(NFS_diropargs_sz+NFS_path_sz+NFS_sattr_sz)
#define NFS_symlinkargs_sz	(NFS_diropargs_sz+1+NFS_sattr_sz)
#define NFS_readdirargs_sz	(NFS_fhandle_sz+2)

#define NFS_attrstat_sz		(1+NFS_fattr_sz)
@@ -351,11 +351,26 @@ nfs_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs_linkargs *args)
static int
nfs_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_symlinkargs *args)
{
	struct xdr_buf *sndbuf = &req->rq_snd_buf;
	size_t pad;

	p = xdr_encode_fhandle(p, args->fromfh);
	p = xdr_encode_array(p, args->fromname, args->fromlen);
	p = xdr_encode_array(p, args->topath, args->tolen);
	*p++ = htonl(args->pathlen);
	sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);

	xdr_encode_pages(sndbuf, args->pages, 0, args->pathlen);

	/*
	 * xdr_encode_pages may have added a few bytes to ensure the
	 * pathname ends on a 4-byte boundary.  Start encoding the
	 * attributes after the pad bytes.
	 */
	pad = sndbuf->tail->iov_len;
	if (pad > 0)
		p++;
	p = xdr_encode_sattr(p, args->sattr);
	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
	sndbuf->len += xdr_adjust_iovec(sndbuf->tail, p) - pad;
	return 0;
}

+7 −7
Original line number Diff line number Diff line
@@ -544,8 +544,8 @@ nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
}

static int
nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct qstr *path,
		  struct iattr *sattr)
nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
		  unsigned int len, struct iattr *sattr)
{
	struct nfs_fh fhandle;
	struct nfs_fattr fattr, dir_attr;
@@ -553,8 +553,8 @@ nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct qstr *path,
		.fromfh		= NFS_FH(dir),
		.fromname	= dentry->d_name.name,
		.fromlen	= dentry->d_name.len,
		.topath		= path->name,
		.tolen		= path->len,
		.pages		= &page,
		.pathlen	= len,
		.sattr		= sattr
	};
	struct nfs3_diropres	res = {
@@ -569,11 +569,11 @@ nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct qstr *path,
	};
	int			status;

	if (path->len > NFS3_MAXPATHLEN)
	if (len > NFS3_MAXPATHLEN)
		return -ENAMETOOLONG;

	dprintk("NFS call  symlink %s -> %s\n", dentry->d_name.name,
			path->name);
	dprintk("NFS call  symlink %s\n", dentry->d_name.name);

	nfs_fattr_init(&dir_attr);
	nfs_fattr_init(&fattr);
	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+5 −2
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@
#define NFS3_writeargs_sz	(NFS3_fh_sz+5)
#define NFS3_createargs_sz	(NFS3_diropargs_sz+NFS3_sattr_sz)
#define NFS3_mkdirargs_sz	(NFS3_diropargs_sz+NFS3_sattr_sz)
#define NFS3_symlinkargs_sz	(NFS3_diropargs_sz+NFS3_path_sz+NFS3_sattr_sz)
#define NFS3_symlinkargs_sz	(NFS3_diropargs_sz+1+NFS3_sattr_sz)
#define NFS3_mknodargs_sz	(NFS3_diropargs_sz+2+NFS3_sattr_sz)
#define NFS3_renameargs_sz	(NFS3_diropargs_sz+NFS3_diropargs_sz)
#define NFS3_linkargs_sz		(NFS3_fh_sz+NFS3_diropargs_sz)
@@ -398,8 +398,11 @@ nfs3_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_symlinkargs *args
	p = xdr_encode_fhandle(p, args->fromfh);
	p = xdr_encode_array(p, args->fromname, args->fromlen);
	p = xdr_encode_sattr(p, args->sattr);
	p = xdr_encode_array(p, args->topath, args->tolen);
	*p++ = htonl(args->pathlen);
	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);

	/* Copy the page */
	xdr_encode_pages(&req->rq_snd_buf, args->pages, 0, args->pathlen);
	return 0;
}

+7 −5
Original line number Diff line number Diff line
@@ -2085,7 +2085,7 @@ static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *n
}

static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
		struct qstr *path, struct iattr *sattr)
		struct page *page, unsigned int len, struct iattr *sattr)
{
	struct nfs_server *server = NFS_SERVER(dir);
	struct nfs_fh fhandle;
@@ -2111,10 +2111,11 @@ static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
	};
	int			status;

	if (path->len > NFS4_MAXPATHLEN)
	if (len > NFS4_MAXPATHLEN)
		return -ENAMETOOLONG;

	arg.u.symlink = path;
	arg.u.symlink.pages = &page;
	arg.u.symlink.len = len;
	nfs_fattr_init(&fattr);
	nfs_fattr_init(&dir_fattr);
	
@@ -2128,13 +2129,14 @@ static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
}

static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
		struct qstr *path, struct iattr *sattr)
		struct page *page, unsigned int len, struct iattr *sattr)
{
	struct nfs4_exception exception = { };
	int err;
	do {
		err = nfs4_handle_exception(NFS_SERVER(dir),
				_nfs4_proc_symlink(dir, dentry, path, sattr),
				_nfs4_proc_symlink(dir, dentry, page,
							len, sattr),
				&exception);
	} while (exception.retry);
	return err;
Loading