diff mbox series

[RFC] NFS: Save 4 bytes when re-exporting

Message ID 20211212210044.16238-1-richard@nod.at (mailing list archive)
State New, archived
Headers show
Series [RFC] NFS: Save 4 bytes when re-exporting | expand

Commit Message

Richard Weinberger Dec. 12, 2021, 9 p.m. UTC
When re-exporting, the whole struct nfs_fh is embedded in the new
fhandle.
But we need only nfs_fh->data[], nfs_fh->size is not needed.
So skip fs_fh->size and save a full word (4 bytes).
The downside is the extra memcpy() in nfs_fh_to_dentry().

Signed-off-by: Richard Weinberger <richard@nod.at>
---
While investigating into improving NFS re-export I noticed that
we can already save 4 bytes of overhead.
I don't think we need to embedd the full struct nfs_fh and
can skip ->size.

Thanks,
//richard
---
 fs/nfs/export.c | 34 ++++++++++++++++++++--------------
 1 file changed, 20 insertions(+), 14 deletions(-)

Comments

Trond Myklebust Dec. 12, 2021, 9:19 p.m. UTC | #1
On Sun, 2021-12-12 at 22:00 +0100, Richard Weinberger wrote:
> When re-exporting, the whole struct nfs_fh is embedded in the new
> fhandle.
> But we need only nfs_fh->data[], nfs_fh->size is not needed.
> So skip fs_fh->size and save a full word (4 bytes).
> The downside is the extra memcpy() in nfs_fh_to_dentry().
> 
> Signed-off-by: Richard Weinberger <richard@nod.at>
> ---
> While investigating into improving NFS re-export I noticed that
> we can already save 4 bytes of overhead.
> I don't think we need to embedd the full struct nfs_fh and
> can skip ->size.
> 

NACK. This will break existing running clients. Any code to change the
filehandle format must be accompanied with code to detect and service
filehandles that are presented in the old format.
Richard Weinberger Dec. 12, 2021, 9:32 p.m. UTC | #2
----- Ursprüngliche Mail -----
> Von: "Trond Myklebust" <trondmy@hammerspace.com>
> On Sun, 2021-12-12 at 22:00 +0100, Richard Weinberger wrote:
>> When re-exporting, the whole struct nfs_fh is embedded in the new
>> fhandle.
>> But we need only nfs_fh->data[], nfs_fh->size is not needed.
>> So skip fs_fh->size and save a full word (4 bytes).
>> The downside is the extra memcpy() in nfs_fh_to_dentry().
>> 
>> Signed-off-by: Richard Weinberger <richard@nod.at>
>> ---
>> While investigating into improving NFS re-export I noticed that
>> we can already save 4 bytes of overhead.
>> I don't think we need to embedd the full struct nfs_fh and
>> can skip ->size.
>> 
> 
> NACK. This will break existing running clients. Any code to change the
> filehandle format must be accompanied with code to detect and service
> filehandles that are presented in the old format.

One possible way to distinguish between old and new formats
is looking at the length of the data.
2 * XDR_UNIT = new format (without ->size).
3 * XDR_UNIT = old format.

What do you think?

Thanks,
//richard
Richard Weinberger Dec. 12, 2021, 9:51 p.m. UTC | #3
----- Ursprüngliche Mail -----
> Von: "richard" <richard@nod.at>
> ----- Ursprüngliche Mail -----
>> Von: "Trond Myklebust" <trondmy@hammerspace.com>
>> On Sun, 2021-12-12 at 22:00 +0100, Richard Weinberger wrote:
>>> When re-exporting, the whole struct nfs_fh is embedded in the new
>>> fhandle.
>>> But we need only nfs_fh->data[], nfs_fh->size is not needed.
>>> So skip fs_fh->size and save a full word (4 bytes).
>>> The downside is the extra memcpy() in nfs_fh_to_dentry().
>>> 
>>> Signed-off-by: Richard Weinberger <richard@nod.at>
>>> ---
>>> While investigating into improving NFS re-export I noticed that
>>> we can already save 4 bytes of overhead.
>>> I don't think we need to embedd the full struct nfs_fh and
>>> can skip ->size.
>>> 
>> 
>> NACK. This will break existing running clients. Any code to change the
>> filehandle format must be accompanied with code to detect and service
>> filehandles that are presented in the old format.
> 
> One possible way to distinguish between old and new formats
> is looking at the length of the data.
> 2 * XDR_UNIT = new format (without ->size).
> 3 * XDR_UNIT = old format.

Never mind. This won't work.

Thanks,
//richard
Trond Myklebust Dec. 12, 2021, 9:53 p.m. UTC | #4
On Sun, 2021-12-12 at 22:32 +0100, Richard Weinberger wrote:
> ----- Ursprüngliche Mail -----
> > Von: "Trond Myklebust" <trondmy@hammerspace.com>
> > On Sun, 2021-12-12 at 22:00 +0100, Richard Weinberger wrote:
> > > When re-exporting, the whole struct nfs_fh is embedded in the new
> > > fhandle.
> > > But we need only nfs_fh->data[], nfs_fh->size is not needed.
> > > So skip fs_fh->size and save a full word (4 bytes).
> > > The downside is the extra memcpy() in nfs_fh_to_dentry().
> > > 
> > > Signed-off-by: Richard Weinberger <richard@nod.at>
> > > ---
> > > While investigating into improving NFS re-export I noticed that
> > > we can already save 4 bytes of overhead.
> > > I don't think we need to embedd the full struct nfs_fh and
> > > can skip ->size.
> > > 
> > 
> > NACK. This will break existing running clients. Any code to change
> > the
> > filehandle format must be accompanied with code to detect and
> > service
> > filehandles that are presented in the old format.
> 
> One possible way to distinguish between old and new formats
> is looking at the length of the data.
> 2 * XDR_UNIT = new format (without ->size).
> 3 * XDR_UNIT = old format.
> 
> What do you think?
> 

You don't a priori know the length of the underlying filehandle or its
structure. All you know is that you have n bytes of data, and it is
possible that the first 2 bytes represent the size 'n-2'. However it is
also possible that those 2 bytes are something else that just happens
to match the value 'n-2'.
Richard Weinberger Dec. 12, 2021, 9:57 p.m. UTC | #5
----- Ursprüngliche Mail -----
> Von: "Trond Myklebust" <trondmy@hammerspace.com>
>> What do you think?
>> 
> 
> You don't a priori know the length of the underlying filehandle or its
> structure. All you know is that you have n bytes of data, and it is
> possible that the first 2 bytes represent the size 'n-2'. However it is
> also possible that those 2 bytes are something else that just happens
> to match the value 'n-2'.

Yes. ;-\
Our mails have crossed, after hitting send I realized my fault.

Thanks,
//richard
diff mbox series

Patch

diff --git a/fs/nfs/export.c b/fs/nfs/export.c
index 5f6e1b715545..5579c87106a1 100644
--- a/fs/nfs/export.c
+++ b/fs/nfs/export.c
@@ -22,9 +22,9 @@  enum {
 };
 
 
-static struct nfs_fh *nfs_exp_embedfh(__u32 *p)
+static unsigned char *nfs_exp_embedfh(__u32 *p)
 {
-	return (struct nfs_fh *)(p + EMBED_FH_OFF);
+	return (unsigned char *)(p + EMBED_FH_OFF);
 }
 
 /*
@@ -35,8 +35,8 @@  static int
 nfs_encode_fh(struct inode *inode, __u32 *p, int *max_len, struct inode *parent)
 {
 	struct nfs_fh *server_fh = NFS_FH(inode);
-	struct nfs_fh *clnt_fh = nfs_exp_embedfh(p);
-	size_t fh_size = offsetof(struct nfs_fh, data) + server_fh->size;
+	unsigned char *raw_fh = nfs_exp_embedfh(p);
+	size_t fh_size = server_fh->size;
 	int len = EMBED_FH_OFF + XDR_QUADLEN(fh_size);
 
 	dprintk("%s: max fh len %d inode %p parent %p",
@@ -58,7 +58,9 @@  nfs_encode_fh(struct inode *inode, __u32 *p, int *max_len, struct inode *parent)
 	p[FILEID_LOW_OFF] = NFS_FILEID(inode);
 	p[FILE_I_TYPE_OFF] = inode->i_mode & S_IFMT;
 	p[len - 1] = 0; /* Padding */
-	nfs_copy_fh(clnt_fh, server_fh);
+
+	memcpy(raw_fh, server_fh->data, server_fh->size);
+
 	*max_len = len;
 	dprintk("%s: result fh fileid %llu mode %u size %d\n",
 		__func__, NFS_FILEID(inode), inode->i_mode, *max_len);
@@ -70,18 +72,22 @@  nfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
 		 int fh_len, int fh_type)
 {
 	struct nfs_fattr *fattr = NULL;
-	struct nfs_fh *server_fh = nfs_exp_embedfh(fid->raw);
-	size_t fh_size = offsetof(struct nfs_fh, data) + server_fh->size;
+	unsigned char *raw_server_fh = nfs_exp_embedfh(fid->raw);
 	const struct nfs_rpc_ops *rpc_ops;
 	struct dentry *dentry;
 	struct inode *inode;
-	int len = EMBED_FH_OFF + XDR_QUADLEN(fh_size);
 	u32 *p = fid->raw;
+	struct nfs_fh server_fh = { 0 };
 	int ret;
 
-	/* NULL translates to ESTALE */
-	if (fh_len < len || fh_type != len)
+	server_fh.size = (fh_len * XDR_UNIT) - (EMBED_FH_OFF * XDR_UNIT);
+	if (server_fh.size < 1) {
+		WARN_ON_ONCE(1);
+		/* NULL translates to ESTALE */
 		return NULL;
+	}
+
+	memcpy(server_fh.data, raw_server_fh, server_fh.size);
 
 	fattr = nfs_alloc_fattr_with_label(NFS_SB(sb));
 	if (fattr == NULL) {
@@ -95,20 +101,20 @@  nfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
 
 	dprintk("%s: fileid %llu mode %d\n", __func__, fattr->fileid, fattr->mode);
 
-	inode = nfs_ilookup(sb, fattr, server_fh);
+	inode = nfs_ilookup(sb, fattr, &server_fh);
 	if (inode)
 		goto out_found;
 
 	rpc_ops = NFS_SB(sb)->nfs_client->rpc_ops;
-	ret = rpc_ops->getattr(NFS_SB(sb), server_fh, fattr, NULL);
+	ret = rpc_ops->getattr(NFS_SB(sb), &server_fh, fattr, NULL);
 	if (ret) {
 		dprintk("%s: getattr failed %d\n", __func__, ret);
-		trace_nfs_fh_to_dentry(sb, server_fh, fattr->fileid, ret);
+		trace_nfs_fh_to_dentry(sb, &server_fh, fattr->fileid, ret);
 		dentry = ERR_PTR(ret);
 		goto out_free_fattr;
 	}
 
-	inode = nfs_fhget(sb, server_fh, fattr);
+	inode = nfs_fhget(sb, &server_fh, fattr);
 
 out_found:
 	dentry = d_obtain_alias(inode);