diff options
author | Peng Tao <tao.peng@primarydata.com> | 2015-12-06 20:55:09 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-12-28 09:57:08 -0500 |
commit | 68d264cf02b076a2457aa77c044f5e41b6fa8086 (patch) | |
tree | ed59d05a1c064ee8e7459c92077b1cf1375bfd02 | |
parent | 361cad3c89070aeb37560860ea8bfc092d545adc (diff) |
NFS42: handle layoutstats stateid error
When server returns layoutstats stateid error, we should
invalidate client's layout so that next IO can trigger new
layoutget.
Signed-off-by: Peng Tao <tao.peng@primarydata.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r-- | fs/nfs/nfs42proc.c | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index 6b1ce9825430..6e8174930a48 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c | |||
@@ -204,6 +204,8 @@ static void | |||
204 | nfs42_layoutstat_done(struct rpc_task *task, void *calldata) | 204 | nfs42_layoutstat_done(struct rpc_task *task, void *calldata) |
205 | { | 205 | { |
206 | struct nfs42_layoutstat_data *data = calldata; | 206 | struct nfs42_layoutstat_data *data = calldata; |
207 | struct inode *inode = data->inode; | ||
208 | struct pnfs_layout_hdr *lo; | ||
207 | 209 | ||
208 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | 210 | if (!nfs4_sequence_done(task, &data->res.seq_res)) |
209 | return; | 211 | return; |
@@ -211,12 +213,35 @@ nfs42_layoutstat_done(struct rpc_task *task, void *calldata) | |||
211 | switch (task->tk_status) { | 213 | switch (task->tk_status) { |
212 | case 0: | 214 | case 0: |
213 | break; | 215 | break; |
216 | case -NFS4ERR_EXPIRED: | ||
217 | case -NFS4ERR_STALE_STATEID: | ||
218 | case -NFS4ERR_OLD_STATEID: | ||
219 | case -NFS4ERR_BAD_STATEID: | ||
220 | spin_lock(&inode->i_lock); | ||
221 | lo = NFS_I(inode)->layout; | ||
222 | if (lo && nfs4_stateid_match(&data->args.stateid, | ||
223 | &lo->plh_stateid)) { | ||
224 | LIST_HEAD(head); | ||
225 | |||
226 | /* | ||
227 | * Mark the bad layout state as invalid, then retry | ||
228 | * with the current stateid. | ||
229 | */ | ||
230 | set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); | ||
231 | pnfs_mark_matching_lsegs_invalid(lo, &head, NULL); | ||
232 | spin_unlock(&inode->i_lock); | ||
233 | pnfs_free_lseg_list(&head); | ||
234 | } else | ||
235 | spin_unlock(&inode->i_lock); | ||
236 | break; | ||
214 | case -ENOTSUPP: | 237 | case -ENOTSUPP: |
215 | case -EOPNOTSUPP: | 238 | case -EOPNOTSUPP: |
216 | NFS_SERVER(data->inode)->caps &= ~NFS_CAP_LAYOUTSTATS; | 239 | NFS_SERVER(inode)->caps &= ~NFS_CAP_LAYOUTSTATS; |
217 | default: | 240 | default: |
218 | dprintk("%s server returns %d\n", __func__, task->tk_status); | 241 | break; |
219 | } | 242 | } |
243 | |||
244 | dprintk("%s server returns %d\n", __func__, task->tk_status); | ||
220 | } | 245 | } |
221 | 246 | ||
222 | static void | 247 | static void |