diff options
author | Tom Haynes <thomas.haynes@primarydata.com> | 2016-05-25 10:31:14 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2016-05-26 08:40:56 -0400 |
commit | c7d73af2d249f0323f5cdb171a59497ce80011fb (patch) | |
tree | dd0e34ec0c9eab8394c601a2ac25eb9721d39e5e | |
parent | 602c4cd452d93355166daf8a662c84a5f85d2856 (diff) |
pnfs: pnfs_update_layout needs to consider if strict iomode checking is on
As flexfiles has FF_FLAGS_NO_READ_IO, there is a need to generically
support enforcing that a IOMODE_RW segment will not allow READ I/O.
Signed-off-by: Tom Haynes <loghyr@primarydata.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r-- | fs/nfs/filelayout/filelayout.c | 2 | ||||
-rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayout.c | 49 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 34 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 1 |
4 files changed, 61 insertions, 25 deletions
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c index 3e50057eeadf..aa59757389dc 100644 --- a/fs/nfs/filelayout/filelayout.c +++ b/fs/nfs/filelayout/filelayout.c | |||
@@ -890,6 +890,7 @@ filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio, | |||
890 | 0, | 890 | 0, |
891 | NFS4_MAX_UINT64, | 891 | NFS4_MAX_UINT64, |
892 | IOMODE_READ, | 892 | IOMODE_READ, |
893 | false, | ||
893 | GFP_KERNEL); | 894 | GFP_KERNEL); |
894 | if (IS_ERR(pgio->pg_lseg)) { | 895 | if (IS_ERR(pgio->pg_lseg)) { |
895 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | 896 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); |
@@ -915,6 +916,7 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio, | |||
915 | 0, | 916 | 0, |
916 | NFS4_MAX_UINT64, | 917 | NFS4_MAX_UINT64, |
917 | IOMODE_RW, | 918 | IOMODE_RW, |
919 | false, | ||
918 | GFP_NOFS); | 920 | GFP_NOFS); |
919 | if (IS_ERR(pgio->pg_lseg)) { | 921 | if (IS_ERR(pgio->pg_lseg)) { |
920 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | 922 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); |
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index a7aeb7407252..0e8018bc9880 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c | |||
@@ -821,6 +821,36 @@ ff_layout_choose_best_ds_for_read(struct pnfs_layout_segment *lseg, | |||
821 | } | 821 | } |
822 | 822 | ||
823 | static void | 823 | static void |
824 | ff_layout_pg_get_read(struct nfs_pageio_descriptor *pgio, | ||
825 | struct nfs_page *req, | ||
826 | bool strict_iomode) | ||
827 | { | ||
828 | retry_strict: | ||
829 | pnfs_put_lseg(pgio->pg_lseg); | ||
830 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | ||
831 | req->wb_context, | ||
832 | 0, | ||
833 | NFS4_MAX_UINT64, | ||
834 | IOMODE_READ, | ||
835 | strict_iomode, | ||
836 | GFP_KERNEL); | ||
837 | if (IS_ERR(pgio->pg_lseg)) { | ||
838 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | ||
839 | pgio->pg_lseg = NULL; | ||
840 | } | ||
841 | |||
842 | /* If we don't have checking, do get a IOMODE_RW | ||
843 | * segment, and the server wants to avoid READs | ||
844 | * there, then retry! | ||
845 | */ | ||
846 | if (pgio->pg_lseg && !strict_iomode && | ||
847 | ff_layout_avoid_read_on_rw(pgio->pg_lseg)) { | ||
848 | strict_iomode = true; | ||
849 | goto retry_strict; | ||
850 | } | ||
851 | } | ||
852 | |||
853 | static void | ||
824 | ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio, | 854 | ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio, |
825 | struct nfs_page *req) | 855 | struct nfs_page *req) |
826 | { | 856 | { |
@@ -830,19 +860,10 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio, | |||
830 | int ds_idx; | 860 | int ds_idx; |
831 | 861 | ||
832 | /* Use full layout for now */ | 862 | /* Use full layout for now */ |
833 | if (!pgio->pg_lseg || ff_layout_avoid_read_on_rw(pgio->pg_lseg)) { | 863 | if (!pgio->pg_lseg) |
834 | pnfs_put_lseg(pgio->pg_lseg); | 864 | ff_layout_pg_get_read(pgio, req, false); |
835 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 865 | else if (ff_layout_avoid_read_on_rw(pgio->pg_lseg)) |
836 | req->wb_context, | 866 | ff_layout_pg_get_read(pgio, req, true); |
837 | 0, | ||
838 | NFS4_MAX_UINT64, | ||
839 | IOMODE_READ, | ||
840 | GFP_KERNEL); | ||
841 | if (IS_ERR(pgio->pg_lseg)) { | ||
842 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | ||
843 | pgio->pg_lseg = NULL; | ||
844 | } | ||
845 | } | ||
846 | 867 | ||
847 | /* If no lseg, fall back to read through mds */ | 868 | /* If no lseg, fall back to read through mds */ |
848 | if (pgio->pg_lseg == NULL) | 869 | if (pgio->pg_lseg == NULL) |
@@ -894,6 +915,7 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio, | |||
894 | 0, | 915 | 0, |
895 | NFS4_MAX_UINT64, | 916 | NFS4_MAX_UINT64, |
896 | IOMODE_RW, | 917 | IOMODE_RW, |
918 | false, | ||
897 | GFP_NOFS); | 919 | GFP_NOFS); |
898 | if (IS_ERR(pgio->pg_lseg)) { | 920 | if (IS_ERR(pgio->pg_lseg)) { |
899 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | 921 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); |
@@ -952,6 +974,7 @@ ff_layout_pg_get_mirror_count_write(struct nfs_pageio_descriptor *pgio, | |||
952 | 0, | 974 | 0, |
953 | NFS4_MAX_UINT64, | 975 | NFS4_MAX_UINT64, |
954 | IOMODE_RW, | 976 | IOMODE_RW, |
977 | false, | ||
955 | GFP_NOFS); | 978 | GFP_NOFS); |
956 | if (IS_ERR(pgio->pg_lseg)) { | 979 | if (IS_ERR(pgio->pg_lseg)) { |
957 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | 980 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 79ae3049608d..0c7e0d45a4de 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -1321,23 +1321,28 @@ out_existing: | |||
1321 | 1321 | ||
1322 | /* | 1322 | /* |
1323 | * iomode matching rules: | 1323 | * iomode matching rules: |
1324 | * iomode lseg match | 1324 | * iomode lseg strict match |
1325 | * ----- ----- ----- | 1325 | * iomode |
1326 | * ANY READ true | 1326 | * ----- ----- ------ ----- |
1327 | * ANY RW true | 1327 | * ANY READ N/A true |
1328 | * RW READ false | 1328 | * ANY RW N/A true |
1329 | * RW RW true | 1329 | * RW READ N/A false |
1330 | * READ READ true | 1330 | * RW RW N/A true |
1331 | * READ RW true | 1331 | * READ READ N/A true |
1332 | * READ RW true false | ||
1333 | * READ RW false true | ||
1332 | */ | 1334 | */ |
1333 | static bool | 1335 | static bool |
1334 | pnfs_lseg_range_match(const struct pnfs_layout_range *ls_range, | 1336 | pnfs_lseg_range_match(const struct pnfs_layout_range *ls_range, |
1335 | const struct pnfs_layout_range *range) | 1337 | const struct pnfs_layout_range *range, |
1338 | bool strict_iomode) | ||
1336 | { | 1339 | { |
1337 | struct pnfs_layout_range range1; | 1340 | struct pnfs_layout_range range1; |
1338 | 1341 | ||
1339 | if ((range->iomode == IOMODE_RW && | 1342 | if ((range->iomode == IOMODE_RW && |
1340 | ls_range->iomode != IOMODE_RW) || | 1343 | ls_range->iomode != IOMODE_RW) || |
1344 | (range->iomode != ls_range->iomode && | ||
1345 | strict_iomode == true) || | ||
1341 | !pnfs_lseg_range_intersecting(ls_range, range)) | 1346 | !pnfs_lseg_range_intersecting(ls_range, range)) |
1342 | return 0; | 1347 | return 0; |
1343 | 1348 | ||
@@ -1352,7 +1357,8 @@ pnfs_lseg_range_match(const struct pnfs_layout_range *ls_range, | |||
1352 | */ | 1357 | */ |
1353 | static struct pnfs_layout_segment * | 1358 | static struct pnfs_layout_segment * |
1354 | pnfs_find_lseg(struct pnfs_layout_hdr *lo, | 1359 | pnfs_find_lseg(struct pnfs_layout_hdr *lo, |
1355 | struct pnfs_layout_range *range) | 1360 | struct pnfs_layout_range *range, |
1361 | bool strict_iomode) | ||
1356 | { | 1362 | { |
1357 | struct pnfs_layout_segment *lseg, *ret = NULL; | 1363 | struct pnfs_layout_segment *lseg, *ret = NULL; |
1358 | 1364 | ||
@@ -1361,7 +1367,8 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, | |||
1361 | list_for_each_entry(lseg, &lo->plh_segs, pls_list) { | 1367 | list_for_each_entry(lseg, &lo->plh_segs, pls_list) { |
1362 | if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags) && | 1368 | if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags) && |
1363 | !test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags) && | 1369 | !test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags) && |
1364 | pnfs_lseg_range_match(&lseg->pls_range, range)) { | 1370 | pnfs_lseg_range_match(&lseg->pls_range, range, |
1371 | strict_iomode)) { | ||
1365 | ret = pnfs_get_lseg(lseg); | 1372 | ret = pnfs_get_lseg(lseg); |
1366 | break; | 1373 | break; |
1367 | } | 1374 | } |
@@ -1478,6 +1485,7 @@ pnfs_update_layout(struct inode *ino, | |||
1478 | loff_t pos, | 1485 | loff_t pos, |
1479 | u64 count, | 1486 | u64 count, |
1480 | enum pnfs_iomode iomode, | 1487 | enum pnfs_iomode iomode, |
1488 | bool strict_iomode, | ||
1481 | gfp_t gfp_flags) | 1489 | gfp_t gfp_flags) |
1482 | { | 1490 | { |
1483 | struct pnfs_layout_range arg = { | 1491 | struct pnfs_layout_range arg = { |
@@ -1539,7 +1547,7 @@ lookup_again: | |||
1539 | goto out_unlock; | 1547 | goto out_unlock; |
1540 | } | 1548 | } |
1541 | 1549 | ||
1542 | lseg = pnfs_find_lseg(lo, &arg); | 1550 | lseg = pnfs_find_lseg(lo, &arg, strict_iomode); |
1543 | if (lseg) { | 1551 | if (lseg) { |
1544 | trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, | 1552 | trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, |
1545 | PNFS_UPDATE_LAYOUT_FOUND_CACHED); | 1553 | PNFS_UPDATE_LAYOUT_FOUND_CACHED); |
@@ -1883,6 +1891,7 @@ pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *r | |||
1883 | req_offset(req), | 1891 | req_offset(req), |
1884 | rd_size, | 1892 | rd_size, |
1885 | IOMODE_READ, | 1893 | IOMODE_READ, |
1894 | false, | ||
1886 | GFP_KERNEL); | 1895 | GFP_KERNEL); |
1887 | if (IS_ERR(pgio->pg_lseg)) { | 1896 | if (IS_ERR(pgio->pg_lseg)) { |
1888 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | 1897 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); |
@@ -1907,6 +1916,7 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, | |||
1907 | req_offset(req), | 1916 | req_offset(req), |
1908 | wb_size, | 1917 | wb_size, |
1909 | IOMODE_RW, | 1918 | IOMODE_RW, |
1919 | false, | ||
1910 | GFP_NOFS); | 1920 | GFP_NOFS); |
1911 | if (IS_ERR(pgio->pg_lseg)) { | 1921 | if (IS_ERR(pgio->pg_lseg)) { |
1912 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | 1922 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index f9f3331bef49..b21bd0bee784 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -288,6 +288,7 @@ struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino, | |||
288 | loff_t pos, | 288 | loff_t pos, |
289 | u64 count, | 289 | u64 count, |
290 | enum pnfs_iomode iomode, | 290 | enum pnfs_iomode iomode, |
291 | bool strict_iomode, | ||
291 | gfp_t gfp_flags); | 292 | gfp_t gfp_flags); |
292 | void pnfs_clear_layoutreturn_waitbit(struct pnfs_layout_hdr *lo); | 293 | void pnfs_clear_layoutreturn_waitbit(struct pnfs_layout_hdr *lo); |
293 | 294 | ||