diff options
Diffstat (limited to 'fs/nfs/nfs42proc.c')
-rw-r--r-- | fs/nfs/nfs42proc.c | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index 6f4752734804..64b43b4ad9dd 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c | |||
@@ -318,10 +318,22 @@ static void | |||
318 | nfs42_layoutstat_prepare(struct rpc_task *task, void *calldata) | 318 | nfs42_layoutstat_prepare(struct rpc_task *task, void *calldata) |
319 | { | 319 | { |
320 | struct nfs42_layoutstat_data *data = calldata; | 320 | struct nfs42_layoutstat_data *data = calldata; |
321 | struct nfs_server *server = NFS_SERVER(data->args.inode); | 321 | struct inode *inode = data->inode; |
322 | struct nfs_server *server = NFS_SERVER(inode); | ||
323 | struct pnfs_layout_hdr *lo; | ||
322 | 324 | ||
325 | spin_lock(&inode->i_lock); | ||
326 | lo = NFS_I(inode)->layout; | ||
327 | if (!pnfs_layout_is_valid(lo)) { | ||
328 | spin_unlock(&inode->i_lock); | ||
329 | rpc_exit(task, 0); | ||
330 | return; | ||
331 | } | ||
332 | nfs4_stateid_copy(&data->args.stateid, &lo->plh_stateid); | ||
333 | spin_unlock(&inode->i_lock); | ||
323 | nfs41_setup_sequence(nfs4_get_session(server), &data->args.seq_args, | 334 | nfs41_setup_sequence(nfs4_get_session(server), &data->args.seq_args, |
324 | &data->res.seq_res, task); | 335 | &data->res.seq_res, task); |
336 | |||
325 | } | 337 | } |
326 | 338 | ||
327 | static void | 339 | static void |
@@ -341,11 +353,11 @@ nfs42_layoutstat_done(struct rpc_task *task, void *calldata) | |||
341 | case -NFS4ERR_ADMIN_REVOKED: | 353 | case -NFS4ERR_ADMIN_REVOKED: |
342 | case -NFS4ERR_DELEG_REVOKED: | 354 | case -NFS4ERR_DELEG_REVOKED: |
343 | case -NFS4ERR_STALE_STATEID: | 355 | case -NFS4ERR_STALE_STATEID: |
344 | case -NFS4ERR_OLD_STATEID: | ||
345 | case -NFS4ERR_BAD_STATEID: | 356 | case -NFS4ERR_BAD_STATEID: |
346 | spin_lock(&inode->i_lock); | 357 | spin_lock(&inode->i_lock); |
347 | lo = NFS_I(inode)->layout; | 358 | lo = NFS_I(inode)->layout; |
348 | if (lo && nfs4_stateid_match(&data->args.stateid, | 359 | if (pnfs_layout_is_valid(lo) && |
360 | nfs4_stateid_match(&data->args.stateid, | ||
349 | &lo->plh_stateid)) { | 361 | &lo->plh_stateid)) { |
350 | LIST_HEAD(head); | 362 | LIST_HEAD(head); |
351 | 363 | ||
@@ -359,11 +371,23 @@ nfs42_layoutstat_done(struct rpc_task *task, void *calldata) | |||
359 | } else | 371 | } else |
360 | spin_unlock(&inode->i_lock); | 372 | spin_unlock(&inode->i_lock); |
361 | break; | 373 | break; |
374 | case -NFS4ERR_OLD_STATEID: | ||
375 | spin_lock(&inode->i_lock); | ||
376 | lo = NFS_I(inode)->layout; | ||
377 | if (pnfs_layout_is_valid(lo) && | ||
378 | nfs4_stateid_match_other(&data->args.stateid, | ||
379 | &lo->plh_stateid)) { | ||
380 | /* Do we need to delay before resending? */ | ||
381 | if (!nfs4_stateid_is_newer(&lo->plh_stateid, | ||
382 | &data->args.stateid)) | ||
383 | rpc_delay(task, HZ); | ||
384 | rpc_restart_call_prepare(task); | ||
385 | } | ||
386 | spin_unlock(&inode->i_lock); | ||
387 | break; | ||
362 | case -ENOTSUPP: | 388 | case -ENOTSUPP: |
363 | case -EOPNOTSUPP: | 389 | case -EOPNOTSUPP: |
364 | NFS_SERVER(inode)->caps &= ~NFS_CAP_LAYOUTSTATS; | 390 | NFS_SERVER(inode)->caps &= ~NFS_CAP_LAYOUTSTATS; |
365 | default: | ||
366 | break; | ||
367 | } | 391 | } |
368 | 392 | ||
369 | dprintk("%s server returns %d\n", __func__, task->tk_status); | 393 | dprintk("%s server returns %d\n", __func__, task->tk_status); |