summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWeston Andros Adamson <dros@primarydata.com>2014-05-15 11:56:54 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-05-29 11:11:48 -0400
commit5002c58639d41b93e800c8a4b7eca49c40d57822 (patch)
treeb9d9981b3396f4f7a5f518f905d8a1199e087509
parent7f714720fac03383d687dbe39494cc96b845bd46 (diff)
pnfs: support multiple verfs per direct req
Support direct requests that span multiple pnfs data servers by comparing nfs_pgio_header->verf to a cached verf in pnfs_commit_bucket. Continue to use dreq->verf if the MDS is used / non-pNFS. Signed-off-by: Weston Andros Adamson <dros@primarydata.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r--fs/nfs/direct.c102
-rw-r--r--fs/nfs/nfs4filelayout.c6
-rw-r--r--include/linux/nfs.h5
-rw-r--r--include/linux/nfs_xdr.h2
4 files changed, 109 insertions, 6 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 2c0e08f4cf71..4ad7bc388679 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -108,6 +108,97 @@ static inline int put_dreq(struct nfs_direct_req *dreq)
108 return atomic_dec_and_test(&dreq->io_count); 108 return atomic_dec_and_test(&dreq->io_count);
109} 109}
110 110
111/*
112 * nfs_direct_select_verf - select the right verifier
113 * @dreq - direct request possibly spanning multiple servers
114 * @ds_clp - nfs_client of data server or NULL if MDS / non-pnfs
115 * @ds_idx - index of data server in data server list, only valid if ds_clp set
116 *
117 * returns the correct verifier to use given the role of the server
118 */
119static struct nfs_writeverf *
120nfs_direct_select_verf(struct nfs_direct_req *dreq,
121 struct nfs_client *ds_clp,
122 int ds_idx)
123{
124 struct nfs_writeverf *verfp = &dreq->verf;
125
126#ifdef CONFIG_NFS_V4_1
127 if (ds_clp) {
128 /* pNFS is in use, use the DS verf */
129 if (ds_idx >= 0 && ds_idx < dreq->ds_cinfo.nbuckets)
130 verfp = &dreq->ds_cinfo.buckets[ds_idx].direct_verf;
131 else
132 WARN_ON_ONCE(1);
133 }
134#endif
135 return verfp;
136}
137
138
139/*
140 * nfs_direct_set_hdr_verf - set the write/commit verifier
141 * @dreq - direct request possibly spanning multiple servers
142 * @hdr - pageio header to validate against previously seen verfs
143 *
144 * Set the server's (MDS or DS) "seen" verifier
145 */
146static void nfs_direct_set_hdr_verf(struct nfs_direct_req *dreq,
147 struct nfs_pgio_header *hdr)
148{
149 struct nfs_writeverf *verfp;
150
151 verfp = nfs_direct_select_verf(dreq, hdr->data->ds_clp,
152 hdr->data->ds_idx);
153 WARN_ON_ONCE(verfp->committed >= 0);
154 memcpy(verfp, &hdr->verf, sizeof(struct nfs_writeverf));
155 WARN_ON_ONCE(verfp->committed < 0);
156}
157
158/*
159 * nfs_direct_cmp_hdr_verf - compare verifier for pgio header
160 * @dreq - direct request possibly spanning multiple servers
161 * @hdr - pageio header to validate against previously seen verf
162 *
163 * set the server's "seen" verf if not initialized.
164 * returns result of comparison between @hdr->verf and the "seen"
165 * verf of the server used by @hdr (DS or MDS)
166 */
167static int nfs_direct_set_or_cmp_hdr_verf(struct nfs_direct_req *dreq,
168 struct nfs_pgio_header *hdr)
169{
170 struct nfs_writeverf *verfp;
171
172 verfp = nfs_direct_select_verf(dreq, hdr->data->ds_clp,
173 hdr->data->ds_idx);
174 if (verfp->committed < 0) {
175 nfs_direct_set_hdr_verf(dreq, hdr);
176 return 0;
177 }
178 return memcmp(verfp, &hdr->verf, sizeof(struct nfs_writeverf));
179}
180
181#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
182/*
183 * nfs_direct_cmp_commit_data_verf - compare verifier for commit data
184 * @dreq - direct request possibly spanning multiple servers
185 * @data - commit data to validate against previously seen verf
186 *
187 * returns result of comparison between @data->verf and the verf of
188 * the server used by @data (DS or MDS)
189 */
190static int nfs_direct_cmp_commit_data_verf(struct nfs_direct_req *dreq,
191 struct nfs_commit_data *data)
192{
193 struct nfs_writeverf *verfp;
194
195 verfp = nfs_direct_select_verf(dreq, data->ds_clp,
196 data->ds_commit_index);
197 WARN_ON_ONCE(verfp->committed < 0);
198 return memcmp(verfp, &data->verf, sizeof(struct nfs_writeverf));
199}
200#endif
201
111/** 202/**
112 * nfs_direct_IO - NFS address space operation for direct I/O 203 * nfs_direct_IO - NFS address space operation for direct I/O
113 * @rw: direction (read or write) 204 * @rw: direction (read or write)
@@ -168,6 +259,7 @@ static inline struct nfs_direct_req *nfs_direct_req_alloc(void)
168 kref_get(&dreq->kref); 259 kref_get(&dreq->kref);
169 init_completion(&dreq->completion); 260 init_completion(&dreq->completion);
170 INIT_LIST_HEAD(&dreq->mds_cinfo.list); 261 INIT_LIST_HEAD(&dreq->mds_cinfo.list);
262 dreq->verf.committed = NFS_INVALID_STABLE_HOW; /* not set yet */
171 INIT_WORK(&dreq->work, nfs_direct_write_schedule_work); 263 INIT_WORK(&dreq->work, nfs_direct_write_schedule_work);
172 spin_lock_init(&dreq->lock); 264 spin_lock_init(&dreq->lock);
173 265
@@ -602,7 +694,7 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
602 dprintk("NFS: %5u commit failed with error %d.\n", 694 dprintk("NFS: %5u commit failed with error %d.\n",
603 data->task.tk_pid, status); 695 data->task.tk_pid, status);
604 dreq->flags = NFS_ODIRECT_RESCHED_WRITES; 696 dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
605 } else if (memcmp(&dreq->verf, &data->verf, sizeof(data->verf))) { 697 } else if (nfs_direct_cmp_commit_data_verf(dreq, data)) {
606 dprintk("NFS: %5u commit verify failed\n", data->task.tk_pid); 698 dprintk("NFS: %5u commit verify failed\n", data->task.tk_pid);
607 dreq->flags = NFS_ODIRECT_RESCHED_WRITES; 699 dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
608 } 700 }
@@ -811,13 +903,13 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
811 if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES) 903 if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES)
812 bit = NFS_IOHDR_NEED_RESCHED; 904 bit = NFS_IOHDR_NEED_RESCHED;
813 else if (dreq->flags == 0) { 905 else if (dreq->flags == 0) {
814 memcpy(&dreq->verf, &hdr->verf, 906 nfs_direct_set_hdr_verf(dreq, hdr);
815 sizeof(dreq->verf));
816 bit = NFS_IOHDR_NEED_COMMIT; 907 bit = NFS_IOHDR_NEED_COMMIT;
817 dreq->flags = NFS_ODIRECT_DO_COMMIT; 908 dreq->flags = NFS_ODIRECT_DO_COMMIT;
818 } else if (dreq->flags == NFS_ODIRECT_DO_COMMIT) { 909 } else if (dreq->flags == NFS_ODIRECT_DO_COMMIT) {
819 if (memcmp(&dreq->verf, &hdr->verf, sizeof(dreq->verf))) { 910 if (nfs_direct_set_or_cmp_hdr_verf(dreq, hdr)) {
820 dreq->flags = NFS_ODIRECT_RESCHED_WRITES; 911 dreq->flags =
912 NFS_ODIRECT_RESCHED_WRITES;
821 bit = NFS_IOHDR_NEED_RESCHED; 913 bit = NFS_IOHDR_NEED_RESCHED;
822 } else 914 } else
823 bit = NFS_IOHDR_NEED_COMMIT; 915 bit = NFS_IOHDR_NEED_COMMIT;
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 7a665e0f35b7..0ebc521ea6fc 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -560,6 +560,7 @@ filelayout_read_pagelist(struct nfs_pgio_data *data)
560 /* No multipath support. Use first DS */ 560 /* No multipath support. Use first DS */
561 atomic_inc(&ds->ds_clp->cl_count); 561 atomic_inc(&ds->ds_clp->cl_count);
562 data->ds_clp = ds->ds_clp; 562 data->ds_clp = ds->ds_clp;
563 data->ds_idx = idx;
563 fh = nfs4_fl_select_ds_fh(lseg, j); 564 fh = nfs4_fl_select_ds_fh(lseg, j);
564 if (fh) 565 if (fh)
565 data->args.fh = fh; 566 data->args.fh = fh;
@@ -603,6 +604,7 @@ filelayout_write_pagelist(struct nfs_pgio_data *data, int sync)
603 data->pgio_done_cb = filelayout_write_done_cb; 604 data->pgio_done_cb = filelayout_write_done_cb;
604 atomic_inc(&ds->ds_clp->cl_count); 605 atomic_inc(&ds->ds_clp->cl_count);
605 data->ds_clp = ds->ds_clp; 606 data->ds_clp = ds->ds_clp;
607 data->ds_idx = idx;
606 fh = nfs4_fl_select_ds_fh(lseg, j); 608 fh = nfs4_fl_select_ds_fh(lseg, j);
607 if (fh) 609 if (fh)
608 data->args.fh = fh; 610 data->args.fh = fh;
@@ -875,6 +877,8 @@ filelayout_alloc_commit_info(struct pnfs_layout_segment *lseg,
875 for (i = 0; i < size; i++) { 877 for (i = 0; i < size; i++) {
876 INIT_LIST_HEAD(&buckets[i].written); 878 INIT_LIST_HEAD(&buckets[i].written);
877 INIT_LIST_HEAD(&buckets[i].committing); 879 INIT_LIST_HEAD(&buckets[i].committing);
880 /* mark direct verifier as unset */
881 buckets[i].direct_verf.committed = NFS_INVALID_STABLE_HOW;
878 } 882 }
879 883
880 spin_lock(cinfo->lock); 884 spin_lock(cinfo->lock);
@@ -885,6 +889,8 @@ filelayout_alloc_commit_info(struct pnfs_layout_segment *lseg,
885 &buckets[i].written); 889 &buckets[i].written);
886 list_splice(&cinfo->ds->buckets[i].committing, 890 list_splice(&cinfo->ds->buckets[i].committing,
887 &buckets[i].committing); 891 &buckets[i].committing);
892 buckets[i].direct_verf.committed =
893 cinfo->ds->buckets[i].direct_verf.committed;
888 buckets[i].wlseg = cinfo->ds->buckets[i].wlseg; 894 buckets[i].wlseg = cinfo->ds->buckets[i].wlseg;
889 buckets[i].clseg = cinfo->ds->buckets[i].clseg; 895 buckets[i].clseg = cinfo->ds->buckets[i].clseg;
890 } 896 }
diff --git a/include/linux/nfs.h b/include/linux/nfs.h
index 3e794c12e90a..610af5155ef2 100644
--- a/include/linux/nfs.h
+++ b/include/linux/nfs.h
@@ -46,6 +46,9 @@ static inline void nfs_copy_fh(struct nfs_fh *target, const struct nfs_fh *sourc
46enum nfs3_stable_how { 46enum nfs3_stable_how {
47 NFS_UNSTABLE = 0, 47 NFS_UNSTABLE = 0,
48 NFS_DATA_SYNC = 1, 48 NFS_DATA_SYNC = 1,
49 NFS_FILE_SYNC = 2 49 NFS_FILE_SYNC = 2,
50
51 /* used by direct.c to mark verf as invalid */
52 NFS_INVALID_STABLE_HOW = -1
50}; 53};
51#endif /* _LINUX_NFS_H */ 54#endif /* _LINUX_NFS_H */
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index ae636013fb1f..9a1396e70310 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1112,6 +1112,7 @@ struct pnfs_commit_bucket {
1112 struct list_head committing; 1112 struct list_head committing;
1113 struct pnfs_layout_segment *wlseg; 1113 struct pnfs_layout_segment *wlseg;
1114 struct pnfs_layout_segment *clseg; 1114 struct pnfs_layout_segment *clseg;
1115 struct nfs_writeverf direct_verf;
1115}; 1116};
1116 1117
1117struct pnfs_ds_commit_info { 1118struct pnfs_ds_commit_info {
@@ -1294,6 +1295,7 @@ struct nfs_pgio_data {
1294 __u64 mds_offset; /* Filelayout dense stripe */ 1295 __u64 mds_offset; /* Filelayout dense stripe */
1295 struct nfs_page_array pages; 1296 struct nfs_page_array pages;
1296 struct nfs_client *ds_clp; /* pNFS data server */ 1297 struct nfs_client *ds_clp; /* pNFS data server */
1298 int ds_idx; /* ds index if ds_clp is set */
1297}; 1299};
1298 1300
1299struct nfs_rw_header { 1301struct nfs_rw_header {