aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/objlayout/objlayout.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/objlayout/objlayout.c')
-rw-r--r--fs/nfs/objlayout/objlayout.c232
1 files changed, 231 insertions, 1 deletions
diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c
index 5157ef6d0041..f7caecff6b4d 100644
--- a/fs/nfs/objlayout/objlayout.c
+++ b/fs/nfs/objlayout/objlayout.c
@@ -50,6 +50,10 @@ objlayout_alloc_layout_hdr(struct inode *inode, gfp_t gfp_flags)
50 struct objlayout *objlay; 50 struct objlayout *objlay;
51 51
52 objlay = kzalloc(sizeof(struct objlayout), gfp_flags); 52 objlay = kzalloc(sizeof(struct objlayout), gfp_flags);
53 if (objlay) {
54 spin_lock_init(&objlay->lock);
55 INIT_LIST_HEAD(&objlay->err_list);
56 }
53 dprintk("%s: Return %p\n", __func__, objlay); 57 dprintk("%s: Return %p\n", __func__, objlay);
54 return &objlay->pnfs_layout; 58 return &objlay->pnfs_layout;
55} 59}
@@ -64,6 +68,7 @@ objlayout_free_layout_hdr(struct pnfs_layout_hdr *lo)
64 68
65 dprintk("%s: objlay %p\n", __func__, objlay); 69 dprintk("%s: objlay %p\n", __func__, objlay);
66 70
71 WARN_ON(!list_empty(&objlay->err_list));
67 kfree(objlay); 72 kfree(objlay);
68} 73}
69 74
@@ -183,6 +188,7 @@ objlayout_alloc_io_state(struct pnfs_layout_hdr *pnfs_layout_type,
183 pgbase &= ~PAGE_MASK; 188 pgbase &= ~PAGE_MASK;
184 } 189 }
185 190
191 INIT_LIST_HEAD(&state->err_list);
186 state->lseg = lseg; 192 state->lseg = lseg;
187 state->rpcdata = rpcdata; 193 state->rpcdata = rpcdata;
188 state->pages = pages; 194 state->pages = pages;
@@ -213,7 +219,52 @@ objlayout_iodone(struct objlayout_io_state *state)
213{ 219{
214 dprintk("%s: state %p status\n", __func__, state); 220 dprintk("%s: state %p status\n", __func__, state);
215 221
216 objlayout_free_io_state(state); 222 if (likely(state->status >= 0)) {
223 objlayout_free_io_state(state);
224 } else {
225 struct objlayout *objlay = OBJLAYOUT(state->lseg->pls_layout);
226
227 spin_lock(&objlay->lock);
228 list_add(&objlay->err_list, &state->err_list);
229 spin_unlock(&objlay->lock);
230 }
231}
232
233/*
234 * objlayout_io_set_result - Set an osd_error code on a specific osd comp.
235 *
236 * The @index component IO failed (error returned from target). Register
237 * the error for later reporting at layout-return.
238 */
239void
240objlayout_io_set_result(struct objlayout_io_state *state, unsigned index,
241 struct pnfs_osd_objid *pooid, int osd_error,
242 u64 offset, u64 length, bool is_write)
243{
244 struct pnfs_osd_ioerr *ioerr = &state->ioerrs[index];
245
246 BUG_ON(index >= state->num_comps);
247 if (osd_error) {
248 ioerr->oer_component = *pooid;
249 ioerr->oer_comp_offset = offset;
250 ioerr->oer_comp_length = length;
251 ioerr->oer_iswrite = is_write;
252 ioerr->oer_errno = osd_error;
253
254 dprintk("%s: err[%d]: errno=%d is_write=%d dev(%llx:%llx) "
255 "par=0x%llx obj=0x%llx offset=0x%llx length=0x%llx\n",
256 __func__, index, ioerr->oer_errno,
257 ioerr->oer_iswrite,
258 _DEVID_LO(&ioerr->oer_component.oid_device_id),
259 _DEVID_HI(&ioerr->oer_component.oid_device_id),
260 ioerr->oer_component.oid_partition_id,
261 ioerr->oer_component.oid_object_id,
262 ioerr->oer_comp_offset,
263 ioerr->oer_comp_length);
264 } else {
265 /* User need not call if no error is reported */
266 ioerr->oer_errno = 0;
267 }
217} 268}
218 269
219/* Function scheduled on rpc workqueue to call ->nfs_readlist_complete(). 270/* Function scheduled on rpc workqueue to call ->nfs_readlist_complete().
@@ -382,6 +433,185 @@ objlayout_write_pagelist(struct nfs_write_data *wdata,
382 return PNFS_ATTEMPTED; 433 return PNFS_ATTEMPTED;
383} 434}
384 435
436static int
437err_prio(u32 oer_errno)
438{
439 switch (oer_errno) {
440 case 0:
441 return 0;
442
443 case PNFS_OSD_ERR_RESOURCE:
444 return OSD_ERR_PRI_RESOURCE;
445 case PNFS_OSD_ERR_BAD_CRED:
446 return OSD_ERR_PRI_BAD_CRED;
447 case PNFS_OSD_ERR_NO_ACCESS:
448 return OSD_ERR_PRI_NO_ACCESS;
449 case PNFS_OSD_ERR_UNREACHABLE:
450 return OSD_ERR_PRI_UNREACHABLE;
451 case PNFS_OSD_ERR_NOT_FOUND:
452 return OSD_ERR_PRI_NOT_FOUND;
453 case PNFS_OSD_ERR_NO_SPACE:
454 return OSD_ERR_PRI_NO_SPACE;
455 default:
456 WARN_ON(1);
457 /* fallthrough */
458 case PNFS_OSD_ERR_EIO:
459 return OSD_ERR_PRI_EIO;
460 }
461}
462
463static void
464merge_ioerr(struct pnfs_osd_ioerr *dest_err,
465 const struct pnfs_osd_ioerr *src_err)
466{
467 u64 dest_end, src_end;
468
469 if (!dest_err->oer_errno) {
470 *dest_err = *src_err;
471 /* accumulated device must be blank */
472 memset(&dest_err->oer_component.oid_device_id, 0,
473 sizeof(dest_err->oer_component.oid_device_id));
474
475 return;
476 }
477
478 if (dest_err->oer_component.oid_partition_id !=
479 src_err->oer_component.oid_partition_id)
480 dest_err->oer_component.oid_partition_id = 0;
481
482 if (dest_err->oer_component.oid_object_id !=
483 src_err->oer_component.oid_object_id)
484 dest_err->oer_component.oid_object_id = 0;
485
486 if (dest_err->oer_comp_offset > src_err->oer_comp_offset)
487 dest_err->oer_comp_offset = src_err->oer_comp_offset;
488
489 dest_end = end_offset(dest_err->oer_comp_offset,
490 dest_err->oer_comp_length);
491 src_end = end_offset(src_err->oer_comp_offset,
492 src_err->oer_comp_length);
493 if (dest_end < src_end)
494 dest_end = src_end;
495
496 dest_err->oer_comp_length = dest_end - dest_err->oer_comp_offset;
497
498 if ((src_err->oer_iswrite == dest_err->oer_iswrite) &&
499 (err_prio(src_err->oer_errno) > err_prio(dest_err->oer_errno))) {
500 dest_err->oer_errno = src_err->oer_errno;
501 } else if (src_err->oer_iswrite) {
502 dest_err->oer_iswrite = true;
503 dest_err->oer_errno = src_err->oer_errno;
504 }
505}
506
507static void
508encode_accumulated_error(struct objlayout *objlay, __be32 *p)
509{
510 struct objlayout_io_state *state, *tmp;
511 struct pnfs_osd_ioerr accumulated_err = {.oer_errno = 0};
512
513 list_for_each_entry_safe(state, tmp, &objlay->err_list, err_list) {
514 unsigned i;
515
516 for (i = 0; i < state->num_comps; i++) {
517 struct pnfs_osd_ioerr *ioerr = &state->ioerrs[i];
518
519 if (!ioerr->oer_errno)
520 continue;
521
522 printk(KERN_ERR "%s: err[%d]: errno=%d is_write=%d "
523 "dev(%llx:%llx) par=0x%llx obj=0x%llx "
524 "offset=0x%llx length=0x%llx\n",
525 __func__, i, ioerr->oer_errno,
526 ioerr->oer_iswrite,
527 _DEVID_LO(&ioerr->oer_component.oid_device_id),
528 _DEVID_HI(&ioerr->oer_component.oid_device_id),
529 ioerr->oer_component.oid_partition_id,
530 ioerr->oer_component.oid_object_id,
531 ioerr->oer_comp_offset,
532 ioerr->oer_comp_length);
533
534 merge_ioerr(&accumulated_err, ioerr);
535 }
536 list_del(&state->err_list);
537 objlayout_free_io_state(state);
538 }
539
540 pnfs_osd_xdr_encode_ioerr(p, &accumulated_err);
541}
542
543void
544objlayout_encode_layoutreturn(struct pnfs_layout_hdr *pnfslay,
545 struct xdr_stream *xdr,
546 const struct nfs4_layoutreturn_args *args)
547{
548 struct objlayout *objlay = OBJLAYOUT(pnfslay);
549 struct objlayout_io_state *state, *tmp;
550 __be32 *start;
551
552 dprintk("%s: Begin\n", __func__);
553 start = xdr_reserve_space(xdr, 4);
554 BUG_ON(!start);
555
556 spin_lock(&objlay->lock);
557
558 list_for_each_entry_safe(state, tmp, &objlay->err_list, err_list) {
559 __be32 *last_xdr = NULL, *p;
560 unsigned i;
561 int res = 0;
562
563 for (i = 0; i < state->num_comps; i++) {
564 struct pnfs_osd_ioerr *ioerr = &state->ioerrs[i];
565
566 if (!ioerr->oer_errno)
567 continue;
568
569 dprintk("%s: err[%d]: errno=%d is_write=%d "
570 "dev(%llx:%llx) par=0x%llx obj=0x%llx "
571 "offset=0x%llx length=0x%llx\n",
572 __func__, i, ioerr->oer_errno,
573 ioerr->oer_iswrite,
574 _DEVID_LO(&ioerr->oer_component.oid_device_id),
575 _DEVID_HI(&ioerr->oer_component.oid_device_id),
576 ioerr->oer_component.oid_partition_id,
577 ioerr->oer_component.oid_object_id,
578 ioerr->oer_comp_offset,
579 ioerr->oer_comp_length);
580
581 p = pnfs_osd_xdr_ioerr_reserve_space(xdr);
582 if (unlikely(!p)) {
583 res = -E2BIG;
584 break; /* accumulated_error */
585 }
586
587 last_xdr = p;
588 pnfs_osd_xdr_encode_ioerr(p, &state->ioerrs[i]);
589 }
590
591 /* TODO: use xdr_write_pages */
592 if (unlikely(res)) {
593 /* no space for even one error descriptor */
594 BUG_ON(!last_xdr);
595
596 /* we've encountered a situation with lots and lots of
597 * errors and no space to encode them all. Use the last
598 * available slot to report the union of all the
599 * remaining errors.
600 */
601 encode_accumulated_error(objlay, last_xdr);
602 goto loop_done;
603 }
604 list_del(&state->err_list);
605 objlayout_free_io_state(state);
606 }
607loop_done:
608 spin_unlock(&objlay->lock);
609
610 *start = cpu_to_be32((xdr->p - start - 1) * 4);
611 dprintk("%s: Return\n", __func__);
612}
613
614
385/* 615/*
386 * Get Device Info API for io engines 616 * Get Device Info API for io engines
387 */ 617 */