diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-28 13:57:14 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-28 13:57:14 -0500 |
commit | 08d21b5f93eb92a781daea71b6fcb3a340909141 (patch) | |
tree | 365a88c9d977914a6dd42dcc1c27e33f80c0b76c | |
parent | 627f4b3ee3899bb70263ee77454a43c73136562f (diff) | |
parent | 19350e7627a6f3b0f662cbd2eb1128c9961a41fe (diff) |
Merge branch 'for-linus' of git://git.open-osd.org/linux-open-osd
Pull exofs and ore fixes from Boaz Harrosh:
"The main fix here, the first patch, is also destined for -stable. The
rest is small trivia and cosmetics. The ORE patches effect both exofs
and pnfs-objects very reproducible bugs"
[ ORE is "object raid engine", used by exofs and pnfs - Linus ]
* 'for-linus' of git://git.open-osd.org/linux-open-osd:
exofs: Print less in r4w
exofs: Allow corrupted directory entry to be empty file
exofs: Allow O_DIRECT open
ore: Don't crash on NULL bio in _clear_bio
ore: Fix wrong math in allocation of per device BIO
-rw-r--r-- | fs/exofs/inode.c | 31 | ||||
-rw-r--r-- | fs/exofs/ore.c | 45 | ||||
-rw-r--r-- | include/scsi/osd_ore.h | 1 |
3 files changed, 51 insertions, 26 deletions
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index a52a5d23c30b..ee4317faccb1 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c | |||
@@ -577,7 +577,7 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate) | |||
577 | 577 | ||
578 | if (offset >= i_size) { | 578 | if (offset >= i_size) { |
579 | *uptodate = true; | 579 | *uptodate = true; |
580 | EXOFS_DBGMSG("offset >= i_size index=0x%lx\n", index); | 580 | EXOFS_DBGMSG2("offset >= i_size index=0x%lx\n", index); |
581 | return ZERO_PAGE(0); | 581 | return ZERO_PAGE(0); |
582 | } | 582 | } |
583 | 583 | ||
@@ -596,10 +596,10 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate) | |||
596 | *uptodate = true; | 596 | *uptodate = true; |
597 | else | 597 | else |
598 | *uptodate = PageUptodate(page); | 598 | *uptodate = PageUptodate(page); |
599 | EXOFS_DBGMSG("index=0x%lx uptodate=%d\n", index, *uptodate); | 599 | EXOFS_DBGMSG2("index=0x%lx uptodate=%d\n", index, *uptodate); |
600 | return page; | 600 | return page; |
601 | } else { | 601 | } else { |
602 | EXOFS_DBGMSG("YES that_locked_page index=0x%lx\n", | 602 | EXOFS_DBGMSG2("YES that_locked_page index=0x%lx\n", |
603 | pcol->that_locked_page->index); | 603 | pcol->that_locked_page->index); |
604 | *uptodate = true; | 604 | *uptodate = true; |
605 | return pcol->that_locked_page; | 605 | return pcol->that_locked_page; |
@@ -611,11 +611,11 @@ static void __r4w_put_page(void *priv, struct page *page) | |||
611 | struct page_collect *pcol = priv; | 611 | struct page_collect *pcol = priv; |
612 | 612 | ||
613 | if ((pcol->that_locked_page != page) && (ZERO_PAGE(0) != page)) { | 613 | if ((pcol->that_locked_page != page) && (ZERO_PAGE(0) != page)) { |
614 | EXOFS_DBGMSG("index=0x%lx\n", page->index); | 614 | EXOFS_DBGMSG2("index=0x%lx\n", page->index); |
615 | page_cache_release(page); | 615 | page_cache_release(page); |
616 | return; | 616 | return; |
617 | } | 617 | } |
618 | EXOFS_DBGMSG("that_locked_page index=0x%lx\n", | 618 | EXOFS_DBGMSG2("that_locked_page index=0x%lx\n", |
619 | ZERO_PAGE(0) == page ? -1 : page->index); | 619 | ZERO_PAGE(0) == page ? -1 : page->index); |
620 | } | 620 | } |
621 | 621 | ||
@@ -961,6 +961,14 @@ static void exofs_invalidatepage(struct page *page, unsigned int offset, | |||
961 | WARN_ON(1); | 961 | WARN_ON(1); |
962 | } | 962 | } |
963 | 963 | ||
964 | |||
965 | /* TODO: Should be easy enough to do proprly */ | ||
966 | static ssize_t exofs_direct_IO(int rw, struct kiocb *iocb, | ||
967 | const struct iovec *iov, loff_t offset, unsigned long nr_segs) | ||
968 | { | ||
969 | return 0; | ||
970 | } | ||
971 | |||
964 | const struct address_space_operations exofs_aops = { | 972 | const struct address_space_operations exofs_aops = { |
965 | .readpage = exofs_readpage, | 973 | .readpage = exofs_readpage, |
966 | .readpages = exofs_readpages, | 974 | .readpages = exofs_readpages, |
@@ -974,7 +982,7 @@ const struct address_space_operations exofs_aops = { | |||
974 | 982 | ||
975 | /* Not implemented Yet */ | 983 | /* Not implemented Yet */ |
976 | .bmap = NULL, /* TODO: use osd's OSD_ACT_READ_MAP */ | 984 | .bmap = NULL, /* TODO: use osd's OSD_ACT_READ_MAP */ |
977 | .direct_IO = NULL, /* TODO: Should be trivial to do */ | 985 | .direct_IO = exofs_direct_IO, |
978 | 986 | ||
979 | /* With these NULL has special meaning or default is not exported */ | 987 | /* With these NULL has special meaning or default is not exported */ |
980 | .get_xip_mem = NULL, | 988 | .get_xip_mem = NULL, |
@@ -1010,7 +1018,7 @@ static int _do_truncate(struct inode *inode, loff_t newsize) | |||
1010 | if (likely(!ret)) | 1018 | if (likely(!ret)) |
1011 | truncate_setsize(inode, newsize); | 1019 | truncate_setsize(inode, newsize); |
1012 | 1020 | ||
1013 | EXOFS_DBGMSG("(0x%lx) size=0x%llx ret=>%d\n", | 1021 | EXOFS_DBGMSG2("(0x%lx) size=0x%llx ret=>%d\n", |
1014 | inode->i_ino, newsize, ret); | 1022 | inode->i_ino, newsize, ret); |
1015 | return ret; | 1023 | return ret; |
1016 | } | 1024 | } |
@@ -1094,14 +1102,13 @@ static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi, | |||
1094 | /* If object is lost on target we might as well enable it's | 1102 | /* If object is lost on target we might as well enable it's |
1095 | * delete. | 1103 | * delete. |
1096 | */ | 1104 | */ |
1097 | if ((ret == -ENOENT) || (ret == -EINVAL)) | 1105 | ret = 0; |
1098 | ret = 0; | ||
1099 | goto out; | 1106 | goto out; |
1100 | } | 1107 | } |
1101 | 1108 | ||
1102 | ret = extract_attr_from_ios(ios, &attrs[0]); | 1109 | ret = extract_attr_from_ios(ios, &attrs[0]); |
1103 | if (ret) { | 1110 | if (ret) { |
1104 | EXOFS_ERR("%s: extract_attr of inode_data failed\n", __func__); | 1111 | EXOFS_ERR("%s: extract_attr 0 of inode failed\n", __func__); |
1105 | goto out; | 1112 | goto out; |
1106 | } | 1113 | } |
1107 | WARN_ON(attrs[0].len != EXOFS_INO_ATTR_SIZE); | 1114 | WARN_ON(attrs[0].len != EXOFS_INO_ATTR_SIZE); |
@@ -1109,7 +1116,7 @@ static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi, | |||
1109 | 1116 | ||
1110 | ret = extract_attr_from_ios(ios, &attrs[1]); | 1117 | ret = extract_attr_from_ios(ios, &attrs[1]); |
1111 | if (ret) { | 1118 | if (ret) { |
1112 | EXOFS_ERR("%s: extract_attr of inode_data failed\n", __func__); | 1119 | EXOFS_ERR("%s: extract_attr 1 of inode failed\n", __func__); |
1113 | goto out; | 1120 | goto out; |
1114 | } | 1121 | } |
1115 | if (attrs[1].len) { | 1122 | if (attrs[1].len) { |
@@ -1124,7 +1131,7 @@ static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi, | |||
1124 | 1131 | ||
1125 | ret = extract_attr_from_ios(ios, &attrs[2]); | 1132 | ret = extract_attr_from_ios(ios, &attrs[2]); |
1126 | if (ret) { | 1133 | if (ret) { |
1127 | EXOFS_ERR("%s: extract_attr of inode_data failed\n", __func__); | 1134 | EXOFS_ERR("%s: extract_attr 2 of inode failed\n", __func__); |
1128 | goto out; | 1135 | goto out; |
1129 | } | 1136 | } |
1130 | if (attrs[2].len) { | 1137 | if (attrs[2].len) { |
diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c index b74422888604..dae884694bd9 100644 --- a/fs/exofs/ore.c +++ b/fs/exofs/ore.c | |||
@@ -103,7 +103,7 @@ int ore_verify_layout(unsigned total_comps, struct ore_layout *layout) | |||
103 | 103 | ||
104 | layout->max_io_length = | 104 | layout->max_io_length = |
105 | (BIO_MAX_PAGES_KMALLOC * PAGE_SIZE - layout->stripe_unit) * | 105 | (BIO_MAX_PAGES_KMALLOC * PAGE_SIZE - layout->stripe_unit) * |
106 | layout->group_width; | 106 | (layout->group_width - layout->parity); |
107 | if (layout->parity) { | 107 | if (layout->parity) { |
108 | unsigned stripe_length = | 108 | unsigned stripe_length = |
109 | (layout->group_width - layout->parity) * | 109 | (layout->group_width - layout->parity) * |
@@ -286,7 +286,8 @@ int ore_get_rw_state(struct ore_layout *layout, struct ore_components *oc, | |||
286 | if (length) { | 286 | if (length) { |
287 | ore_calc_stripe_info(layout, offset, length, &ios->si); | 287 | ore_calc_stripe_info(layout, offset, length, &ios->si); |
288 | ios->length = ios->si.length; | 288 | ios->length = ios->si.length; |
289 | ios->nr_pages = (ios->length + PAGE_SIZE - 1) / PAGE_SIZE; | 289 | ios->nr_pages = ((ios->offset & (PAGE_SIZE - 1)) + |
290 | ios->length + PAGE_SIZE - 1) / PAGE_SIZE; | ||
290 | if (layout->parity) | 291 | if (layout->parity) |
291 | _ore_post_alloc_raid_stuff(ios); | 292 | _ore_post_alloc_raid_stuff(ios); |
292 | } | 293 | } |
@@ -430,8 +431,12 @@ int ore_check_io(struct ore_io_state *ios, ore_on_dev_error on_dev_error) | |||
430 | if (likely(!ret)) | 431 | if (likely(!ret)) |
431 | continue; | 432 | continue; |
432 | 433 | ||
433 | if (OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) { | 434 | if ((OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) && |
434 | /* start read offset passed endof file */ | 435 | per_dev->bio) { |
436 | /* start read offset passed endof file. | ||
437 | * Note: if we do not have bio it means read-attributes | ||
438 | * In this case we should return error to caller. | ||
439 | */ | ||
435 | _clear_bio(per_dev->bio); | 440 | _clear_bio(per_dev->bio); |
436 | ORE_DBGMSG("start read offset passed end of file " | 441 | ORE_DBGMSG("start read offset passed end of file " |
437 | "offset=0x%llx, length=0x%llx\n", | 442 | "offset=0x%llx, length=0x%llx\n", |
@@ -536,6 +541,7 @@ void ore_calc_stripe_info(struct ore_layout *layout, u64 file_offset, | |||
536 | u64 H = LmodS - G * T; | 541 | u64 H = LmodS - G * T; |
537 | 542 | ||
538 | u32 N = div_u64(H, U); | 543 | u32 N = div_u64(H, U); |
544 | u32 Nlast; | ||
539 | 545 | ||
540 | /* "H - (N * U)" is just "H % U" so it's bound to u32 */ | 546 | /* "H - (N * U)" is just "H % U" so it's bound to u32 */ |
541 | u32 C = (u32)(H - (N * U)) / stripe_unit + G * group_width; | 547 | u32 C = (u32)(H - (N * U)) / stripe_unit + G * group_width; |
@@ -568,6 +574,10 @@ void ore_calc_stripe_info(struct ore_layout *layout, u64 file_offset, | |||
568 | si->length = T - H; | 574 | si->length = T - H; |
569 | if (si->length > length) | 575 | if (si->length > length) |
570 | si->length = length; | 576 | si->length = length; |
577 | |||
578 | Nlast = div_u64(H + si->length + U - 1, U); | ||
579 | si->maxdevUnits = Nlast - N; | ||
580 | |||
571 | si->M = M; | 581 | si->M = M; |
572 | } | 582 | } |
573 | EXPORT_SYMBOL(ore_calc_stripe_info); | 583 | EXPORT_SYMBOL(ore_calc_stripe_info); |
@@ -583,13 +593,16 @@ int _ore_add_stripe_unit(struct ore_io_state *ios, unsigned *cur_pg, | |||
583 | int ret; | 593 | int ret; |
584 | 594 | ||
585 | if (per_dev->bio == NULL) { | 595 | if (per_dev->bio == NULL) { |
586 | unsigned pages_in_stripe = ios->layout->group_width * | 596 | unsigned bio_size; |
587 | (ios->layout->stripe_unit / PAGE_SIZE); | 597 | |
588 | unsigned nr_pages = ios->nr_pages * ios->layout->group_width / | 598 | if (!ios->reading) { |
589 | (ios->layout->group_width - | 599 | bio_size = ios->si.maxdevUnits; |
590 | ios->layout->parity); | 600 | } else { |
591 | unsigned bio_size = (nr_pages + pages_in_stripe) / | 601 | bio_size = (ios->si.maxdevUnits + 1) * |
592 | ios->layout->group_width; | 602 | (ios->layout->group_width - ios->layout->parity) / |
603 | ios->layout->group_width; | ||
604 | } | ||
605 | bio_size *= (ios->layout->stripe_unit / PAGE_SIZE); | ||
593 | 606 | ||
594 | per_dev->bio = bio_kmalloc(GFP_KERNEL, bio_size); | 607 | per_dev->bio = bio_kmalloc(GFP_KERNEL, bio_size); |
595 | if (unlikely(!per_dev->bio)) { | 608 | if (unlikely(!per_dev->bio)) { |
@@ -609,8 +622,12 @@ int _ore_add_stripe_unit(struct ore_io_state *ios, unsigned *cur_pg, | |||
609 | added_len = bio_add_pc_page(q, per_dev->bio, pages[pg], | 622 | added_len = bio_add_pc_page(q, per_dev->bio, pages[pg], |
610 | pglen, pgbase); | 623 | pglen, pgbase); |
611 | if (unlikely(pglen != added_len)) { | 624 | if (unlikely(pglen != added_len)) { |
612 | ORE_DBGMSG("Failed bio_add_pc_page bi_vcnt=%u\n", | 625 | /* If bi_vcnt == bi_max then this is a SW BUG */ |
613 | per_dev->bio->bi_vcnt); | 626 | ORE_DBGMSG("Failed bio_add_pc_page bi_vcnt=0x%x " |
627 | "bi_max=0x%x BIO_MAX=0x%x cur_len=0x%x\n", | ||
628 | per_dev->bio->bi_vcnt, | ||
629 | per_dev->bio->bi_max_vecs, | ||
630 | BIO_MAX_PAGES_KMALLOC, cur_len); | ||
614 | ret = -ENOMEM; | 631 | ret = -ENOMEM; |
615 | goto out; | 632 | goto out; |
616 | } | 633 | } |
@@ -1098,7 +1115,7 @@ int ore_truncate(struct ore_layout *layout, struct ore_components *oc, | |||
1098 | size_attr->attr = g_attr_logical_length; | 1115 | size_attr->attr = g_attr_logical_length; |
1099 | size_attr->attr.val_ptr = &size_attr->newsize; | 1116 | size_attr->attr.val_ptr = &size_attr->newsize; |
1100 | 1117 | ||
1101 | ORE_DBGMSG("trunc(0x%llx) obj_offset=0x%llx dev=%d\n", | 1118 | ORE_DBGMSG2("trunc(0x%llx) obj_offset=0x%llx dev=%d\n", |
1102 | _LLU(oc->comps->obj.id), _LLU(obj_size), i); | 1119 | _LLU(oc->comps->obj.id), _LLU(obj_size), i); |
1103 | ret = _truncate_mirrors(ios, i * ios->layout->mirrors_p1, | 1120 | ret = _truncate_mirrors(ios, i * ios->layout->mirrors_p1, |
1104 | &size_attr->attr); | 1121 | &size_attr->attr); |
diff --git a/include/scsi/osd_ore.h b/include/scsi/osd_ore.h index a5f9b960dfc8..6ca3265a4dca 100644 --- a/include/scsi/osd_ore.h +++ b/include/scsi/osd_ore.h | |||
@@ -102,6 +102,7 @@ struct ore_striping_info { | |||
102 | unsigned unit_off; | 102 | unsigned unit_off; |
103 | unsigned cur_pg; | 103 | unsigned cur_pg; |
104 | unsigned cur_comp; | 104 | unsigned cur_comp; |
105 | unsigned maxdevUnits; | ||
105 | }; | 106 | }; |
106 | 107 | ||
107 | struct ore_io_state; | 108 | struct ore_io_state; |