summaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs42proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs42proc.c')
-rw-r--r--fs/nfs/nfs42proc.c34
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
318nfs42_layoutstat_prepare(struct rpc_task *task, void *calldata) 318nfs42_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
327static void 339static 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);