summaryrefslogtreecommitdiffstats
path: root/fs/nfs/callback_proc.c
diff options
context:
space:
mode:
authorAlexandros Batsakis <batsakis@netapp.com>2009-12-05 13:48:55 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2009-12-05 13:48:55 -0500
commit2597641deae82c9a95e255518da189ab557da0af (patch)
tree0b2dc7c46f2a0398ecefd6bb63a657710cf921fa /fs/nfs/callback_proc.c
parent0629e370dd5819efa5cf8d418a8e6729efe388ef (diff)
downloadlinux-2597641deae82c9a95e255518da189ab557da0af.tar.bz2
nfs41: v2 fix cb_recall bug
in NFSv4.1 the seqid part of a stateid in CB_RECALL must be 0 Signed-off-by: Alexandros Batsakis <batsakis@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/callback_proc.c')
-rw-r--r--fs/nfs/callback_proc.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 61b85306bb25..defa9b4c470e 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -61,6 +61,16 @@ out:
return res->status;
}
+static int (*nfs_validate_delegation_stateid(struct nfs_client *clp))(struct nfs_delegation *, const nfs4_stateid *)
+{
+#if defined(CONFIG_NFS_V4_1)
+ if (clp->cl_minorversion > 0)
+ return nfs41_validate_delegation_stateid;
+#endif
+ return nfs4_validate_delegation_stateid;
+}
+
+
__be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
{
struct nfs_client *clp;
@@ -81,7 +91,8 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
inode = nfs_delegation_find_inode(clp, &args->fh);
if (inode != NULL) {
/* Set up a helper thread to actually return the delegation */
- switch(nfs_async_inode_return_delegation(inode, &args->stateid)) {
+ switch (nfs_async_inode_return_delegation(inode, &args->stateid,
+ nfs_validate_delegation_stateid(clp))) {
case 0:
res = 0;
break;
@@ -102,8 +113,31 @@ out:
return res;
}
+int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid)
+{
+ if (delegation == NULL || memcmp(delegation->stateid.data, stateid->data,
+ sizeof(delegation->stateid.data)) != 0)
+ return 0;
+ return 1;
+}
+
#if defined(CONFIG_NFS_V4_1)
+int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid)
+{
+ if (delegation == NULL)
+ return 0;
+
+ /* seqid is 4-bytes long */
+ if (((u32 *) &stateid->data)[0] != 0)
+ return 0;
+ if (memcmp(&delegation->stateid.data[4], &stateid->data[4],
+ sizeof(stateid->data)-4))
+ return 0;
+
+ return 1;
+}
+
/*
* Validate the sequenceID sent by the server.
* Return success if the sequenceID is one more than what we last saw on
@@ -255,5 +289,4 @@ out:
dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
return status;
}
-
#endif /* CONFIG_NFS_V4_1 */