diff options
-rw-r--r-- | fs/nfs/filelayout/filelayout.c | 2 | ||||
-rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayout.c | 6 | ||||
-rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayoutdev.c | 99 | ||||
-rw-r--r-- | fs/nfs/internal.h | 2 | ||||
-rw-r--r-- | fs/nfs/write.c | 7 |
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); |
1955 | out: | 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 | ||
221 | static bool ds_error_can_merge(struct nfs4_ff_layout_ds_err *err, u64 offset, | 221 | static int |
222 | u64 length, int status, enum nfs_opnum4 opnum, | 222 | ff_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)); | |
233 | static 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 | ||
244 | static bool | 245 | static void |
245 | ff_layout_add_ds_error_locked(struct nfs4_flexfile_layout *flo, | 246 | ff_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; | |
260 | static bool | ||
261 | ff_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 | ||
280 | int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo, | 272 | int 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); |
486 | void nfs_commitdata_release(struct nfs_commit_data *data); | 486 | void nfs_commitdata_release(struct nfs_commit_data *data); |
487 | void nfs_request_add_commit_list(struct nfs_page *req, struct list_head *dst, | 487 | void nfs_request_add_commit_list(struct nfs_page *req, |
488 | struct nfs_commit_info *cinfo); | 488 | struct nfs_commit_info *cinfo); |
489 | void nfs_request_add_commit_list_locked(struct nfs_page *req, | 489 | void 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 | */ |
832 | void | 832 | void |
833 | nfs_request_add_commit_list(struct nfs_page *req, struct list_head *dst, | 833 | nfs_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 | ||
898 | static void | 897 | static void |