Now that file handle comparison ignores the unused parts of the file handle container, there is no longer any need to clear the file handle container before copying in a file handle. This allows us to remove a 128 byte memset() from several hot paths. Patch against 2.6.7-rc3. Patch 05-nfs_fh_compare.patch is required before applying this patch. fs/nfs/inode.c | 8 ++------ fs/nfs/mount_clnt.c | 2 -- fs/nfs/nfs2xdr.c | 2 -- fs/nfs/nfs3xdr.c | 4 ---- fs/nfs/nfsroot.c | 6 ++---- include/linux/nfs.h | 7 +++++++ 6 files changed, 11 insertions(+), 18 deletions(-) Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust diff -X /home/cel/src/linux/dont-diff -Naurp 05-nfs_fh_compare/fs/nfs/inode.c 06-nfs_copy_fh/fs/nfs/inode.c --- 05-nfs_fh_compare/fs/nfs/inode.c 2004-06-08 17:36:31.476506000 -0400 +++ 06-nfs_copy_fh/fs/nfs/inode.c 2004-06-08 17:47:10.516145000 -0400 @@ -609,11 +609,10 @@ static int nfs_init_locked(struct inode *inode, void *opaque) { struct nfs_find_desc *desc = (struct nfs_find_desc *)opaque; - struct nfs_fh *fh = desc->fh; struct nfs_fattr *fattr = desc->fattr; NFS_FILEID(inode) = fattr->fileid; - memcpy(NFS_FH(inode), fh, sizeof(struct nfs_fh)); + nfs_copy_fh(NFS_FH(inode), desc->fh); return 0; } @@ -1289,9 +1288,7 @@ static struct super_block *nfs_get_sb(st init_nfsv4_state(server); root = &server->fh; - memcpy(root, &data->root, sizeof(*root)); - if (root->size < sizeof(root->data)) - memset(root->data+root->size, 0, sizeof(root->data)-root->size); + nfs_copy_fh(root, (struct nfs_fh *) &data->root); if (data->version != NFS_MOUNT_VERSION) { printk("nfs warning: mount version %s than kernel\n", @@ -1302,7 +1299,6 @@ static struct super_block *nfs_get_sb(st data->bsize = 0; if (data->version < 4) { data->flags &= ~NFS_MOUNT_VER3; - memset(root, 0, sizeof(*root)); root->size = NFS2_FHSIZE; memcpy(root->data, data->old_root.data, NFS2_FHSIZE); } diff -X /home/cel/src/linux/dont-diff -Naurp 05-nfs_fh_compare/fs/nfs/mount_clnt.c 06-nfs_copy_fh/fs/nfs/mount_clnt.c --- 05-nfs_fh_compare/fs/nfs/mount_clnt.c 2004-05-09 22:31:59.000000000 -0400 +++ 06-nfs_copy_fh/fs/nfs/mount_clnt.c 2004-06-08 17:47:10.520149000 -0400 @@ -108,7 +108,6 @@ xdr_decode_fhstatus(struct rpc_rqst *req { struct nfs_fh *fh = res->fh; - memset((void *)fh, 0, sizeof(*fh)); if ((res->status = ntohl(*p++)) == 0) { fh->size = NFS2_FHSIZE; memcpy(fh->data, p, NFS2_FHSIZE); @@ -121,7 +120,6 @@ xdr_decode_fhstatus3(struct rpc_rqst *re { struct nfs_fh *fh = res->fh; - memset((void *)fh, 0, sizeof(*fh)); if ((res->status = ntohl(*p++)) == 0) { int size = ntohl(*p++); if (size <= NFS3_FHSIZE) { diff -X /home/cel/src/linux/dont-diff -Naurp 05-nfs_fh_compare/fs/nfs/nfs2xdr.c 06-nfs_copy_fh/fs/nfs/nfs2xdr.c --- 05-nfs_fh_compare/fs/nfs/nfs2xdr.c 2004-06-08 17:21:53.138630000 -0400 +++ 06-nfs_copy_fh/fs/nfs/nfs2xdr.c 2004-06-08 17:47:10.524148000 -0400 @@ -77,8 +77,6 @@ xdr_encode_fhandle(u32 *p, struct nfs_fh static inline u32 * xdr_decode_fhandle(u32 *p, struct nfs_fh *fhandle) { - /* Zero handle first to allow comparisons */ - memset(fhandle, 0, sizeof(*fhandle)); /* NFSv2 handles have a fixed length */ fhandle->size = NFS2_FHSIZE; memcpy(fhandle->data, p, NFS2_FHSIZE); diff -X /home/cel/src/linux/dont-diff -Naurp 05-nfs_fh_compare/fs/nfs/nfs3xdr.c 06-nfs_copy_fh/fs/nfs/nfs3xdr.c --- 05-nfs_fh_compare/fs/nfs/nfs3xdr.c 2004-06-08 17:21:53.142629000 -0400 +++ 06-nfs_copy_fh/fs/nfs/nfs3xdr.c 2004-06-08 17:47:10.529145000 -0400 @@ -109,10 +109,6 @@ xdr_encode_fhandle(u32 *p, struct nfs_fh static inline u32 * xdr_decode_fhandle(u32 *p, struct nfs_fh *fh) { - /* - * Zero all nonused bytes - */ - memset((u8 *)fh, 0, sizeof(*fh)); if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) { memcpy(fh->data, p, fh->size); return p + XDR_QUADLEN(fh->size); diff -X /home/cel/src/linux/dont-diff -Naurp 05-nfs_fh_compare/fs/nfs/nfsroot.c 06-nfs_copy_fh/fs/nfs/nfsroot.c --- 05-nfs_fh_compare/fs/nfs/nfsroot.c 2004-05-09 22:32:54.000000000 -0400 +++ 06-nfs_copy_fh/fs/nfs/nfsroot.c 2004-06-08 17:47:10.533145000 -0400 @@ -495,10 +495,8 @@ static int __init root_nfs_get_handle(vo if (status < 0) printk(KERN_ERR "Root-NFS: Server returned error %d " "while mounting %s\n", status, nfs_path); - else { - nfs_data.root.size = fh.size; - memcpy(nfs_data.root.data, fh.data, fh.size); - } + else + nfs_copy_fh(nfs_data.root, fh); return status; } diff -X /home/cel/src/linux/dont-diff -Naurp 05-nfs_fh_compare/include/linux/nfs.h 06-nfs_copy_fh/include/linux/nfs.h --- 05-nfs_fh_compare/include/linux/nfs.h 2004-06-08 17:36:31.480509000 -0400 +++ 06-nfs_copy_fh/include/linux/nfs.h 2004-06-08 17:47:10.537148000 -0400 @@ -150,6 +150,12 @@ nfs_compare_fh(struct nfs_fh *a, struct return (int) result | memcmp(a->data, b->data, a->size); } +static inline void nfs_copy_fh(struct nfs_fh *target, const struct nfs_fh *source) +{ + target->size = source->size; + memcpy(target->data, source->data, source->size); +} + /* * This is really a general kernel constant, but since nothing like