diff options
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r-- | fs/nfs/pnfs.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 4755858e37a0..cb53d450ae32 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -662,7 +662,18 @@ pnfs_destroy_all_layouts(struct nfs_client *clp) | |||
662 | */ | 662 | */ |
663 | static bool pnfs_seqid_is_newer(u32 s1, u32 s2) | 663 | static bool pnfs_seqid_is_newer(u32 s1, u32 s2) |
664 | { | 664 | { |
665 | return (s32)s1 - (s32)s2 > 0; | 665 | return (s32)(s1 - s2) > 0; |
666 | } | ||
667 | |||
668 | static void | ||
669 | pnfs_verify_layout_stateid(struct pnfs_layout_hdr *lo, | ||
670 | const nfs4_stateid *new, | ||
671 | struct list_head *free_me_list) | ||
672 | { | ||
673 | if (nfs4_stateid_match_other(&lo->plh_stateid, new)) | ||
674 | return; | ||
675 | /* Layout is new! Kill existing layout segments */ | ||
676 | pnfs_mark_matching_lsegs_invalid(lo, free_me_list, NULL); | ||
666 | } | 677 | } |
667 | 678 | ||
668 | /* update lo->plh_stateid with new if is more recent */ | 679 | /* update lo->plh_stateid with new if is more recent */ |
@@ -1315,6 +1326,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) | |||
1315 | struct nfs4_layoutget_res *res = &lgp->res; | 1326 | struct nfs4_layoutget_res *res = &lgp->res; |
1316 | struct pnfs_layout_segment *lseg; | 1327 | struct pnfs_layout_segment *lseg; |
1317 | struct inode *ino = lo->plh_inode; | 1328 | struct inode *ino = lo->plh_inode; |
1329 | LIST_HEAD(free_me); | ||
1318 | int status = 0; | 1330 | int status = 0; |
1319 | 1331 | ||
1320 | /* Inject layout blob into I/O device driver */ | 1332 | /* Inject layout blob into I/O device driver */ |
@@ -1341,6 +1353,8 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) | |||
1341 | goto out_forget_reply; | 1353 | goto out_forget_reply; |
1342 | } | 1354 | } |
1343 | 1355 | ||
1356 | /* Check that the new stateid matches the old stateid */ | ||
1357 | pnfs_verify_layout_stateid(lo, &res->stateid, &free_me); | ||
1344 | /* Done processing layoutget. Set the layout stateid */ | 1358 | /* Done processing layoutget. Set the layout stateid */ |
1345 | pnfs_set_layout_stateid(lo, &res->stateid, false); | 1359 | pnfs_set_layout_stateid(lo, &res->stateid, false); |
1346 | 1360 | ||
@@ -1355,6 +1369,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) | |||
1355 | } | 1369 | } |
1356 | 1370 | ||
1357 | spin_unlock(&ino->i_lock); | 1371 | spin_unlock(&ino->i_lock); |
1372 | pnfs_free_lseg_list(&free_me); | ||
1358 | return lseg; | 1373 | return lseg; |
1359 | out: | 1374 | out: |
1360 | return ERR_PTR(status); | 1375 | return ERR_PTR(status); |