diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-12-28 12:57:53 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-12-28 14:33:04 -0500 |
commit | 41c9127d6d588138c66b2614ac596ea63313acca (patch) | |
tree | caff36c19e6748b76edd562af06c875842567223 /fs/nfs | |
parent | fc7ff36747b991d1be0d68987066ea87eedbb43e (diff) |
NFSv4.1/pNFS: Ensure we enforce RFC5661 Section 12.5.5.2.1
The RFC requires us to check if the server is recalling a stateid that we
haven't yet received. If so, tell it to wait.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/callback_proc.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index 34852ece4057..1b24ad07d4f5 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c | |||
@@ -160,6 +160,22 @@ static struct pnfs_layout_hdr * get_layout_by_fh(struct nfs_client *clp, | |||
160 | return lo; | 160 | return lo; |
161 | } | 161 | } |
162 | 162 | ||
163 | /* | ||
164 | * Enforce RFC5661 section 12.5.5.2.1. (Layout Recall and Return Sequencing) | ||
165 | */ | ||
166 | static bool pnfs_check_stateid_sequence(struct pnfs_layout_hdr *lo, | ||
167 | const nfs4_stateid *new) | ||
168 | { | ||
169 | u32 oldseq, newseq; | ||
170 | |||
171 | oldseq = be32_to_cpu(lo->plh_stateid.seqid); | ||
172 | newseq = be32_to_cpu(new->seqid); | ||
173 | |||
174 | if (newseq > oldseq + 1) | ||
175 | return false; | ||
176 | return true; | ||
177 | } | ||
178 | |||
163 | static u32 initiate_file_draining(struct nfs_client *clp, | 179 | static u32 initiate_file_draining(struct nfs_client *clp, |
164 | struct cb_layoutrecallargs *args) | 180 | struct cb_layoutrecallargs *args) |
165 | { | 181 | { |
@@ -175,6 +191,10 @@ static u32 initiate_file_draining(struct nfs_client *clp, | |||
175 | ino = lo->plh_inode; | 191 | ino = lo->plh_inode; |
176 | 192 | ||
177 | spin_lock(&ino->i_lock); | 193 | spin_lock(&ino->i_lock); |
194 | if (!pnfs_check_stateid_sequence(lo, &args->cbl_stateid)) { | ||
195 | rv = NFS4ERR_DELAY; | ||
196 | goto unlock; | ||
197 | } | ||
178 | pnfs_set_layout_stateid(lo, &args->cbl_stateid, true); | 198 | pnfs_set_layout_stateid(lo, &args->cbl_stateid, true); |
179 | spin_unlock(&ino->i_lock); | 199 | spin_unlock(&ino->i_lock); |
180 | 200 | ||