Commit 14671e6f authored by Trond Myklebust's avatar Trond Myklebust

NFS: While the storage container for NFS file handles must be able to

   store 128 bytes, usually NFS servers don't use file handles that
   are more than 32 bytes in size.  This patch creates an efficient
   mechanism for comparing file handles that ignores the unused bytes
   in a file handle.
Signed-off-by: default avatarChuck Lever <cel@netapp.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@fys.uio.no>
parent 4ea5dc72
...@@ -67,7 +67,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result, ...@@ -67,7 +67,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
down(&nlm_file_sema); down(&nlm_file_sema);
for (file = nlm_files[hash]; file; file = file->f_next) for (file = nlm_files[hash]; file; file = file->f_next)
if (!memcmp(&file->f_handle, f, sizeof(*f))) if (!nfs_compare_fh(&file->f_handle, f))
goto found; goto found;
dprintk("lockd: creating file for (%08x %08x %08x %08x %08x %08x)\n", dprintk("lockd: creating file for (%08x %08x %08x %08x %08x %08x)\n",
......
...@@ -610,7 +610,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) ...@@ -610,7 +610,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
verifier = nfs_save_change_attribute(dir); verifier = nfs_save_change_attribute(dir);
error = nfs_cached_lookup(dir, dentry, &fhandle, &fattr); error = nfs_cached_lookup(dir, dentry, &fhandle, &fattr);
if (!error) { if (!error) {
if (memcmp(NFS_FH(inode), &fhandle, sizeof(struct nfs_fh))!= 0) if (nfs_compare_fh(NFS_FH(inode), &fhandle))
goto out_bad; goto out_bad;
if (nfs_lookup_verify_inode(inode, isopen)) if (nfs_lookup_verify_inode(inode, isopen))
goto out_zap_parent; goto out_zap_parent;
...@@ -623,7 +623,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) ...@@ -623,7 +623,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
if (error) if (error)
goto out_bad; goto out_bad;
if (memcmp(NFS_FH(inode), &fhandle, sizeof(struct nfs_fh))!= 0) if (nfs_compare_fh(NFS_FH(inode), &fhandle))
goto out_bad; goto out_bad;
if ((error = nfs_refresh_inode(inode, &fattr)) != 0) if ((error = nfs_refresh_inode(inode, &fattr)) != 0)
goto out_bad; goto out_bad;
......
...@@ -596,7 +596,7 @@ nfs_find_actor(struct inode *inode, void *opaque) ...@@ -596,7 +596,7 @@ nfs_find_actor(struct inode *inode, void *opaque)
if (NFS_FILEID(inode) != fattr->fileid) if (NFS_FILEID(inode) != fattr->fileid)
return 0; return 0;
if (memcmp(NFS_FH(inode), fh, sizeof(struct nfs_fh)) != 0) if (nfs_compare_fh(NFS_FH(inode), fh))
return 0; return 0;
if (is_bad_inode(inode)) if (is_bad_inode(inode))
return 0; return 0;
...@@ -1259,7 +1259,7 @@ static int nfs_compare_super(struct super_block *sb, void *data) ...@@ -1259,7 +1259,7 @@ static int nfs_compare_super(struct super_block *sb, void *data)
return 0; return 0;
if (old->addr.sin_port != server->addr.sin_port) if (old->addr.sin_port != server->addr.sin_port)
return 0; return 0;
return !memcmp(&old->fh, &server->fh, sizeof(struct nfs_fh)); return !nfs_compare_fh(&old->fh, &server->fh);
} }
static struct super_block *nfs_get_sb(struct file_system_type *fs_type, static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#define _LINUX_NFS_H #define _LINUX_NFS_H
#include <linux/sunrpc/msg_prot.h> #include <linux/sunrpc/msg_prot.h>
#include <linux/string.h>
#define NFS_PROGRAM 100003 #define NFS_PROGRAM 100003
#define NFS_PORT 2049 #define NFS_PORT 2049
...@@ -138,6 +139,16 @@ struct nfs_fh { ...@@ -138,6 +139,16 @@ struct nfs_fh {
unsigned char data[NFS_MAXFHSIZE]; unsigned char data[NFS_MAXFHSIZE];
}; };
/*
* Returns a zero iff the size and data fields match.
* Checks only "size" bytes in the data field.
*/
static inline int nfs_compare_fh(const struct nfs_fh *a, const struct nfs_fh *b)
{
return a->size != b->size || memcmp(a->data, b->data, a->size) != 0;
}
/* /*
* This is really a general kernel constant, but since nothing like * This is really a general kernel constant, but since nothing like
* this is defined in the kernel headers, I have to do it here. * this is defined in the kernel headers, I have to do it here.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment