ore: RAID5 Support
Subsystems (4)
cover ore: RAID5 Support
I'm proud to present RAID5 support to ORE. Which enables raid5 for both exofs and pnfs-objects-layout driver.
The ORE with raid0/1/5 and soon 6 support has become a compact and abstract library, that with not a lot of effort, can support not only OSD but any type of devices. For example BTRFS, does it have a RAID5 support yet? if not it could use ORE. The ORE gets a bunch of pages at the top and produces bios for each device at the bottom. The libosd API can be easily abstracted and be used for block devices, just the same. The RAID layout supported by ORE is very rich, multi layered striping/mirroring/raid. even reacher then stacked MD. You can read about this layout here:
http://git.open-osd.org/gitweb.cgi?p=ietf-rfc5664.git;a=blob_plain;f=draft-ietf-nfsv4-rfc5664bis.html;hb=boaz2
Start at: 5.3. "Data Mapping Schemes" up to:
5.4.5. "RAID Usage and Implementation Notes"
There where some problems with the previous patchset here are the differences I squashed it to a new patchset at osd/linux-next.
[PATCH 1/1] SQUASHME: into: ore: Only IO one group at a time (API change)
And without farther ado Here is the RAID5 support. This is highly complicated stuff, for humble me at least, and I would appreciate any review and/or comments you guys can give it. Thanks in advance. (Pretty Please? :-))
[PATCH 1/6] ore: Make ore_calc_stripe_info EXPORT_SYMBOL [PATCH 2/6] ore: RAID5 read
[PATCH 3/6] ore: RAID5 Write
[PATCH 4/6] exofs: Support for RAID5 read-4-write interface. [PATCH 5/6] pnfs-obj: Support for RAID5 read-4-write interface. [PATCH 6/6] ore: Enable RAID5 mounts
A tree with above plus all prerequisites is at:
$ git clone git://open-osd.org/linux-open-osd linux-next [http://git.open-osd.org/gitweb.cgi?p=linux-open-osd.git;a=shortlog;h=refs/heads/merge_and_compile]
The code passes my tests, the highlight of which is git-clone linux and compare to and identical clone on ext4. But there must be month of farther testing done on this to get it better. For example. Aligned on stripe IO write back should be improved on all the way down to the VFS layer.
Thanks
Boaz
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/1 SQUASHME: into: ore: Only IO one group at a time (API change)
To re submit a page that went through write_cache_pages() (Recived on writepage_t) We need to take it out of write_back and into set_page_dirty(). Then it will be resubmitted again just fine. Checked!
And one more fix for the ios->numdevs.
---
git diff --stat -p -M origin/linux-next 201e3d7b
fs/exofs/inode.c | 15 ++++++++++----- fs/exofs/ore.c | 6 +----- 2 files changed, 11 insertions(+), 10 deletions(-)
fs/exofs/inode.c +10 -5
@@ -295,7 +295,7 @@ static int _maybe_not_all_in_one_io(struct ore_io_state *ios,for (i =0 ; i < pages_less; ++i) pcol->pages[i] = *src_page++; - EXOFS_DBGMSG("Length was adjusted nr_pages=0x%x pages_less=%d " + EXOFS_DBGMSG("Length was adjusted nr_pages=0x%x pages_less=0x%x " "expected_pages=0x%x next_offset=0x%llx " "next_len=0x%lx\n", pcol_src->nr_pages, pages_less, pcol->expected_pages,
@@ -758,14 +758,19 @@ static int exofs_writepages(struct address_space *mapping,if (wbc->sync_mode ==WB_SYNC_ALL ) {return write_exec (&pcol);/* pump the last reminder */ - }else {/* not SYNC let the reminder join the next writeout */ + }else if (pcol.nr_pages) { +/* not SYNC let the reminder join the next writeout */ unsigned i; -for (i =0 ; i < pcol.nr_pages; i++) -unlock_page (pcol.pages[i]); +for (i =0 ; i < pcol.nr_pages; i++) { +struct page *page = pcol.pages[i]; -return 0 ; +end_page_writeback (page); +set_page_dirty (page); +unlock_page (page); + } } +return 0 ; }static int exofs_writepage (struct page *page,struct writeback_control *wbc)
fs/exofs/ore.c +1 -5
@@ -506,7 +506,6 @@ static int _prepare_for_striping(struct ore_io_state *ios)unsigned devs_in_group = ios->layout->group_width * mirrors_p1;unsigned dev = si->dev;unsigned first_dev = dev - (dev % devs_in_group); -unsigned max_comp = ios->numdevs ? ios->numdevs - mirrors_p1 :0 ;unsigned cur_pg = ios->pages_consumed;u64 length = ios->length;int ret =0 ;
@@ -538,9 +537,6 @@ static int _prepare_for_striping(struct ore_io_state *ios) per_dev->offset = si->obj_offset - si->unit_off; cur_len = stripe_unit; } - -if (max_comp < comp) - max_comp = comp; }else { cur_len = stripe_unit; }
@@ -558,7 +554,7 @@ static int _prepare_for_striping(struct ore_io_state *ios) length -= cur_len; } out: - ios->numdevs = max_comp + mirrors_p1; + ios->numdevs = devs_in_group; ios->pages_consumed = cur_pg;if (unlikely (ret)) {if (length == ios->length)
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 2/6 ore: RAID5 read
In reply to a message not in the archiveThis patch introduces the first stage of RAID5 support mainly the skip-over-raid-units when reading. For writes it inserts BLANK units, into where XOR blocks should be calculated and written to.
It introduces the new "general raid maths", and the main additional parameters and components needed for raid5.
Since at this stage it could corrupt future version that actually do support raid5. The enablement of raid5 mounting and setting of parity-count > 0 is disabled. So the raid5 code will never be used. Mounting of raid5 is only enabled later once the basic XOR write is also in. But if the patch "enable RAID5" is applied this code has been tested to be able to properly read raid5 volumes and is according to standard.
Also it has been tested that the new maths still properly supports RAID0 and grouping code just as before. (BTW: I have found more bugs in the pnfs-obj RAID math
fixed here)
The ore.c file is getting too big, so new ore_raid.[hc] files are added that will include the special raid stuff that are not used in striping and mirrors. In future write support these will get bigger.
When adding the ore_raid.c to Kbuild file I was forced to rename ore.ko to libore.ko. Is it possible to keep source file, say ore.c and module file ore.ko the same even if there are multiple files inside ore.ko?
--- fs/exofs/Kbuild | 3 +- fs/exofs/ore.c | 326 ++++++++++++++++++++++++++++++++++++----------- fs/exofs/ore_raid.c | 140 +++++++++++++++++++++ fs/exofs/ore_raid.h | 64 ++++++++++ include/scsi/osd_ore.h | 21 +++- 5 files changed, 473 insertions(+), 81 deletions(-) create mode 100644 fs/exofs/ore_raid.c create mode 100644 fs/exofs/ore_raid.h
fs/exofs/Kbuild +2 -1
@@ -13,7 +13,8 @@ # # ore module library -obj-$(CONFIG_ORE) += ore.o +libore-y := ore.o ore_raid.o +obj-$(CONFIG_ORE) += libore.o exofs-y := inode.o file.o symlink.o namei.o dir.o super.o obj-$(CONFIG_EXOFS_FS) += exofs.o
fs/exofs/ore.c +249 -77
487 lines not on this page · raw message
fs/exofs/ore_raid.c new file +140 -0
140 lines not on this page · raw message
fs/exofs/ore_raid.h new file +64 -0
64 lines not on this page · raw message
include/scsi/osd_ore.h +18 -3
@@ -40,6 +40,7 @@ struct ore_layout {unsigned mirrors_p1;unsigned group_width; +unsigned parity;u64 group_depth;unsigned group_count;
@@ -89,11 +90,16 @@ static inline void ore_comp_set_dev( }struct ore_striping_info { +u64 offset;u64 obj_offset; -u64 group_length; +u64 length; +u64 first_stripe_start;/* only used in raid writes */ u64 M;/* for truncate */ +unsigned bytes_in_stripe;unsigned dev; +unsigned par_dev;unsigned unit_off; +unsigned cur_comp; };struct ore_io_state ;
@@ -127,6 +133,13 @@ struct ore_io_state {bool reading; +/* House keeping of Parity pages */ +bool extra_part_alloc; +struct page **parity_pages; +unsigned max_par_pages; +unsigned cur_par_page; +unsigned sgs_per_dev; +/* Variable array of size numdevs */ unsigned numdevs;struct ore_per_dev_state {
@@ -134,7 +147,10 @@ struct ore_io_state {struct bio *bio;loff_t offset;unsigned length; +unsigned last_sgs_total;unsigned dev; +struct osd_sg_entry *sglist; +unsigned cur_sg; } per_dev[]; };
@@ -147,8 +163,7 @@ static inline unsigned ore_io_state_size(unsigned numdevs)/* ore.c */ int ore_verify_layout (unsigned total_comps,struct ore_layout *layout);void ore_calc_stripe_info (struct ore_layout *layout,u64 file_offset, -struct ore_striping_info *si); - +u64 length,struct ore_striping_info *si);int ore_get_rw_state (struct ore_layout *layout,struct ore_components *comps,bool is_reading,u64 offset,u64 length,struct ore_io_state **ios);
Signature · 6 lines
1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 3/6 ore: RAID5 Write
In reply to a message not in the archiveThis is finally the RAID5 Write support.
The bigger part of this patch is not the XOR engine itself, But the read4write logic, which is a complete mini prepare_for_striping reading engine that can read scattered pages of a stripe into cache so it can be used for XOR calculation. That is, if the write was not stripe aligned.
The main algorithm behind the XOR engine is the 2 dimensional array:
struct __stripe_pages_2d.
A drawing might save 1000 words
---
__stripe_pages_2d
|
n = pages_in_stripe_unit;
w = group_width - parity;
| pages array presented to the XOR lib
| |
V |
__1_page_stripe[0].pages --> [c0][c1]..[cw][c_par] <---|
| |
__1_page_stripe[1].pages --> [c0][c1]..[cw][c_par] <---
|
... | ...
|
__1_page_stripe[n].pages --> [c0][c1]..[cw][c_par]
^
|
data added columns first then row---
The pages are put on this array columns first. .i.e:
p0-of-c0, p1-of-c0, ... pn-of-c0, p0-of-c1, ...
So we are doing a corner turn of the pages.
Note that pages will zigzag down and left. but are put sequentially in growing order. So when the time comes to XOR the stripe, only the beginning and end of the array need be checked. We scan the array and any NULL spot will be field by pages-to-be-read.
The FS that wants to support RAID5 needs to supply an operations-vector that searches a given page in cache, and specifies if the page is uptodate or need reading. All these pages to be read are put on a slave ore_io_state and synchronously read. All the pages of a stripe are read in one IO, using the scatter gather mechanism.
In write we constrain our IO to only be incomplete on a single stripe. Meaning either the complete IO is within a single stripe so we might have pages to read from both beginning or end of the strip. Or we have some reading to do at beginning but end at strip boundary. The left over pages are pushed to the next IO by the API already established by previous work, where an IO offset/length combination presented to the ORE might get the length truncated and the user must re-submit the leftover pages. (Both exofs and NFS support this)
But any ORE user should make it's best effort to align it's IO before hand and avoid complications. A cached ore_layout->stripe_size member can be used for that calculation. (NOTE: that ORE demands that stripe_size may not be bigger then 32bit)
What else? Well read it and tell me.
--- fs/exofs/Kconfig | 9 +- fs/exofs/ore.c | 36 +++- fs/exofs/ore_raid.c | 534 +++++++++++++++++++++++++++++++++++++++++++++++- fs/exofs/ore_raid.h | 15 ++ include/scsi/osd_ore.h | 9 + 5 files changed, 587 insertions(+), 16 deletions(-)
fs/exofs/Kconfig +8 -1
@@ -1,10 +1,17 @@ +# Note ORE needs to "select ASYNC_XOR". So Not to force multiple selects +# for every ORE user we do it like this. Any user should add itself here +# at the "depends on EXOFS_FS || ..." with an ||. The dependencies are +# selected here, and we default to "ON". So in effect it is like been +# selected by any of the users. config ORE tristate + depends on EXOFS_FS || PNFS_OBJLAYOUT + select ASYNC_XOR + default m config EXOFS_FS tristate "exofs: OSD based file system support" depends on SCSI_OSD_ULD - select ORE help EXOFS is a file system that uses an OSD storage device, as its backing storage.
fs/exofs/ore.c +28 -8
@@ -95,6 +95,14 @@ int ore_verify_layout(unsigned total_comps, struct ore_layout *layout) layout->max_io_length = (BIO_MAX_PAGES_KMALLOC *PAGE_SIZE - layout->stripe_unit) * layout->group_width; +if (layout->parity) { +unsigned stripe_length = + (layout->group_width - layout->parity) * + layout->stripe_unit; + + layout->max_io_length /= stripe_length; + layout->max_io_length *= stripe_length; + }return 0 ; }EXPORT_SYMBOL (ore_verify_layout);
@@ -118,7 +126,7 @@ static struct osd_dev *_ios_od(struct ore_io_state *ios, unsigned index)return ore_comp_dev (ios->oc, index); } -static int _ore_get_io_state (struct ore_layout *layout, +int _ore_get_io_state (struct ore_layout *layout,struct ore_components *oc,unsigned numdevs,unsigned sgs_per_dev,unsigned num_par_pages,struct ore_io_state **pios)
@@ -334,7 +342,7 @@ static void _done_io(struct osd_request *or, void *p)kref_put (&ios->kref, _last_io); } -static int ore_io_execute (struct ore_io_state *ios) +int ore_io_execute (struct ore_io_state *ios) {DECLARE_COMPLETION_ONSTACK (wait);bool sync = (ios->done ==NULL );
@@ -597,6 +605,8 @@ int _ore_add_stripe_unit(struct ore_io_state *ios, unsigned *cur_pg, ret = -ENOMEM ; goto out; } +_add_stripe_page (ios->sp2d, &ios->si, pages[pg]); + pgbase =0 ; ++pg; }
@@ -636,6 +646,7 @@ static int _prepare_for_striping(struct ore_io_state *ios) dev_order =_dev_order (devs_in_group, mirrors_p1, si->par_dev, dev); si->cur_comp = dev_order; + si->cur_pg = si->unit_off /PAGE_SIZE ;while (length) {unsigned comp = dev - first_dev;
@@ -677,14 +688,14 @@ static int _prepare_for_striping(struct ore_io_state *ios) length -= cur_len; si->cur_comp = (si->cur_comp +1 ) % group_width; -if (unlikely ((dev == si->par_dev) || - (!length && ios->parity_pages))) { -if (!length) +if (unlikely ((dev == si->par_dev) || (!length && ios->sp2d))) { +if (!length && ios->sp2d) {/* If we are writing and this is the very last * stripe. then operate on parity dev. */ dev = si->par_dev; -if (ios->reading) + } +if (ios->sp2d)/* In writes cur_len just means if it's the * last one. See _ore_add_parity_unit. */
@@ -709,6 +720,7 @@ static int _prepare_for_striping(struct ore_io_state *ios) devs_in_group + first_dev;/* Next stripe, start fresh */ si->cur_comp =0 ; + si->cur_pg =0 ; } } out:
@@ -873,6 +885,14 @@ int ore_write(struct ore_io_state *ios)int i;int ret; +if (unlikely (ios->sp2d && !ios->r4w)) { +/* A library is attempting a RAID-write without providing +* a pages lock interface. +*/ +WARN_ON_ONCE (1 ); +return -ENOTSUPP ; + } + ret =_prepare_for_striping (ios);if (unlikely (ret))return ret;
@@ -888,7 +908,7 @@ int ore_write(struct ore_io_state *ios) }EXPORT_SYMBOL (ore_write); -static int _read_mirror (struct ore_io_state *ios,unsigned cur_comp) +int _ore_read_mirror (struct ore_io_state *ios,unsigned cur_comp) {struct osd_request *or;struct ore_per_dev_state *per_dev = &ios->per_dev[cur_comp];
@@ -952,7 +972,7 @@ int ore_read(struct ore_io_state *ios)return ret;for (i =0 ; i < ios->numdevs; i += ios->layout->mirrors_p1) { - ret =_read_mirror (ios, i); + ret =_ore_read_mirror (ios, i);if (unlikely (ret))return ret; }
fs/exofs/ore_raid.c +527 -7
599 lines not on this page · raw message
fs/exofs/ore_raid.h +15 -0
@@ -57,8 +57,23 @@ void _ore_add_sg_seg(struct ore_per_dev_state *per_dev, unsigned cur_len, bool not_last);int _ore_add_parity_unit (struct ore_io_state *ios,struct ore_striping_info *si,struct ore_per_dev_state *per_dev,unsigned cur_len); +void _ore_add_stripe_page (struct __stripe_pages_2d *sp2d, +struct ore_striping_info *si,struct page *page); +static inline void _add_stripe_page (struct __stripe_pages_2d *sp2d, +struct ore_striping_info *si,struct page *page) +{ +if (!sp2d)/* Inline the fast path */ +return ;/* Hay no raid stuff */ +_ore_add_stripe_page (sp2d, si, page); +}/* ios.c stuff needed by ios_raid.c */ +int _ore_get_io_state (struct ore_layout *layout, +struct ore_components *oc,unsigned numdevs, +unsigned sgs_per_dev,unsigned num_par_pages, +struct ore_io_state **pios);int _ore_add_stripe_unit (struct ore_io_state *ios,unsigned *cur_pg,unsigned pgbase,struct page **pages,struct ore_per_dev_state *per_dev,int cur_len); +int _ore_read_mirror (struct ore_io_state *ios,unsigned cur_comp); +int ore_io_execute (struct ore_io_state *ios);
include/scsi/osd_ore.h +9 -0
@@ -99,11 +99,17 @@ struct ore_striping_info {unsigned dev;unsigned par_dev;unsigned unit_off; +unsigned cur_pg;unsigned cur_comp; };struct ore_io_state ;typedef void (*ore_io_done_fn )(struct ore_io_state *ios,void *private); +struct _ore_r4w_op { +/* @Priv given here is passed ios->private */ +struct page * (*get_page)(void *priv,u64 page_index,bool *uptodate); +void (*put_page)(void *priv,struct page *page); +};struct ore_io_state {struct kref kref;
@@ -139,6 +145,9 @@ struct ore_io_state {unsigned max_par_pages;unsigned cur_par_page;unsigned sgs_per_dev; +struct __stripe_pages_2d *sp2d; +struct ore_io_state *ios_read_4_write; +const struct _ore_r4w_op *r4w;/* Variable array of size numdevs */ unsigned numdevs;
Signature · 6 lines
1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 5/6 pnfs-obj: Support for RAID5 read-4-write interface.
In reply to a message not in the archiveThe ore need suplied a r4w_get_page/r4w_put_page API from Filesystem so it can get cache pages to read-into when writing parial stripes.
--- fs/nfs/objlayout/objio_osd.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 38 insertions(+), 0 deletions(-)
fs/nfs/objlayout/objio_osd.c +38 -0
@@ -459,6 +459,43 @@ static void _write_done(struct ore_io_state *ios, void *private)objlayout_write_done (&objios->oir, status, objios->sync); } +static struct page *__r4w_get_page (void *priv,u64 offset,bool *uptodate) +{ +struct objio_state *objios = priv; +struct nfs_write_data *wdata = objios->oir.rpcdata; +pgoff_t index = offset /PAGE_SIZE ; +struct page *page =find_get_page (wdata->inode->i_mapping, index); + +if (!page) { + page =find_or_create_page (wdata->inode->i_mapping, + index,GFP_NOFS ); +if (unlikely (!page)) { +dprintk ("%s: grab_cache_page Failed index=0x%lx\n" , + __func__, index); +return NULL ; + } +unlock_page (page); + } +if (PageDirty (page) ||PageWriteback (page)) + *uptodate = true; +else + *uptodate =PageUptodate (page); +dprintk ("%s: index=0x%lx uptodate=%d\n" , __func__, index, *uptodate); +return page; +} + +static void __r4w_put_page (void *priv,struct page *page) +{ +dprintk ("%s: index=0x%lx\n" , __func__, page->index); +page_cache_release (page); +return ; +} + +static const struct _ore_r4w_op _r4w_op = { + .get_page = &__r4w_get_page, + .put_page = &__r4w_put_page, +}; +int objio_write_pagelist (struct nfs_write_data *wdata,int how) {struct objio_state *objios;
@@ -472,6 +509,7 @@ int objio_write_pagelist(struct nfs_write_data *wdata, int how)return ret; objios->sync =0 != (how &FLUSH_SYNC ); + objios->ios->r4w = &_r4w_op;if (!objios->sync) objios->ios->done = _write_done;
Signature · 6 lines
1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 6/6 ore: Enable RAID5 mounts
In reply to a message not in the archiveNow that we support raid5 Enable it at mount. Raid6 will come next raid4 is not demanded for so it will probably not be enabled. (Until some one wants it)
NOTE: That mkfs.exofs had support for raid5/6 since long time ago. (Making an empty raidX FS is just as easy as raid0 ;-} )
--- fs/exofs/ore.c | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-)
fs/exofs/ore.c +11 -3
@@ -49,9 +49,17 @@ int ore_verify_layout(unsigned total_comps, struct ore_layout *layout) {u64 stripe_length; -/* FIXME: Only raid0 is supported for now. */ -if (layout->raid_algorithm !=PNFS_OSD_RAID_0 ) { -ORE_ERR ("Only RAID_0 for now\n" ); +switch (layout->raid_algorithm) { +case PNFS_OSD_RAID_0 : + layout->parity =0 ; +break ; +case PNFS_OSD_RAID_5 : + layout->parity =1 ; +break ; +case PNFS_OSD_RAID_PQ : +case PNFS_OSD_RAID_4 : +default : +ORE_ERR ("Only RAID_0/5 for now\n" );return -EINVAL ; }if (0 != (layout->stripe_unit & ~PAGE_MASK )) {
Signature · 6 lines
1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 1/6 ore: Make ore_calc_stripe_info EXPORT_SYMBOL
In reply to Boaz Harroshore_calc_stripe_info is needed by exofs::export.c
for the layout calculations. Make it exportable
--- fs/exofs/ore.c | 8 +++----- include/scsi/osd_ore.h | 3 +++ 2 files changed, 6 insertions(+), 5 deletions(-)
fs/exofs/ore.c +3 -5
@@ -57,9 +57,6 @@ MODULE_LICENSE("GPL");* 3. Cache some havily used calculations that will be needed by users. */ -static void ore_calc_stripe_info (struct ore_layout *layout,u64 file_offset, -struct ore_striping_info *si); -enum {BIO_MAX_PAGES_KMALLOC = (PAGE_SIZE -sizeof (struct bio )) /sizeof (struct bio_vec ),};
@@ -409,8 +406,8 @@ EXPORT_SYMBOL(ore_check_io);* * O = L % stripe_unit + N * stripe_unit + M * group_depth * stripe_unit */ -static void ore_calc_stripe_info (struct ore_layout *layout,u64 file_offset, -struct ore_striping_info *si) +void ore_calc_stripe_info (struct ore_layout *layout,u64 file_offset, +struct ore_striping_info *si) {u32 stripe_unit = layout->stripe_unit;u32 group_width = layout->group_width;
@@ -443,6 +440,7 @@ static void ore_calc_stripe_info(struct ore_layout *layout, u64 file_offset, si->group_length =T -H ; si->M =M ; } +EXPORT_SYMBOL (ore_calc_stripe_info); static int _add_stripe_unit(struct ore_io_state *ios, unsigned *cur_pg, unsigned pgbase, struct ore_per_dev_state *per_dev,
include/scsi/osd_ore.h +3 -0
@@ -146,6 +146,9 @@ static inline unsigned ore_io_state_size(unsigned numdevs)/* ore.c */ int ore_verify_layout (unsigned total_comps,struct ore_layout *layout); +void ore_calc_stripe_info (struct ore_layout *layout,u64 file_offset, +struct ore_striping_info *si); +int ore_get_rw_state (struct ore_layout *layout,struct ore_components *comps,bool is_reading,u64 offset,u64 length,struct ore_io_state **ios);
Signature · 1 line
1.7.2.3
PATCH 4/6 exofs: Support for RAID5 read-4-write interface.
In reply to Boaz HarroshThe ore need suplied a r4w_get_page/r4w_put_page API from Filesystem so it can get cache pages to read-into when writing parial stripes.
Also I commented out and NULLed the .writepage (singular) vector. Because it gives terrible write pattern to raid and is apparently not needed. Even in OOM conditions the system copes (even better) with out it.
TODO: How to specify to write_cache_pages() to start
or include a certain page?
--- fs/exofs/inode.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 59 insertions(+), 2 deletions(-)
fs/exofs/inode.c +59 -2
@@ -63,6 +63,7 @@ struct page_collect {bool read_4_write;/* This means two things: that the read is sync * And the pages should not be unlocked. */ +struct page *that_locked_page; }; static void _pcol_init(struct page_collect *pcol, unsigned expected_pages,
@@ -81,6 +82,7 @@ static void _pcol_init(struct page_collect *pcol, unsigned expected_pages, pcol->length =0 ; pcol->pg_first =-1 ; pcol->read_4_write = false; + pcol->that_locked_page =NULL ; }static void _pcol_reset (struct page_collect *pcol)
@@ -93,6 +95,7 @@ static void _pcol_reset(struct page_collect *pcol) pcol->length =0 ; pcol->pg_first =-1 ; pcol->ios =NULL ; + pcol->that_locked_page =NULL ;/* this is probably the end of the loop but in writes * it might not end here. don't be left with nothing
@@ -391,6 +394,8 @@ static int readpage_strip(void *data, struct page *page)EXOFS_ERR ("PageUptodate(0x%lx, 0x%lx)\n" , pcol->inode->i_ino, page->index); + pcol->that_locked_page = page; +if (page->index < end_index) len =PAGE_CACHE_SIZE ;else if (page->index == end_index)
@@ -560,6 +565,56 @@ static void writepages_done(struct ore_io_state *ios, void *p)EXOFS_DBGMSG2 ("writepages_done END\n" ); } +static struct page *__r4w_get_page (void *priv,u64 offset,bool *uptodate) +{ +struct page_collect *pcol = priv; +pgoff_t index = offset /PAGE_SIZE ; + +if (!pcol->that_locked_page || + (pcol->that_locked_page->index != index)) { +struct page *page =find_get_page (pcol->inode->i_mapping, index); + +if (!page) { + page =find_or_create_page (pcol->inode->i_mapping, + index,GFP_NOFS ); +if (unlikely (!page)) { +EXOFS_DBGMSG ("grab_cache_page Failed " +"index=0x%llx\n" ,_LLU (index)); +return NULL ; + } +unlock_page (page); + } +if (PageDirty (page) ||PageWriteback (page)) + *uptodate = true; +else + *uptodate =PageUptodate (page); +EXOFS_DBGMSG ("index=0x%lx uptodate=%d\n" , index, *uptodate); +return page; + }else { +EXOFS_DBGMSG ("YES that_locked_page index=0x%lx\n" , + pcol->that_locked_page->index); + *uptodate = true; +return pcol->that_locked_page; + } +} + +static void __r4w_put_page (void *priv,struct page *page) +{ +struct page_collect *pcol = priv; + +if (pcol->that_locked_page != page) { +EXOFS_DBGMSG ("index=0x%lx\n" , page->index); +page_cache_release (page); +return ; + } +EXOFS_DBGMSG ("that_locked_page index=0x%lx\n" , page->index); +} + +static const struct _ore_r4w_op _r4w_op = { + .get_page = &__r4w_get_page, + .put_page = &__r4w_put_page, +}; +static int write_exec (struct page_collect *pcol) {struct exofs_i_info *oi =exofs_i (pcol->inode);
@@ -589,6 +644,7 @@ static int write_exec(struct page_collect *pcol) ios = pcol->ios; ios->pages = pcol_copy->pages; ios->done = writepages_done; + ios->r4w = &_r4w_op; ios->private = pcol_copy;/* pages ownership was passed to pcol_copy */
@@ -773,6 +829,7 @@ static int exofs_writepages(struct address_space *mapping,return 0 ; } +/* static int exofs_writepage(struct page *page, struct writeback_control *wbc) { struct page_collect pcol;
@@ -788,7 +845,7 @@ static int exofs_writepage(struct page *page, struct writeback_control *wbc)return write_exec(&pcol); } - +*/ /* i_mutex held using inode->i_size directly */ static void _write_failed (struct inode *inode,loff_t to) {
@@ -894,7 +951,7 @@ static void exofs_invalidatepage(struct page *page, unsigned long offset)const struct address_space_operations exofs_aops = { .readpage = exofs_readpage, .readpages = exofs_readpages, - .writepage = exofs_writepage, + .writepage =NULL , .writepages = exofs_writepages, .write_begin = exofs_write_begin_export, .write_end = exofs_write_end,
Signature · 1 line
1.7.2.3
Awesome!
Benny
-----Original Message-----
From: Boaz Harrosh <[email protected]>
Sender: [email protected]
Date: Fri, 14 Oct 2011 19:24:14
To: Welch, Brent<[email protected]>; open-osd<[email protected]>; NFS list<[email protected]>; linux-fsdevel<[email protected]>
Subject: [PATCHSET 0/1 0/6] ore: RAID5 Support
I'm proud to present RAID5 support to ORE. Which enables raid5 for both exofs and pnfs-objects-layout driver.
The ORE with raid0/1/5 and soon 6 support has become a compact and abstract library, that with not a lot of effort, can support not only OSD but any type of devices. For example BTRFS, does it have a RAID5 support yet? if not it could use ORE. The ORE gets a bunch of pages at the top and produces bios for each device at the bottom. The libosd API can be easily abstracted and be used for block devices, just the same. The RAID layout supported by ORE is very rich, multi layered striping/mirroring/raid. even reacher then stacked MD. You can read about this layout here:
http://git.open-osd.org/gitweb.cgi?p=ietf-rfc5664.git;a=blob_plain;f=draft-ietf-nfsv4-rfc5664bis.html;hb=boaz2
Start at: 5.3. "Data Mapping Schemes" up to:
5.4.5. "RAID Usage and Implementation Notes"
There where some problems with the previous patchset here are the differences I squashed it to a new patchset at osd/linux-next.
[PATCH 1/1] SQUASHME: into: ore: Only IO one group at a time (API change)
And without farther ado Here is the RAID5 support. This is highly complicated stuff, for humble me at least, and I would appreciate any review and/or comments you guys can give it. Thanks in advance. (Pretty Please? :-))
[PATCH 1/6] ore: Make ore_calc_stripe_info EXPORT_SYMBOL [PATCH 2/6] ore: RAID5 read
[PATCH 3/6] ore: RAID5 Write
[PATCH 4/6] exofs: Support for RAID5 read-4-write interface. [PATCH 5/6] pnfs-obj: Support for RAID5 read-4-write interface. [PATCH 6/6] ore: Enable RAID5 mounts
A tree with above plus all prerequisites is at:
$ git clone git://open-osd.org/linux-open-osd linux-next [http://git.open-osd.org/gitweb.cgi?p=linux-open-osd.git;a=shortlog;h=refs/heads/merge_and_compile]
The code passes my tests, the highlight of which is git-clone linux and compare to and identical clone on ext4. But there must be month of farther testing done on this to get it better. For example. Aligned on stripe IO write back should be improved on all the way down to the VFS layer.
Thanks
Boaz
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Thanks Benny.
Is it OK if we merge, pnfs tree and open-osd, on Monday in BAT first thing? Tonight it's to late, and tomorrow I'm already flying. So Monday.
Have a safe trip
Boaz
Quoted 57 lines · Benny Halevy
Awesome!
Benny
-----Original Message-----
From: Boaz Harrosh <[email protected]>
Sender: [email protected]
Date: Fri, 14 Oct 2011 19:24:14
To: Welch, Brent<[email protected]>; open-osd<[email protected]>; NFS list<[email protected]>; linux-fsdevel<[email protected]>
Subject: [PATCHSET 0/1 0/6] ore: RAID5 SupportI'm proud to present RAID5 support to ORE. Which enables raid5 for both exofs and pnfs-objects-layout driver.
The ORE with raid0/1/5 and soon 6 support has become a compact and abstract library, that with not a lot of effort, can support not only OSD but any type of devices. For example BTRFS, does it have a RAID5 support yet? if not it could use ORE. The ORE gets a bunch of pages at the top and produces bios for each device at the bottom. The libosd API can be easily abstracted and be used for block devices, just the same. The RAID layout supported by ORE is very rich, multi layered striping/mirroring/raid. even reacher then stacked MD. You can read about this layout here:
http://git.open-osd.org/gitweb.cgi?p=ietf-rfc5664.git;a=blob_plain;f=draft-ietf-nfsv4-rfc5664bis.html;hb=boaz2
Start at: 5.3. "Data Mapping Schemes" up to:
5.4.5. "RAID Usage and Implementation Notes"There where some problems with the previous patchset here are the differences I squashed it to a new patchset at osd/linux-next.
[PATCH 1/1] SQUASHME: into: ore: Only IO one group at a time (API change)
And without farther ado Here is the RAID5 support. This is highly complicated stuff, for humble me at least, and I would appreciate any review and/or comments you guys can give it. Thanks in advance. (Pretty Please? :-))
[PATCH 1/6] ore: Make
ore_calc_stripe_infoEXPORT_SYMBOL[PATCH 2/6] ore: RAID5 read
[PATCH 3/6] ore: RAID5 Write
[PATCH 4/6] exofs: Support for RAID5 read-4-write interface. [PATCH 5/6] pnfs-obj: Support for RAID5 read-4-write interface. [PATCH 6/6] ore: Enable RAID5 mountsA tree with above plus all prerequisites is at:
$ git clone git://open-osd.org/linux-open-osd linux-next [http://git.open-osd.org/gitweb.cgi?p=linux-open-osd.git;a=shortlog;h=refs/heads/merge_and_compile]The code passes my tests, the highlight of which is git-clone linux and compare to and identical clone on ext4. But there must be month of farther testing done on this to get it better. For example. Aligned on stripe IO write back should be improved on all the way down to the VFS layer.
Thanks
Boaz
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Sure. Monday it is.
Benny
Quoted 67 lines · Boaz Harrosh
Thanks Benny.
Is it OK if we merge, pnfs tree and open-osd, on Monday in BAT first thing? Tonight it's to late, and tomorrow I'm already flying. So Monday.
Have a safe trip
BoazQuoted 51 lines · Benny Halevy
Awesome!
Benny
-----Original Message-----
From: Boaz Harrosh <[email protected]>
Sender: [email protected]
Date: Fri, 14 Oct 2011 19:24:14
To: Welch, Brent<[email protected]>; open-osd<[email protected]>; NFS list<[email protected]>; linux-fsdevel<[email protected]>
Subject: [PATCHSET 0/1 0/6] ore: RAID5 SupportI'm proud to present RAID5 support to ORE. Which enables raid5 for both exofs and pnfs-objects-layout driver.
The ORE with raid0/1/5 and soon 6 support has become a compact and abstract library, that with not a lot of effort, can support not only OSD but any type of devices. For example BTRFS, does it have a RAID5 support yet? if not it could use ORE. The ORE gets a bunch of pages at the top and produces bios for each device at the bottom. The libosd API can be easily abstracted and be used for block devices, just the same. The RAID layout supported by ORE is very rich, multi layered striping/mirroring/raid. even reacher then stacked MD. You can read about this layout here:
http://git.open-osd.org/gitweb.cgi?p=ietf-rfc5664.git;a=blob_plain;f=draft-ietf-nfsv4-rfc5664bis.html;hb=boaz2
Start at: 5.3. "Data Mapping Schemes" up to:
5.4.5. "RAID Usage and Implementation Notes"There where some problems with the previous patchset here are the differences I squashed it to a new patchset at osd/linux-next.
[PATCH 1/1] SQUASHME: into: ore: Only IO one group at a time (API change)
And without farther ado Here is the RAID5 support. This is highly complicated stuff, for humble me at least, and I would appreciate any review and/or comments you guys can give it. Thanks in advance. (Pretty Please? :-))
[PATCH 1/6] ore: Make
ore_calc_stripe_infoEXPORT_SYMBOL[PATCH 2/6] ore: RAID5 read
[PATCH 3/6] ore: RAID5 Write
[PATCH 4/6] exofs: Support for RAID5 read-4-write interface. [PATCH 5/6] pnfs-obj: Support for RAID5 read-4-write interface. [PATCH 6/6] ore: Enable RAID5 mountsA tree with above plus all prerequisites is at:
$ git clone git://open-osd.org/linux-open-osd linux-next [http://git.open-osd.org/gitweb.cgi?p=linux-open-osd.git;a=shortlog;h=refs/heads/merge_and_compile]The code passes my tests, the highlight of which is git-clone linux and compare to and identical clone on ext4. But there must be month of farther testing done on this to get it better. For example. Aligned on stripe IO write back should be improved on all the way down to the VFS layer.
Quoted 6 lines
Thanks
Boaz
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 5 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html