aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/filelayout/filelayout.c2
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.c6
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayoutdev.c99
-rw-r--r--fs/nfs/internal.h2
-rw-r--r--fs/nfs/write.c7
5 files changed, 47 insertions, 69 deletions
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c
index bb1f4e7a3270..3384dc8e6683 100644
--- a/fs/nfs/filelayout/filelayout.c
+++ b/fs/nfs/filelayout/filelayout.c
@@ -971,7 +971,7 @@ filelayout_mark_request_commit(struct nfs_page *req,
971 u32 i, j; 971 u32 i, j;
972 972
973 if (fl->commit_through_mds) { 973 if (fl->commit_through_mds) {
974 nfs_request_add_commit_list(req, &cinfo->mds->list, cinfo); 974 nfs_request_add_commit_list(req, cinfo);
975 } else { 975 } else {
976 /* Note that we are calling nfs4_fl_calc_j_index on each page 976 /* Note that we are calling nfs4_fl_calc_j_index on each page
977 * that ends up being committed to a data server. An attractive 977 * that ends up being committed to a data server. An attractive
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index 6594e9f903a0..5bcd92d50e82 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -1948,11 +1948,9 @@ ff_layout_encode_layoutreturn(struct pnfs_layout_hdr *lo,
1948 start = xdr_reserve_space(xdr, 4); 1948 start = xdr_reserve_space(xdr, 4);
1949 BUG_ON(!start); 1949 BUG_ON(!start);
1950 1950
1951 if (ff_layout_encode_ioerr(flo, xdr, args)) 1951 ff_layout_encode_ioerr(flo, xdr, args);
1952 goto out;
1953
1954 ff_layout_encode_iostats(flo, xdr, args); 1952 ff_layout_encode_iostats(flo, xdr, args);
1955out: 1953
1956 *start = cpu_to_be32((xdr->p - start - 1) * 4); 1954 *start = cpu_to_be32((xdr->p - start - 1) * 4);
1957 dprintk("%s: Return\n", __func__); 1955 dprintk("%s: Return\n", __func__);
1958} 1956}
diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c
index bd0327541366..29898a9550fa 100644
--- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c
+++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c
@@ -218,63 +218,55 @@ static void extend_ds_error(struct nfs4_ff_layout_ds_err *err,
218 err->length = end - err->offset; 218 err->length = end - err->offset;
219} 219}
220 220
221static bool ds_error_can_merge(struct nfs4_ff_layout_ds_err *err, u64 offset, 221static int
222 u64 length, int status, enum nfs_opnum4 opnum, 222ff_ds_error_match(const struct nfs4_ff_layout_ds_err *e1,
223 nfs4_stateid *stateid, 223 const struct nfs4_ff_layout_ds_err *e2)
224 struct nfs4_deviceid *deviceid)
225{ 224{
226 return err->status == status && err->opnum == opnum && 225 int ret;
227 nfs4_stateid_match(&err->stateid, stateid) && 226
228 !memcmp(&err->deviceid, deviceid, sizeof(*deviceid)) && 227 if (e1->opnum != e2->opnum)
229 end_offset(err->offset, err->length) >= offset && 228 return e1->opnum < e2->opnum ? -1 : 1;
230 err->offset <= end_offset(offset, length); 229 if (e1->status != e2->status)
231} 230 return e1->status < e2->status ? -1 : 1;
232 231 ret = memcmp(&e1->stateid, &e2->stateid, sizeof(e1->stateid));
233static bool merge_ds_error(struct nfs4_ff_layout_ds_err *old, 232 if (ret != 0)
234 struct nfs4_ff_layout_ds_err *new) 233 return ret;
235{ 234 ret = memcmp(&e1->deviceid, &e2->deviceid, sizeof(e1->deviceid));
236 if (!ds_error_can_merge(old, new->offset, new->length, new->status, 235 if (ret != 0)
237 new->opnum, &new->stateid, &new->deviceid)) 236 return ret;
238 return false; 237 if (end_offset(e1->offset, e1->length) < e2->offset)
239 238 return -1;
240 extend_ds_error(old, new->offset, new->length); 239 if (e1->offset > end_offset(e2->offset, e2->length))
241 return true; 240 return 1;
241 /* If ranges overlap or are contiguous, they are the same */
242 return 0;
242} 243}
243 244
244static bool 245static void
245ff_layout_add_ds_error_locked(struct nfs4_flexfile_layout *flo, 246ff_layout_add_ds_error_locked(struct nfs4_flexfile_layout *flo,
246 struct nfs4_ff_layout_ds_err *dserr) 247 struct nfs4_ff_layout_ds_err *dserr)
247{ 248{
248 struct nfs4_ff_layout_ds_err *err; 249 struct nfs4_ff_layout_ds_err *err, *tmp;
249 250 struct list_head *head = &flo->error_list;
250 list_for_each_entry(err, &flo->error_list, list) { 251 int match;
251 if (merge_ds_error(err, dserr)) { 252
252 return true; 253 /* Do insertion sort w/ merges */
253 } 254 list_for_each_entry_safe(err, tmp, &flo->error_list, list) {
254 } 255 match = ff_ds_error_match(err, dserr);
255 256 if (match < 0)
256 list_add(&dserr->list, &flo->error_list); 257 continue;
257 return false; 258 if (match > 0) {
258} 259 /* Add entry "dserr" _before_ entry "err" */
259 260 head = &err->list;
260static bool
261ff_layout_update_ds_error(struct nfs4_flexfile_layout *flo, u64 offset,
262 u64 length, int status, enum nfs_opnum4 opnum,
263 nfs4_stateid *stateid, struct nfs4_deviceid *deviceid)
264{
265 bool found = false;
266 struct nfs4_ff_layout_ds_err *err;
267
268 list_for_each_entry(err, &flo->error_list, list) {
269 if (ds_error_can_merge(err, offset, length, status, opnum,
270 stateid, deviceid)) {
271 found = true;
272 extend_ds_error(err, offset, length);
273 break; 261 break;
274 } 262 }
263 /* Entries match, so merge "err" into "dserr" */
264 extend_ds_error(dserr, err->offset, err->length);
265 list_del(&err->list);
266 kfree(err);
275 } 267 }
276 268
277 return found; 269 list_add_tail(&dserr->list, head);
278} 270}
279 271
280int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo, 272int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo,
@@ -283,7 +275,6 @@ int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo,
283 gfp_t gfp_flags) 275 gfp_t gfp_flags)
284{ 276{
285 struct nfs4_ff_layout_ds_err *dserr; 277 struct nfs4_ff_layout_ds_err *dserr;
286 bool needfree;
287 278
288 if (status == 0) 279 if (status == 0)
289 return 0; 280 return 0;
@@ -291,14 +282,6 @@ int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo,
291 if (mirror->mirror_ds == NULL) 282 if (mirror->mirror_ds == NULL)
292 return -EINVAL; 283 return -EINVAL;
293 284
294 spin_lock(&flo->generic_hdr.plh_inode->i_lock);
295 if (ff_layout_update_ds_error(flo, offset, length, status, opnum,
296 &mirror->stateid,
297 &mirror->mirror_ds->id_node.deviceid)) {
298 spin_unlock(&flo->generic_hdr.plh_inode->i_lock);
299 return 0;
300 }
301 spin_unlock(&flo->generic_hdr.plh_inode->i_lock);
302 dserr = kmalloc(sizeof(*dserr), gfp_flags); 285 dserr = kmalloc(sizeof(*dserr), gfp_flags);
303 if (!dserr) 286 if (!dserr)
304 return -ENOMEM; 287 return -ENOMEM;
@@ -313,10 +296,8 @@ int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo,
313 NFS4_DEVICEID4_SIZE); 296 NFS4_DEVICEID4_SIZE);
314 297
315 spin_lock(&flo->generic_hdr.plh_inode->i_lock); 298 spin_lock(&flo->generic_hdr.plh_inode->i_lock);
316 needfree = ff_layout_add_ds_error_locked(flo, dserr); 299 ff_layout_add_ds_error_locked(flo, dserr);
317 spin_unlock(&flo->generic_hdr.plh_inode->i_lock); 300 spin_unlock(&flo->generic_hdr.plh_inode->i_lock);
318 if (needfree)
319 kfree(dserr);
320 301
321 return 0; 302 return 0;
322} 303}
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 4e8cc942336c..9a547aa3ec8e 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -484,7 +484,7 @@ void nfs_retry_commit(struct list_head *page_list,
484 struct nfs_commit_info *cinfo, 484 struct nfs_commit_info *cinfo,
485 u32 ds_commit_idx); 485 u32 ds_commit_idx);
486void nfs_commitdata_release(struct nfs_commit_data *data); 486void nfs_commitdata_release(struct nfs_commit_data *data);
487void nfs_request_add_commit_list(struct nfs_page *req, struct list_head *dst, 487void nfs_request_add_commit_list(struct nfs_page *req,
488 struct nfs_commit_info *cinfo); 488 struct nfs_commit_info *cinfo);
489void nfs_request_add_commit_list_locked(struct nfs_page *req, 489void nfs_request_add_commit_list_locked(struct nfs_page *req,
490 struct list_head *dst, 490 struct list_head *dst,
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index ce43cd6d88c6..5754835a2886 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -830,11 +830,10 @@ EXPORT_SYMBOL_GPL(nfs_request_add_commit_list_locked);
830 * holding the nfs_page lock. 830 * holding the nfs_page lock.
831 */ 831 */
832void 832void
833nfs_request_add_commit_list(struct nfs_page *req, struct list_head *dst, 833nfs_request_add_commit_list(struct nfs_page *req, struct nfs_commit_info *cinfo)
834 struct nfs_commit_info *cinfo)
835{ 834{
836 spin_lock(cinfo->lock); 835 spin_lock(cinfo->lock);
837 nfs_request_add_commit_list_locked(req, dst, cinfo); 836 nfs_request_add_commit_list_locked(req, &cinfo->mds->list, cinfo);
838 spin_unlock(cinfo->lock); 837 spin_unlock(cinfo->lock);
839 nfs_mark_page_unstable(req->wb_page, cinfo); 838 nfs_mark_page_unstable(req->wb_page, cinfo);
840} 839}
@@ -892,7 +891,7 @@ nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg,
892{ 891{
893 if (pnfs_mark_request_commit(req, lseg, cinfo, ds_commit_idx)) 892 if (pnfs_mark_request_commit(req, lseg, cinfo, ds_commit_idx))
894 return; 893 return;
895 nfs_request_add_commit_list(req, &cinfo->mds->list, cinfo); 894 nfs_request_add_commit_list(req, cinfo);
896} 895}
897 896
898static void 897static void