diff options
author | Alexandros Batsakis <batsakis@netapp.com> | 2009-12-05 13:48:55 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-12-05 13:48:55 -0500 |
commit | 2597641deae82c9a95e255518da189ab557da0af (patch) | |
tree | 0b2dc7c46f2a0398ecefd6bb63a657710cf921fa /fs/nfs/callback_proc.c | |
parent | 0629e370dd5819efa5cf8d418a8e6729efe388ef (diff) |
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.c | 37 |
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: | |||
61 | return res->status; | 61 | return res->status; |
62 | } | 62 | } |
63 | 63 | ||
64 | static int (*nfs_validate_delegation_stateid(struct nfs_client *clp))(struct nfs_delegation *, const nfs4_stateid *) | ||
65 | { | ||
66 | #if defined(CONFIG_NFS_V4_1) | ||
67 | if (clp->cl_minorversion > 0) | ||
68 | return nfs41_validate_delegation_stateid; | ||
69 | #endif | ||
70 | return nfs4_validate_delegation_stateid; | ||
71 | } | ||
72 | |||
73 | |||
64 | __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) | 74 | __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) |
65 | { | 75 | { |
66 | struct nfs_client *clp; | 76 | struct nfs_client *clp; |
@@ -81,7 +91,8 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) | |||
81 | inode = nfs_delegation_find_inode(clp, &args->fh); | 91 | inode = nfs_delegation_find_inode(clp, &args->fh); |
82 | if (inode != NULL) { | 92 | if (inode != NULL) { |
83 | /* Set up a helper thread to actually return the delegation */ | 93 | /* Set up a helper thread to actually return the delegation */ |
84 | switch(nfs_async_inode_return_delegation(inode, &args->stateid)) { | 94 | switch (nfs_async_inode_return_delegation(inode, &args->stateid, |
95 | nfs_validate_delegation_stateid(clp))) { | ||
85 | case 0: | 96 | case 0: |
86 | res = 0; | 97 | res = 0; |
87 | break; | 98 | break; |
@@ -102,8 +113,31 @@ out: | |||
102 | return res; | 113 | return res; |
103 | } | 114 | } |
104 | 115 | ||
116 | int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid) | ||
117 | { | ||
118 | if (delegation == NULL || memcmp(delegation->stateid.data, stateid->data, | ||
119 | sizeof(delegation->stateid.data)) != 0) | ||
120 | return 0; | ||
121 | return 1; | ||
122 | } | ||
123 | |||
105 | #if defined(CONFIG_NFS_V4_1) | 124 | #if defined(CONFIG_NFS_V4_1) |
106 | 125 | ||
126 | int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid) | ||
127 | { | ||
128 | if (delegation == NULL) | ||
129 | return 0; | ||
130 | |||
131 | /* seqid is 4-bytes long */ | ||
132 | if (((u32 *) &stateid->data)[0] != 0) | ||
133 | return 0; | ||
134 | if (memcmp(&delegation->stateid.data[4], &stateid->data[4], | ||
135 | sizeof(stateid->data)-4)) | ||
136 | return 0; | ||
137 | |||
138 | return 1; | ||
139 | } | ||
140 | |||
107 | /* | 141 | /* |
108 | * Validate the sequenceID sent by the server. | 142 | * Validate the sequenceID sent by the server. |
109 | * Return success if the sequenceID is one more than what we last saw on | 143 | * Return success if the sequenceID is one more than what we last saw on |
@@ -255,5 +289,4 @@ out: | |||
255 | dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); | 289 | dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); |
256 | return status; | 290 | return status; |
257 | } | 291 | } |
258 | |||
259 | #endif /* CONFIG_NFS_V4_1 */ | 292 | #endif /* CONFIG_NFS_V4_1 */ |