aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Haynes <thomas.haynes@primarydata.com>2016-05-25 10:31:14 -0400
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2016-05-26 08:40:56 -0400
commitc7d73af2d249f0323f5cdb171a59497ce80011fb (patch)
treedd0e34ec0c9eab8394c601a2ac25eb9721d39e5e
parent602c4cd452d93355166daf8a662c84a5f85d2856 (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.c2
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.c49
-rw-r--r--fs/nfs/pnfs.c34
-rw-r--r--fs/nfs/pnfs.h1
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
823static void 823static void
824ff_layout_pg_get_read(struct nfs_pageio_descriptor *pgio,
825 struct nfs_page *req,
826 bool strict_iomode)
827{
828retry_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
853static void
824ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio, 854ff_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 */
1333static bool 1335static bool
1334pnfs_lseg_range_match(const struct pnfs_layout_range *ls_range, 1336pnfs_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 */
1353static struct pnfs_layout_segment * 1358static struct pnfs_layout_segment *
1354pnfs_find_lseg(struct pnfs_layout_hdr *lo, 1359pnfs_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);
292void pnfs_clear_layoutreturn_waitbit(struct pnfs_layout_hdr *lo); 293void pnfs_clear_layoutreturn_waitbit(struct pnfs_layout_hdr *lo);
293 294