diff --git a/deps/mio/AUTHORS b/deps/mio/AUTHORS
new file mode 100644
index 0000000000000000000000000000000000000000..d79ec35741251a426b1a2b0d6e33ca2eeb19a625
--- /dev/null
+++ b/deps/mio/AUTHORS
@@ -0,0 +1 @@
+Sining Wu <sining.wu@seagate.com>
diff --git a/deps/mio/COPYING b/deps/mio/COPYING
new file mode 100644
index 0000000000000000000000000000000000000000..d758885ee9f86ad03f3422cacf8d1384086bc821
--- /dev/null
+++ b/deps/mio/COPYING
@@ -0,0 +1,2 @@
+Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates, All Rights Reserved
+License: MPL v2.0 (see License)
diff --git a/deps/mio/ChangeLog b/deps/mio/ChangeLog
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/deps/mio/LICENSE b/deps/mio/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..a1913aae5702eb9403dfb8fd17c3949ecc969ab4
--- /dev/null
+++ b/deps/mio/LICENSE
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+    means each individual or legal entity that creates, contributes to
+    the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+    means the combination of the Contributions of others (if any) used
+    by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+    means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+    means Source Code Form to which the initial Contributor has attached
+    the notice in Exhibit A, the Executable Form of such Source Code
+    Form, and Modifications of such Source Code Form, in each case
+    including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+    means
+
+    (a) that the initial Contributor has attached the notice described
+        in Exhibit B to the Covered Software; or
+
+    (b) that the Covered Software was made available under the terms of
+        version 1.1 or earlier of the License, but not also under the
+        terms of a Secondary License.
+
+1.6. "Executable Form"
+    means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+    means a work that combines Covered Software with other material, in 
+    a separate file or files, that is not Covered Software.
+
+1.8. "License"
+    means this document.
+
+1.9. "Licensable"
+    means having the right to grant, to the maximum extent possible,
+    whether at the time of the initial grant or subsequently, any and
+    all of the rights conveyed by this License.
+
+1.10. "Modifications"
+    means any of the following:
+
+    (a) any file in Source Code Form that results from an addition to,
+        deletion from, or modification of the contents of Covered
+        Software; or
+
+    (b) any new file in Source Code Form that contains any Covered
+        Software.
+
+1.11. "Patent Claims" of a Contributor
+    means any patent claim(s), including without limitation, method,
+    process, and apparatus claims, in any patent Licensable by such
+    Contributor that would be infringed, but for the grant of the
+    License, by the making, using, selling, offering for sale, having
+    made, import, or transfer of either its Contributions or its
+    Contributor Version.
+
+1.12. "Secondary License"
+    means either the GNU General Public License, Version 2.0, the GNU
+    Lesser General Public License, Version 2.1, the GNU Affero General
+    Public License, Version 3.0, or any later versions of those
+    licenses.
+
+1.13. "Source Code Form"
+    means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+    means an individual or a legal entity exercising rights under this
+    License. For legal entities, "You" includes any entity that
+    controls, is controlled by, or is under common control with You. For
+    purposes of this definition, "control" means (a) the power, direct
+    or indirect, to cause the direction or management of such entity,
+    whether by contract or otherwise, or (b) ownership of more than
+    fifty percent (50%) of the outstanding shares or beneficial
+    ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+    Licensable by such Contributor to use, reproduce, make available,
+    modify, display, perform, distribute, and otherwise exploit its
+    Contributions, either on an unmodified basis, with Modifications, or
+    as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+    for sale, have made, import, and otherwise transfer either its
+    Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+    or
+
+(b) for infringements caused by: (i) Your and any other third party's
+    modifications of Covered Software, or (ii) the combination of its
+    Contributions with other software (except as part of its Contributor
+    Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+    its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+    Form, as described in Section 3.1, and You must inform recipients of
+    the Executable Form how they can obtain a copy of such Source Code
+    Form by reasonable means in a timely manner, at a charge no more
+    than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+    License, or sublicense it under different terms, provided that the
+    license for the Executable Form does not attempt to limit or alter
+    the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+*                                                                      *
+*  6. Disclaimer of Warranty                                           *
+*  -------------------------                                           *
+*                                                                      *
+*  Covered Software is provided under this License on an "as is"       *
+*  basis, without warranty of any kind, either expressed, implied, or  *
+*  statutory, including, without limitation, warranties that the       *
+*  Covered Software is free of defects, merchantable, fit for a        *
+*  particular purpose or non-infringing. The entire risk as to the     *
+*  quality and performance of the Covered Software is with You.        *
+*  Should any Covered Software prove defective in any respect, You     *
+*  (not any Contributor) assume the cost of any necessary servicing,   *
+*  repair, or correction. This disclaimer of warranty constitutes an   *
+*  essential part of this License. No use of any Covered Software is   *
+*  authorized under this License except under this disclaimer.         *
+*                                                                      *
+************************************************************************
+
+************************************************************************
+*                                                                      *
+*  7. Limitation of Liability                                          *
+*  --------------------------                                          *
+*                                                                      *
+*  Under no circumstances and under no legal theory, whether tort      *
+*  (including negligence), contract, or otherwise, shall any           *
+*  Contributor, or anyone who distributes Covered Software as          *
+*  permitted above, be liable to You for any direct, indirect,         *
+*  special, incidental, or consequential damages of any character      *
+*  including, without limitation, damages for lost profits, loss of    *
+*  goodwill, work stoppage, computer failure or malfunction, or any    *
+*  and all other commercial damages or losses, even if such party      *
+*  shall have been informed of the possibility of such damages. This   *
+*  limitation of liability shall not apply to liability for death or   *
+*  personal injury resulting from such party's negligence to the       *
+*  extent applicable law prohibits such limitation. Some               *
+*  jurisdictions do not allow the exclusion or limitation of           *
+*  incidental or consequential damages, so this exclusion and          *
+*  limitation may not apply to You.                                    *
+*                                                                      *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+  This Source Code Form is subject to the terms of the Mozilla Public
+  License, v. 2.0. If a copy of the MPL was not distributed with this
+  file, You can obtain one at https://urldefense.proofpoint.com/v2/url?u=http-3A__mozilla.org_MPL_2.0_&d=DwIGAg&c=IGDlg0lD0b-nebmJJ0Kp8A&r=hP9i0a2dylNof_BddtBQSPyJc_9TlHHZ-xqQ6WnSg58&m=KIzUSoG_oqOVYCLgZ-9FvofAcLFZl_5qNlYFiLJ6gEs&s=v9pYlPD3qxkg_6dfQJATPzJY_RCImCaMbHeQUQ21bZk&e= .
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+  This Source Code Form is "Incompatible With Secondary Licenses", as
+  defined by the Mozilla Public License, v. 2.0.
diff --git a/deps/mio/Makefile.am b/deps/mio/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..38126b65eee8b817afe6ac2858607f10b1fbb2af
--- /dev/null
+++ b/deps/mio/Makefile.am
@@ -0,0 +1,151 @@
+# Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+# All Rights Reserved
+#
+# This software is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#-------------------------------------------------------------------------------
+#                             Quick Start                                      #
+#-------------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------------
+#                            Automake configuration                            #
+#-------------------------------------------------------------------------------
+
+# control verbosity level of make depending on 'V' command-line argument and
+# --enable-silent-rules option of configure script
+make_verbose   = $(make_verbose_$(V))
+make_verbose_  = $(make_verbose_$(AM_DEFAULT_VERBOSITY))
+make_verbose_0 = --no-print-directory
+
+MAKEFLAGS = $(make_verbose)
+
+# in order to suppress annoying automake warning "CFLAGS: non-POSIX variable name"
+# -Wno-portability automake option should be set for this makefile, this is
+# required for xcode generation
+AUTOMAKE_OPTIONS = -Wno-portability
+
+# required to properly rebuild aclocal.m4 macros on configure.ac or Makefile.am
+# updates
+ACLOCAL_AMFLAGS = -I m4
+
+# default XXXFLAGS, used for preprocessing, compiling and linking for all
+# user-space targets
+
+AM_CPPFLAGS  = @MIO_CPPFLAGS@
+AM_CFLAGS    = @MIO_CFLAGS@
+AM_LDFLAGS   = @MIO_LDFLAGS@
+
+#-------------------------------------------------------------------------------
+#                               Global variables                               #
+#-------------------------------------------------------------------------------
+
+# initialize variables, so values can be appended later with += if needed
+
+# everything that needs to be installed/packaged goes here
+bin_PROGRAMS       =
+lib_LTLIBRARIES    =
+
+# non-installable/packageable stuff: build helpers, local tests, etc.
+noinst_PROGRAMS    =
+noinst_LTLIBRARIES =
+
+# documentation
+man_MANS   =
+
+# Extra files with distribution
+EXTRA_DIST =
+
+# Files to clean
+CLEANFILES =
+
+#-------------------------------------------------------------------------------
+#                                  MIO Libraries                               #
+#-------------------------------------------------------------------------------
+
+lib_LTLIBRARIES          += lib/libmio.la
+lib_libmio_la_CPPFLAGS  = -DM0_TARGET='libmero' $(AM_CPPFLAGS)
+lib_libmio_la_LDFLAGS   = -version-info @LT_VERSION@ $(AM_LDFLAGS)
+#lib_libmio_la_LIBADD    = @MERO_LIBS@ @YAML_LIBS@ 
+lib_libmio_la_LIBADD    = -lmero -lyaml 
+
+lib_libmio_la_SOURCES =
+
+# install directory for public libmio headers
+mio_includedir             = $(includedir)/mio
+
+nobase_mio_include_HEADERS = config.h
+
+include $(top_srcdir)/src/Makefile.sub
+
+
+#-------------------------------------------------------------------------------
+#                                 Unit Tests                                   #
+#-------------------------------------------------------------------------------
+
+
+#-------------------------------------------------------------------------------
+#                                 MIO Examples                                 #
+#-------------------------------------------------------------------------------
+
+noinst_PROGRAMS                   += examples/mio_cat 
+noinst_PROGRAMS                   += examples/mio_copy 
+noinst_PROGRAMS                   += examples/mio_touch 
+noinst_PROGRAMS                   += examples/mio_unlink 
+noinst_PROGRAMS                   += examples/mio_hint_set
+noinst_PROGRAMS                   += examples/mio_hint_stat
+noinst_PROGRAMS                   += examples/mio_kvs_create_set 
+noinst_PROGRAMS                   += examples/mio_kvs_del_set 
+noinst_PROGRAMS                   += examples/mio_kvs_insert 
+noinst_PROGRAMS                   += examples/mio_kvs_retrieve 
+noinst_PROGRAMS                   += examples/mio_kvs_del_pairs 
+noinst_PROGRAMS                   += examples/mio_comp_obj_example 
+noinst_PROGRAMS                   += examples/mio_rw_threads 
+
+examples_mio_cat_CPPFLAGS = -DMIO_TARGET='mio_cat' $(AM_CPPFLAGS)
+examples_mio_cat_LDADD    = $(top_builddir)/lib/libmio.la
+
+examples_mio_copy_CPPFLAGS = -DMIO_TARGET='mio_copy' $(AM_CPPFLAGS)
+examples_mio_copy_LDADD    = $(top_builddir)/lib/libmio.la
+
+examples_mio_touch_CPPFLAGS = -DMIO_TARGET='mio_touch' $(AM_CPPFLAGS)
+examples_mio_touch_LDADD    = $(top_builddir)/lib/libmio.la
+
+examples_mio_unlink_CPPFLAGS = -DMIO_TARGET='mio_unlink' $(AM_CPPFLAGS)
+examples_mio_unlink_LDADD    = $(top_builddir)/lib/libmio.la
+
+examples_mio_hint_set_CPPFLAGS = -DMIO_TARGET='mio_hint_set' $(AM_CPPFLAGS)
+examples_mio_hint_set_LDADD    = $(top_builddir)/lib/libmio.la
+
+examples_mio_hint_stat_CPPFLAGS = -DMIO_TARGET='mio_hint_stat' $(AM_CPPFLAGS)
+examples_mio_hint_stat_LDADD    = $(top_builddir)/lib/libmio.la
+
+examples_mio_kvs_create_set_CPPFLAGS = -DMIO_TARGET='mio_kvs_create_set' $(AM_CPPFLAGS)
+examples_mio_kvs_create_set_LDADD    = $(top_builddir)/lib/libmio.la
+
+examples_mio_kvs_del_set_CPPFLAGS = -DMIO_TARGET='mio_kvs_del_set' $(AM_CPPFLAGS)
+examples_mio_kvs_del_set_LDADD    = $(top_builddir)/lib/libmio.la
+
+examples_mio_kvs_insert_CPPFLAGS = -DMIO_TARGET='mio_kvs_insert' $(AM_CPPFLAGS)
+examples_mio_kvs_insert_LDADD    = $(top_builddir)/lib/libmio.la
+
+examples_mio_kvs_retrieve_CPPFLAGS = -DMIO_TARGET='mio_kvs_retrieve' $(AM_CPPFLAGS)
+examples_mio_kvs_retrieve_LDADD    = $(top_builddir)/lib/libmio.la
+
+examples_mio_kvs_del_pairs_CPPFLAGS = -DMIO_TARGET='mio_kvs_del_pairs' $(AM_CPPFLAGS)
+examples_mio_kvs_del_pairs_LDADD    = $(top_builddir)/lib/libmio.la
+
+examples_mio_comp_obj_example_CPPFLAGS = -DMIO_TARGET='mio_comp_obj_example' $(AM_CPPFLAGS)
+examples_mio_comp_obj_example_LDADD    = $(top_builddir)/lib/libmio.la
+
+examples_mio_rw_threads_CPPFLAGS = -DMIO_TARGET='mio_comp_obj_example' $(AM_CPPFLAGS)
+examples_mio_rw_threads_LDADD    = $(top_builddir)/lib/libmio.la -lpthread -lcrypto -lssl
+
+include $(top_srcdir)/examples/Makefile.sub
+
+#-------------------------------------------------------------------------------
+#                                 Build rules                                  # 
+#-------------------------------------------------------------------------------
+
+# vim: textwidth=80 nowrap foldmethod=marker
diff --git a/deps/mio/NEWS b/deps/mio/NEWS
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/deps/mio/README b/deps/mio/README
new file mode 100644
index 0000000000000000000000000000000000000000..5b7f343700dfbf87e91e136b9f3de0e07b30712c
--- /dev/null
+++ b/deps/mio/README
@@ -0,0 +1,60 @@
+
+Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+All Rights Reserved
+
+This software is subject to the terms of the Mozilla Public License, v. 2.0.
+If a copy of the MPL was not distributed with this file, You can obtain
+one at http://mozilla.org/MPL/2.0/.
+
+
+1. Build MIO library
+
+Uncompress the source code package.
+
+Run the following steps to build MIO library and examples.
+(1) ./autogen.sh
+(2) ./configure
+    if you install Mero rpms in a customized directory such as your home
+    directory or build Mero from source, run configure like this
+
+    ./configure --with-libmero=libmero_directory --with-mero-headers=mero_headers_directory
+
+(3) make
+
+2. Run MIO examples
+
+MIO source code is shipped with varied examples.
+
+mio_rw_threads starts specified number of READ/WRITE threads. WRITE threads
+create MIO objects and write data to them, and then inform the READ trheads
+to read the written objects. READ threads will verify the data fetched from
+objects.
+
+Run mio_rw_threads following the steps below:
+(1) Start Mero (follow the Mero instruction)
+
+(2) cd tests
+MIO provides a sample configuration file mio_config.yaml in this directory.
+Edit mio_config.yaml to reflect Mero configurations in your system: (a) replace
+the clovis local address, MERO_CLOVIS_INST_ADDR, to yours. (b) replace MERO_HA_ADDR
+with your HA address. (c) MERO_PROFILE and MERO_PROCESS_FID (usually no need to
+change these 2 parameters)
+
+Methods to get the above parameters:
+(a) hctl mero status
+(b) checkout /etc/mero/conf.xc to search strings for M0_CST_HA
+(c) if your system is shipped with clovis sample apps, run
+    clovis-sample-app-dir/scripts/c0appzrcgen 
+
+(3) sudo ../examples/mio_rw_threads -s 4096 -c 1 -n 10 -t 1 -y ./mio_config.yaml -o 1:12346800
+
+Usage of mio_rw_thread
+  -o, --object         FID       Starting object ID
+  -n, --nr_objs        INT       The number of objects
+  -s, --block-size     INT       block size in bytes or with suffix b/k/m/g/K/M/G 
+  -c, --block-count    INT       number of blocks written to an object with suffix b/k/m/g/K/M/G
+  -t, --threads                  Number of threads
+  -y, --mio_conf                 MIO YAML configuration file
+  -h, --help                     shows this help text and exit
+
+All MIO examples use 2 uint64_t to represent an object ID.
diff --git a/deps/mio/autogen.sh b/deps/mio/autogen.sh
new file mode 100755
index 0000000000000000000000000000000000000000..8eecac56c809038b29f41d17bb504d4fb6d1b197
--- /dev/null
+++ b/deps/mio/autogen.sh
@@ -0,0 +1,8 @@
+# Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+# All Rights Reserved
+#
+# This software is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+autoreconf --install --force
diff --git a/deps/mio/configure.ac b/deps/mio/configure.ac
new file mode 100644
index 0000000000000000000000000000000000000000..d6eb403bd5fe7f4d60ad92b098b737eb9058cf89
--- /dev/null
+++ b/deps/mio/configure.ac
@@ -0,0 +1,328 @@
+# Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+# All Rights Reserved
+#
+# This software is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# MIO version
+m4_define([MIO_VERSION_MAJOR],[0])
+m4_define([MIO_VERSION_MINOR],[1])
+m4_define([MIO_VERSION_PATCH],[0])
+m4_define([MIO_VERSION],[MIO_VERSION_MAJOR.MIO_VERSION_MINOR.MIO_VERSION_PATCH])
+
+#
+# Autoconf/Automake/Libtool configuration 
+#
+
+AC_PREREQ(2.63)
+AC_INIT([mio],[MIO_VERSION],[mio@seagate.com])
+
+# The AC_PROG_CC macro sets CFLAGS to '-g -O2' by default if CFLAGS is not
+# initialized by the user, we don't need this because we use a separate
+# MIO_CFLAGS variable to control compiler's options while allowing user to
+# override it via CFLAGS from command-line.
+CFLAGS=${CFLAGS:=""}
+
+AM_INIT_AUTOMAKE([-Wall -Werror nostdinc foreign subdir-objects silent-rules])
+AM_SILENT_RULES([yes])
+
+LT_INIT([disable-static])
+
+AC_CONFIG_SRCDIR([src/mio.c])
+AC_CONFIG_MACRO_DIR([m4])
+
+AC_CONFIG_HEADERS([config.h])
+
+#
+# Global variables 
+#
+
+# PACKAGE_VERSION is a default autoconf variable, generated by AC_INIT from
+# it's "version" argument
+AC_SUBST([LT_RELEASE], [$PACKAGE_VERSION])
+
+# The value passed to libtool's `-version-info` parameter.
+#
+# [https://autotools.io/libtool/version.html#idm46422828083360]
+# |
+# | To set the version of the library, libtool provides the `-version-info`
+# | parameter, which accepts three numbers, separated by colons, that are
+# | called respectively, _current_, _revision_ and _age_. Both their name
+# | and their behaviour, nowadays, have to be considered fully arbitrary,
+# | as the explanation provided in the official documentation is confusing
+# | to say the least, and can be, in some cases, considered completely wrong.
+# |
+# | *Warning*
+# |
+# |     A common mistake is to assume that the three values passed to
+# |     `-version-info` map directly into the three numbers at the end of
+# |     the library name. This is not the case, and indeed, current,
+# |     revision and age are applied differently depending on the operating
+# |     system that one is using.
+#
+# E.g., LT_VERSION=1:1:0 results in mero/.libs/libmero.so.1.0.1 file.
+#
+# See also
+# https://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning
+AC_SUBST([LT_VERSION], [MIO_VERSION_MAJOR:MIO_VERSION_MINOR:MIO_VERSION_PATCH])
+
+# the following variables are only for internal use within this configure script
+# external scripts should use collection of variables, which is automatically
+# provided by autoconf:
+#
+#    @srcdir@
+#    @top_srcdir@
+#    @abs_top_srcdir@
+#    @builddir@
+#    @top_builddir@
+#    @abs_top_builddir@
+#
+SRCDIR="$srcdir"
+ABS_SRCDIR="$(cd $srcdir; pwd)"
+ABS_BUILDDIR="$(pwd)"
+AC_SUBST([ABS_BUILDDIR])
+
+AC_SUBST([MIO_VERSION_CODE],
+         ["$(( (MIO_VERSION_MAJOR << 24) + (MIO_VERSION_MINOR << 16) + (MIO_VERSION_PATCH << 8) ))U"]
+)
+
+BUILD_HOST=$(hostname)
+AC_SUBST([BUILD_HOST])
+AC_SUBST([BUILD_USER],["$(whoami)"])
+AC_SUBST([BUILD_TIME],["$(date -u)"])
+AC_SUBST([BUILD_GCC],["$(gcc -v 2>&1 | grep '^gcc version' | sed -e 's/(GCC)//')"])
+
+#-------------------------------------------------------------------------------
+# Checking for OS support
+#-------------------------------------------------------------------------------
+
+AC_MSG_CHECKING([for operating system])
+AC_MSG_RESULT([$host_os])
+
+AS_CASE([$host_os],
+        # supported operating systems:
+        [linux*], [],
+        # default action for unsupported OS is to abort with error
+        [AC_MSG_ERROR([Unsupported platform detected!])]
+)
+
+#------------------------------------------------------------------------------#
+#                            Configuration options                             #
+#------------------------------------------------------------------------------#
+
+# define macros 
+AH_TEMPLATE([ENABLE_DEBUG],      [Enable debug info and disable optimizations.])
+AH_TEMPLATE([MERO_LIB],          [Mero library directory])
+AH_TEMPLATE([MERO_INCLUDE],      [Directory for Mero development header files])
+
+# enable/disable options
+AC_ARG_ENABLE([debug],
+        [AS_HELP_STRING([--enable-debug],
+                        [enable debug information and disable optimizations])],
+        [], [enable_debug=no]
+)
+AM_CONDITIONAL([ENABLE_DEBUG],
+               [test "x$enable_debug" = xyes])
+
+# Set directories for default or customized libmero and Mero headers.
+AC_ARG_WITH([libmero],
+        [AS_HELP_STRING([--with-libmero=path],
+                        [set path to Mero library libmero, default is /usr/lib64])],
+        [LIBMERO=$with_libmero],
+        [LIBMERO=/usr/lib64]
+)
+AS_IF([test -z "$LIBMERO" || ! test -d "$LIBMERO/"],
+      [AC_MSG_ERROR([libmero not found! Please, install Mero package or \
+provide the path to a directory using --with-lustre option.])]
+)
+AC_SUBST([LIBMERO])
+
+AC_ARG_WITH([mero-headers],
+        [AS_HELP_STRING([--with-mero-headers=path],
+                        [set path to Mero headers, default is /usr/include/mero])],
+        [MERO_HEADERS=$with_mero_headers],
+        [MERO_HEADERS=/usr/include/mero]
+)
+AS_IF([test -z "$MERO_HEADERS" || ! test -d "$MERO_HEADERS/"],
+      [AC_MSG_ERROR([Mero headers not found! Please, install Mero headers or \
+provide the path to a directory using --with-mero-headers option.])]
+)
+AC_SUBST([MERO_HEADERS])
+
+#
+#------------------------------------------------------------------------------#
+#                         Check required programs                              #
+#------------------------------------------------------------------------------#
+
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_CPP
+AC_PROG_AWK
+AC_PROG_SED
+AC_PROG_LN_S
+
+#------------------------------------------------------------------------------#
+#                        Check required libraries                              #
+#------------------------------------------------------------------------------#
+
+# pthread library is required for a subset of pthread_XXX funcs
+AC_SEARCH_LIBS([pthread_create], [c pthread], [],
+        [pthread_create cannot be found! Try to install libc-devel or libpthread-devel.]
+)
+
+#------------------------------------------------------------------------------#
+#                       Check for required header files                        #
+#------------------------------------------------------------------------------#
+
+AC_CHECK_HEADERS([fcntl.h malloc.h stdint.h stdlib.h string.h sys/time.h unistd.h])
+
+AC_CHECK_HEADERS([pthread.h], [], [AC_MSG_ERROR([pthread.h cannot be found!])])
+
+AC_HEADER_STDBOOL
+
+#------------------------------------------------------------------------------#
+#                       Check required types                                #
+#------------------------------------------------------------------------------#
+
+AC_TYPE_INT32_T
+AC_TYPE_INT64_T
+AC_TYPE_MODE_T
+AC_TYPE_OFF_T
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_TYPE_UID_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+AC_TYPE_UINT64_T
+AC_TYPE_UINT8_T
+
+AC_CHECK_TYPES([pthread_barrier_t], [], [], [[#include <pthread.h>]])
+
+#------------------------------------------------------------------------------#
+#                      Checking compiler characteristics                       #
+#------------------------------------------------------------------------------#
+
+AC_CHECK_SIZEOF([long])
+
+AC_MSG_CHECKING([whether target platform is a 64-bit one])
+AS_IF([test $ac_cv_sizeof_long -eq 8],
+      [AC_MSG_RESULT([yes])],
+      [
+       AC_MSG_RESULT([no])
+       AC_MSG_ERROR([Only 64bit platforms are supported!])
+      ]
+)
+
+AC_C_INLINE
+
+#------------------------------------------------------------------------------#
+#                        Check required library functions                      #
+#------------------------------------------------------------------------------#
+
+AC_FUNC_MALLOC
+AC_CHECK_FUNCS([gettimeofday memset strchr strdup strstr strtoull])
+
+# Check libyaml 
+AC_SEARCH_LIBS([yaml_parser_initialize], [yaml], [],
+                 [yaml_parser_initialize cannot be found! Try install yaml package])
+AC_CHECK_HEADERS([yaml.h], [],
+                 AC_MSG_ERROR([yaml.h is not found. Try to install libyaml-devel package]))
+
+# Check libmero
+#AC_SEARCH_LIBS([m0_clovis_init], [mero], [],
+#                 [m0_clovis_init cannot be found! Try install libmero package])
+#AC_CHECK_HEADERS([clovis/clovis.h], [],
+#                 AC_MSG_ERROR([clovis.h is not found. Try to install libmero package]))
+
+#------------------------------------------------------------------------------#
+#                      Handle configuration options                            #
+#------------------------------------------------------------------------------#
+
+AS_IF([test x$enable_debug = xyes],
+      [
+       MIO_CPPFLAGS="-DDEBUG $MIO_CPPFLAGS"
+       MIO_CFLAGS="-g -O0 $MIO_CFLAGS"
+       AC_DEFINE([ENABLE_DEBUG])
+      ],[
+       MIO_CFLAGS="-g -O2 $MIO_CFLAGS"
+      ]
+)
+
+#------------------------------------------------------------------------------#
+#                             Set up build variables                           #
+#------------------------------------------------------------------------------#
+
+MIO_CPPFLAGS="-D_REENTRANT -D_GNU_SOURCE -DM0_INTERNAL='' -DM0_EXTERN=extern \
+             -iquote'$ABS_BUILDDIR' -iquote'$SRCDIR' -include'config.h' \
+             -I$MERO_HEADERS $MIO_CPPFLAGS"
+
+MIO_CPPFLAGS_DIST=$(echo "$MIO_CPPFLAGS" | grep -Po -e '-D\S+|-I/usr\S+' | xargs echo)
+
+# -Wno-attributes is required to suppress warnings about unrecognized
+# __attribute__, such as __attribute__((gccxml(...))). It's important because we
+# use -Werror, which turns warnings into errors, but we still need to be able to
+# use gccxml attributes.
+MIO_CFLAGS="-pipe -Wall -Werror -Wno-attributes -fno-strict-aliasing $MIO_CFLAGS"
+
+# Prevents gcc from introducing common symbols in object files. These symbols
+# are avoided because they break the compilation toolchain that Parallel
+# Scientific is using.
+MIO_CFLAGS="-fno-common $MIO_CFLAGS"
+
+MIO_LDFLAGS="-rdynamic -L$LIBMERO $MIO_LDFLAGS"
+
+# trim spaces at the end of flags
+MIO_CPPFLAGS=$(echo $MIO_CPPFLAGS | sed 's/[[[:blank:]]]*$//')
+MIO_CFLAGS=$(echo $MIO_CFLAGS | sed 's/[[[:blank:]]]*$//')
+MIO_LDFLAGS=$(echo $MIO_LDFLAGS | sed 's/[[[:blank:]]]*$//')
+
+AC_SUBST([MIO_CPPFLAGS])
+AC_SUBST([MIO_CPPFLAGS_DIST])
+AC_SUBST([MIO_CFLAGS])
+AC_SUBST([MIO_LDFLAGS])
+
+AC_SUBST([BUILD_CONFIGURE_OPTS],["$ac_configure_args"])
+AC_SUBST([BUILD_CFLAGS],["$MIO_CPPFLAGS $MIO_CFLAGS $CPPFLAGS $CFLAGS"])
+AC_SUBST([BUILD_LDFLAGS],["$MIO_LDFLAGS"])
+
+#
+# Setup output files 
+#
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
+
+#
+# Display resulting values of some important build variables 
+#
+
+echo ""
+
+AS_IF([test "x$CFLAGS" != x],
+      [echo "CFLAGS       :  \"$CFLAGS\""])
+AS_IF([test "x$CPPFLAGS" != x],
+      [echo "CPPFLAGS     :  \"$CPPFLAGS\""])
+AS_IF([test "x$LDFLAGS" != x],
+      [echo "LDFLAGS      :  \"$LDFLAGS\""])
+AS_IF([test "x$LIBS" != x],
+      [echo "LIBS         :  \"$LIBS\""])
+
+echo ""
+echo "MIO version :  $PACKAGE_VERSION"
+echo ""
+echo "CONFIGURE_OPTS:  $BUILD_CONFIGURE_OPTS"
+echo ""
+echo "LIBMERO     :  \"$LIBMERO\""
+echo "MERO_HEADERS     :  \"$MERO_HEADERS\""
+echo ""
+echo "MIO_CPPFLAGS    :  \"$MIO_CPPFLAGS\""
+echo "MIO_CFLAGS      :  \"$MIO_CFLAGS\""
+echo "MIO_LDFLAGS     :  \"$MIO_LDFLAGS\""
+echo ""
+echo "Gcc            :  \"$BUILD_GCC\""
+echo ""
+echo 'Run `make` to build MIO or `make help` for other options'
+
+# vim: tabstop=4 shiftwidth=4 expandtab textwidth=80 nowrap foldmethod=marker
diff --git a/deps/mio/examples/Makefile.sub b/deps/mio/examples/Makefile.sub
new file mode 100644
index 0000000000000000000000000000000000000000..28d6e283e4b1bba33e307abc079a55991060dc45
--- /dev/null
+++ b/deps/mio/examples/Makefile.sub
@@ -0,0 +1,50 @@
+# Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+# All Rights Reserved
+#
+# This software is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+examples_mio_cat_SOURCES = examples/mio_cat.c examples/obj.c \
+	  examples/obj_io_poll.c examples/obj_io_cbs.c \
+	  examples/helpers.c
+
+examples_mio_copy_SOURCES = examples/mio_copy.c examples/obj.c \
+	  examples/obj_io_poll.c examples/obj_io_cbs.c \
+	  examples/helpers.c
+
+examples_mio_rw_threads_SOURCES = examples/mio_rw_threads.c \
+	  examples/obj.c examples/obj_io_poll.c \
+	  examples/helpers.c
+
+examples_mio_touch_SOURCES = examples/mio_touch.c examples/obj.c \
+	  examples/helpers.c
+ 
+examples_mio_unlink_SOURCES = examples/mio_unlink.c  examples/obj.c \
+	  examples/helpers.c
+
+examples_mio_hint_set_SOURCES = examples/mio_hint_set.c examples/obj.c \
+	  examples/helpers.c
+
+examples_mio_hint_stat_SOURCES = examples/mio_hint_stat.c examples/obj.c \
+	  examples/helpers.c
+
+examples_mio_comp_obj_example_SOURCES = examples/mio_comp_obj.c examples/obj.c \
+	  examples/helpers.c
+
+examples_mio_kvs_create_set_SOURCES = examples/mio_kvs_create_set.c examples/kvs.c \
+	  examples/helpers.c
+
+examples_mio_kvs_del_set_SOURCES = examples/mio_kvs_del_set.c examples/kvs.c \
+	  examples/helpers.c
+
+examples_mio_kvs_insert_SOURCES = examples/mio_kvs_insert.c examples/kvs.c \
+	  examples/helpers.c
+
+examples_mio_kvs_retrieve_SOURCES = examples/mio_kvs_retrieve.c  examples/kvs.c \
+	  examples/helpers.c
+
+examples_mio_kvs_del_pairs_SOURCES = examples/mio_kvs_del_pairs.c  examples/kvs.c \
+	  examples/helpers.c 
+
diff --git a/deps/mio/examples/helpers.c b/deps/mio/examples/helpers.c
new file mode 100644
index 0000000000000000000000000000000000000000..105df9945668cb2c6112679e0bf8f47ddae1a14b
--- /dev/null
+++ b/deps/mio/examples/helpers.c
@@ -0,0 +1,76 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <string.h>     
+#include <stdlib.h>
+#include <errno.h>
+#include <errno.h>
+
+#include "src/mio.h"
+
+int mio_cmd_strtou64(const char *arg, uint64_t *out)
+{
+	char *end = NULL;
+	char *pos;
+	static const char suffix[] = "bkmgKMG";
+	int rc = 0;
+
+	static const uint64_t multiplier[] = {
+		1 << 9,
+		1 << 10,
+		1 << 20,
+		1 << 30,
+		1000,
+		1000 * 1000,
+		1000 * 1000 * 1000
+	};
+
+	*out = strtoull(arg, &end, 0);
+
+	if (*end != 0 && rc == 0) {
+		pos = strchr(suffix, *end);
+		if (pos != NULL) {
+			if (*out <= UINT64_MAX / multiplier[pos - suffix])
+				*out *= multiplier[pos - suffix];
+			else
+				rc = -EOVERFLOW;
+		} else
+			rc = -EINVAL;
+	}
+	return rc;
+}
+
+int mio_cmd_wait_on_op(struct mio_op *op)
+{
+	struct mio_pollop pop;
+
+	memset(&pop, 0, sizeof pop);
+	pop.mp_op = op;
+	mio_op_poll(&pop, 1, MIO_TIME_NEVER);
+	return op->mop_rc;
+}
+
+uint32_t mio_cmd_random(uint32_t max)
+{
+	return (uint32_t)random() % max;
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/helpers.h b/deps/mio/examples/helpers.h
new file mode 100644
index 0000000000000000000000000000000000000000..7db3bcef34758a41fcd7f0af6626e697cc371402
--- /dev/null
+++ b/deps/mio/examples/helpers.h
@@ -0,0 +1,33 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#ifndef __HELPERS_H__
+#define __HELPERS_H__
+
+int mio_cmd_strtou64(const char *arg, uint64_t *out);
+int mio_cmd_wait_on_op(struct mio_op *op);
+uint32_t mio_cmd_random(uint32_t max);
+
+#endif /* __HELPERS_H__ */
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/kvs.c b/deps/mio/examples/kvs.c
new file mode 100644
index 0000000000000000000000000000000000000000..9719b914a7c6c34a094d60b6d330ab15d7eaf651
--- /dev/null
+++ b/deps/mio/examples/kvs.c
@@ -0,0 +1,454 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <asm/byteorder.h>
+
+#include "kvs.h"
+#include "helpers.h"
+
+struct kvs_id_uint128 {
+	uint64_t k_hi;
+	uint64_t k_lo;
+};
+
+enum {
+	KVS_MAX_KEY_LEN = 64,
+	KVS_MAX_VAL_LEN = 64,
+	KVS_MAX_NR_PAIRS_PER_OP = 1024
+};
+
+#define KVS_VAL_STRING  ("Hidden Gnome")
+
+static int kvs_id_sscanf(char *idstr, struct mio_kvs_id *kid)
+{
+        int rc;
+        int n;
+        uint64_t u1;
+        uint64_t u2;
+
+        rc = sscanf(idstr, "%"SCNx64" : %"SCNx64" %n", &u1, &u2, &n);
+        if (rc < 0)
+                return rc;
+        u1 = __cpu_to_be64(u1);
+        u2 = __cpu_to_be64(u2);
+
+        memcpy(kid->mki_bytes, &u1, sizeof u1);
+        memcpy(kid->mki_bytes + sizeof u1, &u2, sizeof u2);
+        return 0;
+}
+
+static void kvs_id_to_uint128(struct kvs_id_uint128 *kid128,
+			      struct mio_kvs_id *kid)
+{
+	uint8_t *ptr;
+        uint64_t u1;
+        uint64_t u2;
+
+	ptr = kid->mki_bytes;
+	memcpy(&u1, ptr, sizeof u1);
+	ptr += sizeof u1;
+	memcpy(&u2, ptr, sizeof u2);
+
+	u1 = __be64_to_cpu(u1);
+	u2 = __be64_to_cpu(u2);
+	kid128->k_hi = u1;
+	kid128->k_lo = u2;
+}
+
+static void kvs_free_pairs(struct mio_kv_pair *pairs)
+{
+	if (pairs != NULL)
+		free(pairs);
+}
+
+static struct mio_kv_pair* kvs_alloc_pairs(int nr)
+{
+	struct mio_kv_pair *pairs;
+
+	pairs = malloc(nr * sizeof(struct mio_kv_pair));
+	return pairs;
+}
+
+static
+int kvs_fill_pairs(struct mio_kvs_id *kid, struct mio_kv_pair *pairs,
+		   int start_kno, int nr_pairs, bool set_vals)
+{
+	int   i;
+	int   rc;
+	int   klen = 0;
+	int   vlen = 0;
+	char *prefix = NULL;
+	char *tmp_str = NULL;
+	char *key_str = NULL;
+	char *val_str = NULL;
+	struct kvs_id_uint128 id128;
+
+	if (pairs == NULL)
+		return -EINVAL;
+
+	rc = -ENOMEM;
+	prefix = malloc(KVS_MAX_KEY_LEN);
+	if (prefix == NULL)
+		goto error;
+
+	tmp_str = malloc(KVS_MAX_KEY_LEN);
+	if (tmp_str == NULL)
+		goto error;
+
+	/*
+	 * Keys are flled with this format (index fid:key's serial number).
+	 */
+	kvs_id_to_uint128(&id128, kid);
+	for (i = 0; i < nr_pairs; i++) {
+		sprintf(tmp_str,
+			"%"PRIx64":%"PRIx64":%d",
+			id128.k_hi, id128.k_lo, start_kno + i);
+		klen = strlen(tmp_str) + 1;
+		key_str = malloc(klen);
+		if (key_str == NULL)
+			goto error;
+		strncpy(key_str, tmp_str, klen);
+		pairs[i].mkp_klen = klen;
+		pairs[i].mkp_key  = key_str;
+
+		if (set_vals) {
+			memset(tmp_str, 0, KVS_MAX_KEY_LEN);
+			sprintf(tmp_str, "%s %d",
+				KVS_VAL_STRING, (int)mio_cmd_random(nr_pairs));
+			vlen = strlen(tmp_str) + 1;
+			val_str = malloc(vlen);
+			if (val_str == NULL)
+				goto error;
+			strncpy(val_str, tmp_str, vlen);
+			pairs[i].mkp_vlen = vlen;
+			pairs[i].mkp_val  = val_str;
+		}
+	}
+
+	return 0;
+
+error:
+	if (prefix)
+		free(prefix);
+	if (tmp_str)
+		free(tmp_str);
+	if (key_str)
+		free(key_str);
+	if (val_str)
+		free(val_str);
+
+	for (i = 0; i < nr_pairs; ++i) {
+		if (pairs[i].mkp_key)
+			free(pairs[i].mkp_key);
+		if (pairs[i].mkp_val)
+			free(pairs[i].mkp_val);
+		pairs[i].mkp_klen = 0;
+		pairs[i].mkp_vlen = 0;
+	}
+
+	return rc;
+}
+
+static void
+kvs_print_pairs(struct mio_kv_pair *pairs, int nr_pairs, FILE *log)
+{
+	int i;
+
+	for (i = 0; i < nr_pairs; i++) {
+		fprintf(log, "%s\t\t%s\n",
+			(char *)pairs[i].mkp_key, (char *)pairs[i].mkp_val);
+	}
+}
+
+static int kvs_create_set(struct mio_kvs_id *kid)
+{
+	int rc;
+	struct mio_op op;
+
+	rc = mio_kvs_create_set(kid, &op);
+	if (rc != 0)
+		return rc;
+
+	rc = mio_cmd_wait_on_op(&op);
+	if (rc < 0)
+		fprintf(stderr, "Failed in creating an KVS set!\n");
+
+	return rc;
+}
+
+static int kvs_delete_set(struct mio_kvs_id *kid)
+{
+	int rc;
+	struct mio_op op;
+
+	rc = mio_kvs_del_set(kid, &op);
+	if (rc != 0)
+		return rc;
+
+	rc = mio_cmd_wait_on_op(&op);
+	if (rc < 0)
+		fprintf(stderr, "Failed in creating an KVS set!\n");
+
+	return rc;
+}
+
+static int
+kvs_query_put(struct mio_kvs_id *kid, int start_kno, int nr_kvp, FILE *log)
+{
+	int rc;
+	int *rcs;
+	struct mio_op op;
+	struct mio_kv_pair *pairs;
+
+	rcs = malloc(nr_kvp * sizeof(int));
+	if (rcs == NULL)
+		return -ENOMEM;
+
+	pairs = kvs_alloc_pairs(nr_kvp);
+	if (pairs == NULL) {
+		free(rcs);
+		return -ENOMEM;
+	}
+	kvs_fill_pairs(kid, pairs, start_kno, nr_kvp, true);
+	if (log)
+		kvs_print_pairs(pairs, nr_kvp, log);
+
+	rc = mio_kvs_pair_put(kid, nr_kvp, pairs, rcs, &op);
+	if (rc != 0)
+		return rc;
+
+	rc = mio_cmd_wait_on_op(&op);
+	if (rc < 0)
+		fprintf(stderr, "Failed in inserting kv pairs to aset!\n");
+
+	kvs_free_pairs(pairs);
+	return rc;
+}
+
+static int
+kvs_query_get(struct mio_kvs_id *kid, int start_kno, int nr_kvp, FILE *log)
+{
+	int rc;
+	int *rcs;
+	struct mio_op op;
+	struct mio_kv_pair *pairs;
+
+	rcs = malloc(nr_kvp * sizeof(int));
+	if (rcs == NULL)
+		return -ENOMEM;
+	pairs = kvs_alloc_pairs(nr_kvp);
+	if (pairs == NULL) {
+		free(rcs);
+		return -ENOMEM;
+	}
+	kvs_fill_pairs(kid, pairs, start_kno, nr_kvp, false);
+
+	rc = mio_kvs_pair_get(kid, nr_kvp, pairs, rcs, &op);
+	if (rc != 0)
+		return rc;
+
+	rc = mio_cmd_wait_on_op(&op);
+	if (rc < 0)
+		fprintf(stderr, "Failed in retrieving kv pairs to aset!\n");
+
+	if (rc == 0 && log != NULL)
+		kvs_print_pairs(pairs, nr_kvp, log);
+
+	kvs_free_pairs(pairs);
+	return rc;
+}
+
+static int
+kvs_query_del(struct mio_kvs_id *kid, int start_kno, int nr_kvp, FILE *log)
+{
+	int rc;
+	int *rcs;
+	struct mio_op op;
+	struct mio_kv_pair *pairs;
+
+	rcs = malloc(nr_kvp * sizeof(int));
+	if (rcs == NULL)
+		return -ENOMEM;
+	pairs = kvs_alloc_pairs(nr_kvp);
+	if (pairs == NULL) {
+		free(rcs);
+		return -ENOMEM;
+	}
+	kvs_fill_pairs(kid, pairs, start_kno, nr_kvp, false);
+	if (log != NULL)
+		kvs_print_pairs(pairs, nr_kvp,log);
+
+	rc = mio_kvs_pair_del(kid, nr_kvp, pairs, rcs, &op);
+	if (rc != 0)
+		return rc;
+
+	rc = mio_cmd_wait_on_op(&op);
+	if (rc < 0)
+		fprintf(stderr, "Failed in retrieving kv pairs to aset!\n");
+
+	kvs_free_pairs(pairs);
+	return rc;
+}
+
+int mio_cmd_kvs_create_set(struct mio_kvs_id *kid)
+{
+	return kvs_create_set(kid);
+}
+
+int mio_cmd_kvs_delete_set(struct mio_kvs_id *kid)
+{
+	return kvs_delete_set(kid);
+}
+
+int mio_cmd_kvs_insert_pairs(struct mio_kvs_id *kid,
+			     int start_kno, int nr_pairs, FILE *log)
+{
+	int rc = 0;
+	int nr_pairs_op;
+
+	while(nr_pairs > 0) {
+		nr_pairs_op = nr_pairs > KVS_MAX_NR_PAIRS_PER_OP?
+			      KVS_MAX_NR_PAIRS_PER_OP : nr_pairs;
+		rc = kvs_query_put(kid, start_kno, nr_pairs_op, log);
+		if (rc != 0)
+			break;
+		nr_pairs -= nr_pairs_op;
+		start_kno += nr_pairs_op;
+	}
+
+	return rc;
+}
+
+int mio_cmd_kvs_retrieve_pairs(struct mio_kvs_id *kid,
+			       int start_kno, int nr_pairs, FILE *log)
+{
+	int rc = 0;
+	int nr_pairs_op;
+
+	while(nr_pairs > 0) {
+		nr_pairs_op = nr_pairs > KVS_MAX_NR_PAIRS_PER_OP?
+			      KVS_MAX_NR_PAIRS_PER_OP : nr_pairs;
+
+		rc = kvs_query_get(kid, start_kno, nr_pairs_op, log);
+		if (rc != 0)
+			break;
+		nr_pairs -= nr_pairs_op;
+		start_kno += nr_pairs_op;
+	}
+
+	return rc;
+}
+
+int mio_cmd_kvs_del_pairs(struct mio_kvs_id *kid,
+			  int start_kno, int nr_pairs, FILE *log)
+{
+	int rc = 0;
+	int nr_pairs_op;
+
+	while(nr_pairs > 0) {
+		nr_pairs_op = nr_pairs > KVS_MAX_NR_PAIRS_PER_OP?
+			      KVS_MAX_NR_PAIRS_PER_OP : nr_pairs;
+
+		rc = kvs_query_del(kid, start_kno, nr_pairs_op, log);
+		if (rc != 0)
+			break;
+		nr_pairs -= nr_pairs_op;
+		start_kno += nr_pairs_op;
+	}
+
+	return rc;
+}
+
+int mio_cmd_kvs_args_init(int argc, char **argv,
+			  struct mio_cmd_kvs_params *params,
+			  void (*usage)(FILE *, char *))
+{
+	int v;
+	int option_index = 0;
+	static struct option l_opts[] = {
+				{"kvs",       required_argument, NULL, 'k'},
+				{"start_key", required_argument, NULL, 's'},
+				{"nr_pairs",  required_argument, NULL, 'n'},
+				{"mio_conf",  required_argument, NULL, 'y'},
+				{"log_file",  required_argument, NULL, 'l'},
+				{"help",      no_argument,       NULL, 'h'},
+				{0,           0,                 0,     0 }};
+
+	memset(params, 0, sizeof *params);
+	params->ckp_nr_pairs = 1;
+
+	while ((v = getopt_long(argc, argv, ":k:s:n:y:l:h", l_opts,
+				&option_index)) != -1)
+	{
+		switch (v) {
+		case 'k':
+			kvs_id_sscanf(optarg, &params->ckp_kid);
+			continue;
+		case 's':
+			params->ckp_start_kno = atoi(optarg);
+			continue;
+		case 'n':
+			params->ckp_nr_pairs = atoi(optarg);
+			continue;
+		case 'y':
+			params->ckp_conf_fname = strdup(optarg);
+			if (params->ckp_conf_fname == NULL)
+				exit(EXIT_FAILURE);
+			continue;
+		case 'l':
+			params->ckp_log = strdup(optarg);
+			if (params->ckp_log == NULL)
+				exit(EXIT_FAILURE);
+			continue;
+		case 'h':
+			usage(stderr, basename(argv[0]));
+			exit(EXIT_FAILURE);
+		case '?':
+			fprintf(stderr, "Unsupported option '%c'\n",
+				optopt);
+			usage(stderr, basename(argv[0]));
+			exit(EXIT_FAILURE);
+		case ':':
+			fprintf(stderr, "No argument given for '%c'\n",
+				optopt);
+			usage(stderr, basename(argv[0]));
+			exit(EXIT_FAILURE);
+		default:
+			fprintf(stderr, "Unsupported option '%c'\n", v);
+		}
+	}
+
+	return 0;
+}
+
+void  mio_cmd_kvs_args_fini(struct mio_cmd_kvs_params *params)
+{
+	if(params->ckp_conf_fname)
+		free(params->ckp_conf_fname);
+	if (params->ckp_log)
+		free(params->ckp_log);
+}
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/kvs.h b/deps/mio/examples/kvs.h
new file mode 100644
index 0000000000000000000000000000000000000000..2ab33542fe21fd1c458081779eb85fb882f84455
--- /dev/null
+++ b/deps/mio/examples/kvs.h
@@ -0,0 +1,63 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#ifndef __KVS_H__
+#define __KVS_H__
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/time.h>
+
+#include "src/mio.h"
+
+struct mio_cmd_kvs_params {
+	char *ckp_conf_fname;
+
+	struct mio_kvs_id ckp_kid;
+	int ckp_nr_pairs;
+	int ckp_start_kno;
+
+	char *ckp_log;
+};
+
+int mio_cmd_kvs_args_init(int argc, char **argv,
+			  struct mio_cmd_kvs_params *params,
+			  void (*usage)(FILE *, char *));
+void  mio_cmd_kvs_args_fini(struct mio_cmd_kvs_params *params);
+
+int mio_cmd_kvs_create_set(struct mio_kvs_id *kid);
+int mio_cmd_kvs_delete_set(struct mio_kvs_id *kid);
+
+int mio_cmd_kvs_insert_pairs(struct mio_kvs_id *kid,
+			     int start_kno, int nr_pairs, FILE *log);
+int mio_cmd_kvs_retrieve_pairs(struct mio_kvs_id *kid,
+			       int start_kno, int nr_pairs, FILE *log);
+int mio_cmd_kvs_del_pairs(struct mio_kvs_id *kid,
+			  int start_kno, int nr_pairs, FILE *log);
+
+#endif /* __KVS_H__ */
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/mio_cat.c b/deps/mio/examples/mio_cat.c
new file mode 100644
index 0000000000000000000000000000000000000000..ef29cf024ce33d241ab971b90f173bbd9bb1e378
--- /dev/null
+++ b/deps/mio/examples/mio_cat.c
@@ -0,0 +1,82 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "obj.h"
+
+static void cat_usage(FILE *file, char *prog_name)
+{
+	fprintf(file, "Usage: %s [OPTION]... OUTPUT_FILE\n"
+"DISPLAY an MIO object's content to OUTPUT_FILE.\n"
+"\n"
+"Mandatory arguments to long options are mandatory for short options too.\n"
+"  -o, --object         OID       ID of the mero object\n"
+"  -s, --block-size     INT       block size in bytes or with " \
+				 "suffix b/k/m/g/K/M/G (see --block-count)\n"
+"  -c, --block-count    INT       number of blocks for IO, can give with " \
+				 "suffix b/k/m/g/K/M/G (see --block-size)\n"
+"  -a, --async_mode               Set to async IO mode\n"
+"  -y, --mio_conf_file            MIO YAML configuration file\n"
+"  -h, --help                     shows this help text and exit\n"
+, prog_name);
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+	struct mio_cmd_obj_params cat_params;
+	char *dst_fname = NULL;
+
+	mio_cmd_obj_args_init(argc, argv, &cat_params, &cat_usage);
+	if (argv[optind] != NULL)
+		dst_fname = strdup(argv[optind]);
+	if (cat_params.cop_async_mode && dst_fname == NULL) {
+		fprintf(stderr, "Missed source file to write to !\n");
+		cat_usage(stderr, basename(argv[0]));
+		exit(-1);
+	}
+
+	rc = mio_init(cat_params.cop_conf_fname);
+	if (rc < 0) {
+		fprintf(stderr, "mio_init failed! rc = %d\n", rc);
+		exit(EXIT_FAILURE);
+	}
+
+	rc = cat_params.cop_async_mode?
+	     mio_cmd_obj_read_async(&cat_params.cop_oid, dst_fname,
+				    cat_params.cop_block_size,
+				    cat_params.cop_block_count) :
+	     mio_cmd_obj_read(&cat_params.cop_oid, dst_fname,
+			      cat_params.cop_block_size,
+			      cat_params.cop_block_count);
+	if (rc < 0)
+		fprintf(stderr, "mio_cmd_obj_read failed! rc = %d\n", rc);
+
+	mio_fini();
+	if (dst_fname)
+		free(dst_fname);
+	mio_cmd_obj_args_fini(&cat_params);
+	return rc;
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/mio_comp_obj.c b/deps/mio/examples/mio_comp_obj.c
new file mode 100644
index 0000000000000000000000000000000000000000..c2cf66e76d89a8f145e609dfa17ea1c2c5c34e68
--- /dev/null
+++ b/deps/mio/examples/mio_comp_obj.c
@@ -0,0 +1,400 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <asm/byteorder.h>
+
+#include "obj.h"
+#include "helpers.h"
+
+static void comp_obj_usage(FILE *file, char *prog_name)
+{
+	fprintf(file, "Usage: %s [OPTION]...\n"
+"Examples for composite object APIs.\n"
+"\n"
+"Mandatory arguments to long options are mandatory for short options too.\n"
+"  -o, --object         OID       ID of the mero object\n"
+"  -y, --mio_conf_file            MIO YAML configuration file\n"
+"  -h, --help                     shows this help text and exit\n"
+, prog_name);
+}
+
+/**
+ * Calculate the layer's ids from composite object id. Here we
+ * naviely assume a simple relation between composite object id
+ * and layers'.
+ */
+static void layer_ids_get(struct mio_obj_id *oid, int nr_layers,
+			  struct mio_obj_id *layer_ids)
+{
+	int i;
+	uint64_t u1;
+	uint64_t u2;
+	uint64_t n1;
+	uint64_t n2;
+	struct mio_obj_id *layer_id;
+
+	memcpy(&u1, oid->moi_bytes, sizeof u1);
+	memcpy(&u2, oid->moi_bytes + sizeof u1, sizeof u2);
+	u1 = __be64_to_cpu(u1);
+	u2 = __be64_to_cpu(u2);
+
+	for (i = 0; i < nr_layers; i++) {
+		layer_id = layer_ids + i;
+		n1 = u1 + i + 1;
+		n2 = u2;
+		n1 = __cpu_to_be64(n1);
+		n2 = __cpu_to_be64(n2);
+		memcpy(layer_id->moi_bytes, &n1, sizeof n1);
+		memcpy(layer_id->moi_bytes + sizeof n1, &n2, sizeof n2);
+	}
+}
+
+static int
+comp_obj_add_extents(struct mio_obj *obj, int nr_layers, int nr_exts)
+{
+	int i;
+	int j;
+	int rc = 0;
+	struct mio_obj_id *layer_ids;
+	struct mio_obj_ext *exts;
+	struct mio_op op;
+
+	layer_ids = malloc(nr_layers * sizeof(*layer_ids));
+	exts = malloc(nr_exts * sizeof(*exts));
+	if (layer_ids == NULL || exts == NULL) {
+		rc = -ENOMEM;
+		goto exit;
+	}
+	layer_ids_get(&obj->mo_id, nr_layers, layer_ids);
+
+	for (i = 0; i < nr_layers; i++) {
+		for (j = 0; j < nr_exts; j++) {
+			exts[j].moe_off = (i * nr_exts + j) * 4096 * 4096;
+			exts[j].moe_size = 4096 * 4096;
+		}
+
+		mio_op_init(&op);
+		rc = mio_composite_obj_add_extents(
+			obj, layer_ids + i, nr_exts, exts, &op) ? :
+		     mio_cmd_wait_on_op(&op);
+		mio_op_fini(&op);
+		if (rc < 0)
+			break;
+	}
+
+	/*
+	 * Note: the example here doesn't clean-up the extents
+	 * that have been added if there is an error.
+ 	 */
+
+exit:
+	free(layer_ids);
+	free(exts);
+	return rc;
+} 
+
+static int
+comp_obj_del_extents(struct mio_obj *obj, int nr_layers, int nr_exts)
+{
+	int i;
+	int j;
+	int rc = 0;
+	struct mio_obj_id *layer_ids;
+	struct mio_obj_ext *exts;
+	struct mio_op op;
+
+	layer_ids = malloc(nr_layers * sizeof(*layer_ids));
+	exts = malloc(nr_exts * sizeof(*exts));
+	if (layer_ids == NULL || exts == NULL) {
+		rc = -ENOMEM;
+		goto exit;
+	}
+	layer_ids_get(&obj->mo_id, nr_layers, layer_ids);
+
+	for (i = 0; i < nr_layers; i++) {
+		for (j = 0; j < nr_exts; j++) {
+			exts[j].moe_off = (i * nr_exts + j) * 4096 * 4096;
+			exts[j].moe_size = 4096 * 4096;
+		}
+
+		mio_op_init(&op);
+		rc = mio_composite_obj_del_extents(
+			obj, layer_ids + i, nr_exts, exts, &op)? :
+		     mio_cmd_wait_on_op(&op);
+		mio_op_fini(&op);
+		if (rc < 0)
+			break;
+	}
+
+exit:
+	free(layer_ids);
+	free(exts);
+	return rc;
+}
+
+static int
+comp_obj_list_extents(struct mio_obj *obj, int nr_layers, int nr_exts)
+{
+	int i;
+	int j;
+	int rc = 0;
+	int nr_ret_exts;
+	off_t offset;
+	struct mio_obj_id *layer_ids;
+	struct mio_obj_ext *exts;
+	struct mio_op op;
+
+	layer_ids = malloc(nr_layers * sizeof(*layer_ids));
+	exts = malloc(nr_exts * sizeof(*exts));
+	if (layer_ids == NULL || exts == NULL) {
+		rc = -ENOMEM;
+		goto exit;
+	}
+	layer_ids_get(&obj->mo_id, nr_layers, layer_ids);
+
+	for (i = 0; i < nr_layers; i++) {
+		offset = 0; //i * nr_exts * 4096 * 4096;
+
+		mio_op_init(&op);
+		rc = mio_composite_obj_get_extents(
+			obj, layer_ids + i, offset, nr_exts, exts,
+			&nr_ret_exts, &op)? :
+		     mio_cmd_wait_on_op(&op);
+		mio_op_fini(&op);
+		if (rc < 0)
+			continue;
+
+		for (j = 0; j < nr_ret_exts; j++) {
+			fprintf(stderr, "layer %d: (%ld, %ld)\n",
+				i, exts[j].moe_off, exts[j].moe_size);
+		}
+	}
+
+exit:
+	free(layer_ids);
+	free(exts);
+	return rc;
+}
+
+
+static int comp_obj_add_layers(struct mio_obj *obj, int nr_layers)
+{
+	int i;
+	int rc = 0;
+	struct mio_comp_obj_layer *layers;
+	struct mio_obj_id *layer_ids;
+	struct mio_op op;
+
+	layers = malloc(nr_layers * sizeof(*layers));
+	layer_ids = malloc(nr_layers * sizeof(*layer_ids));
+	if (layers == NULL || layer_ids == NULL) {
+		rc = -ENOMEM;
+		goto exit;
+	}
+	layer_ids_get(&obj->mo_id, nr_layers, layer_ids);
+
+	/* Create objects for each layer. */
+	for (i = 0; i < nr_layers; i++) {
+		rc = mio_cmd_obj_touch(layer_ids + i);
+		if (rc < 0)
+			goto exit;
+	}
+
+	/* Add layers to the composite object. */
+	for (i = 0; i < nr_layers; i++) {
+		layers[i].mcol_priority = 0;
+		memcpy(&layers[i].mcol_oid, layer_ids + i,
+		       sizeof(struct mio_obj_id));
+	}
+
+	mio_op_init(&op);
+	rc = mio_composite_obj_add_layers(obj, nr_layers, layers, &op)? :
+	     mio_cmd_wait_on_op(&op);
+	mio_op_fini(&op);
+
+exit:
+	if (layers != NULL)
+		free(layers);
+	if (layer_ids != NULL)
+		free(layer_ids);
+	return rc;
+}
+
+static int comp_obj_del_layers(struct mio_obj *obj, int nr_layers)
+{
+	int i;
+	int rc = 0;
+	struct mio_comp_obj_layer *layers;
+	struct mio_obj_id *layer_ids;
+	struct mio_op op;
+
+	layers = malloc(nr_layers * sizeof(*layers));
+	layer_ids = malloc(nr_layers * sizeof(*layer_ids));
+	if (layers == NULL || layer_ids == NULL)
+		return -ENOMEM;
+	layer_ids_get(&obj->mo_id, nr_layers, layer_ids);
+
+	for (i = 0; i < nr_layers; i++)
+		/* No need to set priority for deleting layers. */
+		memcpy(&layers[i].mcol_oid, layer_ids + i,
+		       sizeof(struct mio_obj_id));
+
+	mio_op_init(&op);
+	rc = mio_composite_obj_del_layers(obj, nr_layers, layers, &op)? :
+	     mio_cmd_wait_on_op(&op);
+	mio_op_fini(&op);
+
+	free(layer_ids);
+	return rc;
+}
+
+static int comp_obj_list_layers(struct mio_obj *obj)
+{
+	int i;
+	int rc = 0;
+	struct mio_comp_obj_layout layout;
+	struct mio_op op;
+
+	mio_op_init(&op);
+	rc = mio_composite_obj_list_layers(obj, &layout, &op)? :
+	     mio_cmd_wait_on_op(&op);
+	mio_op_fini(&op);
+	if (rc < 0)
+		return rc;
+
+	for (i = 0; i < layout.mlo_nr_layers; i++) {
+		fprintf(stderr, "Layer %d -- ", i);
+		obj_id_printf(&layout.mlo_layers[i].mcol_oid);
+		fprintf(stderr, "\n");
+	}
+	return 0;
+}
+
+static int comp_obj_create(struct mio_obj_id *oid, struct mio_obj *obj)
+{
+	int rc;
+	struct mio_op op;
+
+	memset(&op, 0, sizeof op);
+	rc = obj_open(oid, obj);
+	if (rc == 0) {
+		fprintf(stderr, "Object exists!\n");
+		return -EEXIST;
+	} else if (rc == -ENOENT)
+		goto step_1;
+	else
+		return rc;
+
+step_1:
+	memset(&op, 0, sizeof op);
+	rc = mio_obj_create(oid, NULL, obj, &op)? :
+	     mio_cmd_wait_on_op(&op);
+	if (rc < 0)
+		return rc;
+
+	/* step_2: */
+	memset(&op, 0, sizeof op);
+	rc = mio_composite_obj_create(oid, obj, &op)? :
+	     mio_cmd_wait_on_op(&op);
+	if (rc < 0) {
+		mio_obj_close(obj);
+		return rc;
+	}
+
+	return rc;
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+	struct mio_cmd_obj_params comp_obj_params;
+	struct mio_obj obj;
+
+	mio_cmd_obj_args_init(argc, argv, &comp_obj_params, &comp_obj_usage);
+
+	rc = mio_init(comp_obj_params.cop_conf_fname);
+	if (rc < 0) {
+		fprintf(stderr, "mio_init failed! rc = %d\n", rc);
+		exit(EXIT_FAILURE);
+	}
+
+	fprintf(stderr, "MIO composite example ...\n");
+
+	fprintf(stderr, "1. Create a composite object ...");
+	rc = comp_obj_create(&comp_obj_params.cop_oid, &obj);
+	if (rc < 0) {
+		fprintf(stderr, "failed!\n");
+		goto exit;
+	} else
+		fprintf(stderr, "success!\n");
+
+	fprintf(stderr, "2. Add layers ...");
+	rc = comp_obj_add_layers(&obj, 3);
+	if (rc < 0) {
+		fprintf(stderr, "failed!\n");
+		goto exit;
+	} else
+		fprintf(stderr, "success!\n");
+
+	rc = comp_obj_list_layers(&obj);
+	if (rc < 0)
+		goto exit;
+
+	fprintf(stderr, "3. Add extents to layers ...");
+	rc = comp_obj_add_extents(&obj, 3, 1);
+	if (rc < 0) {
+		fprintf(stderr, "failed!\n");
+		goto exit;
+	} else
+		fprintf(stderr, "success!\n");
+
+	fprintf(stderr, "4. List extents of layers ...\n");
+	rc = comp_obj_list_extents(&obj, 3, 1);
+	if (rc < 0)
+		goto exit;
+
+	fprintf(stderr, "5. Del extents of layers ...");
+	rc = comp_obj_del_extents(&obj, 1, 1);
+	if (rc < 0) {
+		fprintf(stderr, "failed!\n");
+		goto exit;
+	} else
+		fprintf(stderr, "success!\n");
+
+	fprintf(stderr, "6. Del layers ...");
+	rc = comp_obj_del_layers(&obj, 1);
+	if (rc < 0) {
+		fprintf(stderr, "failed!\n");
+		goto exit;
+	} else
+		fprintf(stderr, "success!\n");
+
+	mio_obj_close(&obj);
+
+exit:
+	mio_fini();
+	mio_cmd_obj_args_fini(&comp_obj_params);
+	return rc;
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/mio_copy.c b/deps/mio/examples/mio_copy.c
new file mode 100644
index 0000000000000000000000000000000000000000..2f8e641deb9ca2dd3f4e793470f976a9a6331ae2
--- /dev/null
+++ b/deps/mio/examples/mio_copy.c
@@ -0,0 +1,81 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "obj.h"
+
+static void copy_usage(FILE *file, char *prog_name)
+{
+	fprintf(file, "Usage: %s [OPTION]... SOURCE\n"
+"Copy SOURCE to MIO.\n"
+"\n"
+"Mandatory arguments to long options are mandatory for short options too.\n"
+"  -o, --object         OID       ID of the mero object\n"
+"  -s, --block-size     INT       block size in bytes or with " \
+				 "suffix b/k/m/g/K/M/G (see --block-count)\n"
+"  -c, --block-count    INT       number of blocks to copy, can give with " \
+				 "suffix b/k/m/g/K/M/G (see --block-size)\n"
+"  -a, --async_mode               Set to async IO mode\n"
+"  -y, --mio_conf_file            MIO YAML configuration file\n"
+"  -h, --help                     shows this help text and exit\n"
+, prog_name);
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+	struct mio_cmd_obj_params copy_params;
+	char *src_fname = NULL;
+
+	mio_cmd_obj_args_init(argc, argv, &copy_params, &copy_usage);
+	if (argv[optind] != NULL)
+		src_fname = strdup(argv[optind]);
+	if (src_fname == NULL) {
+		fprintf(stderr, "Missed source file to copy !\n");
+		copy_usage(stderr, basename(argv[0]));
+		exit(-1);
+	}
+
+	rc = mio_init(copy_params.cop_conf_fname);
+	if (rc < 0) {
+		fprintf(stderr, "mio_init failed! rc = %d\n", rc);
+		exit(EXIT_FAILURE);
+	}
+
+	rc = copy_params.cop_async_mode?
+	     mio_cmd_obj_write_async(src_fname, &copy_params.cop_oid,
+				     copy_params.cop_block_size,
+				     copy_params.cop_block_count) :
+	     mio_cmd_obj_write(src_fname, &copy_params.cop_oid,
+			       copy_params.cop_block_size,
+			       copy_params.cop_block_count);
+	if (rc < 0)
+		fprintf(stderr, "mio_cmd_obj_write failed! rc = %d\n", rc);
+
+	mio_fini();
+	free(src_fname);
+	mio_cmd_obj_args_fini(&copy_params);
+	return rc;
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/mio_hint_set.c b/deps/mio/examples/mio_hint_set.c
new file mode 100644
index 0000000000000000000000000000000000000000..47cbe70b375b878abca699e89443a0804c4f28fd
--- /dev/null
+++ b/deps/mio/examples/mio_hint_set.c
@@ -0,0 +1,89 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "obj.h"
+
+static void hset_usage(FILE *file, char *prog_name)
+{
+	fprintf(file, "Usage: %s [OPTION]...\n"
+"Create an object.\n"
+"\n"
+"Mandatory arguments to long options are mandatory for short options too.\n"
+"  -o, --object         OID       ID of the mero object\n"
+"  -y, --mio_conf_file            MIO YAML configuration file\n"
+"  -h, --help                     shows this help text and exit\n"
+, prog_name);
+}
+
+static int obj_hint_set(struct mio_obj_id *oid)
+{
+	int i;
+	int rc;
+	struct mio_obj obj;
+	struct mio_hints hints;
+
+	memset(&obj, 0, sizeof obj);
+	rc = mio_cmd_obj_open(oid, &obj);
+	if (rc < 0)
+		return rc;
+	mio_hints_init(&hints);
+
+	for (i = 0; i < MIO_HINT_KEY_NUM; i++) {
+		rc = mio_hint_add(&hints, i, i);
+		if (rc < 0) {
+			fprintf(stderr, "Failed to set hint %s\n",
+				mio_hint_name(i));
+			break;
+		}
+	}
+	mio_obj_hints_set(&obj, &hints);
+
+	mio_hints_fini(&hints);
+	mio_cmd_obj_close(&obj);
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+	struct mio_cmd_obj_params hset_params;
+
+	mio_cmd_obj_args_init(argc, argv, &hset_params, &hset_usage);
+
+	rc = mio_init(hset_params.cop_conf_fname);
+	if (rc < 0) {
+		fprintf(stderr, "mio_init failed! rc = %d\n", rc);
+		exit(EXIT_FAILURE);
+	}
+
+	rc = obj_hint_set(&hset_params.cop_oid);
+	if (rc < 0)
+		fprintf(stderr, "mio_cmd_obj_hset failed! rc = %d\n", rc);
+
+	mio_fini();
+	mio_cmd_obj_args_fini(&hset_params);
+	return rc;
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/mio_hint_stat.c b/deps/mio/examples/mio_hint_stat.c
new file mode 100644
index 0000000000000000000000000000000000000000..1fc617c30dc71d03f032284362daca2884723577
--- /dev/null
+++ b/deps/mio/examples/mio_hint_stat.c
@@ -0,0 +1,96 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <asm/byteorder.h>
+
+#include "obj.h"
+
+static void hstat_usage(FILE *file, char *prog_name)
+{
+	fprintf(file, "Usage: %s [OPTION]...\n"
+"Create an object.\n"
+"\n"
+"Mandatory arguments to long options are mandatory for short options too.\n"
+"  -o, --object         OID       ID of the mero object\n"
+"  -y, --mio_conf_file            MIO YAML configuration file\n"
+"  -h, --help                     shows this help text and exit\n"
+, prog_name);
+}
+
+static int obj_hint_stat(struct mio_obj_id *oid)
+{
+	int i;
+	int rc;
+	char *hname;
+	uint64_t hvalue;
+	struct mio_obj obj;
+	struct mio_hints hints;
+
+	memset(&obj, 0, sizeof obj);
+	rc = mio_cmd_obj_open(oid, &obj);
+	if (rc < 0)
+		return rc;
+
+	memset(&hints, 0, sizeof hints);
+	rc = mio_obj_hints_get(&obj, &hints);
+	if (rc < 0)
+		return rc;
+
+	for (i = 0; i < MIO_HINT_KEY_NUM; i++) {
+		hname = mio_hint_name(i);
+		rc = mio_hint_lookup(&hints, i, &hvalue);
+		if (rc < 0)
+			continue;
+
+		obj_id_printf(oid);
+		fprintf(stderr, "\t%s\t%"PRIu64"\n", hname, hvalue);
+	}
+
+	mio_cmd_obj_close(&obj);
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+	struct mio_cmd_obj_params hstat_params;
+
+	mio_cmd_obj_args_init(argc, argv, &hstat_params, &hstat_usage);
+
+	rc = mio_init(hstat_params.cop_conf_fname);
+	if (rc < 0) {
+		fprintf(stderr, "mio_init failed! rc = %d\n", rc);
+		exit(EXIT_FAILURE);
+	}
+
+	rc = obj_hint_stat(&hstat_params.cop_oid);
+	if (rc < 0)
+		fprintf(stderr, "mio_cmd_obj_hstat failed! rc = %d\n", rc);
+
+	mio_fini();
+	mio_cmd_obj_args_fini(&hstat_params);
+	return rc;
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/mio_kvs_create_set.c b/deps/mio/examples/mio_kvs_create_set.c
new file mode 100644
index 0000000000000000000000000000000000000000..5b42ac8d8638aa79d8079962e7ce1c55c01eafa6
--- /dev/null
+++ b/deps/mio/examples/mio_kvs_create_set.c
@@ -0,0 +1,61 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "kvs.h"
+
+static void create_set_usage(FILE *file, char *prog_name)
+{
+	fprintf(file, "Usage: %s [OPTION]...\n"
+"Create a key/value set.\n"
+"\n"
+"Mandatory arguments to long options are mandatory for short options too.\n"
+"  -k, --kvset         ID       ID of the MIO key/value set \n"
+"  -y, --mio_conf_file          MIO YAML configuration file\n"
+"  -h, --help                   shows this help text and exit\n"
+, prog_name);
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+	struct mio_cmd_kvs_params create_set_params;
+
+	mio_cmd_kvs_args_init(argc, argv, &create_set_params, &create_set_usage);
+
+	rc = mio_init(create_set_params.ckp_conf_fname);
+	if (rc < 0) {
+		fprintf(stderr, "mio_init failed! rc = %d\n", rc);
+		exit(EXIT_FAILURE);
+	}
+
+	rc = mio_cmd_kvs_create_set(&create_set_params.ckp_kid);
+	if (rc < 0)
+		fprintf(stderr, "mio_cmd_kvs_create_set failed! rc = %d\n", rc);
+
+	mio_fini();
+	mio_cmd_kvs_args_fini(&create_set_params);
+	return rc;
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/mio_kvs_del_pairs.c b/deps/mio/examples/mio_kvs_del_pairs.c
new file mode 100644
index 0000000000000000000000000000000000000000..c599dc4e693b2acfa5a6c588018ce65cff7a1819
--- /dev/null
+++ b/deps/mio/examples/mio_kvs_del_pairs.c
@@ -0,0 +1,73 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "kvs.h"
+
+static void del_usage(FILE *file, char *prog_name)
+{
+	fprintf(file, "Usage: %s [OPTION]...\n"
+"Insert pairs to a key/value set.\n"
+"\n"
+"Mandatory arguments to long options are mandatory for short options too.\n"
+"  -k, --kvset         ID        ID of the mero object\n"
+"  -s, --startkey      No.       The first serial number of keys\n"
+"  -n, --pairs         nr_pairs  The number of key/value pairs to insert\n"
+"  -y, --mio_conf_file           MIO YAML configuration file\n"
+"  -h, --help                    shows this help text and exit\n"
+, prog_name);
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+	struct mio_cmd_kvs_params del_params;
+	FILE *log = NULL;
+
+	mio_cmd_kvs_args_init(argc, argv, &del_params, &del_usage);
+	if (del_params.ckp_log != NULL) {
+		log = fopen(del_params.ckp_log, "w");
+		if (log == NULL)
+			exit(EXIT_FAILURE);
+	}
+
+	rc = mio_init(del_params.ckp_conf_fname);
+	if (rc < 0) {
+		fprintf(stderr, "mio_init failed! rc = %d\n", rc);
+		exit(EXIT_FAILURE);
+	}
+
+	rc = mio_cmd_kvs_del_pairs(&del_params.ckp_kid,
+				   del_params.ckp_start_kno,
+				   del_params.ckp_nr_pairs, log);
+	if (rc < 0)
+		fprintf(stderr, "mio_cmd_kvs_put failed! rc = %d\n", rc);
+
+	mio_fini();
+	if (log != NULL)
+		fclose(log);
+	mio_cmd_kvs_args_fini(&del_params);
+	return rc;
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/mio_kvs_del_set.c b/deps/mio/examples/mio_kvs_del_set.c
new file mode 100644
index 0000000000000000000000000000000000000000..5cbf9baa8e319b5b3eda72f7f22095a6458af659
--- /dev/null
+++ b/deps/mio/examples/mio_kvs_del_set.c
@@ -0,0 +1,61 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "kvs.h"
+
+static void del_set_usage(FILE *file, char *prog_name)
+{
+	fprintf(file, "Usage: %s [OPTION]...\n"
+"Create a key/value set.\n"
+"\n"
+"Mandatory arguments to long options are mandatory for short options too.\n"
+"  -k, --kvset         ID       ID of the mero object\n"
+"  -y, --mio_conf_file          MIO YAML configuration file\n"
+"  -h, --help                   shows this help text and exit\n"
+, prog_name);
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+	struct mio_cmd_kvs_params del_set_params;
+
+	mio_cmd_kvs_args_init(argc, argv, &del_set_params, &del_set_usage);
+
+	rc = mio_init(del_set_params.ckp_conf_fname);
+	if (rc < 0) {
+		fprintf(stderr, "mio_init failed! rc = %d\n", rc);
+		exit(EXIT_FAILURE);
+	}
+
+	rc = mio_cmd_kvs_delete_set(&del_set_params.ckp_kid);
+	if (rc < 0)
+		fprintf(stderr, "mio_cmd_kvs_create_set failed! rc = %d\n", rc);
+
+	mio_fini();
+	mio_cmd_kvs_args_fini(&del_set_params);
+	return rc;
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/mio_kvs_insert.c b/deps/mio/examples/mio_kvs_insert.c
new file mode 100644
index 0000000000000000000000000000000000000000..29ffde2226a15685d8d2d727e096171231357e33
--- /dev/null
+++ b/deps/mio/examples/mio_kvs_insert.c
@@ -0,0 +1,73 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "kvs.h"
+
+static void put_usage(FILE *file, char *prog_name)
+{
+	fprintf(file, "Usage: %s [OPTION]...\n"
+"Insert pairs to a key/value set.\n"
+"\n"
+"Mandatory arguments to long options are mandatory for short options too.\n"
+"  -k, --kvset         ID        ID of the mero object\n"
+"  -s, --startkey      No.       The first serial number of keys\n"
+"  -n, --pairs         nr_pairs  The number of key/value pairs to insert\n"
+"  -y, --mio_conf_file           MIO YAML configuration file\n"
+"  -h, --help                    shows this help text and exit\n"
+, prog_name);
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+	struct mio_cmd_kvs_params put_params;
+	FILE *log = NULL;
+
+	mio_cmd_kvs_args_init(argc, argv, &put_params, &put_usage);
+	if (put_params.ckp_log != NULL) {
+		log = fopen(put_params.ckp_log, "w");
+		if (log == NULL)
+			exit(EXIT_FAILURE);
+	}
+
+	rc = mio_init(put_params.ckp_conf_fname);
+	if (rc < 0) {
+		fprintf(stderr, "mio_init failed! rc = %d\n", rc);
+		exit(EXIT_FAILURE);
+	}
+
+	rc = mio_cmd_kvs_insert_pairs(&put_params.ckp_kid,
+				      put_params.ckp_start_kno,
+				      put_params.ckp_nr_pairs, log);
+	if (rc < 0)
+		fprintf(stderr, "mio_cmd_kvs_put failed! rc = %d\n", rc);
+
+	mio_fini();
+	if (log != NULL)
+		fclose(log);
+	mio_cmd_kvs_args_fini(&put_params);
+	return rc;
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/mio_kvs_retrieve.c b/deps/mio/examples/mio_kvs_retrieve.c
new file mode 100644
index 0000000000000000000000000000000000000000..d55c88a55f8ece44d1d93f32b6abffdf1ddc33ed
--- /dev/null
+++ b/deps/mio/examples/mio_kvs_retrieve.c
@@ -0,0 +1,74 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "kvs.h"
+
+static void get_usage(FILE *file, char *prog_name)
+{
+	fprintf(file, "Usage: %s [OPTION]...\n"
+"Insert pairs to a key/value set.\n"
+"\n"
+"Mandatory arguments to long options are mandatory for short options too.\n"
+"  -k, --kvset         ID        ID of the mero object\n"
+"  -s, --startkey      No.       The first serial number of keys\n"
+"  -n, --pairs         nr_pairs  The number of key/value pairs to insert\n"
+"  -y, --mio_conf_file conf      MIO YAML configuration file\n"
+"  -l, --log           log       Log file to record key/value pairs\n"
+"  -h, --help                    shows this help text and exit\n"
+, prog_name);
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+	struct mio_cmd_kvs_params get_params;
+	FILE *log = NULL;
+
+	mio_cmd_kvs_args_init(argc, argv, &get_params, &get_usage);
+	if (get_params.ckp_log != NULL) {
+		log = fopen(get_params.ckp_log, "w");
+		if (log == NULL)
+			exit(EXIT_FAILURE);
+	}
+
+	rc = mio_init(get_params.ckp_conf_fname);
+	if (rc < 0) {
+		fprintf(stderr, "mio_init failed! rc = %d\n", rc);
+		exit(EXIT_FAILURE);
+	}
+
+	rc = mio_cmd_kvs_retrieve_pairs(&get_params.ckp_kid,
+					get_params.ckp_start_kno,
+					get_params.ckp_nr_pairs, log);
+	if (rc < 0)
+		fprintf(stderr, "mio_cmd_kvs_put failed! rc = %d\n", rc);
+
+	mio_fini();
+	if(log != NULL)
+		fclose(log);
+	mio_cmd_kvs_args_fini(&get_params);
+	return rc;
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/mio_rw_threads.c b/deps/mio/examples/mio_rw_threads.c
new file mode 100644
index 0000000000000000000000000000000000000000..af8ce42b61878c5f80f8fb214037d0b997c876a1
--- /dev/null
+++ b/deps/mio/examples/mio_rw_threads.c
@@ -0,0 +1,604 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
+#include <assert.h>
+#include <asm/byteorder.h>
+#include <pthread.h>
+#include <openssl/md5.h>
+
+#include "obj.h"
+#include "helpers.h"
+
+struct rwt_obj_todo {
+	struct mio_obj_id ot_oid;
+	uint32_t ot_block_size;
+	uint32_t ot_block_count;
+
+	unsigned char ot_md5sum_write[MD5_DIGEST_LENGTH];
+	unsigned char ot_md5sum_read[MD5_DIGEST_LENGTH];
+	struct rwt_obj_todo *ot_next;
+};
+
+struct rwt_obj_todo_list {
+	pthread_cond_t otl_cond;
+	pthread_mutex_t otl_mutex;
+
+	int otl_nr_in_list;
+	int otl_nr_todo;
+	int otl_nr_done;
+	int otl_nr_failed;
+	int otl_nr_matched;
+	struct rwt_obj_todo otl_head;
+};
+
+static struct rwt_obj_todo_list obj_to_write_list;
+static struct rwt_obj_todo_list obj_to_read_list;
+
+enum {
+	RWT_MAX_RAND_NUM = 1024
+};
+
+static pthread_t **read_threads = NULL;
+static pthread_t **write_threads = NULL;
+static int *read_tids = NULL;
+static int *write_tids = NULL;
+
+/**
+ * rwt - Read Write Threads
+ */
+static void rw_threads_usage(FILE *file, char *prog_name)
+{
+	fprintf(file, "Usage: %s [OPTION]\n"
+"Example for current Read/Write threads.\n"
+"\n"
+"  -o, --object         OID       Starting object ID\n"
+"  -n, --nr_objs        INT       The number of objects\n"
+"  -s, --block-size     INT       block size in bytes or with " \
+				 "suffix b/k/m/g/K/M/G (see --block-count)\n"
+"  -c, --block-count    INT       number of blocks written to an object with "\
+				 "suffix b/k/m/g/K/M/G (see --block-size)\n"
+"  -t, --threads                  Number of threads\n"
+"  -y, --mio_conf                 MIO YAML configuration file\n"
+"  -h, --help                     shows this help text and exit\n"
+, prog_name);
+}
+
+static int
+rwt_thread_init(pthread_t **ret_th, void* (*func)(void *), void *args)
+{
+	int rc;
+	pthread_t *th;
+
+	th = (pthread_t *) malloc(sizeof(*th));
+	if (th == NULL)
+		return -ENOMEM;
+
+	rc = pthread_create(th, NULL, func, args);
+	if (rc == 0)
+		*ret_th = th;
+
+	return -rc;
+}
+
+static int rwt_thread_join(pthread_t *th)
+{
+	int rc = 0;
+	void *result;
+
+	if (pthread_join(*th, &result) == 0) {
+		if (result) {
+			rc = *((int *)result);
+			free(result);
+		}
+		return rc;
+	} else
+		return -1;
+}
+
+static void rwt_thread_fini(pthread_t *th)
+{
+	free(th);
+	return;
+}
+
+static void 
+rwt_generate_data(uint32_t bcount, uint32_t bsize,
+		  struct mio_iovec *data, MD5_CTX *md5_ctx)
+{
+	int i;
+	int j;
+	uint32_t rand;
+	char *ptr;
+
+	for (i = 0; i < bcount; i++) {
+		rand = mio_cmd_random(RWT_MAX_RAND_NUM);
+		ptr = data[i].miov_base;
+		for (j = 0; j < bsize/sizeof(rand); j++) {
+			memcpy(ptr, &rand, sizeof(rand));
+			ptr += sizeof(rand);
+		};
+		MD5_Update(md5_ctx, data[i].miov_base, bsize);
+	}
+}
+
+static bool rwt_obj_verify_md5sums(struct rwt_obj_todo *todo)
+{
+	int i;
+	int rc;
+
+	obj_id_printf(&todo->ot_oid);	
+	printf("\t");
+	for (i = 0; i < MD5_DIGEST_LENGTH; i++)
+		printf("%02x", todo->ot_md5sum_write[i]);
+	printf("\t");
+	for (i = 0; i < MD5_DIGEST_LENGTH; i++)
+		printf("%02x", todo->ot_md5sum_read[i]);
+	printf("\n");
+
+	rc = memcmp(todo->ot_md5sum_write,
+		    todo->ot_md5sum_read,
+		    MD5_DIGEST_LENGTH);
+
+	return rc == 0? true : false;
+}
+
+static int rwt_obj_write(struct rwt_obj_todo *todo)
+{
+	int rc = 0;
+	uint32_t bcount;
+	uint32_t block_size;
+	uint32_t block_count;
+	uint64_t last_index;
+	struct mio_iovec *data;
+	struct mio_obj obj;
+	struct mio_obj_id *oid = &todo->ot_oid;
+	MD5_CTX md5_ctx;
+
+	block_size = todo->ot_block_size;
+	block_count = todo->ot_block_count;
+
+	/* Create the target object if it doesn't exist. */
+	memset(&obj, 0, sizeof obj);
+	rc = obj_create(oid, &obj);
+	if (rc < 0)
+		return rc;
+
+	last_index = 0;
+	MD5_Init(&md5_ctx);
+	while (block_count > 0) {
+		bcount = (block_count > MIO_CMD_MAX_BLOCK_COUNT)?
+			  MIO_CMD_MAX_BLOCK_COUNT:block_count;
+		rc = obj_alloc_iovecs(&data, bcount, block_size, last_index);
+		if (rc != 0)
+			break;
+		rwt_generate_data(bcount, block_size, data, &md5_ctx);
+
+		rc = obj_write(&obj, bcount, data);
+		if (rc != 0) {
+			fprintf(stderr, "Writing to object failed!\n");
+			obj_cleanup_iovecs(data);
+			break;
+		}
+
+		obj_cleanup_iovecs(data);
+		block_count -= bcount;
+		last_index += bcount * block_size;
+	}
+	MD5_Final(todo->ot_md5sum_write, &md5_ctx);
+
+	mio_obj_close(&obj);
+	return rc;
+}
+
+static int rwt_obj_read(struct rwt_obj_todo *todo)
+{
+	int i;
+	int rc = 0;
+	uint32_t bcount;
+	uint32_t block_size;
+	uint32_t block_count;
+	uint64_t last_index;
+	struct mio_iovec *data;
+	struct mio_obj obj;
+	struct mio_obj_id *oid = &todo->ot_oid;
+	MD5_CTX md5_ctx;
+
+	block_size = todo->ot_block_size;
+	block_count = todo->ot_block_count;
+
+	memset(&obj, 0, sizeof obj);
+	rc = obj_open(oid, &obj);
+	if (rc < 0)
+		goto dest_close;
+
+	last_index = 0;
+	MD5_Init(&md5_ctx);
+	while (block_count > 0) {
+		bcount = (block_count > MIO_CMD_MAX_BLOCK_COUNT)?
+			  MIO_CMD_MAX_BLOCK_COUNT:block_count;
+		rc = obj_alloc_iovecs(&data, bcount, block_size, last_index);
+		if (rc != 0)
+			break;
+
+		/* Read data from obj. */
+		rc = obj_read(&obj, bcount, data);
+		if (rc != 0) {
+			fprintf(stderr, "Failed in reading from file!\n");
+			obj_cleanup_iovecs(data);
+			break;
+		}
+
+		/* Calculate md5sum from data. */
+		for (i = 0; i < bcount; i++)
+			MD5_Update(&md5_ctx, data[i].miov_base, block_size);
+
+		obj_cleanup_iovecs(data);
+		block_count -= bcount;
+		last_index += bcount * block_size;
+	}
+	MD5_Final(todo->ot_md5sum_read, &md5_ctx);
+
+	mio_obj_close(&obj);
+
+dest_close:
+	return rc;
+}
+
+
+static void* rwt_writer(void *in)
+{
+	int rc;
+	struct rwt_obj_todo *todo;	
+	struct mio_thread thread;
+
+	mio_thread_init(&thread);
+
+	/* main loop */
+	while(1) {
+		pthread_mutex_lock(&obj_to_write_list.otl_mutex);
+		if (obj_to_write_list.otl_nr_in_list == 0) {
+			pthread_mutex_unlock(&obj_to_write_list.otl_mutex);
+			break;
+		}
+		todo = obj_to_write_list.otl_head.ot_next;
+		assert(todo != NULL);
+		obj_to_write_list.otl_head.ot_next = todo->ot_next;
+		todo->ot_next = NULL;
+		obj_to_write_list.otl_nr_in_list--;
+		pthread_mutex_unlock(&obj_to_write_list.otl_mutex);
+
+		rc = rwt_obj_write(todo);
+
+		/* WRITE complete, add to the READ todo list. */
+		pthread_mutex_lock(&obj_to_read_list.otl_mutex);
+		if (rc == 0) {
+			todo->ot_next = obj_to_read_list.otl_head.ot_next;
+			obj_to_read_list.otl_head.ot_next = todo;
+			obj_to_read_list.otl_nr_in_list++;
+		} else if (rc < 0) {
+			fprintf(stderr, "Failed to write to object! \n");
+			obj_to_read_list.otl_nr_failed++;
+		}
+		pthread_cond_broadcast(&obj_to_read_list.otl_cond);
+		pthread_mutex_unlock(&obj_to_read_list.otl_mutex);
+	}
+
+	mio_thread_fini(&thread);
+	
+	pthread_mutex_lock(&obj_to_read_list.otl_mutex);
+	pthread_cond_broadcast(&obj_to_read_list.otl_cond);
+	pthread_mutex_unlock(&obj_to_read_list.otl_mutex);
+
+	return NULL;
+}
+
+static void* rwt_reader(void *in)
+{
+	int rc = 0;
+	bool matched = false;
+	struct rwt_obj_todo *todo;	
+	struct mio_thread thread;
+	int tid = *((int *)in);
+	bool read_all_done = false;
+
+	mio_thread_init(&thread);
+
+	if (tid == 1)
+		fprintf(stderr, "%10s\t%32s\t%32s\n",
+			"Object ID", "WRITE MD5", "READ MD5");
+
+	/* main loop */
+	while(1) {
+		pthread_mutex_lock(&obj_to_read_list.otl_mutex);
+		while (obj_to_read_list.otl_nr_in_list == 0) {
+			if ((obj_to_read_list.otl_nr_done + 
+			     obj_to_read_list.otl_nr_failed) ==
+			    obj_to_read_list.otl_nr_todo) {
+				read_all_done = true;
+				pthread_mutex_unlock(
+					&obj_to_read_list.otl_mutex);
+				goto exit;
+			}
+
+			pthread_cond_wait(&obj_to_read_list.otl_cond,
+					  &obj_to_read_list.otl_mutex);
+		}
+		todo = obj_to_read_list.otl_head.ot_next;
+		obj_to_read_list.otl_head.ot_next = todo->ot_next;
+		todo->ot_next = NULL;
+		obj_to_read_list.otl_nr_in_list--;
+		pthread_mutex_unlock(&obj_to_read_list.otl_mutex);
+
+		rc = rwt_obj_read(todo);
+
+		pthread_mutex_lock(&obj_to_read_list.otl_mutex);
+		if (rc < 0) {
+			fprintf(stderr, "Failed to write to object! \n");
+			obj_to_read_list.otl_nr_failed++;
+		} else {
+			matched = rwt_obj_verify_md5sums(todo);
+			if (matched)
+				obj_to_read_list.otl_nr_matched++;
+			obj_to_read_list.otl_nr_done++;
+			if ((obj_to_read_list.otl_nr_done +
+			     obj_to_read_list.otl_nr_failed) ==
+		    	    obj_to_read_list.otl_nr_todo)
+				read_all_done = true;	
+		}
+		pthread_mutex_unlock(&obj_to_read_list.otl_mutex);
+
+		obj_rm(&todo->ot_oid);
+		free(todo);
+
+exit:
+		if (read_all_done)
+			break;
+	}
+
+	mio_thread_fini(&thread);
+	
+	pthread_mutex_lock(&obj_to_read_list.otl_mutex);
+	pthread_cond_broadcast(&obj_to_read_list.otl_cond);
+	pthread_mutex_unlock(&obj_to_read_list.otl_mutex);
+
+	return NULL;
+}
+
+static void
+rwt_set_obj_id(struct rwt_obj_todo *todo, struct mio_obj_id *st_oid, int idx)
+{
+	uint64_t u1;
+	uint64_t u2;
+	uint64_t n1;
+	uint64_t n2;
+
+	memcpy(&u1, st_oid->moi_bytes, sizeof u1);
+	memcpy(&u2, st_oid->moi_bytes + sizeof u1, sizeof u2);
+	u1 = __be64_to_cpu(u1);
+	u2 = __be64_to_cpu(u2);
+
+	n1 = u1 + idx;
+	n2 = u2;
+	n1 = __cpu_to_be64(n1);
+	n2 = __cpu_to_be64(n2);
+	memcpy(todo->ot_oid.moi_bytes, &n1, sizeof n1);
+	memcpy(todo->ot_oid.moi_bytes + sizeof n1, &n2, sizeof n2);
+}
+
+static void rwt_todo_lists_fini()
+{
+	int i;
+	struct rwt_obj_todo *todo;
+
+	pthread_mutex_destroy(&obj_to_read_list.otl_mutex);
+	pthread_cond_destroy(&obj_to_read_list.otl_cond);
+	pthread_mutex_destroy(&obj_to_write_list.otl_mutex);
+	pthread_cond_destroy(&obj_to_write_list.otl_cond);
+
+	for (i = 0; i < obj_to_read_list.otl_nr_in_list; i++) {
+		todo = obj_to_read_list.otl_head.ot_next;
+		if (todo == NULL)
+			break;
+		obj_to_read_list.otl_head.ot_next = todo->ot_next;
+		free(todo);
+	}
+
+	for (i = 0; i < obj_to_write_list.otl_nr_in_list; i++) {
+		todo = obj_to_write_list.otl_head.ot_next;
+		if (todo == NULL)
+			break;
+		obj_to_write_list.otl_head.ot_next = todo->ot_next;
+
+		free(todo);
+	}
+}
+
+static int rwt_todo_lists_init(struct mio_obj_id *st_oid, int nr_objs,
+			      uint32_t block_size, uint32_t block_count)
+{
+	int i;
+	int rc = 0;
+	struct rwt_obj_todo *todo;
+
+	memset(&obj_to_read_list, 0, sizeof(obj_to_read_list));
+	pthread_cond_init(&obj_to_read_list.otl_cond, NULL);
+	pthread_mutex_init(&obj_to_read_list.otl_mutex, NULL);
+	obj_to_read_list.otl_nr_todo = nr_objs;
+
+	memset(&obj_to_write_list, 0, sizeof(obj_to_write_list));
+	pthread_cond_init(&obj_to_write_list.otl_cond, NULL);
+	pthread_mutex_init(&obj_to_write_list.otl_mutex, NULL);
+	obj_to_write_list.otl_nr_todo = nr_objs;
+
+	/*
+ 	 * Insert all objects into the WRITE todo list.
+ 	 */
+	for (i = 0; i < nr_objs; i++) {
+		todo = malloc(sizeof(struct rwt_obj_todo));
+		if (todo == NULL) {
+			rc = -ENOMEM;
+			break;
+		}
+
+		rwt_set_obj_id(todo, st_oid, i);
+		todo->ot_block_size = block_size;
+		todo->ot_block_count = block_count;
+		todo->ot_next = obj_to_write_list.otl_head.ot_next;
+		obj_to_write_list.otl_head.ot_next = todo;
+		obj_to_write_list.otl_nr_in_list++;
+	}
+	if (rc < 0)
+		rwt_todo_lists_fini();
+
+	return rc;
+}
+static void rwt_report()
+{
+	fprintf(stderr, "[Final Report] \t");
+	fprintf(stderr, "Objects TODO: %d\t", obj_to_read_list.otl_nr_todo);
+	fprintf(stderr, "Completed: %d\t", obj_to_read_list.otl_nr_done);
+	fprintf(stderr, "Failed: %d\t", obj_to_read_list.otl_nr_failed);
+	fprintf(stderr, "Matched: %d\t", obj_to_read_list.otl_nr_matched);
+	fprintf(stderr, "\n");
+}
+
+static int
+mio_rwt_start(int nr_threads, struct mio_obj_id *st_oid, int nr_objs,
+	      uint32_t block_size, uint32_t block_count)
+{
+	int i;
+	int rc = 0;
+
+	rwt_todo_lists_init(st_oid, nr_objs, block_size, block_count);
+	
+	/*
+	 * For simplicity, the same number of READ and WRITE threads
+	 * are created.
+	 */
+	read_threads = malloc(nr_threads * sizeof(*read_threads));
+	write_threads = malloc(nr_threads * sizeof(*write_threads));
+	read_tids = malloc(nr_threads * sizeof(*read_tids));
+	write_tids = malloc(nr_threads * sizeof(*write_tids));
+	if (read_threads == NULL || write_threads == NULL || 
+	    read_tids == NULL || write_tids == NULL) {
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	for (i = 0; i < nr_threads; i++) {
+		write_tids[i] = i;
+		rc = rwt_thread_init(
+			write_threads + i, &rwt_writer, write_tids + i);
+		if (rc < 0)
+			goto error;
+	}
+
+	for (i = 0; i < nr_threads; i++) {
+		read_tids[i] = i;
+		rc = rwt_thread_init(
+			read_threads + i, &rwt_reader, read_tids + i);
+		if (rc < 0)
+			goto error;
+	}
+
+	return 0;
+
+error:
+	if (read_threads)
+		free(read_threads);
+	if (write_threads)
+		free(write_threads);
+	if (read_tids)
+		free(read_tids);
+	if (write_tids)
+		free(write_tids);
+	return rc;
+}
+
+static void mio_rwt_stop(int nr_threads)
+{
+	int i;
+
+	for (i = 0; i < nr_threads; i++) {
+		if (write_threads[i] == NULL)
+			break;
+
+		rwt_thread_join(write_threads[i]);
+		rwt_thread_fini(write_threads[i]);
+		write_threads[i] = NULL;
+	}
+
+	for (i = 0; i < nr_threads; i++) {
+		if (read_threads[i] == NULL)
+			break;
+
+		rwt_thread_join(read_threads[i]);
+		rwt_thread_fini(read_threads[i]);
+		read_threads[i] = NULL;
+
+	}
+	free(read_threads);
+	free(write_threads);
+	free(read_tids);
+	free(write_tids);
+
+	rwt_report();	
+
+	rwt_todo_lists_fini();
+
+	return;
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+	struct mio_cmd_obj_params rwt_params;
+
+	mio_cmd_obj_args_init(argc, argv, &rwt_params, &rw_threads_usage);
+
+	rc = mio_init(rwt_params.cop_conf_fname);
+	if (rc < 0) {
+		fprintf(stderr, "mio_init failed! errno = %d\n", rc);
+		goto exit;
+	}
+
+	rc = mio_rwt_start(rwt_params.cop_nr_threads, &rwt_params.cop_oid,
+			   rwt_params.cop_nr_objs,
+			   rwt_params.cop_block_size,
+			   rwt_params.cop_block_count);
+	if (rc < 0) {
+		fprintf(stderr, "Failed to start threads! errno = %d\n", rc);
+		goto exit;
+	}
+
+	mio_rwt_stop(rwt_params.cop_nr_threads);
+
+exit:
+	mio_fini();
+	mio_cmd_obj_args_fini(&rwt_params);
+	return rc;
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/mio_touch.c b/deps/mio/examples/mio_touch.c
new file mode 100644
index 0000000000000000000000000000000000000000..3dfded320795a3bbb0c99370cb2c597217a4ee09
--- /dev/null
+++ b/deps/mio/examples/mio_touch.c
@@ -0,0 +1,61 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "obj.h"
+
+static void touch_usage(FILE *file, char *prog_name)
+{
+	fprintf(file, "Usage: %s [OPTION]...\n"
+"Create an object.\n"
+"\n"
+"Mandatory arguments to long options are mandatory for short options too.\n"
+"  -o, --object         OID       ID of the mero object\n"
+"  -y, --mio_conf_file            MIO YAML configuration file\n"
+"  -h, --help                     shows this help text and exit\n"
+, prog_name);
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+	struct mio_cmd_obj_params touch_params;
+
+	mio_cmd_obj_args_init(argc, argv, &touch_params, &touch_usage);
+
+	rc = mio_init(touch_params.cop_conf_fname);
+	if (rc < 0) {
+		fprintf(stderr, "mio_init failed! rc = %d\n", rc);
+		exit(EXIT_FAILURE);
+	}
+
+	rc = mio_cmd_obj_touch(&touch_params.cop_oid);
+	if (rc < 0)
+		fprintf(stderr, "mio_cmd_obj_touch failed! rc = %d\n", rc);
+
+	mio_fini();
+	mio_cmd_obj_args_fini(&touch_params);
+	return rc;
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/mio_unlink.c b/deps/mio/examples/mio_unlink.c
new file mode 100644
index 0000000000000000000000000000000000000000..98693161308ec318bec7aeb299b6434358d56a62
--- /dev/null
+++ b/deps/mio/examples/mio_unlink.c
@@ -0,0 +1,61 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "obj.h"
+
+static void unlink_usage(FILE *file, char *prog_name)
+{
+	fprintf(file, "Usage: %s [OPTION]...\n"
+"Remove an object.\n"
+"\n"
+"Mandatory arguments to long options are mandatory for short options too.\n"
+"  -o, --object         OID       ID of the mero object\n"
+"  -y, --mio_conf_file            MIO YAML configuration file\n"
+"  -h, --help                     shows this help text and exit\n"
+, prog_name);
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+	struct mio_cmd_obj_params unlink_params;
+
+	mio_cmd_obj_args_init(argc, argv, &unlink_params, &unlink_usage);
+
+	rc = mio_init(unlink_params.cop_conf_fname);
+	if (rc < 0) {
+		fprintf(stderr, "mio_init failed! rc = %d\n", rc);
+		exit(EXIT_FAILURE);
+	}
+
+	rc = mio_cmd_obj_unlink(&unlink_params.cop_oid);
+	if (rc < 0)
+		fprintf(stderr, "mio_cmd_obj_unlink failed! rc = %d\n", rc);
+
+	mio_fini();
+	mio_cmd_obj_args_fini(&unlink_params);
+	return rc;
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/obj.c b/deps/mio/examples/obj.c
new file mode 100644
index 0000000000000000000000000000000000000000..9f0892fb10b2f923763c82c03223b4b0f6e139a8
--- /dev/null
+++ b/deps/mio/examples/obj.c
@@ -0,0 +1,303 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <asm/byteorder.h>
+#include <pthread.h>
+
+#include "obj.h"
+#include "helpers.h"
+
+int obj_alloc_iovecs(struct mio_iovec **data, uint32_t bcount,
+		     uint32_t bsize, uint64_t offset)
+{
+	int i;
+	int rc;
+	struct mio_iovec *iovecs;
+	char *base;
+
+	iovecs = mio_mem_alloc(bcount * sizeof(*iovecs));
+	base = mio_mem_alloc(bcount * bsize);
+	if (iovecs == NULL || base == NULL) {
+		fprintf(stderr, "Can't allocate memory!\n");
+		rc = -ENOMEM;
+		goto error_exit;
+	}
+
+	for(i = 0; i < bcount; i++) {
+		iovecs[i].miov_base = base + i * bsize;
+		iovecs[i].miov_off = offset + i * bsize; 
+		iovecs[i].miov_len = bsize;
+	}
+	*data = iovecs;
+	return 0;
+
+error_exit:
+	mio_mem_free(base);
+	mio_mem_free(iovecs);
+	return rc;
+}
+
+void obj_cleanup_iovecs(struct mio_iovec *data)
+{
+	mio_mem_free(data[0].miov_base);
+	mio_mem_free(data);
+}
+
+int obj_read_data_from_file(FILE *fp, uint32_t bcount, uint32_t bsize,
+			    struct mio_iovec *data)
+{
+	int i;
+	int rc;
+
+	for (i = 0; i < bcount; i++) {
+		rc = fread(data[i].miov_base, bsize, 1, fp);
+		if (rc != 1)
+			break;
+	}
+	return i;
+}
+
+int obj_write_data_to_file(FILE *fp, bool console,
+			   uint32_t bcount, struct mio_iovec *data)
+{
+	int i = 0;
+	int j;
+	int rc;
+
+	if (fp != NULL) {
+		fseek(fp, data[0].miov_off, SEEK_SET);
+		for(i = 0; i < bcount; i++) {
+			rc = fwrite(data[i].miov_base, data[i].miov_len, 1, fp);
+			if (rc != 1) {
+				fprintf(stderr, "Writing to object failed!\n");
+				break;
+			}
+		}
+	}
+
+	if (console) {
+		/* putchar the output */
+		for (i = 0; i < bcount; ++i) {
+			for (j = 0; j < data[i].miov_len; ++j)
+				putchar(data[i].miov_base[j]);
+		}
+
+	}
+
+	return i;
+}
+
+static int obj_id_sscanf(char *idstr, struct mio_obj_id *oid)
+{
+	int rc;
+	int n;
+	uint64_t u1;
+	uint64_t u2;
+
+	rc = sscanf(idstr, "%"SCNx64" : %"SCNx64" %n", &u1, &u2, &n);
+	if (rc < 0)
+		return rc;
+	u1 = __cpu_to_be64(u1);
+	u2 = __cpu_to_be64(u2);
+
+	memcpy(oid->moi_bytes, &u1, sizeof u1);
+	memcpy(oid->moi_bytes + sizeof u1, &u2, sizeof u2);
+	return 0;
+}
+
+void obj_id_printf(struct mio_obj_id *oid)
+{
+	uint64_t u1;
+	uint64_t u2;
+
+	memcpy(&u1, oid->moi_bytes,sizeof u1);
+	memcpy(&u2, oid->moi_bytes + sizeof u1, sizeof u2);
+	u1 = __be64_to_cpu(u1);
+	u2 = __be64_to_cpu(u2);
+	fprintf(stderr, "%"PRIx64":%"PRIx64"", u1, u2);
+}
+
+int obj_open(struct mio_obj_id *oid, struct mio_obj *obj)
+{
+	int rc;
+	struct mio_op op;
+
+	memset(&op, 0, sizeof op);
+	rc = mio_obj_open(oid, obj, &op);
+	if (rc != 0)
+		return rc;
+
+	/* If the object doesn't exist, -ENOENT will be returned? */
+	rc = mio_cmd_wait_on_op(&op);
+	return rc;
+}
+
+void obj_close(struct mio_obj *obj)
+{
+	mio_obj_close(obj);
+}
+
+int obj_create(struct mio_obj_id *oid, struct mio_obj *obj)
+{
+	int rc;
+	struct mio_op op;
+
+	memset(&op, 0, sizeof op);
+	rc = obj_open(oid, obj);
+	if (rc == 0) {
+		fprintf(stderr, "Object exists!\n");
+		return -EEXIST;
+	} else if (rc == -ENOENT)
+		goto create;
+	else
+		return rc;
+
+create:
+	memset(&op, 0, sizeof op);
+	rc = mio_obj_create(oid, NULL, obj, &op);
+	if (rc != 0)
+		return rc;
+
+	rc = mio_cmd_wait_on_op(&op);
+	return rc;
+}
+
+int obj_rm(struct mio_obj_id *oid)
+{
+	int rc;
+	struct mio_op op;
+
+	memset(&op, 0, sizeof op);
+	rc = mio_obj_delete(oid, &op);
+	if (rc != 0)
+		return rc;
+
+	rc = mio_cmd_wait_on_op(&op);
+	return rc;
+}
+
+int mio_cmd_obj_touch(struct mio_obj_id *oid)
+{
+	struct mio_obj obj;
+
+	memset(&obj, 0, sizeof obj);
+	return obj_create(oid, &obj);
+}
+
+int mio_cmd_obj_unlink(struct mio_obj_id *oid)
+{
+	return obj_rm(oid);
+}
+
+int mio_cmd_obj_open(struct mio_obj_id *oid, struct mio_obj *obj)
+{
+	return obj_open(oid, obj);
+}
+
+void mio_cmd_obj_close(struct mio_obj *obj)
+{
+	obj_close(obj);
+}
+
+int mio_cmd_obj_args_init(int argc, char **argv,
+			  struct mio_cmd_obj_params *params,
+			  void (*usage)(FILE *, char *))
+{
+	int v;
+	int rc;
+	int option_index = 0;
+	static struct option l_opts[] = {
+				{"object",      required_argument, NULL, 'o'},
+				{"block-size",  required_argument, NULL, 's'},
+				{"block-count", required_argument, NULL, 'c'},
+				{"nr_objs",     required_argument, NULL, 'n'},
+				{"async_mod",   no_argument,       NULL, 'a'},
+				{"mio_conf",    required_argument, NULL, 'y'},
+				{"help",        no_argument,       NULL, 'h'},
+				{0,             0,                 0,     0 }};
+
+	memset(params, 0, sizeof *params);
+	params->cop_nr_objs = 1;
+	params->cop_async_mode = false;
+
+	while ((v = getopt_long(argc, argv, ":o:s:c:n:y:t:ah", l_opts,
+				&option_index)) != -1)
+	{
+		switch (v) {
+		case 'o':
+			obj_id_sscanf(optarg, &params->cop_oid);
+			continue;
+			
+		case 's':
+			rc = mio_cmd_strtou64(optarg, &params->cop_block_size);
+			if (rc < 0)
+				exit(EXIT_FAILURE);
+			continue;
+		case 'c':
+			rc = mio_cmd_strtou64(optarg, &params->cop_block_count);
+			if (rc < 0)
+				exit(EXIT_FAILURE);
+			continue;
+		case 'n':
+			params->cop_nr_objs = atoi(optarg);
+			continue;
+		case 't':
+			params->cop_nr_threads = atoi(optarg);
+			continue;
+		case 'y':
+			params->cop_conf_fname = strdup(optarg);
+			if (params->cop_conf_fname == NULL)
+				exit(EXIT_FAILURE);
+			continue;
+		case 'a':
+			params->cop_async_mode = true;
+			continue;
+		case 'h':
+			usage(stderr, basename(argv[0]));
+			exit(EXIT_FAILURE);
+		case '?':
+			fprintf(stderr, "Unsupported option '%c'\n",
+				optopt);
+			usage(stderr, basename(argv[0]));
+			exit(EXIT_FAILURE);
+		case ':':
+			fprintf(stderr, "No argument given for '%c'\n",
+				optopt);
+			usage(stderr, basename(argv[0]));
+			exit(EXIT_FAILURE);
+		default:
+			fprintf(stderr, "Unsupported option '%c'\n", v);
+		}
+	}
+
+	return 0;
+}
+
+void mio_cmd_obj_args_fini(struct mio_cmd_obj_params *params)
+{
+	if (params->cop_conf_fname)
+		free(params->cop_conf_fname);
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/obj.h b/deps/mio/examples/obj.h
new file mode 100644
index 0000000000000000000000000000000000000000..985128fc085019d13cdd5c65b00acc01cfdc72b3
--- /dev/null
+++ b/deps/mio/examples/obj.h
@@ -0,0 +1,96 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#ifndef __OBJ_H__
+#define __OBJ_H__
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/time.h>
+
+#include "src/mio.h"
+
+enum {
+	MIO_CMD_MAX_BLOCK_COUNT = 100
+};
+
+struct mio_cmd_obj_params {
+	char *cop_conf_fname;
+
+	struct mio_obj_id cop_oid;
+	int cop_nr_objs;
+	uint64_t cop_block_size;
+	uint64_t cop_block_count;
+
+	bool cop_async_mode;
+
+	int cop_nr_threads;
+};
+
+int mio_cmd_obj_args_init(int argc, char **argv,
+			  struct mio_cmd_obj_params *params,
+			  void (*usage)(FILE *, char *));
+void mio_cmd_obj_args_fini(struct mio_cmd_obj_params *params);
+
+int mio_cmd_obj_write(char *src, struct mio_obj_id *oid,
+		      uint32_t block_size, uint32_t block_count);
+
+int mio_cmd_obj_write_async(char *src, struct mio_obj_id *oid,
+			    uint32_t block_size, uint32_t block_count);
+
+int mio_cmd_obj_read(struct mio_obj_id *oid, char *dest,
+		     uint32_t block_size, uint32_t block_count);
+int mio_cmd_obj_read_async(struct mio_obj_id *oid, char *dest,
+			   uint32_t block_size, uint32_t block_count);
+
+int mio_cmd_obj_touch(struct mio_obj_id *oid);
+int mio_cmd_obj_unlink(struct mio_obj_id *id);
+
+int mio_cmd_obj_open(struct mio_obj_id *oid,struct mio_obj *obj);
+void mio_cmd_obj_close(struct mio_obj *obj);
+
+/** Helper functions. */
+int obj_alloc_iovecs(struct mio_iovec **data, uint32_t bcount,
+		     uint32_t bsize, uint64_t offset);
+void obj_cleanup_iovecs(struct mio_iovec *data);
+int obj_read_data_from_file(FILE *fp, uint32_t bcount, uint32_t bsize,
+			    struct mio_iovec *data);
+int obj_write_data_to_file(FILE *fp, bool console,
+			   uint32_t bcount, struct mio_iovec *data);
+
+int obj_open(struct mio_obj_id *oid, struct mio_obj *obj);
+void obj_close(struct mio_obj *obj);
+int obj_create(struct mio_obj_id *oid, struct mio_obj *obj);
+int obj_rm(struct mio_obj_id *oid);
+
+int obj_write(struct mio_obj *obj, uint32_t bcount, struct mio_iovec *data);
+int obj_read(struct mio_obj *obj, uint32_t bcount, struct mio_iovec *data);
+
+void obj_id_printf(struct mio_obj_id *oid);
+
+#endif /* __OBJ_H__ */
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/obj_io_cbs.c b/deps/mio/examples/obj_io_cbs.c
new file mode 100644
index 0000000000000000000000000000000000000000..ffb3570ac149883b1440cc596705fb201d97ca27
--- /dev/null
+++ b/deps/mio/examples/obj_io_cbs.c
@@ -0,0 +1,343 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <asm/byteorder.h>
+#include <pthread.h>
+
+#include "obj.h"
+#include "helpers.h"
+
+/**
+ * obj_io_cbs.c gives examples on how to use MIO callback functions
+ * for object READ/WRITE.
+ */
+
+struct obj_io_cb_args {
+	int ica_bcount;
+	struct mio_iovec *ica_iovecs;
+	FILE *ica_fp;
+};
+
+pthread_cond_t obj_io_cond;
+pthread_mutex_t obj_io_mutex;
+static int obj_io_nr_ops_on_fly = 0;
+static int obj_io_nr_ops_todo = 0;
+static struct mio_op **obj_io_ops;
+
+void obj_wait_on_all_ops()
+{
+	pthread_mutex_lock(&obj_io_mutex);
+	while(obj_io_nr_ops_on_fly != 0)
+		pthread_cond_wait(&obj_io_cond, &obj_io_mutex);
+	pthread_mutex_unlock(&obj_io_mutex);
+
+}
+
+void obj_write_cb(struct mio_op *op)
+{
+	int i;
+	struct obj_io_cb_args *args;
+	struct mio_iovec *iov;
+
+	args = (struct obj_io_cb_args *)op->mop_app_cbs.moc_cb_data;
+	for (i = 0; i < args->ica_bcount; i++) {
+		iov = args->ica_iovecs + i;
+		fprintf(stderr, "IO from %d to %d %s!\n",
+			(int)iov[0].miov_off,
+			(int)(iov[0].miov_off + iov[0].miov_len),
+			op->mop_rc == 0? "succeed" : "failed");
+	}
+
+	obj_cleanup_iovecs(args->ica_iovecs);
+	free(args);
+
+	pthread_mutex_lock(&obj_io_mutex);
+	obj_io_nr_ops_on_fly--;
+	pthread_cond_signal(&obj_io_cond);
+	pthread_mutex_unlock(&obj_io_mutex);
+}
+
+static int obj_write_async(struct mio_obj *obj, int op_idx,
+			   uint32_t bcount, struct mio_iovec *data)
+{
+	int rc;
+	struct mio_op *op;
+	struct obj_io_cb_args *args;
+
+	args = malloc(sizeof *args);
+	if (args == NULL)
+		return -ENOMEM;
+
+	/*
+ 	 * Allocate memory for op as the op's memory must keep
+ 	 * alive after exiting this function.
+ 	 */
+	op = mio_op_alloc_init();
+	if (op == NULL) {
+		free(args);
+		return -ENOMEM;
+	}
+
+	/*
+	 * Callbacks must be set before calling mio_obj_writev() as
+	 * the op will be launched in this function. Same to other
+	 * MIO APIs if one wants to set callbacks.
+	 */
+	args->ica_bcount = bcount;
+	args->ica_iovecs = data;
+	mio_op_callbacks_set(op, obj_write_cb, obj_write_cb, args);
+	rc = mio_obj_writev(obj, data, bcount, op);
+	if (rc < 0) {
+		mio_op_fini_free(op);
+		free(args);
+	} else
+		obj_io_ops[op_idx] = op;
+	return rc;
+}
+
+void obj_read_cb(struct mio_op *op)
+{
+	int i;
+	struct obj_io_cb_args *args;
+	struct mio_iovec *iov;
+
+	args = (struct obj_io_cb_args *)op->mop_app_cbs.moc_cb_data;
+	for (i = 0; i < args->ica_bcount; i++) {
+		iov = args->ica_iovecs + i;
+		fprintf(stderr, "Read from %d to %d %s!\n",
+			(int)iov[0].miov_off,
+			(int)(iov[0].miov_off + iov[0].miov_len),
+			op->mop_rc == 0? "succeed" : "failed");
+	}
+	obj_write_data_to_file(
+		args->ica_fp, false, args->ica_bcount, args->ica_iovecs);
+	
+	obj_cleanup_iovecs(args->ica_iovecs);
+	free(args);
+
+	pthread_mutex_lock(&obj_io_mutex);
+	obj_io_nr_ops_on_fly--;
+	pthread_cond_signal(&obj_io_cond);
+	pthread_mutex_unlock(&obj_io_mutex);
+}
+
+
+static int
+obj_read_async(struct mio_obj *obj, FILE *write_to_fp, 
+	       int op_idx, uint32_t bcount, struct mio_iovec *data)
+{
+	int rc;
+	struct mio_op *op;
+	struct obj_io_cb_args *args;
+
+	args = malloc(sizeof *args);
+	if (args == NULL)
+		return -ENOMEM;
+
+	op = mio_op_alloc_init();
+	if (op == NULL) {
+		free(args);
+		return -ENOMEM;
+	}
+
+	args->ica_bcount = bcount;
+	args->ica_iovecs = data;
+	args->ica_fp = write_to_fp;
+	mio_op_callbacks_set(op, obj_read_cb, obj_read_cb, args);
+	rc = mio_obj_readv(obj, data, bcount, op);
+	if (rc < 0) {
+		mio_op_fini_free(op);
+		free(args);
+	} else
+		obj_io_ops[op_idx] = op;
+	return rc;
+}
+
+static int obj_io_async_init(int bcount)
+{
+	obj_io_nr_ops_todo =
+		(bcount + MIO_CMD_MAX_BLOCK_COUNT - 1) /
+		 MIO_CMD_MAX_BLOCK_COUNT; 
+	obj_io_ops = malloc(obj_io_nr_ops_todo * sizeof(struct mio_op *));
+	if (obj_io_ops == NULL)
+		return -ENOMEM;
+	memset(obj_io_ops, 0, obj_io_nr_ops_todo * sizeof(struct mio_op *));
+
+	pthread_cond_init(&obj_io_cond, NULL);
+	pthread_mutex_init(&obj_io_mutex, NULL);
+
+	return 0;
+}
+
+static void obj_io_async_fini()
+{
+	int i;
+
+	pthread_mutex_destroy(&obj_io_mutex);
+	pthread_cond_destroy(&obj_io_cond);
+
+	for (i = 0; i < obj_io_nr_ops_todo; i++) {
+		if (obj_io_ops[i] != NULL) {
+			mio_op_fini(obj_io_ops[i]);
+			free(obj_io_ops[i]);
+		}
+	}	
+
+	free(obj_io_ops);
+}
+
+int mio_cmd_obj_write_async(char *src, struct mio_obj_id *oid,
+			    uint32_t block_size, uint32_t block_count)
+{
+	int rc = 0;
+	uint32_t bcount;
+	uint64_t last_index;
+	struct mio_iovec *data;
+	struct mio_obj obj;
+	FILE *fp;
+
+	fp = fopen(src, "r");
+	if (fp == NULL)
+		return -errno;
+
+	memset(&obj, 0, sizeof obj);
+	rc = obj_create(oid, &obj);
+	if (rc < 0)
+		goto src_close;
+
+	rc = obj_io_async_init(block_count);
+	if (rc < 0)
+		goto obj_close;
+
+	pthread_mutex_lock(&obj_io_mutex);
+	last_index = 0;
+	while (block_count > 0) {
+		bcount = (block_count > MIO_CMD_MAX_BLOCK_COUNT)?
+			  MIO_CMD_MAX_BLOCK_COUNT:block_count;
+		rc = obj_alloc_iovecs(&data, bcount, block_size, last_index);
+		if (rc != 0)
+			break;
+
+		/* Read data from source file. */
+		rc = obj_read_data_from_file(fp, bcount, block_size, data);
+		if (rc != bcount) {
+			fprintf(stderr, "Failed in reading from file!\n");
+			obj_cleanup_iovecs(data);
+			break;
+		}
+
+		/* Copy data to the object*/
+		rc = obj_write_async(&obj, obj_io_nr_ops_on_fly, bcount, data);
+		if (rc != 0) {
+			fprintf(stderr, "Writing to object failed!\n");
+			obj_cleanup_iovecs(data);
+			break;
+		}
+		block_count -= bcount;
+		last_index += bcount * block_size;
+
+		++obj_io_nr_ops_on_fly;
+	}
+	pthread_mutex_unlock(&obj_io_mutex);
+
+	obj_wait_on_all_ops();
+
+	obj_io_async_fini();
+
+obj_close:
+	mio_obj_close(&obj);
+src_close:
+	fclose(fp);
+	return rc;
+}
+
+int mio_cmd_obj_read_async(struct mio_obj_id *oid, char *dest,
+			   uint32_t block_size, uint32_t block_count)
+{
+	int rc = 0;
+	uint32_t bcount;
+	uint64_t last_index;
+	struct mio_iovec *data;
+	struct mio_obj obj;
+	FILE *fp = NULL;
+
+	if (dest == NULL)
+		return -EINVAL;
+
+	fp = fopen(dest, "w");
+	if (fp == NULL)
+		return -errno;
+	/*
+	 * As 'obj' keeps alive in the scope of this function till
+	 * all operation are done, so it is ok not to allocate memory
+	 * for 'obj' here. Make sure that 'obj' is kept alive until
+	 * all the ops which are doing IO on it are done.
+	 */
+	memset(&obj, 0, sizeof obj);
+	rc = obj_open(oid, &obj);
+	if (rc < 0)
+		goto dest_close;
+
+	rc = obj_io_async_init(block_count);
+	if (rc < 0)
+		goto obj_close;
+
+	pthread_mutex_lock(&obj_io_mutex);
+	last_index = 0;
+	while (block_count > 0) {
+		bcount = (block_count > MIO_CMD_MAX_BLOCK_COUNT)?
+			  MIO_CMD_MAX_BLOCK_COUNT:block_count;
+		rc = obj_alloc_iovecs(&data, bcount,
+					      block_size, last_index);
+		if (rc != 0)
+			break;
+
+		/* Read data from obj. */
+		rc = obj_read_async(&obj, fp, obj_io_nr_ops_on_fly,
+				    bcount, data);
+		if (rc != 0) {
+			fprintf(stderr, "Failed in reading from file!\n");
+			obj_cleanup_iovecs(data);
+			break;
+		}
+
+		block_count -= bcount;
+		last_index += bcount * block_size;
+
+		++obj_io_nr_ops_on_fly;
+	}
+	pthread_mutex_unlock(&obj_io_mutex);
+
+	obj_wait_on_all_ops();
+	
+	obj_io_async_fini();
+
+obj_close:
+	mio_obj_close(&obj);
+dest_close:
+	fclose(fp);
+	return rc;
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/examples/obj_io_poll.c b/deps/mio/examples/obj_io_poll.c
new file mode 100644
index 0000000000000000000000000000000000000000..b2ac8283ddb1afee076b09a2f09b265be1b0eec4
--- /dev/null
+++ b/deps/mio/examples/obj_io_poll.c
@@ -0,0 +1,190 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <asm/byteorder.h>
+#include <pthread.h>
+
+#include "obj.h"
+#include "helpers.h"
+
+/**
+ * The object IO examples in this file show how to use MIO APIs
+ * in a blocking fashion. After an operation is created, we wait until
+ * an operation completed or failed by using mio_op_poll().
+ *
+ * Of course, applications can also create (and launch internally
+ * in MIO) operations and poll the operations in a dedicated thread.
+ */
+
+int obj_write(struct mio_obj *obj, uint32_t bcount, struct mio_iovec *data)
+{
+	int rc;
+	struct mio_op op;
+
+	mio_op_init(&op);
+	rc = mio_obj_writev(obj, data, bcount, &op);
+	if (rc < 0)
+		return rc;
+
+	rc = mio_cmd_wait_on_op(&op);
+	if (rc < 0)
+		fprintf(stderr, "Failed in writing to object!\n");
+	mio_op_fini(&op);
+	return rc;
+}
+
+int obj_read(struct mio_obj *obj, uint32_t bcount, struct mio_iovec *data)
+{
+	int rc;
+	struct mio_op op;
+
+	mio_op_init(&op);
+	rc = mio_obj_readv(obj, data, bcount, &op);
+	if (rc < 0)
+		return rc;
+
+	rc = mio_cmd_wait_on_op(&op);
+	if (rc < 0)
+		fprintf(stderr, "Failed in reading from object!\n");
+	mio_op_fini(&op);
+	return rc;
+}
+
+int mio_cmd_obj_write(char *src, struct mio_obj_id *oid,
+		      uint32_t block_size, uint32_t block_count)
+{
+	int rc = 0;
+	uint32_t bcount;
+	uint64_t last_index;
+	struct mio_iovec *data;
+	struct mio_obj obj;
+	FILE *fp;
+
+	/* Open source file */
+	fp = fopen(src, "r");
+	if (fp == NULL)
+		return -errno;
+
+	/* Create the target object if it doesn't exist. */
+	memset(&obj, 0, sizeof obj);
+	rc = obj_create(oid, &obj);
+	if (rc < 0)
+		goto src_close;
+
+	last_index = 0;
+	while (block_count > 0) {
+		bcount = (block_count > MIO_CMD_MAX_BLOCK_COUNT)?
+			  MIO_CMD_MAX_BLOCK_COUNT:block_count;
+		rc = obj_alloc_iovecs(&data, bcount,
+					      block_size, last_index);
+		if (rc != 0)
+			break;
+
+		/* Read data from source file. */
+		rc = obj_read_data_from_file(fp, bcount, block_size, data);
+		if (rc != bcount) {
+			fprintf(stderr, "Failed in reading from file!\n");
+			obj_cleanup_iovecs(data);
+			break;
+		}
+
+		/* Copy data to the object*/
+		rc = obj_write(&obj, bcount, data);
+		if (rc != 0) {
+			fprintf(stderr, "Writing to object failed!\n");
+			obj_cleanup_iovecs(data);
+			break;
+		}
+		obj_cleanup_iovecs(data);
+		block_count -= bcount;
+		last_index += bcount * block_size;
+	}
+
+	mio_obj_close(&obj);
+
+src_close:
+	fclose(fp);
+	return rc;
+}
+
+int mio_cmd_obj_read(struct mio_obj_id *oid, char *dest,
+		     uint32_t block_size, uint32_t block_count)
+{
+	int rc = 0;
+	uint32_t bcount;
+	uint64_t last_index;
+	struct mio_iovec *data;
+	struct mio_obj obj;
+	FILE *fp = NULL;
+
+	if (dest != NULL) {
+		fp = fopen(dest, "w");
+		if (fp == NULL)
+			return -errno;
+
+	}
+
+	memset(&obj, 0, sizeof obj);
+	rc = obj_open(oid, &obj);
+	if (rc < 0)
+		goto dest_close;
+
+	last_index = 0;
+	while (block_count > 0) {
+		bcount = (block_count > MIO_CMD_MAX_BLOCK_COUNT)?
+			  MIO_CMD_MAX_BLOCK_COUNT:block_count;
+		rc = obj_alloc_iovecs(&data, bcount, block_size, last_index);
+		if (rc != 0)
+			break;
+
+		/* Read data from obj. */
+		rc = obj_read(&obj, bcount, data);
+		if (rc != 0) {
+			fprintf(stderr, "Failed in reading from file!\n");
+			obj_cleanup_iovecs(data);
+			break;
+		}
+
+		/* Copy data to the file. */
+		rc = obj_write_data_to_file(fp, true, bcount, data);
+		if (rc != bcount) {
+			fprintf(stderr, "Writing to file failed!\n");
+			obj_cleanup_iovecs(data);
+			break;
+		}
+
+		obj_cleanup_iovecs(data);
+		block_count -= bcount;
+		last_index += bcount * block_size;
+	}
+
+	mio_obj_close(&obj);
+
+dest_close:
+	if(fp != NULL)
+		fclose(fp);
+	return rc;
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/src/Makefile.sub b/deps/mio/src/Makefile.sub
new file mode 100644
index 0000000000000000000000000000000000000000..3390aaa84739641f878d38e17453c30894e396a7
--- /dev/null
+++ b/deps/mio/src/Makefile.sub
@@ -0,0 +1,16 @@
+# Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+# All Rights Reserved
+#
+# This software is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+nobase_mio_include_HEADERS += src/mio.h \
+			      src/mio_internal.h \
+			      src/driver_clovis.h \
+			      src/logger.h
+
+lib_libmio_la_SOURCES += src/parser.c src/logger.c \
+			 src/utils.c src/mio.c src/mio_driver.c \
+			 src/hints.c src/driver_clovis.c \
+			 src/driver_clovis_comp_obj.c
diff --git a/deps/mio/src/driver_clovis.c b/deps/mio/src/driver_clovis.c
new file mode 100644
index 0000000000000000000000000000000000000000..12bb04c3c14f672ce6b702a23817998aa9a6036f
--- /dev/null
+++ b/deps/mio/src/driver_clovis.c
@@ -0,0 +1,1370 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <errno.h>
+#include <assert.h>
+
+#include "logger.h"
+#include "mio.h"
+#include "mio_internal.h"
+#include "driver_clovis.h"
+
+struct m0_clovis *mio_clovis_instance;
+struct m0_clovis_container mio_clovis_container;
+struct m0_clovis_config mio_clovis_conf;
+struct mio_mero_config *mio_clovis_inst_confs;
+
+struct m0_uint128 mio_clovis_obj_md_kvs_id;
+struct m0_fid mio_clovis_obj_md_kvs_fid = M0_FID_TINIT('x', 0, 0x10);
+
+#define MIO_CLOVIS_OP(op) \
+	((struct m0_clovis_op *)op->mop_drv_op_chain.mdoc_head->mdo_op)
+
+/**
+ * pp is short for Post-Process to avoid confusion of cb (callback).
+ */
+static int clovis_obj_attrs_query_free_pp(struct mio_op *op);
+static int clovis_obj_attrs_get_pp(struct mio_op *op);
+static int clovis_obj_attrs_query(int opcode, struct mio_obj *obj,
+				  mio_driver_op_postprocess op_pp,
+				  struct mio_op *op);
+
+/**
+ * Some helper functions.
+ */
+static void clovis_bufvec_free(struct m0_bufvec *bv)
+{
+        if (bv == NULL)
+                return;
+
+        m0_free(bv->ov_buf);
+        m0_free(bv->ov_vec.v_count);
+        m0_free(bv);
+}
+
+struct m0_bufvec* mio__clovis_bufvec_alloc(int nr)
+{
+        struct m0_bufvec *bv;
+
+        bv = m0_alloc(sizeof *bv);
+        if (bv == NULL)
+                return NULL;
+
+        bv->ov_vec.v_nr = nr;
+        M0_ALLOC_ARR(bv->ov_vec.v_count, nr);
+        if (bv->ov_vec.v_count == NULL)
+                goto error;
+
+        M0_ALLOC_ARR(bv->ov_buf, nr);
+        if (bv->ov_buf == NULL)
+                goto error;
+
+        return bv;
+
+error:
+        m0_bufvec_free(bv);
+        return NULL;
+}
+
+static int clovis_create_obj_attrs_kvs()
+{
+        int rc;
+	struct m0_clovis_op *cops[1] = {NULL};
+	struct m0_clovis_idx *idx;
+
+	idx = mio_mem_alloc(sizeof *idx);
+	if (idx == NULL)
+		return -ENOMEM;
+
+	mio_clovis_obj_md_kvs_id.u_hi = mio_clovis_obj_md_kvs_fid.f_container;
+	mio_clovis_obj_md_kvs_id.u_lo = mio_clovis_obj_md_kvs_fid.f_key;
+	m0_clovis_idx_init(idx, &mio_clovis_container.co_realm,
+			   &mio_clovis_obj_md_kvs_id);
+
+	/* Check if object's attrs key-value store exists. */
+        m0_clovis_idx_op(idx, M0_CLOVIS_IC_LOOKUP,
+			 NULL, NULL, NULL, 0, &cops[0]);
+        m0_clovis_op_launch(cops, 1);
+	rc = m0_clovis_op_wait(cops[0],
+			       M0_BITS(M0_CLOVIS_OS_FAILED,
+				       M0_CLOVIS_OS_STABLE),
+			       M0_TIME_NEVER);
+	rc = rc? : m0_clovis_rc(cops[0]);
+	m0_clovis_op_fini(cops[0]);
+	m0_clovis_op_free(cops[0]);
+
+	/*
+ 	 * Check returned value (rc): 	
+ 	 *   - 0: LOOKUP successes and the index has already existed.
+ 	 *   - -ENOENT: the index doesn't exist yet.
+ 	 *   - other error code: LOOKUP op failed for some reason.
+ 	 */
+	if (rc != -ENOENT)
+		goto exit;
+
+	/* Create the attrs kvs. */
+	cops[0] = NULL;
+        rc = m0_clovis_entity_create(NULL, &idx->in_entity, &cops[0]);
+	if (rc < 0)
+		goto exit;
+        m0_clovis_op_launch(cops, 1);
+	rc = m0_clovis_op_wait(cops[0],
+			       M0_BITS(M0_CLOVIS_OS_FAILED,
+				       M0_CLOVIS_OS_STABLE),
+			       M0_TIME_NEVER);
+	rc = rc? : m0_clovis_rc(cops[0]);
+	m0_clovis_op_fini(cops[0]);
+	m0_clovis_op_free(cops[0]);
+
+exit:
+	if (rc == 0)
+		mio_obj_attrs_kvs.mk_drv_kvs = idx;
+	else {
+		m0_clovis_idx_fini(idx);
+		mio_mem_free(idx);
+	}
+	return rc;
+}
+
+/**
+ * Initialise and finalise clovis instance.
+ */
+int mio_clovis_init(struct mio *mio_inst) 
+{
+	int rc;
+	struct mio_mero_config *drv;
+	struct m0_idx_dix_config dix_conf;
+
+	drv = (struct mio_mero_config *)mio_inst->m_driver_confs;
+	mio_clovis_inst_confs = drv;
+
+	/* Set clovis configuration parameters. */
+	mio_clovis_conf.cc_is_oostore            = drv->mc_is_oostore;
+	mio_clovis_conf.cc_is_read_verify        = drv->mc_is_read_verify;
+	mio_clovis_conf.cc_local_addr            = drv->mc_clovis_local_addr;
+	mio_clovis_conf.cc_ha_addr               = drv->mc_ha_addr;
+	mio_clovis_conf.cc_profile               = drv->mc_profile;
+	mio_clovis_conf.cc_process_fid           = drv->mc_process_fid;
+	mio_clovis_conf.cc_tm_recv_queue_min_len = drv->mc_tm_recv_queue_min_len;
+	mio_clovis_conf.cc_max_rpc_msg_size      = drv->mc_max_rpc_msg_size;
+
+	mio_clovis_conf.cc_layout_id =
+		m0_clovis_obj_unit_size_to_layout_id(drv->mc_unit_size);
+
+	mio_clovis_conf.cc_idx_service_id   = M0_CLOVIS_IDX_DIX;
+	dix_conf.kc_create_meta = false;
+	mio_clovis_conf.cc_idx_service_conf = &dix_conf;
+
+	/* Initial clovis instance. */
+	rc = m0_clovis_init(&mio_clovis_instance, &mio_clovis_conf, true);
+	if (rc != 0)
+		return rc;
+
+	/* Initial a container. */
+	m0_clovis_container_init(&mio_clovis_container, NULL,
+				 &M0_CLOVIS_UBER_REALM,
+				 mio_clovis_instance);
+	rc = mio_clovis_container.co_realm.re_entity.en_sm.sm_rc;
+	if (rc != 0) {
+		mio_log(MIO_ERROR, "Failed to open Clovis's uber realm!\n");
+		goto error;
+	}
+
+	/* Create object attrs kvs if it doesn't exist. */
+ 	rc = clovis_create_obj_attrs_kvs();
+	if (rc != 0) {
+		mio_log(MIO_ERROR, "Failed to create attrs key-value set!\n");
+		goto error;
+	}
+	return 0;
+
+error:	
+	m0_clovis_fini(mio_clovis_instance, true);
+	return rc;
+}
+
+static void mio_clovis_fini()
+{
+	m0_clovis_idx_fini(
+		(struct m0_clovis_idx *)mio_obj_attrs_kvs.mk_drv_kvs);
+	m0_clovis_fini(mio_clovis_instance, true);
+}
+
+static int mio_clovis_thread_init(struct mio_thread *thread)
+{
+	struct m0_thread *mthread;
+
+	mthread = mio_mem_alloc(sizeof(*mthread));
+	if (mthread == NULL)
+		return -ENOMEM;
+	memset(mthread, 0, sizeof(struct m0_thread));
+	m0_thread_adopt(mthread, mio_clovis_instance->m0c_mero);
+	thread->mt_drv_thread = mthread;
+	return 0;
+}
+
+static void mio_clovis_thread_fini(struct mio_thread *thread)
+{
+	m0_thread_shun();
+	mio_mem_free(thread->mt_drv_thread);
+}
+
+static struct mio_driver_sys_ops mio_clovis_sys_ops = {
+        .mdo_init = mio_clovis_init,
+        .mdo_fini = mio_clovis_fini,
+        .mdo_thread_init = mio_clovis_thread_init,
+        .mdo_thread_fini = mio_clovis_thread_fini
+};
+
+static void mio_clovis_op_fini(struct mio_op *mop)
+{
+	struct m0_clovis_op *cop; 
+	struct mio_driver_op *dop;
+
+	dop = mop->mop_drv_op_chain.mdoc_head;
+	while(dop != NULL) {
+		mop->mop_drv_op_chain.mdoc_head = dop->mdo_next;
+		dop->mdo_next = NULL;
+
+		cop = (struct m0_clovis_op *)dop->mdo_op;
+		m0_clovis_op_fini(cop);
+		m0_clovis_op_free(cop);
+		mio_mem_free(dop);
+
+		dop = mop->mop_drv_op_chain.mdoc_head;
+	}
+}
+
+static int
+mio_clovis_op_wait(struct mio_op *mop, uint64_t timeout, int *retstate)
+{
+	int rc;
+	struct m0_clovis_op *cop; 
+
+	cop = MIO_CLOVIS_OP(mop);
+	rc = m0_clovis_op_wait(cop, M0_BITS(M0_CLOVIS_OS_STABLE,
+					    M0_CLOVIS_OS_FAILED),
+			       timeout);
+	/*
+	 * Check returned value (rc) from m0_clovis_op_wait:
+	 *   - errors (rc < 0), treat timeout error differently. 
+	 *   - rc == 0, the operation is completed, then check the
+	 *     operation's rc value to see if the op is successful or failed.
+ 	 */
+	if (rc == 0) {
+		if (m0_clovis_rc(cop) < 0) {
+			*retstate = MIO_OP_FAILED;
+			rc = m0_clovis_rc(cop);
+		} else
+			*retstate = MIO_OP_COMPLETED;
+	} else if (rc == -ETIMEDOUT)
+		*retstate = MIO_OP_ONFLY;
+	else
+		*retstate = MIO_OP_FAILED;
+	return rc;
+}
+
+/**
+ * The callback functions defined for MIO operation have different
+ * arguments with the ones of drivers', such as Clovis. A jumper
+ * function here is used to call the callback functions set by MIO
+ * applications.
+ *
+ * The callback functions shown below give examples on how to relay
+ * control to callbacks set by apps.
+ *
+ * This looks a bit ugly, is there any better solution?
+ */
+static void clovis_op_cb_complete(struct m0_clovis_op *cop)
+{
+	int rc;
+	struct mio_op *mop;
+
+	mop = (struct mio_op *)cop->op_datum;
+	if (!mop->mop_drv_op_chain.mdoc_head->mdo_post_proc)
+		goto app_cb;
+
+	rc = mop->mop_drv_op_chain.mdoc_head->mdo_post_proc(mop);
+	if (rc == MIO_DRV_OP_NEXT)
+		return;
+
+app_cb:
+	mio_driver_op_invoke_real_cb(mop, 0);
+}
+
+static void clovis_op_cb_failed(struct m0_clovis_op *cop)
+{
+	struct mio_op *mop;
+
+	mop = (struct mio_op *)cop->op_datum;
+	mio_driver_op_invoke_real_cb(mop, m0_clovis_rc(cop));
+}
+
+static struct m0_clovis_op_ops clovis_op_cbs;
+static int
+mio_clovis_op_set_cbs(struct mio_op *mop)
+
+{
+	struct m0_clovis_op *cop;
+
+	assert(mop != NULL);
+
+	clovis_op_cbs.oop_executed = NULL;
+	clovis_op_cbs.oop_stable = clovis_op_cb_complete;
+	clovis_op_cbs.oop_failed = clovis_op_cb_failed;
+	cop = MIO_CLOVIS_OP(mop);
+	cop->op_datum = (void *)mop;
+	m0_clovis_op_setup(cop, &clovis_op_cbs, 0);
+
+	return 0;
+}
+
+static struct mio_op_ops mio_clovis_op_ops = {
+	.mopo_fini    = mio_clovis_op_fini,
+	.mopo_wait    = mio_clovis_op_wait,
+	.mopo_set_cbs = mio_clovis_op_set_cbs
+};
+
+void mio__uint128_to_obj_id(struct m0_uint128 *uint128,
+			    struct mio_obj_id *oid)
+{
+	uint64_t hi = uint128->u_hi; 
+	uint64_t lo = uint128->u_lo;
+ 
+	hi = mio_byteorder_cpu_to_be64(hi);
+	lo = mio_byteorder_cpu_to_be64(lo);
+
+	mio_mem_copy(&oid->moi_bytes[0], &hi, sizeof(hi));
+	mio_mem_copy(&oid->moi_bytes[8], &lo, sizeof(lo));
+}
+
+void mio__obj_id_to_uint128(const struct mio_obj_id *oid,
+			    struct m0_uint128 *uint128)
+{
+	uint64_t *hi = (uint64_t *)&oid->moi_bytes[0];
+	uint64_t *lo = (uint64_t *)&oid->moi_bytes[8];
+ 
+	uint128->u_hi = mio_byteorder_be64_to_cpu(*hi);
+	uint128->u_lo = mio_byteorder_be64_to_cpu(*lo);
+}
+
+static int clovis_obj_open_pp(struct mio_op *op)
+{
+	int rc;
+	struct mio_obj *obj = op->mop_who.obj;
+	struct m0_clovis_op *cop;
+
+	cop = MIO_CLOVIS_OP(op);
+	rc = m0_clovis_rc(cop);
+	if (rc < 0)
+		return rc;
+
+	/* Launch a new op to get object attributes. */
+	rc = clovis_obj_attrs_query(M0_CLOVIS_IC_GET, obj,
+			            clovis_obj_attrs_get_pp, op);
+	if (rc < 0)
+		return rc;
+	else
+		return MIO_DRV_OP_NEXT;
+}
+
+static int mio_clovis_obj_open(struct mio_obj *obj, struct mio_op *op)
+{
+	int rc;
+	struct m0_uint128 id128;
+	struct m0_clovis_obj *cobj;
+	struct m0_clovis_op *cops[1] = {NULL};
+
+	cobj = mio_mem_alloc(sizeof *cobj);
+	if (cobj == NULL)
+		return -ENOMEM;
+
+	mio__obj_id_to_uint128(&obj->mo_id, &id128);
+	m0_clovis_obj_init(cobj, &mio_clovis_container.co_realm, &id128,
+			   mio_clovis_inst_confs->mc_default_layout_id);
+	rc = m0_clovis_entity_open(&cobj->ob_entity, &cops[0]);
+	if (rc != 0)
+		goto error;
+ 
+	obj->mo_drv_obj = (void *)cobj;
+	rc = mio_driver_op_add(op, clovis_obj_open_pp, NULL, cops[0]);
+	if (rc < 0)
+		goto error;
+	m0_clovis_op_launch(cops, 1);
+	return 0;
+
+error:
+	if (cops[0] != NULL) {
+		m0_clovis_op_fini(cops[0]);
+		m0_clovis_op_free(cops[0]);
+	}
+	m0_clovis_obj_fini(cobj);
+	mio_mem_free(cobj);
+	return rc;
+}
+
+static int mio_clovis_obj_close(struct mio_obj *obj)
+{
+	m0_clovis_obj_fini((struct m0_clovis_obj *)obj->mo_drv_obj);
+	return 0;
+}
+
+static void pool_id_to_fid(const struct mio_pool *pool_id, struct m0_fid *fid)
+{
+	fid->f_container = pool_id->mp_hi;
+	fid->f_key = pool_id->mp_lo;
+}
+
+static int mio_clovis_obj_create(const struct mio_pool *pool_id,
+				 struct mio_obj *obj, struct mio_op *op)
+{
+	int rc = 0;
+	struct m0_fid pfid;
+	struct m0_fid *ptr_pfid = NULL;
+	struct m0_uint128 id128;
+	struct m0_clovis_obj *cobj;
+	struct m0_clovis_op *cops[1] = {NULL};
+
+	if (pool_id != NULL) {
+		pool_id_to_fid(pool_id, &pfid);
+		ptr_pfid = &pfid;
+	}
+
+	cobj = mio_mem_alloc(sizeof *cobj);
+	if (cobj == NULL)
+		return -ENOMEM;
+
+	mio__obj_id_to_uint128(&obj->mo_id, &id128);
+	m0_clovis_obj_init(cobj, &mio_clovis_container.co_realm, &id128,
+			   mio_clovis_inst_confs->mc_default_layout_id);
+	rc = m0_clovis_entity_create(ptr_pfid, &cobj->ob_entity, &cops[0]);
+	if (rc < 0)
+		goto error;
+
+	obj->mo_drv_obj = (void *)cobj;
+	rc = mio_driver_op_add(op, NULL, NULL, cops[0]);
+	if (rc < 0)
+		goto error;
+	m0_clovis_op_launch(cops, 1);
+	return 0;
+
+error:
+	if (cops[0] != NULL) {
+		m0_clovis_op_fini(cops[0]);
+		m0_clovis_op_free(cops[0]);
+	}
+	m0_clovis_obj_fini(cobj);
+	mio_mem_free(cobj);
+	return rc;
+}
+
+static int clovis_obj_delete_pp(struct mio_op *op)
+{
+	int rc = 0;
+	struct mio_obj *mobj = op->mop_who.obj;
+	struct m0_clovis_obj *cobj = (struct m0_clovis_obj *)mobj->mo_drv_obj;
+
+	/* Launch a new op to delete this object's attributes. */
+	rc = clovis_obj_attrs_query(M0_CLOVIS_IC_DEL, mobj,
+				    clovis_obj_attrs_query_free_pp, op);
+
+	/* The opened object is not needed any more. */
+	mio_mem_free(cobj);
+	mio_mem_free(mobj);
+
+	if (rc < 0)
+		return rc;
+	else
+		return MIO_DRV_OP_NEXT;
+}
+
+static int
+clovis_obj_delete_open_pp(struct mio_op *op)
+{
+	int rc = 0;
+	struct m0_clovis_op *cops[1] = {NULL};
+	struct m0_clovis_obj *cobj;
+	struct mio_obj *mobj = op->mop_who.obj;
+
+	cobj = (struct m0_clovis_obj *)mobj->mo_drv_obj;
+	rc = m0_clovis_entity_delete(&cobj->ob_entity, &cops[0]);
+	if (rc != 0) {
+		mio_log(MIO_ERROR, "Creating DELETE op failed!\n");
+		goto error;
+	}
+
+	rc = mio_driver_op_add(op, clovis_obj_delete_pp, NULL, cops[0]);
+	if (rc < 0)
+		goto error;
+	m0_clovis_op_launch(cops, ARRAY_SIZE(cops));
+	return MIO_DRV_OP_NEXT;
+
+error:
+	if (cops[0] != NULL) {
+		m0_clovis_op_fini(cops[0]);
+		m0_clovis_op_free(cops[0]);
+	}
+	m0_clovis_obj_fini(cobj);
+	mio_mem_free(cobj);
+	mio_mem_free(mobj);
+	return rc;
+}
+
+/**
+ * Deleting an object takes the following steps:
+ * (1) Open the object to fetch required Mero-wise object attributes.
+ * (2) Create and launch DELETE op to remove the object data.
+ * (3) Create and launch an KVS DEL op to remove this object MIO attributes.
+ */
+static int
+mio_clovis_obj_delete(const struct mio_obj_id *oid, struct mio_op *op)
+{
+	int rc = 0;
+	struct m0_uint128 id128;
+	struct m0_clovis_obj *cobj;
+	struct m0_clovis_op *cops[1] = {NULL};
+	struct mio_obj *mobj;
+
+	/* Create a mio obj handler for callback. */
+	mobj = mio_mem_alloc(sizeof *mobj);
+	if (mobj == NULL)
+		return -ENOMEM;
+	mobj->mo_id = *oid;
+	op->mop_who.obj = mobj;
+
+	cobj = mio_mem_alloc(sizeof *cobj);
+	if (cobj == NULL) {
+		mio_mem_free(mobj);
+		return -ENOMEM;
+	}
+	mobj->mo_drv_obj = (void *)cobj;
+	mobj->mo_md_kvs = &mio_obj_attrs_kvs;
+
+	mio__obj_id_to_uint128(&mobj->mo_id, &id128);
+	m0_clovis_obj_init(cobj, &mio_clovis_container.co_realm, &id128,
+			   mio_clovis_inst_confs->mc_default_layout_id);
+	rc = m0_clovis_entity_open(&cobj->ob_entity, &cops[0]);
+	if (rc != 0) {
+		mio_log(MIO_ERROR,
+			"Creating OPEN op for object deletion failed!\n");
+		goto error;
+	}
+
+	rc = mio_driver_op_add(op, clovis_obj_delete_open_pp, NULL, cops[0]);
+	if (rc < 0)
+		goto error;
+	m0_clovis_op_launch(cops, ARRAY_SIZE(cops));
+	return 0;
+
+error:
+	if (cops[0] != NULL) {
+		m0_clovis_op_fini(cops[0]);
+		m0_clovis_op_free(cops[0]);
+	}
+	m0_clovis_obj_fini(cobj);
+	mio_mem_free(cobj);
+	mio_mem_free(mobj);
+	return rc;
+}
+
+static bool is_rw_2big(const struct mio_iovec *iov, int iovcnt)
+{
+	int i;
+	int nr_units = 0;
+	uint64_t unit_size;
+
+	unit_size = m0_clovis_obj_layout_id_to_unit_size(
+				mio_clovis_inst_confs->mc_default_layout_id);
+	for (i = 0; i < iovcnt; i++)
+       		nr_units += (iov[i].miov_len + unit_size - 1) / unit_size;
+	return nr_units > MIO_CLOVIS_MAX_RW_NR_UNITS_PER_OP? true : false;
+}
+
+static int clovis_obj_write_pp(struct mio_op *op)
+{
+	int rc;
+	bool update_size;
+	uint64_t *max_eow;
+	struct mio_obj *obj = op->mop_who.obj;
+
+	max_eow = (uint64_t *)
+		  op->mop_drv_op_chain.mdoc_head->mdo_post_proc_data;
+	update_size = (*max_eow <= obj->mo_attrs.moa_size)? false : true;
+	mio_mem_free(max_eow);
+	if (!update_size)
+		return MIO_DRV_OP_FINAL;
+
+	/* Launch a new op to update object size. */
+	obj->mo_attrs.moa_size = *max_eow;
+	rc = clovis_obj_attrs_query(M0_CLOVIS_IC_PUT, obj,
+				    clovis_obj_attrs_query_free_pp, op);
+	if (rc < 0)
+		return rc;
+	else
+		return MIO_DRV_OP_NEXT;
+}
+
+static int clovis_obj_rw(struct mio_obj *obj,
+			 const struct mio_iovec *iov, int iovcnt,
+			 enum m0_clovis_obj_opcode opcode,
+			 struct mio_op *op)
+{
+	int i;
+	int rc = 0;
+	uint64_t *max_eow = NULL; /* eow: End Of Write */
+	struct m0_clovis_obj *cobj;
+	struct m0_clovis_op  *cops[1] = {NULL};
+	struct m0_indexvec ext;
+	struct m0_bufvec data;
+	struct m0_bufvec attr;	
+
+	assert(opcode == M0_CLOVIS_OC_READ || opcode == M0_CLOVIS_OC_WRITE);
+
+	if (is_rw_2big(iov, iovcnt))
+		return -E2BIG;
+	
+	if (iovcnt < 1)
+		return -EINVAL;
+
+	/* Allocate memory for bufvec and indexvec. */
+	rc = m0_bufvec_empty_alloc(&data, iovcnt) ? :
+	     m0_bufvec_alloc(&attr, iovcnt, 1) ? :
+	     m0_indexvec_alloc(&ext, iovcnt);
+	if (rc != 0)
+		goto error;
+
+	max_eow = mio_mem_alloc(sizeof *max_eow);
+	if (max_eow == NULL)
+		goto error;
+
+	/*
+	 * Populate bufvec and indexvec. Avoid copying data
+	 * into bufvec.
+	 */
+	for (i = 0; i < iovcnt; i++) {
+		data.ov_vec.v_count[i] = iov[i].miov_len;
+		data.ov_buf[i] = iov[i].miov_base;
+
+		ext.iv_index[i] = iov[i].miov_off;
+		ext.iv_vec.v_count[i] = iov[i].miov_len;
+		if (iov[i].miov_off + iov[i].miov_len > *max_eow)
+			*max_eow = iov[i].miov_off + iov[i].miov_len;
+
+		/* we don't want any attributes */
+		attr.ov_vec.v_count[i] = 0;
+	}
+
+	/* Create and launch an RW op. */
+	cobj = (struct m0_clovis_obj *)obj->mo_drv_obj;
+	m0_clovis_obj_op(cobj, opcode, &ext, &data, &attr, 0, &cops[0]);
+
+	/* Set callback and then launch IO op. */
+	if (opcode == M0_CLOVIS_OC_WRITE)
+		rc = mio_driver_op_add(
+			op, clovis_obj_write_pp, max_eow, cops[0]);
+	else
+		rc = mio_driver_op_add(op, NULL, NULL, cops[0]);
+	if (rc < 0)
+		goto error;
+
+	m0_clovis_op_launch(cops, ARRAY_SIZE(cops));
+	return 0;
+
+error:
+	m0_indexvec_free(&ext);
+	m0_bufvec_free(&data);
+	m0_bufvec_free(&attr);
+	mio_mem_free(max_eow);
+	return rc;
+}
+
+static int mio_clovis_obj_readv(struct mio_obj *obj,
+				 const struct mio_iovec *iov,
+				 int iovcnt, struct mio_op *op)
+{
+	return clovis_obj_rw(obj, iov, iovcnt, M0_CLOVIS_OC_READ, op);
+}
+
+static int mio_clovis_obj_writev(struct mio_obj *obj,
+				 const struct mio_iovec *iov,
+				 int iovcnt, struct mio_op *op)
+{
+	return clovis_obj_rw(obj, iov, iovcnt, M0_CLOVIS_OC_WRITE, op);
+}
+
+static int mio_clovis_obj_sync(struct mio_obj *obj, struct mio_op *op)
+{
+	int rc;
+	struct m0_clovis_obj *cobj;
+	struct m0_clovis_op  *sync_op = {NULL};
+
+	rc = m0_clovis_sync_op_init(&sync_op);
+	if (rc < 0)
+		return rc;
+
+	cobj = (struct m0_clovis_obj *)obj->mo_drv_obj;
+	rc = m0_clovis_sync_entity_add(sync_op, &cobj->ob_entity);
+	if (rc < 0)
+		goto error;	
+
+	rc = mio_driver_op_add(op, NULL, NULL, sync_op);
+	if (rc < 0)
+		goto error;
+	m0_clovis_op_launch(&sync_op, 1);
+	return 0;
+
+error:
+	m0_clovis_op_fini(sync_op);
+	m0_clovis_op_free(sync_op);
+	return rc;
+}
+
+/**
+ * Note: currently Mero Clovis doesn't store size as object attribute
+ * and doesn't have any API to query object size. MIO will use an index
+ * (attribute index) to manage object attributes such as object size.
+ * This also implies that any object WRITE has to update the size.
+ * Depending on workload and performance of Mero index, MIO may support
+ * multiple indics.
+ * 
+ * Format of object attributes that are stored in attribute index are
+ * defined as below:
+ *
+ * struct clovis_obj_attrs_onwire {
+ *	struct mio_obj_attrs coa_attrs;
+ *      int coa_nr_hints;
+ *      int coa_hint_keys[];   // array of hint's keys
+ *      uint64_t coa_hint_values[]; // array of hint's values
+ * };
+ *
+ * Note: MIO assumes application takes care of concurrent accesses to
+ * an object and its attributes.
+ */
+
+struct clovis_obj_attrs_pp_args {
+	int32_t *aca_rc;
+	struct m0_bufvec *aca_key;
+	struct m0_bufvec *aca_val;
+	/* Where the returned attributes are copied to. */
+	struct mio_obj *aca_to;
+};
+
+static int clovis_obj_attr_nonhint_size(struct mio_obj *obj)
+{
+	int size;
+
+	size = sizeof obj->mo_attrs.moa_size;
+	size += sizeof obj->mo_attrs.moa_wtime;
+	return size;
+}
+
+static int
+clovis_obj_attrs_mem2wire(struct mio_obj *obj,
+			  uint64_t *attr_size, void **attr_buf)
+{
+	int i;
+	int nonhint_size;
+	uint64_t size;
+	void *buf;
+	char *ptr;
+	struct mio_hint_map *map = &obj->mo_attrs.moa_phints.mh_map;
+
+	nonhint_size  = clovis_obj_attr_nonhint_size(obj);
+	size = nonhint_size;
+	size += sizeof(int);
+	size += map->mhm_nr_set * (sizeof(int) + sizeof(uint64_t));
+
+	buf = mio_mem_alloc(size);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	ptr = buf;
+	mio_mem_copy(ptr, &obj->mo_attrs, nonhint_size);
+	ptr += nonhint_size;
+
+	mio_mem_copy(ptr, &map->mhm_nr_set, sizeof(int));
+	ptr += sizeof(int);
+
+	for (i = 0; i < map->mhm_nr_set; i++) {
+		mio_mem_copy(ptr, map->mhm_keys + i, sizeof(int));
+		ptr += sizeof(int);
+	}
+
+	for (i = 0; i < map->mhm_nr_set; i++) {
+		mio_mem_copy(ptr, map->mhm_values + i, sizeof(uint64_t));
+		ptr += sizeof(uint64_t);
+	}
+
+	*attr_size = size;
+	*attr_buf = buf;
+	return 0;
+}
+
+static int
+clovis_obj_attrs_wire2mem(struct mio_obj *obj, int attr_size, void *attr_buf)
+{
+	int i;
+	int nonhint_size;
+	int size;
+	int nr_hints;
+	char *ptr;
+	/* Note that hint map has been initialised with default number. */
+	struct mio_hint_map *map = &obj->mo_hints.mh_map;
+
+	nonhint_size = clovis_obj_attr_nonhint_size(obj);
+	ptr = attr_buf;
+	mio_mem_copy(&obj->mo_attrs, ptr, nonhint_size);
+	ptr += nonhint_size;
+
+	mio_mem_copy(&nr_hints, ptr, sizeof(int));
+	ptr += sizeof(int);
+	if (nr_hints < 0 || nr_hints > MIO_OBJ_HINT_NUM)
+		return -EIO;
+	else if (nr_hints == 0)
+		return 0;
+	map->mhm_nr_set = nr_hints;
+
+	size  = nonhint_size;
+	size += sizeof(int);
+	size += nr_hints * (sizeof(int) + sizeof(uint64_t));
+	if (attr_size != size)
+		return -EIO;
+
+	for (i = 0; i < nr_hints; i++) {
+		mio_mem_copy(map->mhm_keys + i, ptr, sizeof(int));
+		ptr += sizeof(int);
+	}
+
+	for (i = 0; i < nr_hints; i++) {
+		mio_mem_copy(map->mhm_values + i, ptr, sizeof(uint64_t));
+		ptr += sizeof(uint64_t);
+	}
+
+	return 0;
+}
+
+static int clovis_obj_attrs_query(int opcode, struct mio_obj *obj,
+				  mio_driver_op_postprocess op_pp,
+				  struct mio_op *op)
+{
+	int rc;
+	int32_t *qrc = NULL; /* return value for kvs query. */
+        struct m0_uint128 *id128;
+        struct m0_bufvec *key = NULL;
+        struct m0_bufvec *val = NULL;
+	struct m0_clovis_idx *idx;
+	struct m0_clovis_op *cops[1] = {NULL};
+	struct clovis_obj_attrs_pp_args *args;
+
+	assert(opcode == M0_CLOVIS_IC_GET || opcode == M0_CLOVIS_IC_PUT ||
+	       opcode == M0_CLOVIS_IC_DEL);
+
+	id128 = mio_mem_alloc(sizeof *id128);
+	qrc = mio_mem_alloc(sizeof(int32_t));
+	args = mio_mem_alloc(sizeof *args);
+	if (id128 == NULL || qrc == NULL || args == NULL) {
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	/* Allocate bufvec's for keys and values. */
+	key = mio__clovis_bufvec_alloc(1);
+	if (key == NULL) {
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	if (opcode != M0_CLOVIS_IC_DEL) {
+		val = mio__clovis_bufvec_alloc(1);
+		if (val == NULL) {
+			rc = -ENOMEM;
+			goto error;
+		}
+	}
+
+        /* Fill key and value. TODO: serialise key and value? */
+	mio__obj_id_to_uint128(&obj->mo_id, id128);
+	key->ov_vec.v_count[0] = sizeof *id128;
+	key->ov_buf[0] = id128;
+
+	if (opcode == M0_CLOVIS_IC_PUT) 
+		clovis_obj_attrs_mem2wire(obj, &val->ov_vec.v_count[0],
+					  &val->ov_buf[0]);
+
+	/* Create index's op. */
+	idx = (struct m0_clovis_idx *)obj->mo_md_kvs->mk_drv_kvs;
+	rc = m0_clovis_idx_op(idx, opcode, key, val, qrc, 0, &cops[0]);
+	if (rc < 0)
+		goto error;
+
+	/* Set callback function and arguments. */
+	args->aca_val = val;
+	args->aca_key = key;
+	args->aca_rc = qrc;
+	args->aca_to = obj;
+	rc = mio_driver_op_add(op, op_pp, args, cops[0]);
+	if (rc < 0)
+		goto error;
+
+	m0_clovis_op_launch(cops, 1);
+	return 0;
+
+error:
+	clovis_bufvec_free(key);
+	clovis_bufvec_free(val);
+	mio_mem_free(qrc);
+	mio_mem_free(args);
+	return rc;
+}
+
+static int clovis_obj_attrs_query_free_pp(struct mio_op *op)
+{
+	struct clovis_obj_attrs_pp_args *args;
+
+	args = (struct clovis_obj_attrs_pp_args *)
+	       op->mop_drv_op_chain.mdoc_head->mdo_post_proc_data;
+	clovis_bufvec_free(args->aca_key);
+	clovis_bufvec_free(args->aca_val);
+	mio_mem_free(args->aca_rc);
+	mio_mem_free(args);
+
+	return MIO_DRV_OP_FINAL;
+}
+
+static int clovis_obj_attrs_get_pp(struct mio_op *op)
+{
+	struct m0_bufvec *ret_val;
+	struct m0_clovis_op *cop = MIO_CLOVIS_OP(op);
+	struct mio_obj *obj;
+	struct clovis_obj_attrs_pp_args *args;
+
+	assert(cop != NULL);
+	args = (struct clovis_obj_attrs_pp_args *)
+	       op->mop_drv_op_chain.mdoc_head->mdo_post_proc_data;
+	obj = args->aca_to;
+	ret_val = args->aca_val;
+	if (ret_val->ov_vec.v_count[0] != 0)
+		clovis_obj_attrs_wire2mem(obj, ret_val->ov_vec.v_count[0],
+					  ret_val->ov_buf[0]);
+
+	return clovis_obj_attrs_query_free_pp(op);
+}
+
+static int mio_clovis_obj_size(struct mio_obj *obj, struct mio_op *op)
+{
+	return clovis_obj_attrs_query(M0_CLOVIS_IC_GET, obj,
+				      clovis_obj_attrs_get_pp, op);
+}
+
+static int mio_clovis_obj_hint_store(struct mio_obj *obj)
+{
+	int rc;
+	struct mio_op mop;
+	struct m0_clovis_op *cop;
+
+	mio_memset(&mop, 0, sizeof mop);
+	mio_obj_op_init(&mop, obj, MIO_OBJ_ATTRS_SET);
+	rc = clovis_obj_attrs_query(M0_CLOVIS_IC_PUT, obj,
+				    clovis_obj_attrs_query_free_pp, &mop);
+	if (rc < 0)
+		return rc;
+
+	cop = MIO_CLOVIS_OP((&mop));
+	rc = m0_clovis_op_wait(cop,
+			       M0_BITS(M0_CLOVIS_OS_FAILED,
+				       M0_CLOVIS_OS_STABLE),
+			       M0_TIME_NEVER);
+	rc = rc? : m0_clovis_rc(cop);
+	m0_clovis_op_fini(cop);
+	m0_clovis_op_free(cop);
+	return rc;
+}
+
+static int mio_clovis_obj_hint_load(struct mio_obj *obj)
+{
+	/*
+	 * Hints are retrieved when an object is opened, no more work
+	 * here.
+	 */
+	return 0;
+}
+
+static struct mio_obj_ops mio_clovis_obj_ops = {
+        .moo_open         = mio_clovis_obj_open,
+        .moo_close        = mio_clovis_obj_close,
+        .moo_create       = mio_clovis_obj_create,
+        .moo_delete       = mio_clovis_obj_delete,
+        .moo_writev       = mio_clovis_obj_writev,
+        .moo_readv        = mio_clovis_obj_readv,
+        .moo_sync         = mio_clovis_obj_sync,
+        .moo_size         = mio_clovis_obj_size,
+        .moo_hint_store   = mio_clovis_obj_hint_store,
+        .moo_hint_load    = mio_clovis_obj_hint_load,
+};
+
+static void kvs_id_to_uint128(const struct mio_kvs_id *kid,
+			      struct m0_uint128 *uint128)
+{
+	struct m0_fid idx_fid;
+	uint64_t hi;
+	uint64_t lo;
+ 
+	hi = mio_byteorder_be64_to_cpu(*((uint64_t *)(kid->mki_bytes + 0)));
+	lo = mio_byteorder_be64_to_cpu(*((uint64_t *)(kid->mki_bytes + 8)));
+	/* Make mero KVS happy */
+        idx_fid = M0_FID_TINIT('x', hi, lo);
+
+	uint128->u_hi = idx_fid.f_container; 
+	uint128->u_lo = idx_fid.f_key;
+}
+
+static int
+clovis_kvs_idx_alloc_init(struct mio_kvs_id *kid, struct m0_clovis_idx **out)
+{	
+        struct m0_uint128 id;
+	struct m0_clovis_idx *idx;
+
+	idx = mio_mem_alloc(sizeof *idx);
+	if (idx == NULL)
+		return -ENOMEM;
+	
+	kvs_id_to_uint128(kid, &id);
+	m0_clovis_idx_init(idx, &mio_clovis_container.co_realm, &id);
+	*out = idx;
+	return 0;
+}
+
+static void clovis_kvs_idx_fini_free(struct m0_clovis_idx *idx)
+{
+	m0_clovis_entity_fini(&idx->in_entity);
+	mio_mem_free(idx);
+}
+
+static int
+clovis_kvs_keys_vals_alloc(int opcode, int nr_kvps,
+			   struct m0_bufvec **ret_keys,
+			   struct m0_bufvec **ret_vals)
+{
+	int rc = 0;
+        struct m0_bufvec *keys;
+        struct m0_bufvec *vals = NULL;
+
+	assert(opcode == M0_CLOVIS_IC_GET || opcode == M0_CLOVIS_IC_PUT ||
+	       opcode == M0_CLOVIS_IC_DEL);
+
+	keys = mio__clovis_bufvec_alloc(nr_kvps);
+	if (keys == NULL) {
+		rc = -ENOMEM;
+		goto error;
+	}
+	
+	if (opcode != M0_CLOVIS_IC_DEL) {
+		vals = mio__clovis_bufvec_alloc(nr_kvps);
+		if (vals == NULL) {
+			rc = -ENOMEM;
+			goto error;
+		}
+	}
+
+	*ret_keys = keys;
+	*ret_vals = vals;
+	return 0;
+
+error:
+	clovis_bufvec_free(keys);
+	clovis_bufvec_free(vals);
+	return rc;
+}
+
+static int clovis_kvs_query(struct m0_clovis_idx *idx, int opcode,
+			    int nr_kvps, struct mio_kv_pair *kvps, int32_t *rcs,
+			    struct m0_bufvec *keys, struct m0_bufvec *vals,
+			    mio_driver_op_postprocess query_pp, void *cb_args,
+			    struct mio_op *op)
+{
+	int i;
+	int rc = 0;
+	bool set_vals;
+	struct m0_clovis_op *cops[1] = {NULL};
+
+	assert(opcode == M0_CLOVIS_IC_GET || opcode == M0_CLOVIS_IC_PUT ||
+	       opcode == M0_CLOVIS_IC_DEL);
+
+	set_vals = (opcode == M0_CLOVIS_IC_PUT)? true : false;
+
+        /* Fill keys and values. */
+	for (i = 0; i < nr_kvps; i++) {
+		keys->ov_vec.v_count[i] = kvps[i].mkp_klen;
+		keys->ov_buf[i] = kvps[i].mkp_key;
+
+		if (set_vals) {
+			assert(vals != NULL);
+			vals->ov_vec.v_count[i] = kvps[i].mkp_vlen;
+			vals->ov_buf[i] = kvps[i].mkp_val;
+		}
+	}
+
+	/* Create index op. */
+	rc = m0_clovis_idx_op(idx, opcode, keys, vals, rcs, 0, &cops[0]);
+	if (rc < 0)
+		goto error;
+
+	/* Set query's callback and arguments. */
+	rc = mio_driver_op_add(op, query_pp, cb_args, cops[0]);
+	if (rc < 0)
+		goto error;
+
+	/* Launch query. */
+	m0_clovis_op_launch(cops, 1);
+
+	return 0;
+
+error:
+	clovis_bufvec_free(keys);
+	clovis_bufvec_free(vals);
+	return rc;
+}
+
+struct clovis_kvs_get_args {
+	struct m0_bufvec *kga_rvs; /* Returned values from clovis GET op. */
+	struct mio_kv_pair *kga_orig_pairs; /* Original pointer from app. */
+	struct m0_clovis_idx *kga_idx; /* The clovis index for the GET op. */
+};
+
+static int clovis_kvs_get_pp(struct mio_op *op)
+{
+	int i;
+	int nr_kvps;
+	struct clovis_kvs_get_args *args;
+	struct mio_kv_pair *kvps;
+	struct m0_bufvec *rvs;
+	struct m0_clovis_op *cop = MIO_CLOVIS_OP(op);
+
+	assert(cop != NULL);
+	if (cop->op_sm.sm_state != M0_CLOVIS_OS_STABLE)
+		return -EIO;
+
+	/* Copy returned values. */
+	args = (struct clovis_kvs_get_args *)
+	       op->mop_drv_op_chain.mdoc_head->mdo_post_proc_data;
+	kvps = args->kga_orig_pairs;
+	rvs  = args->kga_rvs;
+	nr_kvps = rvs->ov_vec.v_nr;
+	for (i = 0; i < nr_kvps; i++) {
+		kvps[i].mkp_val = rvs->ov_buf[i];
+		kvps[i].mkp_vlen = rvs->ov_vec.v_count[i];
+	}
+
+	clovis_kvs_idx_fini_free(args->kga_idx);
+	mio_mem_free(args);
+	return MIO_DRV_OP_FINAL;
+}
+
+static int mio_clovis_kvs_get(struct mio_kvs_id *kid,
+			      int nr_kvps, struct mio_kv_pair *kvps,
+			      int32_t *rcs, struct mio_op *op)
+{
+	int rc;
+	struct clovis_kvs_get_args *args;
+	struct m0_clovis_idx *idx;
+	struct m0_bufvec *keys = NULL;
+	struct m0_bufvec *vals = NULL;	
+
+	rc = clovis_kvs_idx_alloc_init(kid, &idx);
+	if (rc < 0)
+		return rc;
+
+	rc = clovis_kvs_keys_vals_alloc(
+			M0_CLOVIS_IC_GET, nr_kvps, &keys, &vals);
+	if (rc < 0)
+		goto error;
+
+	args = mio_mem_alloc(sizeof *args);
+	if (args == NULL) {
+		rc = -ENOMEM;
+		goto error;
+	}
+
+       	/* Save the arguments for post-processing. */
+	args->kga_rvs = vals;
+	args->kga_orig_pairs = kvps;
+	args->kga_idx = idx;
+
+	rc = clovis_kvs_query(idx, M0_CLOVIS_IC_GET,
+			      nr_kvps, kvps, rcs, keys, vals,
+			      clovis_kvs_get_pp, args, op);
+	if (rc < 0) {
+		clovis_kvs_idx_fini_free(idx);
+		mio_mem_free(args);
+	}
+	return rc;
+
+error:
+	clovis_kvs_idx_fini_free(idx);
+	clovis_bufvec_free(keys);
+	clovis_bufvec_free(vals);
+	mio_mem_free(args);
+	return rc;
+}
+
+static int clovis_kvs_generic_pp(struct mio_op *op)
+{
+	struct m0_clovis_idx *idx;
+
+	idx = (struct m0_clovis_idx*)
+	      op->mop_drv_op_chain.mdoc_head->mdo_post_proc_data;
+	clovis_kvs_idx_fini_free(idx);
+
+	return MIO_DRV_OP_FINAL;
+}
+
+static int mio_clovis_kvs_put(struct mio_kvs_id *kid,
+			      int nr_kvps, struct mio_kv_pair *kvps,
+			      int32_t *rcs, struct mio_op *op)
+{
+	int rc;
+	struct m0_clovis_idx *idx;
+	struct m0_bufvec *keys = NULL;
+	struct m0_bufvec *vals = NULL;	
+
+	rc = clovis_kvs_idx_alloc_init(kid, &idx);
+	if (rc < 0)
+		return rc;
+
+	rc = clovis_kvs_keys_vals_alloc(
+			M0_CLOVIS_IC_PUT, nr_kvps, &keys, &vals);
+	if (rc < 0) {
+		clovis_kvs_idx_fini_free(idx);
+		return rc;
+	}
+
+	return clovis_kvs_query(idx, M0_CLOVIS_IC_PUT,
+				nr_kvps, kvps, rcs, keys, vals,
+				clovis_kvs_generic_pp, idx, op);
+}
+
+static int mio_clovis_kvs_del(struct mio_kvs_id *kid,
+			      int nr_kvps, struct mio_kv_pair *kvps,
+			      int32_t *rcs, struct mio_op *op)
+{
+
+	int rc;
+	struct m0_clovis_idx *idx;
+	struct m0_bufvec *keys = NULL;
+	struct m0_bufvec *vals = NULL;	
+
+	rc = clovis_kvs_idx_alloc_init(kid, &idx);
+	if (rc < 0)
+		return rc;
+
+	rc = clovis_kvs_keys_vals_alloc(
+			M0_CLOVIS_IC_DEL, nr_kvps, &keys, &vals);
+	if (rc < 0) {
+		clovis_kvs_idx_fini_free(idx);
+		return rc;
+	}
+
+	return clovis_kvs_query(idx, M0_CLOVIS_IC_DEL,
+				nr_kvps, kvps, rcs, keys, vals,
+				clovis_kvs_generic_pp, idx, op);
+}
+
+static int mio_clovis_kvs_create_set(struct mio_kvs_id *kid,
+				     struct mio_op *op)
+{
+        int rc;
+        struct m0_clovis_op *cops[1] = {NULL};
+        struct m0_clovis_idx *idx;
+
+	rc = clovis_kvs_idx_alloc_init(kid, &idx);
+	if (rc < 0)
+		return rc;
+
+        rc = m0_clovis_entity_create(NULL, &idx->in_entity, &cops[0]);
+	if (rc < 0)
+		return rc;
+
+	rc = mio_driver_op_add(op, clovis_kvs_generic_pp, idx, cops[0]);
+	if (rc < 0)
+		goto error;
+        m0_clovis_op_launch(cops, 1);
+	return 0;
+
+error:
+	clovis_kvs_idx_fini_free(idx);
+	m0_clovis_op_fini(cops[0]);
+	m0_clovis_op_free(cops[0]);
+	return rc;
+}
+
+static int mio_clovis_kvs_del_set(struct mio_kvs_id *kid,
+				  struct mio_op *op)
+{
+        int rc;
+        struct m0_clovis_op *cops[1] = {NULL};
+        struct m0_clovis_idx *idx;
+
+	rc = clovis_kvs_idx_alloc_init(kid, &idx);
+	if (rc < 0)
+		return rc;
+
+	/*
+ 	 * Clovis Index has to be opened before deleting it but not before
+ 	 * querying it. How odd! Who to blame? :).
+ 	 * The only thing openning an index is to make sure the index is in
+ 	 * a right state. 
+ 	 */
+	m0_clovis_entity_open(&idx->in_entity, &cops[0]);
+        rc = m0_clovis_entity_delete(&idx->in_entity, &cops[0]);
+	if (rc < 0)
+		goto error;
+
+	rc = mio_driver_op_add(op, clovis_kvs_generic_pp, idx, cops[0]);
+	if (rc < 0)
+		goto error;
+
+        m0_clovis_op_launch(cops, 1);
+	return 0;
+
+error:
+	clovis_kvs_idx_fini_free(idx);
+	m0_clovis_op_fini(cops[0]);
+	m0_clovis_op_free(cops[0]);
+	return rc;
+}
+
+static struct mio_kvs_ops mio_clovis_kvs_ops = {
+        .mko_get        = mio_clovis_kvs_get,
+        .mko_put        = mio_clovis_kvs_put,
+        .mko_del        = mio_clovis_kvs_del,
+        .mko_create_set = mio_clovis_kvs_create_set,
+        .mko_del_set    = mio_clovis_kvs_del_set
+};
+
+void mio_clovis_driver_register()
+{
+	mio_driver_register(
+		MIO_MERO, &mio_clovis_sys_ops,
+		&mio_clovis_op_ops, &mio_clovis_obj_ops,
+		&mio_clovis_kvs_ops, &mio_clovis_comp_obj_ops);
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/src/driver_clovis.h b/deps/mio/src/driver_clovis.h
new file mode 100644
index 0000000000000000000000000000000000000000..0aad5f846c60ae5b4d8421c3c61867e597b017b1
--- /dev/null
+++ b/deps/mio/src/driver_clovis.h
@@ -0,0 +1,64 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#ifndef __DRIVER_CLOVIS_H__
+#define __DRIVER_CLOVIS_H__
+
+#include "lib/memory.h"
+#include "clovis/clovis.h"
+#include "clovis/clovis_idx.h"
+
+#ifndef __MIO_CLOVIS_COMP_OBJ_LAYER_GET_SUPP__
+#include "lib/list.h"
+#include "lib/tlist.h"
+#include "clovis/clovis_layout.h"
+
+#ifndef container_of
+#define container_of(ptr, type, member) \
+        ((type *)((char *)(ptr)-(char *)(&((type *)0)->member)))
+#endif
+#endif /* __MIO_CLOVIS_COMP_OBJ_LAYER_GET_SUPP__*/
+
+#define ARRAY_SIZE(a) ((sizeof (a)) / (sizeof (a)[0]))
+
+enum {
+	MIO_CLOVIS_MAX_RW_NR_UNITS_PER_OP = 1024 
+};
+
+extern struct m0_clovis *mio_clovis_instance;
+extern struct m0_clovis_container mio_clovis_container;
+extern struct mio_mero_config *mio_clovis_inst_confs;
+
+extern struct mio_comp_obj_ops mio_clovis_comp_obj_ops;
+
+void mio_clovis_driver_register();
+
+/* Helper functions. */
+struct m0_bufvec* mio__clovis_bufvec_alloc(int nr);
+void mio__obj_id_to_uint128(const struct mio_obj_id *oid,
+			    struct m0_uint128 *uint128);
+void mio__uint128_to_obj_id(struct m0_uint128 *uint128,
+			    struct mio_obj_id *oid);
+#endif
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/src/driver_clovis_comp_obj.c b/deps/mio/src/driver_clovis_comp_obj.c
new file mode 100644
index 0000000000000000000000000000000000000000..f6accf218b0dfe4c70171b072bd5f35213e48e69
--- /dev/null
+++ b/deps/mio/src/driver_clovis_comp_obj.c
@@ -0,0 +1,679 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <errno.h>
+#include <assert.h>
+
+#include "lib/vec.h"
+#include "clovis/clovis.h"
+#include "clovis/clovis_idx.h"
+
+#include "logger.h"
+#include "mio.h"
+#include "mio_internal.h"
+#include "driver_clovis.h"
+
+/*
+ * Creating a composite object includes 2 steps:
+ * (1) Create a `normal` object.
+ * (2) Set composite layout for this newly created object.
+ *
+ * mio_composite_obj_create() is called after an object is created
+ * by mio_obj_create(). The decision to not pack the above 2 steps
+ * in mio_composite_obj_create() is to handle failures properly.
+ * A failure could happen in creating a `normal` object or setting
+ * composite layout, which requires different clear-up handling. 
+ *
+ * Note: MIO only supports creating a composite object from a newly
+ * created one (not yet written any data).
+ */
+
+static int
+mio_clovis_comp_obj_create(struct mio_obj *obj, struct mio_op *op)
+{
+	int rc;
+	struct m0_clovis_obj *cobj;
+	struct m0_clovis_op *cops[1] = {NULL};
+        struct m0_clovis_layout *layout;
+
+        layout = m0_clovis_layout_alloc(M0_CLOVIS_LT_COMPOSITE);
+	if (layout == NULL)
+		return -ENOMEM;
+
+	cobj = (struct m0_clovis_obj *)obj->mo_drv_obj;
+        /*
+	 * A bug in clovis doesn't set the object's layout pointer.
+	 */
+	if (cobj->ob_layout == NULL)
+		cobj->ob_layout = layout;
+	m0_clovis_layout_op(cobj, M0_CLOVIS_EO_LAYOUT_SET,
+			    layout, &cops[0]);
+
+	rc = mio_driver_op_add(op, NULL, NULL, cops[0]);
+	if (rc < 0)
+		goto error;
+	m0_clovis_op_launch(cops, ARRAY_SIZE(cops));
+	return 0;
+
+error:
+	m0_clovis_op_fini(cops[0]);
+	m0_clovis_op_free(cops[0]);
+	m0_clovis_layout_free(layout);
+	return rc;
+}
+
+struct clovis_comp_obj_add_layer_pp_args {
+	int alpa_nr_layers_to_add;
+	struct m0_clovis_obj *alpa_layer_objs;
+	struct m0_clovis_layout *alpa_layout;
+};
+
+static int clovis_comp_obj_add_layers_pp(struct mio_op *op)
+{
+	int i;
+	struct clovis_comp_obj_add_layer_pp_args *pp_args;
+
+	pp_args = (struct clovis_comp_obj_add_layer_pp_args *)
+		  op->mop_drv_op_chain.mdoc_head->mdo_post_proc_data;
+	for (i = 0; i < pp_args->alpa_nr_layers_to_add; i++)
+		m0_clovis_obj_fini(pp_args->alpa_layer_objs + i);
+	mio_mem_free(pp_args->alpa_layer_objs);
+	mio_mem_free(pp_args);
+
+	return MIO_DRV_OP_FINAL;
+}
+
+static int
+mio_clovis_comp_obj_add_layers(struct mio_obj *obj, int nr_layers,
+			       struct mio_comp_obj_layer *layers,
+			       struct mio_op *op)
+{
+	int rc = 0;
+	int i;
+	int j;
+	struct m0_uint128 id128;
+	struct m0_clovis_obj *layer_objs;
+	struct m0_clovis_obj *cobj;
+	struct m0_clovis_op *cops[1] = {NULL};
+        struct m0_clovis_layout *layout = NULL;
+	struct clovis_comp_obj_add_layer_pp_args *pp_args;
+
+	pp_args = mio_mem_alloc(sizeof(*pp_args));
+	layer_objs = mio_mem_alloc(nr_layers * sizeof(*layer_objs));
+	if (pp_args == NULL || layer_objs == NULL) {
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	cobj = (struct m0_clovis_obj *)obj->mo_drv_obj;
+	/* The layout may have been changed. */
+	if (cobj->ob_layout != NULL)
+		m0_clovis_layout_free(cobj->ob_layout);
+	layout = m0_clovis_layout_alloc(M0_CLOVIS_LT_COMPOSITE);
+	if (layout == NULL) {
+		rc = -ENOMEM;
+		goto error;
+	}
+	cobj->ob_layout = layout;
+
+        for (i = 0; i < nr_layers; i++) {
+		mio__obj_id_to_uint128(&layers[i].mcol_oid, &id128);
+		m0_clovis_obj_init(layer_objs + i, 
+				   &mio_clovis_container.co_realm, &id128,
+				   mio_clovis_inst_confs->mc_default_layout_id);
+                rc = m0_clovis_composite_layer_add(
+			layout, layer_objs + i, layers[i].mcol_priority);
+                if (rc < 0)
+                        break;
+        }
+        if (rc != 0) {
+                for (j = 0; j < i; j++)
+                        m0_clovis_composite_layer_del(
+				layout, layer_objs[j].ob_entity.en_id);
+		goto error;
+        }
+	
+        m0_clovis_layout_op(cobj, M0_CLOVIS_EO_LAYOUT_SET,
+			    layout, &cops[0]);
+
+	pp_args->alpa_nr_layers_to_add = nr_layers;
+	pp_args->alpa_layer_objs = layer_objs;
+	pp_args->alpa_layout = layout;
+	rc = mio_driver_op_add(op, clovis_comp_obj_add_layers_pp,
+			       pp_args, cops[0]);
+	if (rc < 0)
+		goto error;
+
+	m0_clovis_op_launch(cops, ARRAY_SIZE(cops));
+	return 0;
+
+error:
+	if (layout)
+		m0_clovis_layout_free(layout);
+	mio_mem_free(layer_objs);
+	mio_mem_free(pp_args);
+	return rc;
+}
+
+struct clovis_comp_obj_get_layers_args {
+	/* Returned object layout. */
+	struct m0_clovis_layout *gla_clayout;
+	/*
+	 * Customized data for layer query. For layer listing, it is
+	 * set to the pointer of MIO layout data structure from
+	 * applications. But for layer deleting, it is set to
+	 * the pointer of an array of layers to be deleted.
+	 */
+	void *gla_data;
+};
+
+static int
+clovis_comp_obj_get_layers(struct mio_obj *obj,
+			   void *query_data, mio_driver_op_postprocess pp,
+			   struct mio_op *op)
+{
+	int rc;
+	struct clovis_comp_obj_get_layers_args *args;
+	struct m0_clovis_layout *clayout = NULL;
+	struct m0_clovis_obj *cobj;
+	struct m0_clovis_op *cops[1] = {NULL};
+	
+	args = mio_mem_alloc(sizeof *args);
+	if (args == NULL)
+		return -ENOMEM;
+
+	cobj = (struct m0_clovis_obj *)obj->mo_drv_obj;
+	/* The layout may have been changed. */
+	if (cobj->ob_layout != NULL)
+		m0_clovis_layout_free(cobj->ob_layout);
+	clayout = m0_clovis_layout_alloc(M0_CLOVIS_LT_COMPOSITE);
+	if (clayout == NULL) {
+		rc = -ENOMEM;
+		goto error;
+	}
+	cobj->ob_layout = clayout;
+
+        m0_clovis_layout_op(cobj, M0_CLOVIS_EO_LAYOUT_GET, clayout, &cops[0]);
+      
+	args->gla_data = query_data;
+	args->gla_clayout = clayout;
+	rc = mio_driver_op_add(op, pp, args, cops[0]);
+	if (rc < 0)
+		goto error;
+	m0_clovis_op_launch(cops, ARRAY_SIZE(cops));
+	return 0;
+
+error:
+	m0_clovis_op_fini(cops[0]);
+	m0_clovis_op_free(cops[0]);
+	m0_clovis_layout_free(clayout);
+	return rc;
+}
+
+struct clovis_comp_obj_del_layers_args {
+	int dla_nr_layers_to_del;
+	struct mio_comp_obj_layer *dla_layers_to_del;
+};
+
+static int
+clovis_comp_obj_del_layers_pp(struct mio_op *op)
+{
+	int rc = 0;
+	int i;
+	struct mio_obj *obj;
+	struct m0_uint128 id128;
+	struct m0_clovis_obj *cobj;
+	struct m0_clovis_op *cops[1] = {NULL};
+        struct m0_clovis_layout *clayout;
+	int nr_layers_to_del;
+	struct mio_comp_obj_layer *layers_to_del;
+	struct clovis_comp_obj_get_layers_args *args;
+	struct clovis_comp_obj_del_layers_args *del_layers_args;
+
+	obj = op->mop_who.obj;
+	assert(obj != NULL);
+
+	args = (struct clovis_comp_obj_get_layers_args *)
+	       op->mop_drv_op_chain.mdoc_head->mdo_post_proc_data;
+	assert(args != NULL);
+	del_layers_args = 
+		(struct clovis_comp_obj_del_layers_args*) args->gla_data;
+	nr_layers_to_del = del_layers_args->dla_nr_layers_to_del;
+	layers_to_del = del_layers_args->dla_layers_to_del;
+	clayout = (struct m0_clovis_layout *)args->gla_clayout;
+
+	/* Here to remove the layers required. */
+        for (i = 0; i < nr_layers_to_del; i++) {
+		mio__obj_id_to_uint128(&layers_to_del[i].mcol_oid, &id128);	
+		m0_clovis_composite_layer_del(clayout, id128);
+        }
+
+	/* Create and launch LAYOUT op. */
+	cobj = (struct m0_clovis_obj *)obj->mo_drv_obj;
+        m0_clovis_layout_op(cobj, M0_CLOVIS_EO_LAYOUT_SET, clayout, &cops[0]);
+
+	rc = mio_driver_op_add(op, NULL, NULL, cops[0]);
+	if (rc < 0)
+		goto exit;
+	m0_clovis_op_launch(cops, ARRAY_SIZE(cops));
+	rc = MIO_DRV_OP_NEXT;
+
+exit:
+	mio_mem_free(del_layers_args);
+	mio_mem_free(args);
+	return rc;
+}
+
+static int
+mio_clovis_comp_obj_del_layers(struct mio_obj *obj,
+			       int nr_layers_to_del,
+			       struct mio_comp_obj_layer *layers_to_del,
+			       struct mio_op *op)
+{
+	struct clovis_comp_obj_del_layers_args *args;
+
+	/*
+	 * Deleting layers of a composite object is done in 2 steps:
+	 * (1) retrieve the composite object's layout (how many layers).
+	 * (2) delete layers from the layout and launch an operation to
+	 *     update the layout in Mero service side.
+	 */
+	
+	args = mio_mem_alloc(sizeof *args);
+	if (args == NULL)
+		return -ENOMEM;
+	args->dla_nr_layers_to_del = nr_layers_to_del;
+	args->dla_layers_to_del = layers_to_del;
+
+	return clovis_comp_obj_get_layers(obj, args,
+			clovis_comp_obj_del_layers_pp, op);
+}
+
+/**
+ * A new Clovis API to parse the Clovis composite layout data structure is
+ * needed as a privately defined list is used in Clovis.
+ * Place holder: m0_clovis_composite_layer_get().
+ *
+ * Temporary solution: MIO hacks it by iterating the layer list by explictly
+ * manipulating the list as m0_tl_* APIs are exposed in 'libmero'.
+ */
+#ifdef __MIO_CLOVIS_COMP_OBJ_LAYER_GET_SUPP__
+static int clovis_comp_obj_list_layers_pp(struct mio_op *op)
+{
+	int i;
+	int rc = 0;
+	uint64_t nr_layers = 0;
+	struct m0_uint128 *layer_ids;
+	struct m0_clovis_op *cop;
+	struct m0_clovis_layout *clayout;
+	struct mio_comp_obj_layout *mlayout;
+	struct clovis_comp_obj_get_layers_args *args;
+
+	cop = (struct m0_clovis_op *)
+	      op->mop_drv_op_chain.mdoc_head->mdo_op;
+	assert(cop != NULL);
+	if (cop->op_sm.sm_state != M0_CLOVIS_OS_STABLE)
+		return -EIO;
+
+	args = (struct clovis_comp_obj_get_layers_args *)
+	       op->mop_drv_op_chain.mdoc_head->mdo_post_proc_data;
+	mlayout = (struct mio_comp_obj_layout *)args->gla_data;
+	clayout = (struct m0_clovis_layout *)args->gla_clayout;
+
+	/* Retrieve layers. */
+	rc = m0_clovis_composite_layer_get(clayout, &nr_layers, &layer_ids);
+	if (rc < 0)
+		goto exit;
+
+	mlayout->mlo_nr_layers = nr_layers;
+	mlayout->mlo_layers =
+		mio_mem_alloc(nr_layers * sizeof(struct mio_comp_obj_layer));
+	if (mlayout->mlo_layers == NULL) {
+		rc = -ENOMEM;
+		goto exit;
+	}
+
+	for (i = 0; i < nr_layers; i++)
+		mio__uint128_to_obj_id(
+			layers_ids + i, &((mlayout->mlo_layers[i]).mcol_oid));
+	assert(rc == 0);
+
+exit:
+	mio_mem_free(layer_ids);
+	return rc;
+}
+
+#else
+
+/*
+ * Uggly hacking :).
+ */
+static int clovis_comp_obj_list_layers_pp(struct mio_op *op)
+{
+	int i;
+	int rc = 0;
+	uint64_t nr_layers = 0;
+	struct m0_clovis_op *cop;
+	struct m0_clovis_layout *clayout;
+	struct mio_comp_obj_layout *mlayout;
+	struct m0_clovis_composite_layout *comp_layout;
+	struct m0_clovis_composite_layer *comp_layer;
+	struct m0_list_link *lnk;
+	struct m0_tlink *tlnk;
+	struct clovis_comp_obj_get_layers_args *args;
+
+	cop = (struct m0_clovis_op *)
+	      op->mop_drv_op_chain.mdoc_head->mdo_op;
+	assert(cop != NULL);
+	if (cop->op_sm.sm_state != M0_CLOVIS_OS_STABLE)
+		return -EIO;
+
+	args = (struct clovis_comp_obj_get_layers_args *)
+	       op->mop_drv_op_chain.mdoc_head->mdo_post_proc_data;
+	mlayout = (struct mio_comp_obj_layout *)args->gla_data;
+	clayout = (struct m0_clovis_layout *)args->gla_clayout;
+	comp_layout = container_of(clayout, struct m0_clovis_composite_layout,
+				   ccl_layout);
+
+	nr_layers = comp_layout->ccl_nr_layers;
+	mlayout->mlo_nr_layers = nr_layers;
+	mlayout->mlo_layers =
+		mio_mem_alloc(nr_layers * sizeof(struct mio_comp_obj_layer));
+	if (mlayout->mlo_layers == NULL) {
+		rc = -ENOMEM;
+		goto exit;
+	}
+
+	lnk = comp_layout->ccl_layers.t_head.l_head;
+	for (i = 0; i < nr_layers; i++) {
+		if (lnk == NULL)
+			break;
+
+		tlnk = container_of(lnk, struct m0_tlink, t_link);
+		comp_layer = container_of(tlnk,
+					  struct m0_clovis_composite_layer,
+					  ccr_tlink);
+		mio__uint128_to_obj_id(&comp_layer->ccr_subobj,
+				       &(mlayout->mlo_layers[i]).mcol_oid);
+
+		lnk = lnk->ll_next;
+	}
+	assert(rc == 0);
+	return MIO_DRV_OP_FINAL;
+
+exit:
+	/*
+	 * No need to call m0_clovis_layout_free(clayout) as
+	 * m0_clovis_obj_fini() will release layout data structure
+	 * which is triggerred by mio_obj_close().
+	 */
+	return rc;
+}
+#endif
+
+static int
+mio_clovis_comp_obj_list_layers(struct mio_obj *obj,
+				struct mio_comp_obj_layout *ret_layout,
+				struct mio_op *op)
+{
+	return clovis_comp_obj_get_layers(obj, ret_layout,
+			clovis_comp_obj_list_layers_pp, op);
+}
+
+struct clovis_comp_obj_exts_pp_args {
+        struct m0_clovis_idx *epa_idx;
+	struct m0_bufvec *epa_keys;
+	struct m0_bufvec *epa_vals; /* Returned values from Clovis GET op. */
+	int *epa_rcs;
+	int *epa_nr_ret_exts;
+	struct mio_obj_ext *epa_ret_exts;
+};
+
+static int
+clovis_comp_obj_extent_query(struct mio_obj_id *layer_id,
+			     int nr_exts, struct mio_obj_ext *exts,
+			     int *nr_ret_exts, int opcode, struct mio_op *op,
+			     mio_driver_op_postprocess pp,
+			     struct clovis_comp_obj_exts_pp_args *pp_args)
+{
+	int i;
+        int rc = 0;
+	bool set_vals;
+        struct m0_bufvec *keys = NULL;
+        struct m0_bufvec *vals = NULL;
+        int *rcs = NULL;
+	struct m0_uint128 layer_id128;
+        struct m0_clovis_op *cops[1] = {NULL};
+        struct m0_clovis_idx *idx;
+        struct m0_clovis_composite_layer_idx_key key;
+        struct m0_clovis_composite_layer_idx_val val;
+
+	set_vals = (opcode == M0_CLOVIS_IC_PUT)? true : false;
+
+	idx = mio_mem_alloc(sizeof *idx);
+        keys = mio__clovis_bufvec_alloc(nr_exts);
+        M0_ALLOC_ARR(rcs, nr_exts);
+	if (idx == NULL || keys == NULL || rcs == NULL) {
+                rc = -ENOMEM;
+                goto err_exit;
+        }
+	if (opcode != M0_CLOVIS_IC_DEL) {
+		vals = mio__clovis_bufvec_alloc(nr_exts);
+		if (vals == NULL) {
+			rc = -ENOMEM;
+			goto err_exit;
+		}
+	}
+
+	mio__obj_id_to_uint128(layer_id, &layer_id128);
+        for (i = 0; i < nr_exts; i++) {
+                /* For NEXT op, only set the first key. */
+		if (opcode == M0_CLOVIS_IC_NEXT && i >= 1)
+			break;
+
+                key.cek_layer_id = layer_id128;
+                key.cek_off = exts[i].moe_off;
+                rc = m0_clovis_composite_layer_idx_key_to_buf(
+                        &key, &keys->ov_buf[i], &keys->ov_vec.v_count[i]);
+		if (rc < 0)
+			break;
+ 
+		if (set_vals) {
+                	val.cev_len = exts[i].moe_size;
+			rc = m0_clovis_composite_layer_idx_val_to_buf(
+				&val, &vals->ov_buf[i],
+				&vals->ov_vec.v_count[i]);
+		}
+                if (rc < 0)
+                        break;
+        }
+	if (rc != 0)
+		goto err_exit;
+
+        mio_memset(idx, 0, sizeof *idx);
+        m0_clovis_composite_layer_idx(layer_id128, true, idx);
+        m0_clovis_idx_op(idx, opcode, keys, vals, rcs, 0, &cops[0]);
+
+	assert(pp_args != NULL);
+	pp_args->epa_idx = idx;
+	pp_args->epa_keys = keys;
+	pp_args->epa_vals = vals;
+	pp_args->epa_rcs = rcs;
+	pp_args->epa_ret_exts = exts;
+	pp_args->epa_nr_ret_exts = nr_ret_exts;
+	rc = mio_driver_op_add(op, pp, pp_args, cops[0]);
+	if (rc < 0)
+		goto err_exit;
+
+        m0_clovis_op_launch(cops, 1);
+	return 0;
+
+err_exit:
+	if (cops[0] != NULL) {
+		m0_clovis_op_fini(cops[0]);
+		m0_clovis_op_free(cops[0]);
+	}
+        m0_bufvec_free(keys);
+        m0_bufvec_free(vals);
+        m0_free0(&rcs);
+        mio_mem_free(idx);
+        return rc;
+}
+
+static int clovis_comp_obj_exts_release_pp(struct mio_op *op)
+{
+	struct clovis_comp_obj_exts_pp_args *pp_args;
+
+	pp_args = (struct clovis_comp_obj_exts_pp_args *)
+		  op->mop_drv_op_chain.mdoc_head->mdo_post_proc_data;
+	mio_mem_free(pp_args->epa_idx);
+        m0_bufvec_free(pp_args->epa_keys);
+        m0_bufvec_free(pp_args->epa_vals);
+        m0_free0(&pp_args->epa_rcs);
+	mio_mem_free(pp_args);
+
+	return MIO_DRV_OP_FINAL;
+}
+
+static int
+mio_clovis_comp_obj_add_extents(struct mio_obj *obj,
+				struct mio_obj_id *layer_id,
+				int nr_exts, struct mio_obj_ext *exts,
+				struct mio_op *op)
+{
+	int rc;
+	struct clovis_comp_obj_exts_pp_args *pp_args;
+	
+	pp_args = mio_mem_alloc(sizeof *pp_args);
+	if (pp_args == NULL)
+		return -ENOMEM;
+
+	rc = clovis_comp_obj_extent_query(
+		layer_id, nr_exts, exts, NULL, M0_CLOVIS_IC_PUT, op,
+		clovis_comp_obj_exts_release_pp, pp_args);
+	if (rc < 0)
+		mio_mem_free(pp_args);
+	return rc;
+}
+
+static int
+mio_clovis_comp_obj_del_extents(struct mio_obj *obj,
+				struct mio_obj_id *layer_id,
+				int nr_exts, struct mio_obj_ext *exts,
+				struct mio_op *op)
+{
+	int rc;
+	struct clovis_comp_obj_exts_pp_args *pp_args;
+	
+	pp_args = mio_mem_alloc(sizeof *pp_args);
+	if (pp_args == NULL)
+		return -ENOMEM;
+
+	rc = clovis_comp_obj_extent_query(
+		layer_id, nr_exts, exts, NULL, M0_CLOVIS_IC_DEL, op,
+		clovis_comp_obj_exts_release_pp, pp_args);
+	if (rc < 0)
+		mio_mem_free(pp_args);
+	return rc;
+}
+
+static int clovis_comp_obj_exts_get_pp(struct mio_op *op)
+{
+	int i;
+	int nr_exts;
+        struct m0_bufvec *keys;
+        struct m0_bufvec *vals;
+	struct m0_clovis_op *cop;
+	struct m0_clovis_composite_layer_idx_key ekey;
+	struct m0_clovis_composite_layer_idx_val eval;
+	struct clovis_comp_obj_exts_pp_args *pp_args;
+	struct mio_obj_ext *ret_exts;
+
+	cop = (struct m0_clovis_op *)
+	      op->mop_drv_op_chain.mdoc_head->mdo_op;
+	assert(cop != NULL);
+	if (cop->op_sm.sm_state != M0_CLOVIS_OS_STABLE)
+		return -EIO;
+
+	/* Copy returned values. */
+	pp_args = (struct clovis_comp_obj_exts_pp_args *)
+		  op->mop_drv_op_chain.mdoc_head->mdo_post_proc_data;
+	ret_exts = pp_args->epa_ret_exts;
+	assert(ret_exts != NULL);
+	keys  = pp_args->epa_keys;
+	vals  = pp_args->epa_vals;
+	nr_exts = keys->ov_vec.v_nr;
+	for (i = 0; i < nr_exts; i++) {
+		m0_clovis_composite_layer_idx_key_from_buf(
+			&ekey, keys->ov_buf[i]);
+		ret_exts[i].moe_off = ekey.cek_off;
+		if (vals->ov_buf[i] == NULL)
+			continue;
+		m0_clovis_composite_layer_idx_val_from_buf(
+			&eval, vals->ov_buf[i]);
+		ret_exts[i].moe_size = eval.cev_len;
+	}
+	assert(pp_args->epa_nr_ret_exts != NULL);
+	*pp_args->epa_nr_ret_exts = nr_exts;
+
+	/* Free all allocated resources for the extent query. */
+        return clovis_comp_obj_exts_release_pp(op);
+}
+
+static int
+mio_clovis_comp_obj_get_extents(struct mio_obj *obj,
+				struct mio_obj_id *layer_id,
+				off_t offset, int nr_exts,
+				struct mio_obj_ext *exts, int *nr_ret_exts,
+				struct mio_op *op)
+{
+	int rc;
+	struct clovis_comp_obj_exts_pp_args *pp_args;
+
+	pp_args = mio_mem_alloc(sizeof *pp_args);
+	if (pp_args == NULL)
+		return -ENOMEM;
+
+	mio_memset(exts, 0, nr_exts * sizeof(*exts));
+	exts[0].moe_off = offset;
+	rc = clovis_comp_obj_extent_query(
+			layer_id, nr_exts, exts, nr_ret_exts,
+			M0_CLOVIS_IC_NEXT, op,
+			clovis_comp_obj_exts_get_pp, pp_args);
+	if (rc < 0) {
+		mio_mem_free(pp_args);
+		return rc;
+	}
+
+	return 0;
+}
+
+struct mio_comp_obj_ops mio_clovis_comp_obj_ops = {
+        .mcoo_create      = mio_clovis_comp_obj_create,
+        .mcoo_add_layers  = mio_clovis_comp_obj_add_layers,
+        .mcoo_del_layers  = mio_clovis_comp_obj_del_layers,
+        .mcoo_list_layers = mio_clovis_comp_obj_list_layers,
+        .mcoo_add_extents = mio_clovis_comp_obj_add_extents,
+        .mcoo_del_extents = mio_clovis_comp_obj_del_extents,
+        .mcoo_get_extents = mio_clovis_comp_obj_get_extents
+};
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/src/hints.c b/deps/mio/src/hints.c
new file mode 100644
index 0000000000000000000000000000000000000000..d3425ca31684256a2bdf6eb6f6e8323c09a319eb
--- /dev/null
+++ b/deps/mio/src/hints.c
@@ -0,0 +1,294 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <errno.h>
+#include <assert.h>
+
+#include "logger.h"
+#include "mio.h"
+#include "mio_internal.h"
+
+enum {
+	MIO_HINT_INVALID = -1
+};
+
+struct hint {
+	char *h_name;
+	enum mio_hint_type h_type;
+};
+
+static struct hint hint_table[] = {
+	[MIO_HINT_OBJ_CACHE_FLUSH_SIZE] = {
+		.h_name = "MIO_HINT_OBJ_CACHE_FLUSH_SIZE",
+		.h_type = MIO_HINT_SESSION,
+	},
+	[MIO_HINT_OBJ_LIFETIME] = {
+		.h_name = "MIO_HINT_OBJ_LIFETIME",
+		.h_type = MIO_HINT_PERSISTENT,
+	},
+	[MIO_HINT_OBJ_WHERE] = {
+		.h_name = "MIO_HINT_OBJ_WHERE",
+		.h_type = MIO_HINT_SESSION,
+	}
+};
+
+int mio_hint_map_init(struct mio_hint_map *map, int nr_entries)
+{
+	int i;
+
+	assert(map != NULL && nr_entries > 0);
+	map->mhm_nr_entries = nr_entries;
+
+	map->mhm_keys = mio_mem_alloc(nr_entries * sizeof(int));
+	map->mhm_values = mio_mem_alloc(nr_entries * sizeof(uint64_t));
+	if (map->mhm_keys == NULL ||
+	    map->mhm_values == NULL) {
+		mio_log(MIO_ERROR, "Can't create map !");
+		mio_hint_map_fini(map);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < nr_entries; i++) {
+		map->mhm_keys[i] = MIO_HINT_INVALID;
+		map->mhm_values[i] = 0;
+	}
+	map->mhm_nr_set = 0;
+
+	return 0;
+}
+
+void mio_hint_map_fini(struct mio_hint_map *map)
+{
+	mio_mem_free(map->mhm_keys);
+	mio_mem_free(map->mhm_values);
+	map->mhm_nr_entries = 0;
+	map->mhm_nr_set = 0;
+}
+
+int mio_hint_map_copy(struct mio_hint_map *to, struct mio_hint_map *from)
+{
+	int i;
+	int j;
+	int rc;
+	int hkey;
+	uint64_t hvalue;
+	int nr_new = 0;
+
+	assert(to != NULL && from != NULL);	
+
+	if (to->mhm_nr_entries == 0 ) {
+		rc = mio_hint_map_init(to, from->mhm_nr_entries);
+		if (rc < 0) {
+			mio_log(MIO_ERROR, "Failed to initialise hint map!");
+			return rc;
+		}
+	}
+
+	/* Check if 'to' hint map has enough space for new hints. */
+	for (i = 0; i < from->mhm_nr_set; i++) {
+		hkey = from->mhm_keys[i];
+		for (j = 0; j < to->mhm_nr_set; j++)
+			if (to->mhm_keys[j] == hkey)
+				break;
+		if (j == to->mhm_nr_set)
+			nr_new++;
+	}
+	if (to->mhm_nr_set + nr_new > to->mhm_nr_entries)
+		return -E2BIG;
+
+	/* It is safe to add new hints now. */
+	for (i = 0; i < from->mhm_nr_set; i++) {
+		hkey = from->mhm_keys[i];
+		hvalue = from->mhm_values[i];
+		for (j = 0; j < to->mhm_nr_set; j++)
+			if (to->mhm_keys[j] == hkey)
+				break;
+		if (j == to->mhm_nr_set) {
+			j = to->mhm_nr_set;
+			to->mhm_nr_set++;
+		}
+
+		to->mhm_keys[j] = hkey;
+		to->mhm_values[j] = hvalue;
+	}
+	return 0;
+}
+
+int mio_hint_map_set(struct mio_hint_map *map, int key, uint64_t value)
+{
+	int i;
+
+	for (i = 0; i < map->mhm_nr_set; i++) {
+		if (map->mhm_keys[i] == key)
+			break;
+	}
+	if (i == map->mhm_nr_set) {
+		if (map->mhm_nr_set == map->mhm_nr_entries)
+			return -EINVAL;
+		else
+			map->mhm_nr_set++;
+	}
+	
+	map->mhm_keys[i] = key;
+	map->mhm_values[i] = value;
+	return 0;
+}
+
+int mio_hint_map_get(struct mio_hint_map *map, int key, uint64_t *value)
+{
+	int i;
+
+	assert(map != NULL && value != NULL);
+
+	for (i = 0; i < map->mhm_nr_set; i++) {
+		if (map->mhm_keys[i] == key)
+			break;
+	}
+	if (i == map->mhm_nr_set)
+		return -ENOENT;
+	*value = map->mhm_values[i];
+	return 0;
+}
+
+#define NKEYS (sizeof(hint_table)/sizeof(struct hint))
+enum mio_hint_type mio_hint_type(enum mio_hint_key key)
+{
+	assert(key >= 0 && key < NKEYS);
+	return hint_table[key].h_type;
+}
+
+char* mio_hint_name(enum mio_hint_key key)
+{
+	assert(key >= 0 && key < NKEYS);
+	return hint_table[key].h_name;
+}
+
+int mio_hints_init(struct mio_hints *hints)
+{
+	assert(hints != NULL);
+	return mio_hint_map_init(&hints->mh_map, MIO_OBJ_HINT_NUM);
+}
+
+void mio_hints_fini(struct mio_hints *hints)
+{
+	assert(hints != NULL);
+	mio_hint_map_fini(&hints->mh_map);
+}
+
+#define drv_obj_ops (mio_instance->m_driver->md_obj_ops)
+static int mio_obj_hint_store(struct mio_obj *obj)
+{
+	int i;
+	int rc;
+	int nr_hints;
+	int nr_phints = 0;
+	int phint_cnt = 0;
+	struct mio_hints *phints = &obj->mo_attrs.moa_phints;
+
+	nr_hints = obj->mo_hints.mh_map.mhm_nr_set;
+
+	for (i = 0; i < nr_hints; i++)
+		if (mio_hint_type(obj->mo_hints.mh_map.mhm_keys[i]) ==
+		    MIO_HINT_PERSISTENT)
+			nr_phints++;
+
+	if (phints->mh_map.mhm_nr_entries != 0)
+		mio_hint_map_fini(&phints->mh_map);
+	rc = mio_hint_map_init(&phints->mh_map, MIO_OBJ_HINT_NUM);
+	if (rc < 0)
+		return rc;
+
+	for (i = 0; i < nr_hints; i++) {
+		if (mio_hint_type(obj->mo_hints.mh_map.mhm_keys[i]) ==
+		    MIO_HINT_PERSISTENT) {
+			phints->mh_map.mhm_keys[phint_cnt] =
+				obj->mo_hints.mh_map.mhm_keys[i];
+			phints->mh_map.mhm_values[phint_cnt] =
+				obj->mo_hints.mh_map.mhm_values[i];
+			phint_cnt++;
+		}
+	}
+	phints->mh_map.mhm_nr_set = phint_cnt;
+
+	return drv_obj_ops->moo_hint_store(obj);
+}
+
+static int mio_obj_hint_load(struct mio_obj *obj)
+{
+	return drv_obj_ops->moo_hint_load(obj);
+}
+
+int mio_obj_hints_set(struct mio_obj *obj, struct mio_hints *hints)
+{
+	int rc;
+
+	assert(obj != NULL && hints != NULL);
+	
+	rc = mio_hint_map_copy(&obj->mo_hints.mh_map, &hints->mh_map)? :
+	     mio_obj_hint_store(obj);
+	if (rc < 0) {
+		mio_log(MIO_ERROR,
+			"Copying and store hints failed! error = %d\n", rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+int mio_obj_hints_get(struct mio_obj *obj, struct mio_hints *hints)
+{
+	int rc;
+
+	assert(obj != NULL && hints != NULL);
+
+	rc = mio_obj_hint_load(obj);
+	if (rc < 0)
+		return rc;
+	
+	rc = mio_hint_map_copy(&hints->mh_map, &obj->mo_hints.mh_map);
+	return rc;
+}
+
+/**
+ * Helper functions to set or get individual hint.
+ */
+int mio_hint_add(struct mio_hints *hints,
+		 int hint_key, uint64_t hint_value)
+{
+	int rc;
+
+	assert(hints != NULL);
+	/* Overwrite the hint's value if it has already been set before. */
+	rc = mio_hint_map_set(&hints->mh_map, hint_key, hint_value);
+	return rc;
+}
+
+int mio_hint_lookup(struct mio_hints *hints,
+		    int hint_key, uint64_t *hint_value)
+{
+	int rc;
+
+	assert(hints != NULL);
+	rc = mio_hint_map_get(&hints->mh_map, hint_key, hint_value);
+	return rc;
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/src/logger.c b/deps/mio/src/logger.c
new file mode 100644
index 0000000000000000000000000000000000000000..b14ce01529c3212341755286d2fbafed9dfaf190
--- /dev/null
+++ b/deps/mio/src/logger.c
@@ -0,0 +1,76 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include "logger.h"
+#include "mio_internal.h"
+
+enum mio_log_level mio_log_level = MIO_INFO;
+
+struct {
+	const char *name;
+} mio_log_levels[] = {
+        [MIO_ERROR]	= {"error"},
+        [MIO_WARN]	= {"warning"},
+        [MIO_INFO]	= {"info"},
+        [MIO_TRACE]	= {"trace"},
+        [MIO_DEBUG]	= {"debug"},
+};
+
+static FILE *mio_log_file;
+
+void mio_log(enum mio_log_level lev, const char *fmt, ...)
+{
+        va_list va;
+	va_start(va, fmt);
+	fprintf(mio_log_file, "%s: ", mio_log_levels[lev].name);
+	vfprintf(mio_log_file, fmt, va);
+	va_end(va);
+
+}
+
+int mio_log_init(enum mio_log_level level, char *logfile)
+{
+	FILE *fp;	
+
+	if (logfile != NULL) {
+		fp = fopen(logfile, "w");
+		if (fp == NULL) {
+			fprintf(stderr,
+				"Cann't open log file %s (%d)\n", logfile, errno);
+			return -errno;
+		}
+	} else
+		fp = stderr; 
+
+	mio_log_level = level;
+	mio_log_file  = fp;
+	return 0;
+}
+
+void mio_log_fini()
+{
+	fclose(mio_log_file);
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/src/logger.h b/deps/mio/src/logger.h
new file mode 100644
index 0000000000000000000000000000000000000000..67c7baba7b8d0b957d82d98d95349ed95d0b26e4
--- /dev/null
+++ b/deps/mio/src/logger.h
@@ -0,0 +1,44 @@
+/* -*- C -*- */
+/*
+ */
+
+#pragma once
+
+#ifndef __MIO_LOGGER_H__
+#define __MIO_LOGGER_H__
+
+#include <stdarg.h>       /* va_list */
+#include <stdio.h>        /* vfprintf(), stderr */
+
+enum mio_log_level {
+	MIO_LOG_INVALID = -1,
+	MIO_ERROR	= 0,
+	MIO_WARN	= 1,
+	MIO_INFO	= 2,
+	MIO_TRACE	= 3,
+	MIO_DEBUG	= 4,
+	MIO_MAX_LEVEL,
+};
+
+int mio_log_init(enum mio_log_level level, char *logfile);
+void mio_log(enum mio_log_level lev, const char *fmt, ...)
+	__attribute__((format(printf, 2, 3)));
+//void mio_set_debug_level(enum mio_log_level level);
+
+#define mio_log_ex(lev, fmt, args...) \
+	mio_log(lev, "%s:%d "fmt, __FUNCTION__, __LINE__, ##args)
+
+#endif /* __MIO_LOGGER_H__ */
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/src/mio.c b/deps/mio/src/mio.c
new file mode 100644
index 0000000000000000000000000000000000000000..63136283968a2cc4bf9d04e1d7719c27726449be
--- /dev/null
+++ b/deps/mio/src/mio.c
@@ -0,0 +1,442 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+
+#include <errno.h>
+#include <assert.h>
+
+#include "logger.h"
+#include "mio_internal.h"
+#include "mio.h"
+
+struct mio_kvs mio_obj_attrs_kvs;
+struct mio *mio_instance;
+
+/* --------------------------------------------------------------- *
+ *                     Operation                                   *
+ * ----------------------------------------------------------------*/
+
+void mio_op_init(struct mio_op *op)
+{
+	assert(op != NULL);
+
+	/*
+ 	 * When mio_op_init() is called, no driver specific operation
+ 	 * has been created and initialised yet.
+ 	 */ 
+	mio_memset(op, 0, sizeof *op);
+	op->mop_op_ops = mio_instance->m_driver->md_op_ops;
+}
+
+void mio_op_fini(struct mio_op *op)
+{
+	assert(op != NULL && op->mop_op_ops != NULL);
+
+	if (op->mop_op_ops->mopo_fini)
+		op->mop_op_ops->mopo_fini(op);
+}
+
+struct mio_op* mio_op_alloc_init()
+{
+	struct mio_op *op;
+
+	op = mio_mem_alloc(sizeof *op);
+	if (op != NULL)
+		mio_op_init(op);
+	return op;	
+}
+
+void mio_op_fini_free(struct mio_op *op)
+{
+	mio_op_fini(op);
+	mio_mem_free(op);
+}
+
+int mio_op_poll(struct mio_pollop *ops, int nr_ops, uint64_t timeout)
+{
+	int rc;
+	int i;
+	int nr_done = 0;
+	struct mio_op *mop;
+	struct mio_pollop *pop;
+	bool op_done = false;
+	uint64_t start;
+	uint64_t end;
+	mio_driver_op_postprocess post_proc;
+
+	assert(ops != NULL);
+	start = mio_now();
+
+again:
+	for (i = 0; i < nr_ops; i++) {
+		pop = ops + i;
+		mop = pop->mp_op;
+		assert(mop != NULL);
+		assert(mop->mop_op_ops != NULL);
+		op_done = false;
+		mop->mop_rc = mop->mop_op_ops->mopo_wait(
+				mop, timeout, &pop->mp_retstate);
+
+		post_proc = mop->mop_drv_op_chain.mdoc_head->mdo_post_proc;
+		if (pop->mp_retstate == MIO_OP_COMPLETED) { 
+			if (post_proc != NULL) {
+				rc = post_proc(mop);
+				/*
+			 	 * Check to see if a new action has been launched.
+			 	 * If no more action is launched, it is time to
+				 * finalise the operation.
+				 */
+				if (rc == MIO_DRV_OP_NEXT)
+					pop->mp_retstate = MIO_OP_ONFLY;
+				else {
+					assert(rc == MIO_DRV_OP_FINAL);
+					op_done = true;
+				}
+			} else
+				op_done = true;
+		} else if (pop->mp_retstate == MIO_OP_FAILED)
+			op_done = true;
+
+		if (op_done)		
+			nr_done++;
+	}
+	
+	end = mio_now();
+	if (timeout == MIO_TIME_NEVER && nr_done != nr_ops)
+		goto again;
+	else if (timeout != MIO_TIME_NEVER && end - start < timeout) {
+		timeout -= end - start;
+		goto again;
+	}
+
+	/* Return the number of operations done (completed or failed.)*/
+	return nr_done;
+}
+
+void mio_op_callbacks_set(struct mio_op *op,
+			  mio_callback cb_complete,
+			  mio_callback cb_failed,
+			  void *cb_data)
+{
+	assert(op != NULL);
+	op->mop_app_cbs.moc_cb_complete = cb_complete;
+	op->mop_app_cbs.moc_cb_failed   = cb_failed;
+	op->mop_app_cbs.moc_cb_data     = cb_data;
+}
+
+/* --------------------------------------------------------------- *
+ *                     Object Access                               *
+ * ----------------------------------------------------------------*/
+void mio_obj_op_init(struct mio_op *op, struct mio_obj *obj,
+			enum mio_obj_opcode opcode)
+{
+	assert(op != NULL);
+	op->mop_opcode = opcode;
+	op->mop_who.obj = obj;
+	op->mop_op_ops = mio_instance->m_driver->md_op_ops;
+}
+
+static void obj_init(struct mio_obj *obj, const struct mio_obj_id *oid)
+{
+	assert(oid != NULL && obj != NULL);
+	mio_mem_copy(obj->mo_id.moi_bytes,
+		     (void *)oid->moi_bytes, MIO_OBJ_ID_LEN);
+	obj->mo_drv_obj_ops = mio_instance->m_driver->md_obj_ops;
+	/**
+ 	 * TODO: map to an attributes key-value set by a policy
+ 	 * such as object ID.
+ 	 */
+	obj->mo_md_kvs = &mio_obj_attrs_kvs; 
+	mio_hint_map_init(&obj->mo_hints.mh_map, MIO_OBJ_HINT_NUM); 
+}
+
+int mio_obj_open(const struct mio_obj_id *oid,
+		 struct mio_obj *obj, struct mio_op *op)
+{
+	assert(oid != NULL && obj != NULL && op != NULL);
+	obj_init(obj, oid);
+	mio_obj_op_init(op, obj, MIO_OBJ_OPEN);
+	return obj->mo_drv_obj_ops->moo_open(obj, op);
+}
+
+void mio_obj_close(struct mio_obj *obj)
+{
+	assert(obj != NULL);
+	mio_hint_map_fini(&obj->mo_hints.mh_map); 
+	if (obj->mo_drv_obj_ops->moo_close != NULL)
+		obj->mo_drv_obj_ops->moo_close(obj);
+}
+
+int mio_obj_create(const struct mio_obj_id *oid,
+                   const struct mio_pool *pool_id,
+                   struct mio_obj *obj, struct mio_op *op)
+{
+	assert(oid != NULL && obj != NULL && op != NULL);
+	obj_init(obj, oid);
+	mio_obj_op_init(op, obj, MIO_OBJ_CREATE);
+	return obj->mo_drv_obj_ops->moo_create(pool_id, obj, op);
+}
+
+int mio_obj_delete(const struct mio_obj_id *oid, struct mio_op *op)
+{
+	assert(op != NULL);
+	mio_obj_op_init(op, NULL, MIO_OBJ_DELETE);
+	return mio_instance->m_driver->md_obj_ops->moo_delete(oid, op);
+}
+
+int mio_obj_writev(struct mio_obj *obj,
+                   const struct mio_iovec *iov,
+                   int iovcnt, struct mio_op *op)
+{
+	assert(obj != NULL && op != NULL);
+	mio_obj_op_init(op, obj, MIO_OBJ_WRITE);
+	return obj->mo_drv_obj_ops->moo_writev(obj, iov, iovcnt, op);
+}
+
+int mio_obj_readv(struct mio_obj *obj,
+                  const struct mio_iovec *iov,
+                  int iovcnt, struct mio_op *op)
+{
+	assert(obj != NULL && op != NULL);
+	mio_obj_op_init(op, obj, MIO_OBJ_READ);
+	return obj->mo_drv_obj_ops->moo_readv(obj, iov, iovcnt, op);
+}
+
+int mio_obj_sync(struct mio_obj *obj, struct mio_op *op)
+{
+	assert(obj != NULL && op != NULL);
+	mio_obj_op_init(op, obj, MIO_OBJ_SYNC);
+	return obj->mo_drv_obj_ops->moo_sync(obj, op);
+}
+
+int mio_obj_size(struct mio_obj *obj, struct mio_op *op)
+{
+	assert(obj != NULL && op != NULL);
+	mio_obj_op_init(op, obj, MIO_OBJ_ATTRS_GET);
+	return obj->mo_drv_obj_ops->moo_size(obj, op);
+}
+
+/* --------------------------------------------------------------- *
+ *                     Key-value Store                             *
+ * ----------------------------------------------------------------*/
+static void kvs_op_init(struct mio_op *op, struct mio_kvs_id *kid,
+			enum mio_kvs_opcode opcode)
+{
+	assert(op != NULL);
+	mio_memset(op, 0, sizeof op);
+	op->mop_opcode = opcode;
+	op->mop_who.kvs_id = kid;
+	op->mop_op_ops = mio_instance->m_driver->md_op_ops;
+}
+
+#define drv_kvs_ops (mio_instance->m_driver->md_kvs_ops)
+int mio_kvs_pair_get(struct mio_kvs_id *kid,
+                     int nr_kvps, struct mio_kv_pair *kvps,
+                     int32_t *rcs, struct mio_op *op)
+{
+	assert(kid != NULL && op != NULL);
+	if (drv_kvs_ops->mko_get == NULL)
+		return -EOPNOTSUPP;
+
+	kvs_op_init(op, kid, MIO_KVS_GET);
+	return drv_kvs_ops->mko_get(kid, nr_kvps, kvps, rcs, op);
+}
+
+int mio_kvs_pair_put(struct mio_kvs_id *kid,
+                     int nr_kvps, struct mio_kv_pair *kvps,
+                     int32_t *rcs, struct mio_op *op)
+{
+	assert(kid != NULL && op != NULL);
+	if (drv_kvs_ops->mko_put == NULL)
+		return -EOPNOTSUPP;
+
+	kvs_op_init(op, kid, MIO_KVS_PUT);
+	return drv_kvs_ops->mko_put(kid, nr_kvps, kvps, rcs, op);
+}
+
+int mio_kvs_pair_del(struct mio_kvs_id *kid,
+                     int nr_kvps, struct mio_kv_pair *kvps,
+                     int32_t *rcs, struct mio_op *op) 
+{
+	assert(kid != NULL && op != NULL);
+	if (drv_kvs_ops->mko_del == NULL)
+		return -EOPNOTSUPP;
+
+	kvs_op_init(op, kid, MIO_KVS_DEL);
+	return drv_kvs_ops->mko_del(kid, nr_kvps, kvps, rcs, op);
+}
+
+int mio_kvs_create_set(struct mio_kvs_id *kid, struct mio_op *op)
+{
+	assert(kid != NULL && op != NULL);
+	if (drv_kvs_ops->mko_create_set == NULL)
+		return -EOPNOTSUPP;
+
+	kvs_op_init(op, kid, MIO_KVS_CREATE_SET);
+	return drv_kvs_ops->mko_create_set(kid, op);
+}
+
+int mio_kvs_del_set(struct mio_kvs_id *kid, struct mio_op *op)
+{
+	assert(kid != NULL && op != NULL);
+	if (drv_kvs_ops->mko_del_set == NULL)
+		return -EOPNOTSUPP;
+
+	kvs_op_init(op, kid, MIO_KVS_DELETE_SET);
+	return drv_kvs_ops->mko_del_set(kid, op);
+}
+
+/* --------------------------------------------------------------- *
+ *                     Composite Layout                            *
+ * ----------------------------------------------------------------*/
+#define drv_comp_obj_ops (mio_instance->m_driver->md_comp_obj_ops)
+
+int mio_composite_obj_create(const struct mio_obj_id *oid,
+			     struct mio_obj *obj, struct mio_op *op)
+{
+	assert(obj != NULL && op != NULL);
+	obj_init(obj, oid);
+	mio_obj_op_init(op, obj, MIO_COMP_OBJ_CREATE);
+	return drv_comp_obj_ops->mcoo_create(obj, op);
+}
+
+int mio_composite_obj_del(const struct mio_obj_id *oid, struct mio_op *op)
+{
+	assert(op != NULL);
+	mio_obj_op_init(op, NULL, MIO_COMP_OBJ_DELETE);
+	return drv_comp_obj_ops->mcoo_del(oid, op);
+}
+
+int mio_composite_obj_add_layers(struct mio_obj *obj, int nr_layers,
+				 struct mio_comp_obj_layer *layers,
+				 struct mio_op *op)
+{
+	assert(obj != NULL && op != NULL);
+	mio_obj_op_init(op, obj, MIO_COMP_OBJ_ADD_LAYERS);
+	return drv_comp_obj_ops->mcoo_add_layers(obj, nr_layers, layers, op);
+}
+
+int mio_composite_obj_del_layers(struct mio_obj *obj,
+				 int nr_layers_to_del,
+				 struct mio_comp_obj_layer *layers_to_del,
+				 struct mio_op *op)
+{
+	assert(obj != NULL && op != NULL);
+	mio_obj_op_init(op, obj, MIO_COMP_OBJ_DEL_LAYERS);
+	return drv_comp_obj_ops->mcoo_del_layers(
+			obj, nr_layers_to_del, layers_to_del, op);
+}
+
+int mio_composite_obj_list_layers(struct mio_obj *obj,
+                                  struct mio_comp_obj_layout *ret_layout,
+                   		  struct mio_op *op)
+{
+	assert(obj != NULL && op != NULL);
+	mio_obj_op_init(op, obj, MIO_COMP_OBJ_LIST_LAYERS);
+	return drv_comp_obj_ops->mcoo_list_layers(obj, ret_layout, op);
+}
+
+int mio_composite_obj_add_extents(struct mio_obj *obj,
+				  struct mio_obj_id *layer_id,
+				  int nr_exts, struct mio_obj_ext *exts,
+				  struct mio_op *op)
+{
+	assert(obj != NULL && op != NULL);
+	mio_obj_op_init(op, obj, MIO_COMP_OBJ_ADD_EXTENTS);
+	return drv_comp_obj_ops->mcoo_add_extents(
+				obj, layer_id, nr_exts, exts, op);
+}
+
+int mio_composite_obj_del_extents(struct mio_obj *obj,
+				  struct mio_obj_id *layer_id,
+				  int nr_exts, struct mio_obj_ext *exts,
+				  struct mio_op *op)
+{
+	assert(obj != NULL && op != NULL);
+	mio_obj_op_init(op, obj, MIO_COMP_OBJ_DEL_EXTENTS);
+	return drv_comp_obj_ops->mcoo_del_extents(
+				obj, layer_id, nr_exts, exts, op);
+}
+
+int
+mio_composite_obj_get_extents(struct mio_obj *obj,
+			      struct mio_obj_id *layer_id, off_t offset,
+			      int nr_exts, struct mio_obj_ext *exts,
+			      int *nr_ret_exts, struct mio_op *op)
+{
+	assert(obj != NULL && op != NULL);
+	mio_obj_op_init(op, obj, MIO_COMP_OBJ_GET_EXTENTS);
+	return drv_comp_obj_ops->mcoo_get_extents(
+			obj, layer_id, offset, nr_exts, exts, nr_ret_exts, op);
+}
+
+
+/* --------------------------------------------------------------- *
+ *                    MIO initialisation/finalisation              *
+ * ----------------------------------------------------------------*/
+int mio_init(const char *yaml_conf)
+{
+	int rc;
+
+	mio_instance = mio_mem_alloc(sizeof *mio_instance);
+	if (mio_instance == NULL)
+		return -ENOMEM;
+
+	mio_drivers_register();
+
+	rc = mio_conf_init(yaml_conf);
+	if (rc < 0) {
+		fprintf(stderr, "Failed in parsing configuration file\n");
+		return rc;
+	}
+
+	rc = mio_log_init(mio_instance->m_log_level, mio_instance->m_log_file);
+	if (rc < 0) {
+		fprintf(stderr, "Failed to initialise logging sub-system. \n");
+		return rc;
+	}
+
+	rc = mio_instance->m_driver->md_sys_ops->mdo_init(mio_instance);
+	if (rc < 0) {
+		mio_log(MIO_ERROR, "Initialising MIO driver failed!\n");
+		mio_conf_fini();
+	}
+	return rc;
+}
+
+void mio_fini()
+{
+	mio_instance->m_driver->md_sys_ops->mdo_fini();
+	mio_mem_free(mio_instance);
+	mio_conf_fini();
+}
+
+int mio_thread_init(struct mio_thread *thread)
+{
+	return mio_instance->m_driver->md_sys_ops->mdo_thread_init(thread);
+}
+
+void mio_thread_fini(struct mio_thread *thread)
+{
+	mio_instance->m_driver->md_sys_ops->mdo_thread_fini(thread);
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/src/mio.h b/deps/mio/src/mio.h
new file mode 100644
index 0000000000000000000000000000000000000000..c7d8aaab7dcdb3438ccd849d778781efcca92ced
--- /dev/null
+++ b/deps/mio/src/mio.h
@@ -0,0 +1,648 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#ifndef __MIO_H__
+#define __MIO_H__
+
+#include "mio_internal.h"
+#include "logger.h"
+
+typedef void (*mio_callback)(struct mio_op *op);
+struct mio_kvs_id;
+
+/**
+ * Definitions of MIO operations:
+ *   - Data structure (mio_op) to interact with MIO applications.
+ *   - Operation codes for object and key-value store (kvs).
+ *   - mio_op_state defines operation states.
+ *   - operations on ops such as initialisation and finalisation.
+ */
+enum mio_obj_opcode {
+	MIO_OBJ_INVALID,
+	MIO_OBJ_CREATE,
+	MIO_OBJ_DELETE,
+	MIO_OBJ_OPEN,
+	MIO_OBJ_CLOSE,
+	MIO_OBJ_SYNC,
+	MIO_OBJ_ATTRS_SET,
+	MIO_OBJ_ATTRS_GET,
+	MIO_OBJ_READ,
+	MIO_OBJ_WRITE,
+	MIO_OBJ_OP_NR
+};
+
+enum mio_kvs_opcode {
+	MIO_KVS_CREATE_SET = MIO_OBJ_OP_NR + 1,
+	MIO_KVS_DELETE_SET,
+	/** Check a kvs for an existence. */
+	MIO_KVS_LOOKUP_SET,
+	/** Lookup a value with the given key. */
+	MIO_KVS_GET,
+	/** Insert or update the value, given a key. */
+	MIO_KVS_PUT,
+	/** Delete the value, if any, for the given key. */
+	MIO_KVS_DEL,
+	MIO_KVS_OP_NR
+};
+
+enum mio_composite_obj_opcode {
+	MIO_COMP_OBJ_CREATE = MIO_KVS_OP_NR + 1,
+	MIO_COMP_OBJ_DELETE,
+	MIO_COMP_OBJ_ADD_LAYERS,
+	MIO_COMP_OBJ_DEL_LAYERS,
+	MIO_COMP_OBJ_LIST_LAYERS,
+	MIO_COMP_OBJ_ADD_EXTENTS,
+	MIO_COMP_OBJ_DEL_EXTENTS,
+	MIO_COMP_OBJ_GET_EXTENTS,
+	MIO_COMP_OBJ_OP_NR
+};
+
+enum mio_op_state {
+	MIO_OP_ONFLY = 0,
+	MIO_OP_COMPLETED,
+	MIO_OP_FAILED
+};
+
+/**
+ * Callback functions set by applications which are called when
+ * all actions of an operation are done.
+ */
+struct mio_op_app_cbs {
+	mio_callback moc_cb_complete;
+	mio_callback moc_cb_failed;
+	void         *moc_cb_data;
+};
+
+struct mio_op {
+	unsigned int mop_opcode; /* Type of operation. */
+	union {                  /* Which object or key-value set. */
+		struct mio_obj *obj;
+		struct mio_kvs_id *kvs_id; 
+	} mop_who;
+	int mop_state;           /* Current state of operation. */
+	int mop_rc;              /* == 0 when operation successes,
+				  *  < 0 the error code if the
+				  *      operation fails. */
+
+	struct mio_op_app_cbs mop_app_cbs;	
+
+	/* See mio_drv_op_chain in mio_inernal for explanation. */
+	struct mio_driver_op_chain mop_drv_op_chain;
+
+	struct mio_op_ops *mop_op_ops;
+};
+/**
+ * Initialise and finalise an operation. Applications have to allocate
+ * memory for the operation before calling mio_op_init().
+ */
+void mio_op_init(struct mio_op *op);
+void mio_op_fini(struct mio_op *op);
+struct mio_op* mio_op_alloc_init();
+void mio_op_fini_free(struct mio_op *op);
+
+/**
+ * mio_op_poll() is defined similar to POSIX poll() system call
+ * and it waits for one of a set of operations to reach COMPLETED
+ * or FAILED state.
+ *
+ * The set of operations to be monitored is specified in the ops
+ * argument, which is an array of structures of the following form:
+ *
+ *         struct mio_pollop {
+ *             struct mio_op *mp_op;  //Operation to poll.
+ *             int mp_retstate;       // Returned state.
+ *         };
+ * If none of the operations reach states requested (COMPLETED
+ * or FAILED) and no error has occurred for any of the operations,
+ * then mio_op_poll() blocks until one of the states occurs.
+ * The field retstat is an output parameter, filled by MIO with the
+ * state that actually occurred.
+ *
+ * The timeout argument specifies the number of milliseconds that
+ * mio_op_poll()should block waiting for an operation to reach state
+ * requested.  The call will block until either:
+ *     - an operation reaches the state requested;
+ *     - the timeout expires.
+ *
+ * Specifying a negative value in timeout means an infinite timeout.
+ * Specifying a timeout of zero causes mio_op_poll() to
+ * return immediately, even if no operations reach the states
+ * requested.
+ *
+ * @param ops The pointer to an array of data structure mio_pollop,
+ * containing the operations and states to query on.
+ * @param nr_ops The number of members in array ops.
+ * @param timeout. Timeout value in milliseconds.
+ * @return 0 the operation is completed or failed, < 0 for error.
+ */
+struct mio_pollop {
+	struct mio_op *mp_op;  /* Operation to poll. */
+	int mp_retstate;       /* Returned state. */
+};
+
+int mio_op_poll(struct mio_pollop *ops, int nr_ops, uint64_t timeout);
+
+#define MIO_TIME_NEVER (~0ULL)
+
+/**
+ * Callbacks provides an alternative way to handle operations
+ * asynchronously. mio_op_set_callbacks() set callbacks for
+ * an operation.
+ * 
+ * @param op The pointer to operation.
+ * @cb_complete The callback function is triggered when
+ * the operation reach COMPLETED state.
+ * @cb_complete The callback function is triggered when
+ * the operation turns into FAILED state.
+ * @cb_cb The data passed to callback functions. 
+ */
+void mio_op_callbacks_set(struct mio_op *op,
+			  mio_callback cb_complete,
+			  mio_callback cb_failed,
+			  void *cb_data);
+
+/**
+ * Hints set to this opened object. MIO differentiates
+ * 2 types of hints: (a) session hints which are set only for
+ * object that are openned and are kept alive only during
+ * the period of openning session. Session hints will be
+ * destroyed when an object is closed and the hints won't
+ * be valid for next session. Example of session hints: cache
+ * and pre-fetching hints. (b) Persistent hints which are persisted
+ * and are retrieved and set when an object is openned. The
+ * persistent hints are valid for the life time of the object.
+ */
+enum mio_hint_type {
+	MIO_HINT_SESSION,
+	MIO_HINT_PERSISTENT
+};
+
+enum mio_hint_key {
+	MIO_HINT_OBJ_CACHE_FLUSH_SIZE,
+	MIO_HINT_OBJ_LIFETIME,
+	MIO_HINT_OBJ_WHERE,
+	MIO_HINT_KEY_NUM
+};
+
+/**
+ * Hints are stored and managed as a map between hint’s key and value.
+ */
+struct mio_hints {
+    struct mio_hint_map mh_map; 
+};
+
+/**
+ * Object identifier is defined as a byte array with lower-indexed/big-endian
+ * ordering and the option of Maestro changing to 256 bit later,
+ * with lower-bits-0 indicating legacy IDs (i.e., the ones at bytes[8..15]).
+ */
+enum {
+	MIO_OBJ_ID_LEN = 16,
+	MIO_KVS_ID_LEN = 16
+};
+struct mio_obj_id {
+	uint8_t moi_bytes[MIO_OBJ_ID_LEN];
+};
+
+struct mio_kvs_id {
+	uint8_t mki_bytes[MIO_KVS_ID_LEN];
+};
+
+struct mio_pool {
+	uint64_t mp_hi;
+	uint64_t mp_lo;
+};
+
+/**
+ * mio_iovec specifies the base address and length of an area in memory
+ * from/to which data should be written. It also specifies byte range of
+ * an object.
+ */
+struct mio_iovec {
+	char   *miov_base;  /* Base address. */
+	off_t   miov_off;   /* Offset. */
+	size_t  miov_len;   /* Length. */
+};
+
+enum {
+	MIO_MAX_HINTS_PER_OBJ = 16,
+};
+
+/**
+ * Object attributes stored to and loaded from storage backend.
+ */
+struct mio_obj_attrs {
+	uint64_t moa_size;
+	uint64_t moa_wtime;
+
+	/* Persistent hints only. */
+	struct mio_hints moa_phints;
+};
+
+/**
+ * In-memory object handler.
+ */
+struct mio_obj {
+	struct mio_obj_id mo_id;
+	struct mio_obj_op *mo_op;
+
+	/** Driver specific object ops. */
+	struct mio_obj_ops *mo_drv_obj_ops;
+
+	/** Hints (persistent + session hints) set for this object. */
+	struct mio_hints mo_hints;
+
+	/** Associated metadata key-vaule set. */
+	struct mio_kvs *mo_md_kvs;
+
+	struct mio_obj_attrs mo_attrs;
+
+	/** Pointer to driver specific object structure. */
+	void *mo_drv_obj;
+};
+
+/**
+ * Open an object identified by object identifier oid.
+ * Upon successful completion mio_obj_open() return a ‘obj’
+ * pointer. Otherwise, NULL is returned with an error code.
+
+ * @param oid The object identifier.
+ * @param obj Pointer to the object handle which can be used can be
+ * subsequently used to access the object until the object is closed.  
+ * Note that the object handle must be pre-allocated by application.
+ * @param op The open operation for progress query. See Table 5 for 
+ * mio_op data structure definition
+ * @return 0 for success, < 0 for error.
+ */
+int mio_obj_open(const struct mio_obj_id *oid,
+		 struct mio_obj *obj, struct mio_op *op);
+
+/**
+ * Close an object handle and free resources held by the object.
+ * @param obj Pointer to the object handle.
+ */
+void mio_obj_close(struct mio_obj *obj);
+
+/**
+ * Create an object with identifier ‘oid’. See mio_obj_open()
+ * above for notes on object identifier. 
+ * Note that an internal key-value set will be created when
+ * creating an object, offering a convenient mechanism
+ * for applications to store and query customized object attributes.
+
+ *
+ * @param oid The object identifier.
+ * @param pool_id The pool where the object is stored to.
+ * @param[out] obj Pointer to the object handle which can be
+ * used can be subsequently used to access the object until
+ * the object is closed. Note that the object handle must be
+ * pre-allocated by application.
+ * @return 0 for success, < 0 for error.
+ *
+ * TODO: hints to create an object such as which pool to store.
+ * Should MIO expose pools to applications?
+ */
+int mio_obj_create(const struct mio_obj_id *oid,
+                   const struct mio_pool *pool_id,
+                   struct mio_obj *obj, struct mio_op *op);
+
+/**
+ * Delete an object.
+ * @param oid The object identifier.
+ * @return 0 for success, < 0 for error.
+ */
+int mio_obj_delete(const struct mio_obj_id *oid, struct mio_op *op);
+
+/**
+ * mio_obj_writev() writes from a set of buffers specified by
+ * the members of the iov: iov[0], iov[1], ..., iov[iovcnt-1]
+ * to object offsets specified by the members of the offsets:
+ * offsets[0], offsets[1], ...,  offsets[iovcnt-1].
+ *
+ * mio_obj_readv() reads from object offsets specified by
+ * the members of the offsets:
+ * offsets[0], offsets[1], ..., offsets[iovcnt-1] into a set
+ * of buffers of iov: iov[0], iov[1], ..., iov[iovcnt-1].
+ * 
+ * Upon successfully returning, mio_obj_writev() and mio_obj_readv()
+ * return with a launched operation. op can be used to query
+ * the process of the operation.
+ *
+ * @param obj Pointer to the object handle.
+ * @param iov The data buffer array. Each member specifies an
+ * area of memory to write to or read from and an object offset.
+ * @param iovcnt The number of data buffers. The number of
+ * offsets and iov must be equal to iovcnt.
+ * @param op[out]. The returned operation data structure for
+ * state querying.
+ * @return 0 for success, < 0 for error.
+ *
+ */
+int mio_obj_writev(struct mio_obj *obj,
+                   const struct mio_iovec *iov,
+                   int iovcnt, struct mio_op *op);
+
+int mio_obj_readv(struct mio_obj *obj,
+                  const struct mio_iovec *iov,
+                  int iovcnt, struct mio_op *op);
+
+/**
+ * mio_obj_sync() flushes all previous writes to obj to be
+ * persisted to the storage device.
+ *
+ * @param obj The object is going to be sync'ed.
+ * @param op[out]. The returned operation data structure for
+ * state querying.
+ * @return 0 for success, anything else for an error.
+ */
+int mio_obj_sync(struct mio_obj *obj, struct mio_op *op);
+
+/**
+ * Send a request to retrieve object size.
+ *
+ * @param obj The object in question.
+ * @param op[out]. The returned operation data structure for
+ * state querying.
+ * @return 0 for success, anything else for an error.
+ */
+int mio_obj_size(struct mio_obj *obj, struct mio_op *op);
+
+/**
+ * Data structure represents a record stored in a key-value set.
+ * MIO key-value set accepts variable lengths of keys and values.
+ */
+struct mio_kv_pair {
+    void *mkp_key;
+    size_t mkp_klen;
+    void *mkp_val;
+    size_t mkp_vlen;
+};
+
+struct mio_kvs {
+	struct mio_kvs_id mk_id;
+	/** Driver specific key-value set data structure. */
+	void *mk_drv_kvs;
+	struct mio_kvs_ops *mk_ops;
+};
+
+extern struct mio_kvs mio_obj_attrs_kvs;
+
+/**
+ *
+ * For mio_kvs_pair_get() and mio_kvs_pair_del() arguments should be
+ * as follows:
+ * - 'kvps' key-value pairs should set mio_kv_pair::key’s for
+ *   records being requested and set mio_kv_pair::val’s to NULLs.
+ *   At least one key should be specified.
+ * - After successful operation completion retrieved record
+ *   values are stored in mio_kv_pair::mkp_val. If some value
+ *   retrieval has failed, then corresponding element in 'rcs' array
+ *   is set to a suitable error code.
+ *
+ * For mio_kvs_pair_put() arguments should be as follows:
+ * - 'kvps' key-value pairs should set mio_kv_pair::key’s
+ *   for records being requested and set mio_kv_pair::val’s
+ *   to corresponding values.
+ *
+ * Error handling:
+ * 'rcs' holds an array of per-item return codes for the operation.
+ * It should be allocated by user with at least `nr_kvps` elements.
+ * For example, 6 records with keys k0...k5 were requested through
+ * mio_kvs_get(), k3 being absent in the key-value set.
+ * After operation completion rcs[3] will be set to –ENOENT
+ * and rcs[0,1,2,4,5] will be 0.
+ *
+ * Per-item return codes are more fine-grained than global operation
+ * return code (mio_op::mo_rc). On operation completion the global
+ * return code is set to negative value if it's impossible
+ * to process any item .
+ * - If the global return code is 0, then the user should check
+ *   per-item return codes.
+ * - If the global return code is not 0, then per-item return codes
+ *   are undefined.
+ *
+ * @param kvs_id The key-value set identifier. The format of
+ * key-value set identifier is driver specific and must explicitly
+ * stated in documentation.
+ * @param nr_kvps The number of key-value pairs.
+ * @param rcs. Array for per-item return code.
+ * @param op[out]. The operation pointer for progress query.
+ * @return 0 for success, < 0 for error.
+ */
+int mio_kvs_pair_get(struct mio_kvs_id *kvs_id,
+                     int nr_kvps, struct mio_kv_pair *kvps,
+                     int32_t *rcs, struct mio_op *op);
+
+int mio_kvs_pair_put(struct mio_kvs_id *kvs_id,
+                     int nr_kvps, struct mio_kv_pair *kvps,
+                     int32_t *rcs, struct mio_op *op);
+
+int mio_kvs_pair_del(struct mio_kvs_id *kvs_id,
+                     int nr_kvps, struct mio_kv_pair *kvps,
+                     int32_t *rcs, struct mio_op *op); 
+
+/**
+ * mio_kvs_create_set() creates a key-value set,
+ * while mio_kvs_del_set() deletes a key-value set.
+ *
+ * @param kvs_id The key-value set identifier.
+ * @return 0 for success, < 0 for error.
+ */
+int mio_kvs_create_set(struct mio_kvs_id *kvs_id, struct mio_op *op);
+int mio_kvs_del_set(struct mio_kvs_id *kvs_id, struct mio_op *op);
+
+/**
+ * mio_obj_hints_set() sets new values for the hints of the object
+ * handler associated with object.
+ * mio_obj_hints_get() retrieves object’s hints.
+ *
+ * As potentially there may be many hints for an object, the argument
+ * hints allows us to set or get multiple hints in one single call.
+ *
+ * @param obj Pointer to the object handle.
+ * @param hints Hints to set for an object. 
+ * @return 0 for success, < 0 for error.
+ */
+int mio_obj_hints_set(struct mio_obj *obj, struct mio_hints *hints);
+int mio_obj_hints_get(struct mio_obj *obj, struct mio_hints *hints);
+
+/**
+ * Helper functions to set or get individual hint.
+ */
+int mio_hints_init(struct mio_hints *hints);
+void mio_hints_fini(struct mio_hints *hints);
+int mio_hint_add(struct mio_hints *hints, int hint_key, uint64_t hint_value);
+int mio_hint_lookup(struct mio_hints *hints, int hint_key, uint64_t *hint_value);
+
+enum mio_hint_type mio_hint_type(enum mio_hint_key key);
+char* mio_hint_name(enum mio_hint_key key);
+
+/**
+ * TODO: short description/definition of composite object.
+ * 
+ * Data structures and APIs for MIO composite object.
+ *   - object extent is defined as a tuple (offset, size).
+ *   - Composite layer (sub-object).
+ *   - Composite object operations for MIO driver implementation.
+ *   - APIs to create/delete/list layers.
+ *   - APIs to create/delete/list extents. 
+ */
+struct mio_obj_ext {
+	off_t  moe_off;
+	size_t moe_size;
+};
+
+struct mio_comp_obj_layer {
+	int mcol_priority;
+	struct mio_obj_id mcol_oid;
+};
+
+struct mio_comp_obj_layout {
+	int mlo_nr_layers;
+	struct mio_comp_obj_layer *mlo_layers;
+};
+
+/**
+ * mio_composite_obj_create() crates a composite object. If the
+ * object of identifier `oid` exists this function returns –EEXIST
+ * error code.
+ * mio_composite_obj_del() deletes a composite object.
+ *
+ * @param oid The object identifier.
+ * @return 0 for success, anything else for an error
+ */
+int mio_composite_obj_create(const struct mio_obj_id *oid,
+                             struct mio_obj *obj, struct mio_op *op);
+int mio_composite_obj_del(const struct mio_obj_id *oid, struct mio_op *op);
+
+/**
+ * mio_composite_obj_add_layer() adds a new layer (sub-object) to a
+ * composite object. mio_composite_obj_del_layer() deletes a layer
+ * from the composite object. All extents in the layer will
+ * be removed as well.
+ *
+ * @param obj The object to add to.
+ * @param layers  The layers to be added or deleted.
+ * @param op The operation will be initialised when returned.
+ * @return 0 for success, anything else for an error.
+ */
+int mio_composite_obj_add_layers(struct mio_obj *obj, int nr_layers,
+				 struct mio_comp_obj_layer *layers,
+				 struct mio_op *op);
+int mio_composite_obj_del_layers(struct mio_obj *obj,
+				 int nr_layers_to_del,
+				 struct mio_comp_obj_layer *layers_to_del,
+				 struct mio_op *op);
+
+/**
+ * List layers from highest priority to lowest one.
+ * The memory to store layers and priorities are allocated
+ * inside the function.
+ * 
+ * @param object The object to add to.
+ * @param layout[out] The returned composite layout.
+ * @param op The operation will be initialised when returned.
+ * @return 0 for success, anything else for an error.
+ */
+int mio_composite_obj_list_layers(struct mio_obj *obj,
+                                  struct mio_comp_obj_layout *ret_layout,
+                   		  struct mio_op *op);
+
+/**
+ * Add/remove extents of the specified layer of a composite object.
+ *
+ * @param object The object to add to.
+ * @param layer  The sub-object of the layer.
+ * @param ext The extent in question.
+ * @return 0 for success, anything else for an error.
+ */
+int mio_composite_obj_add_extents(struct mio_obj *obj,
+				  struct mio_obj_id *layer_id,
+				  int nr_exts, struct mio_obj_ext *exts,
+				  struct mio_op *op);
+int mio_composite_obj_del_extents(struct mio_obj *obj,
+				  struct mio_obj_id *layer_id,
+				  int nr_exts, struct mio_obj_ext *exts,
+				  struct mio_op *op);
+/**
+ * Query `nr_exts` extents of the specified layer whose offsets are
+ * larger than `offset`. The number of extents found is returned.
+ *
+ * @param object The object to add to.
+ * @param layer  The sub-object of the layer.
+ * @param offset The returned extents’ offset must be >= this
+ * argument.
+ * @param nr_exts. The number of members in the array `exts`.
+ * @param exts[out] The output array for extents.
+ * @param nr_ret_exts[out] The returned number of extents from query.
+ * @return = 0 for success, anything else for an error.
+ */
+int
+mio_composite_obj_get_extents(struct mio_obj *obj,
+			      struct mio_obj_id *layer_id, off_t offset,
+			      int nr_exts, struct mio_obj_ext *exts,
+			      int *nr_ret_exts, struct mio_op *op);
+
+/**
+ * The structure 'mio' holds global information of underlying object store
+ * and key-value set.  
+ */
+struct mio {
+	enum mio_log_level m_log_level;
+	char *m_log_file;
+
+	enum mio_driver_id m_driver_id;
+	struct mio_driver *m_driver;
+	void *m_driver_confs;
+};
+extern struct mio *mio_instance;
+
+/**
+ * Initialises Maestro IO interface.
+ *
+ * @param yaml_conf cnfiguration file in Yaml format.
+ * @return 0 for success, anything else for an error.
+ */
+int mio_init(const char *yaml_conf);
+
+/**
+ * Finalises Maestro IO interface. 
+ */
+void mio_fini();
+
+/**
+ * Some object stores such as Mero supports thread-wise functionalities
+ * (such as ADDB) which requires thread to be initialised in a certain way.
+ * Call mio_thread_init() at the beginning of a thread and mio_thread_fini()
+ * at the end of it.
+ */
+struct mio_thread {
+	void *mt_drv_thread;
+};
+
+int mio_thread_init(struct mio_thread *thread);
+void mio_thread_fini(struct mio_thread *thread);
+
+#endif
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/src/mio_driver.c b/deps/mio/src/mio_driver.c
new file mode 100644
index 0000000000000000000000000000000000000000..ca286ea66a7e40a425cd80d7bcfa0c1353faeed9
--- /dev/null
+++ b/deps/mio/src/mio_driver.c
@@ -0,0 +1,114 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <assert.h>
+#include <sys/errno.h>
+
+#include "mio_internal.h"
+#include "mio.h"
+#include "driver_clovis.h"
+
+static struct mio_driver mio_drivers[MIO_DRIVER_NUM];
+
+/**
+ * This function must be called in each driver specific operation
+ * functions for object, key/value and others before launching
+ * the operations to add driver specific operation into the chain.
+ */
+int mio_driver_op_add(struct mio_op *op, mio_driver_op_postprocess post_proc,
+		       void *post_proc_data, void *drv_op)
+{
+	struct mio_driver_op *dop;
+
+	assert(op != NULL);
+
+	dop = (struct mio_driver_op *)mio_mem_alloc(sizeof *dop);
+	if (dop == NULL)
+		return -ENOMEM;
+
+	/*
+ 	 * Set driver op's action function such as post-processing
+ 	 * for key/value set GET query. See struct mio_driver_op
+ 	 * for details.
+ 	 */
+	dop->mdo_op = drv_op;
+	dop->mdo_post_proc = post_proc;
+	dop->mdo_post_proc_data = post_proc_data;
+
+	/* Insert into the chain. */
+	dop->mdo_next = op->mop_drv_op_chain.mdoc_head;
+	op->mop_drv_op_chain.mdoc_head = dop;
+
+	/*
+	 * Set driver operation's callbacks which will invoke real
+	 * application set callbacks when all job of MIO op is done. 
+	 */
+	if (op->mop_op_ops != NULL && op->mop_op_ops->mopo_set_cbs &&
+	    op->mop_app_cbs.moc_cb_complete != NULL &&
+	    op->mop_app_cbs.moc_cb_failed != NULL) {
+		op->mop_op_ops->mopo_set_cbs(op);
+	}
+
+	return 0;
+}
+
+void mio_driver_op_invoke_real_cb(struct mio_op *op, int rc)
+{
+	struct mio_op_app_cbs *app_cbs;
+
+	assert(op != NULL);
+
+	app_cbs = &op->mop_app_cbs;
+	op->mop_rc = rc;
+	if (rc == 0)
+		app_cbs->moc_cb_complete(op);
+	else
+		app_cbs->moc_cb_failed(op);
+}
+
+struct mio_driver* mio_driver_get(enum mio_driver_id driver_id)
+{
+	return mio_drivers + driver_id;
+}
+
+void mio_driver_register(enum mio_driver_id driver_id,
+			 struct mio_driver_sys_ops *sys_ops,
+			 struct mio_op_ops *op_ops,
+			 struct mio_obj_ops *obj_ops,
+			 struct mio_kvs_ops *kvs_ops,
+			 struct mio_comp_obj_ops *comp_obj_ops)
+{
+	struct mio_driver *drv;
+
+	drv = mio_drivers + driver_id;
+	drv->md_sys_ops = sys_ops;
+	drv->md_op_ops = op_ops;
+	drv->md_obj_ops = obj_ops;
+	drv->md_kvs_ops = kvs_ops;
+	drv->md_comp_obj_ops = comp_obj_ops;
+}
+
+void mio_drivers_register()
+{
+	mio_clovis_driver_register();
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/src/mio_internal.h b/deps/mio/src/mio_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..19730e61f60c5f222133e86ae54fa24e21bd52d1
--- /dev/null
+++ b/deps/mio/src/mio_internal.h
@@ -0,0 +1,350 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#ifndef __MIO_INTERNAL__
+#define __MIO_INTERNAL__
+
+#include <stdint.h>
+
+#include "clovis/clovis.h"
+
+struct mio;
+struct mio_op;
+struct mio_obj_id;
+struct mio_kvs_id;
+struct mio_pool;
+struct mio_obj;
+struct mio_iovec;
+struct mio_kv_pair;
+struct mio_thread;
+
+enum mio_obj_opcode;
+struct mio_obj_ext;
+struct mio_comp_obj_layer;
+struct mio_comp_obj_layout;
+
+/**
+ * MIO defines sets of operations a driver must implemnt:
+ *   - mio_op_ops defines driver specific functions on operation,
+ *     such as initialisation/finalisation and setting callbacks. (mandate)
+ *   - mio_obj_ops defines object access operations (mandate).
+ *   - mio_kvs_ops defines key-value operations (optional).
+ *   - mero-inspired operations, such as composite object related
+ *     operations (optional).
+ *
+ * Notes on writing driver specific functions to implement the sets of
+ * operations mentioned above.
+ *  - mio_driver_op_set() must be called and must be called after the op
+ *    is created and before it being launched.
+ */
+typedef void (*mio_callback)(struct mio_op *op);
+struct mio_op_ops {
+	int  (*mopo_init)(struct mio_op *op);
+	void (*mopo_fini)(struct mio_op *op);
+	int  (*mopo_wait)(struct mio_op *op, uint64_t timeout, int *retstate);
+	int  (*mopo_set_cbs)(struct mio_op *op);
+};
+
+struct mio_obj_ops {
+	int (*moo_open)(struct mio_obj *obj, struct mio_op *op);
+	int (*moo_close)(struct mio_obj *obj);
+	int (*moo_create)(const struct mio_pool *pool_id,
+			  struct mio_obj *obj, struct mio_op *op);
+	int (*moo_delete)(const struct mio_obj_id *oid, struct mio_op *op);
+
+	int (*moo_writev)(struct mio_obj *obj,
+			  const struct mio_iovec *iov,
+			  int iovcnt, struct mio_op *op);
+	int (*moo_readv)(struct mio_obj *obj,
+			 const struct mio_iovec *iov,
+			 int iovcnt, struct mio_op *op);
+	int (*moo_sync)(struct mio_obj *obj, struct mio_op *op);
+	int (*moo_size)(struct mio_obj *obj, struct mio_op *op);
+
+	/**
+	 * Load and store persistent hints. Unlike other operations,
+	 * storing/loading hints are synchronous operations because
+	 * not all hints are persistent hints, if applications use
+	 * only session hints, no IO (to retrieve persistent hints)
+	 * will be launched, thus no 'op' is needed. And as setting
+	 * hints is rare comapred to object accesses, its overhead
+	 * is considered small.
+	 */
+	int (*moo_hint_store)(struct mio_obj *obj);
+	int (*moo_hint_load)(struct mio_obj *obj);
+};
+
+struct mio_kvs_ops {
+	int (*mko_get)(struct mio_kvs_id *kvs_id,
+		       int nr_kvps, struct mio_kv_pair *kvps,
+		       int32_t *rcs, struct mio_op *op);
+
+	int (*mko_put)(struct mio_kvs_id *kvs_id,
+		       int nr_kvps, struct mio_kv_pair *kvps,
+		       int32_t *rcs, struct mio_op *op);
+
+	int (*mko_del)(struct mio_kvs_id *kvs_id,
+		       int nr_kvps, struct mio_kv_pair *kvps,
+		       int32_t *rcs, struct mio_op *op); 
+
+	int (*mko_create_set)(struct mio_kvs_id *kvs_id, struct mio_op *op);
+	int (*mko_del_set)(struct mio_kvs_id *kvs_id, struct mio_op *op);
+};
+
+struct mio_comp_obj_ops {
+	int (*mcoo_create)(struct mio_obj *obj, struct mio_op *op);
+	int (*mcoo_del)(const struct mio_obj_id *oid, struct mio_op *op);
+
+	int (*mcoo_add_layers)(struct mio_obj *obj,
+			       int nr_layers,
+			       struct mio_comp_obj_layer *layers,
+			       struct mio_op *op);
+	int (*mcoo_del_layers)(struct mio_obj *obj,
+			       int nr_layers_to_del,
+			       struct mio_comp_obj_layer *layers_to_del,
+			       struct mio_op *op);
+	int (*mcoo_list_layers)(struct mio_obj *obj,
+				struct mio_comp_obj_layout *ret_layout,
+				struct mio_op *op);
+
+	int (*mcoo_add_extents)(struct mio_obj *obj,
+			        struct mio_obj_id *layer_id,
+				int nr_exts, struct mio_obj_ext *exts,
+				struct mio_op *op);
+	int (*mcoo_del_extents)(struct mio_obj *obj,
+			        struct mio_obj_id *layer_id,
+				int nr_exts, struct mio_obj_ext *exts,
+				struct mio_op *op);
+
+	int (*mcoo_get_extents)(struct mio_obj *obj,
+			        struct mio_obj_id *layer_id, off_t offset,
+				int nr_exts, struct mio_obj_ext *exts,
+				int *nr_ret_exts, struct mio_op *op);
+};
+
+/**
+ * MIO defines a generic driver interface to use different object stores
+ * as backend. It includes:
+ *   - Types of interface driver. Currently only Mero object store is
+ *     supported. Ceph driver will be implemented in future.
+ *   - Operations to initialise and finalise a driver.
+ *   - Operation set that a driver is to implement. Each driver must
+ *     implement an object store interface and key-value set interface.
+ *     mero-inspired interface is optional.
+ */
+enum mio_driver_id {
+	MIO_DRIVER_INVALID = -1,
+	MIO_MERO,
+	MIO_DRIVER_NUM
+};
+
+/**
+ * Initialisation and finalisation functions for an interface driver.
+ */
+struct mio_driver_sys_ops {
+	int (*mdo_init) (struct mio *mio_inst);
+	void (*mdo_fini) (void);
+
+	int (*mdo_thread_init)(struct mio_thread *thread);
+	void (*mdo_thread_fini)(struct mio_thread *thread);
+};
+
+/**
+ * Each Maestro IO driver is defined by a set of operations. Driver
+ * initialisaton/finalisation and object and key-value set accessing operations
+ * must be implemented for a driver, while mero-inspired operations
+ * are optional. 
+ */
+struct mio_driver {
+	/** Driver's operations, such as initialisation and finalisation. */
+	struct mio_driver_sys_ops *md_sys_ops;
+
+	struct mio_op_ops *md_op_ops;
+
+	/** Object and key-value set operations. */
+	struct mio_obj_ops *md_obj_ops;
+	struct mio_kvs_ops *md_kvs_ops;
+
+	/** Mero-inspired APIs. */
+	struct mio_comp_obj_ops *md_comp_obj_ops;
+};
+
+/**
+ * mio_driver_op contains a pointer to the driver specific operation and
+ * a function pointer which is called to do post processing or to create
+ * and move to next op. In this way, MIO is able to chain and execute a
+ * number of dependent ops. Examples of mio_driver_op::mdo_func are:
+ *   - Post-processing of GET operation to copy returned values from
+ *     the key-value store.
+ *   - Object WRITE which includes writing data (to data store) and
+ *     updating object attributes (such as size) to metadata store.
+ *
+ * Beaware that when chaining multiple driver operations to accomplish
+ * a task, it is up to the driver to handle any driver operation's
+ * failure, some driver will roll back to a consistent state if proper
+ * transcation mechanism is implemented. Current version of clovis driver
+ * simply reports the error back to application. This will be re-visited
+ * after DTM is in place.
+ *
+ * An implementation of mio_driver_op::mdo_post_process() should follow the
+ * general rules below:
+ *   - Return value: if it doesn't create a new op,  MIO_DRV_OP_FINAL
+ *     is returned, otherwise a new next function is set and
+ *     MIO_DRV_OP_NEXT is returned.
+ *
+ * mio_driver_op::mdo_post_process is invoked when:
+ *   - mio_op_poll() checks if post processing action is set for an op
+ *     when mio_op_ops::mopo_wait() returns. If post processing is set
+ *     and called and new driver's op is created, mio_op_poll() will
+ *     keep polling if not yet timed out.
+ *  - if an application has set the callback functions, the callback
+ *    functions must check and call the post processing action if set.
+ *  - So, an application can't poll an op whose callback functions have
+ *    been set to avoid double entries to the post processing action.
+ */
+enum {
+	MIO_DRV_OP_NEXT = 0,
+	MIO_DRV_OP_FINAL,
+};
+
+typedef int (*mio_driver_op_postprocess)(struct mio_op *op);
+struct mio_driver_op {
+	/**
+	 * The function and data for post-processing.
+	 */
+	mio_driver_op_postprocess mdo_post_proc;
+	void *mdo_post_proc_data;
+
+	/** Pointers to driver specific op. */
+	void *mdo_op;
+
+	struct mio_driver_op *mdo_next;
+};
+
+struct mio_driver_op_chain {
+	struct mio_driver_op *mdoc_head;
+};
+
+int mio_driver_op_add(struct mio_op *op, mio_driver_op_postprocess post_proc,
+		      void *post_proc_data, void *drv_op);
+void mio_driver_op_invoke_real_cb(struct mio_op *op, int rc);
+
+struct mio_driver* mio_driver_get(enum mio_driver_id driver_id);
+
+/** Register a driver. */
+void mio_driver_register(enum mio_driver_id driver_id,
+			 struct mio_driver_sys_ops *drv_ops,
+			 struct mio_op_ops *op_ops,
+			 struct mio_obj_ops *obj_ops,
+			 struct mio_kvs_ops *kvs_ops,
+			 struct mio_comp_obj_ops *comp_obj_ops);
+
+/** Register all drivers when initialising MIO instance. */
+void mio_drivers_register();
+
+void mio_clovis_driver_register();
+
+/**
+ * mio_mero_config contains configuration parameters to setup an
+ * Mero Clovis instance.
+ */
+struct mio_mero_config {
+	/** oostore mode is set when 'is_oostore' is TRUE. */
+	bool mc_is_oostore;
+	/**
+	 * Flag for verify-on-read. Parity is checked when doing
+	 * READ's if this flag is set.
+	 */
+	bool mc_is_read_verify;
+
+	/** Local endpoint.*/
+	char *mc_clovis_local_addr;
+	/** HA service's endpoint.*/
+	char *mc_ha_addr;
+	/** Process fid for rmservice@clovis. */
+	char *mc_process_fid;
+	char *mc_profile;
+
+	/**
+	 * The minimum length of the 'tm' receive queue,
+         * use M0_NET_TM_RECV_QUEUE_DEF_LEN if unsure.
+         */
+	uint32_t mc_tm_recv_queue_min_len;
+	/**
+	 * The maximum rpc message size, use M0_RPC_DEF_MAX_RPC_MSG_SIZE
+	 * if unsure.
+	 */
+	uint32_t mc_max_rpc_msg_size;
+
+	/**
+	 * Default parity group data unit size of an object. As Clovis
+	 * internally uses layout id instead of unit size, the layout id
+	 * will be computed from unit size.
+	 */
+	int mc_unit_size;
+	int mc_default_layout_id;
+};
+
+/**
+ * A simple map implementation for hints in which key is of type `int`
+ * and value is of type `uint64_t`. As there are usually small number
+ * of hints for each object, arrays are used to store keys and values.
+ * The overhead of looking up entries in arrays is low. 
+ */
+struct mio_hint_map {
+	int mhm_nr_entries;
+	int mhm_nr_set;
+	int *mhm_keys;
+	uint64_t *mhm_values;
+};
+
+enum {
+	MIO_OBJ_HINT_NUM = 32
+};
+int mio_hint_map_init(struct mio_hint_map *map, int nr_entries);
+void mio_hint_map_fini(struct mio_hint_map *map);
+int mio_hint_map_copy(struct mio_hint_map *, struct mio_hint_map *from);
+int mio_hint_map_set(struct mio_hint_map *map, int key, uint64_t value);
+int mio_hint_map_get(struct mio_hint_map *map, int key, uint64_t *value);
+
+void *mio_mem_alloc(size_t size);
+void mio_mem_free(void *p);
+void mio_memset(void *p, int c, size_t size);
+void mio_mem_copy(void *to, void *from, size_t size);
+
+uint64_t mio_now();
+
+uint64_t mio_byteorder_cpu_to_be64(uint64_t cpu_64bits);
+uint64_t mio_byteorder_be64_to_cpu(uint64_t big_endian_64bits);
+
+int mio_conf_init(const char *config_file);
+void mio_conf_fini();
+
+void mio_obj_op_init(struct mio_op *op, struct mio_obj *obj,
+		     enum mio_obj_opcode opcode);
+
+void mio_op_cb_failed(struct mio_op *op);
+void mio_op_cb_complete(struct mio_op *op);
+#endif
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/src/parser.c b/deps/mio/src/parser.c
new file mode 100644
index 0000000000000000000000000000000000000000..c57417466bebfffc60dd81234ea5de21a391802c
--- /dev/null
+++ b/deps/mio/src/parser.c
@@ -0,0 +1,403 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <yaml.h>
+
+#include "clovis/clovis.h"
+
+#include "logger.h"
+#include "mio_internal.h"
+#include "mio.h"
+
+enum {
+	YAML_MAX_KEY_LEN = 128
+};
+
+enum conf_type {
+	MIO = 0,
+	MERO,
+	CEPH,
+};
+
+enum conf_key {
+	MIO_CONF_INVALID = -1,
+
+	/* MIO */
+	MIO_CONFIG = 0,
+	MIO_LOG_LEVEL,
+	MIO_LOG_FILE,
+	MIO_DRIVER,
+
+	/* Mero driver. "MERO_CONFIG" is the key for Mero section. */
+	MERO_CONFIG,
+	MERO_CLOVIS_INST_ADDR,
+	MERO_HA_ADDR,
+	MERO_PROFILE,
+	MERO_PROCESS_FID,
+	MERO_IS_OOSTORE,
+	MERO_IS_READ_VERIFY,
+	MERO_TM_RECV_QUEUE_MIN_LEN,
+	MERO_MAX_RPC_MSG_SIZE,
+	MERO_DEFAULT_UNIT_SIZE,
+
+	/* Other drivers such as Ceph defined here. */
+};
+
+struct conf_entry {
+	char *name;
+	enum conf_type type;
+};
+
+/**
+ * Currently MIO put all configuration entries into one big table defined
+ * below, which is not too difficult to manage considering MIO only
+ * support Mero driver and has limited configurations. But this will become
+ * a problem when more drivers are implemented. A better solution is to
+ * seperate the big table into driver specific ones and to define driver's
+ * configuration operations to parse its entries. 
+ *
+ * TODO: driver specific configuration table and operations.
+ */
+struct conf_entry conf_table[] = {
+	/* MIO */
+	[MIO_CONFIG] = {
+		.name = "MIO_CONFIG",
+		.type = MIO
+	},
+	[MIO_LOG_FILE] = {
+		.name = "MIO_LOG_FILE",
+		.type = MIO
+	},
+	[MIO_LOG_LEVEL] = {
+		.name = "MIO_LOG_LEVEL",
+		.type = MIO
+	},
+	[MIO_DRIVER] = {
+		.name = "MIO_DRIVER",
+		.type = MIO
+	},
+
+	/* Mero driver. */
+	[MERO_CONFIG] = {
+		.name = "MERO_CONFIG",
+		.type = MERO
+	},
+	[MERO_CLOVIS_INST_ADDR] = {
+		.name = "MERO_CLOVIS_INST_ADDR",
+		.type = MERO
+	},
+	[MERO_HA_ADDR] = {
+		.name = "MERO_HA_ADDR",
+		.type = MERO
+	},
+	[MERO_PROFILE] = {
+		.name = "MERO_PROFILE",
+		.type = MERO
+	},
+	[MERO_PROCESS_FID] = {
+		.name = "MERO_PROCESS_FID",
+		.type = MERO
+	},
+	[MERO_IS_OOSTORE] = {
+		.name = "MERO_IS_OOSTORE",
+		.type = MERO
+	},
+	[MERO_IS_READ_VERIFY] = {
+		.name = "MERO_IS_READ_VERIFY",
+		.type = MERO
+	},
+	[MERO_TM_RECV_QUEUE_MIN_LEN] = {
+		.name = "MERO_TM_RECV_QUEUE_MIN_LEN",
+		.type = MERO
+	},
+	[MERO_MAX_RPC_MSG_SIZE] = {
+		.name = "MERO_MAX_RPC_MSG_SIZE",
+		.type = MERO
+	},
+	[MERO_DEFAULT_UNIT_SIZE] = {
+		.name = "MERO_DEFAULT_UNIT_SIZE",
+		.type = MERO
+	},
+};
+
+static enum mio_driver_id mio_inst_drv_id;
+static void *mio_driver_confs[MIO_DRIVER_NUM];
+static struct mio_mero_config *mero_conf;
+
+#define NKEYS (sizeof(conf_table)/sizeof(struct conf_entry))
+
+static int conf_token_to_key(char *token, enum conf_key *key)
+{
+	int rc = 0;
+	int i;
+	char *s1;
+
+	for(i = 0; i < NKEYS; i++) {
+		s1 = strstr(token, conf_table[i].name);
+		if (s1 != NULL && !strcmp(s1, conf_table[i].name)) {
+			*key = i;
+			break;
+		}
+	}
+	if (i == NKEYS)
+		rc = MIO_CONF_INVALID;
+	return rc;
+}
+
+static enum mio_driver_id conf_get_driver_id(const char *str)
+{
+	enum mio_driver_id drv_id = MIO_DRIVER_INVALID;
+
+	assert(str != NULL);
+	if (!strcmp(str, "MERO"))
+		drv_id = MIO_MERO;
+
+	return drv_id;	
+}
+
+static enum mio_log_level conf_get_log_level(const char *str)
+{
+	assert(str != NULL);
+	if (!strcmp(str, "MIO_ERROR"))
+		return MIO_ERROR;
+	else if (!strcmp(str, "MIO_WARN"))
+		return MIO_WARN;
+	else if (!strcmp(str, "MIO_INFO"))
+		return MIO_INFO;
+	else if (!strcmp(str, "MIO_TRACE"))
+		return MIO_TRACE;
+	else if (!strcmp(str, "MIO_DEBUG"))
+		return MIO_DEBUG;
+	else
+		return MIO_LOG_INVALID;
+}
+
+static int conf_copy_str(char **to, char *from)
+{
+	int len = strlen(from) + 1;
+
+	*to = mio_mem_alloc(len);
+	if (*to == NULL)
+		return  -ENOMEM;
+
+	strncpy(*to, from, len);
+	return 0;
+}
+
+static int conf_alloc_driver(int key)
+{
+	int rc = 0;
+	int type;
+
+	/* Allocate driver's configuration structure if it hasn't been. */
+	type = conf_table[key].type;
+	switch(type) {
+	case MERO:
+		if (mero_conf != NULL)
+			break;
+
+		mero_conf = malloc(sizeof(struct mio_mero_config));
+		mio_driver_confs[MIO_MERO] = mero_conf;
+		if (mero_conf == NULL)
+			rc = -ENOMEM;
+		break;
+	case CEPH:
+		fprintf(stderr, "Ceph driver is not supported yet!");
+		rc = -EINVAL;
+		break;
+	default:
+		break;
+	}
+
+	return rc;
+}
+
+static void conf_free_drivers()
+{
+	if (mero_conf) {
+		mio_mem_free(mero_conf->mc_clovis_local_addr);
+		mio_mem_free(mero_conf->mc_ha_addr);
+		mio_mem_free(mero_conf->mc_process_fid);
+		mio_mem_free(mero_conf->mc_profile);
+		free(mero_conf);
+		mio_driver_confs[MIO_MERO] = NULL;
+	}
+}
+
+static int conf_extract_key(enum conf_key *key, char *token)
+{
+	int rc;
+
+	rc = conf_token_to_key(token, key);
+	if (rc < 0) {
+		fprintf(stderr, "Invalid token name: %s\n", token);
+		return rc;
+	}
+
+	rc = conf_alloc_driver(*key);
+	if (rc < 0)
+		fprintf(stderr, "Can't allocate memory for driver!");
+
+	return rc;
+}
+
+static int conf_extract_value(enum conf_key key, char *value)
+{
+	int rc = 0;
+
+	/* Extract configuration value. */
+	switch(key) {
+	case MIO_DRIVER:
+		mio_inst_drv_id = conf_get_driver_id(value); 
+		if (mio_inst_drv_id == MIO_DRIVER_INVALID)
+			rc = -EINVAL;
+		break;
+	case MIO_LOG_LEVEL:
+		assert(mio_instance != NULL);
+		mio_instance->m_log_level = conf_get_log_level(value);
+		if (mio_instance->m_log_level == MIO_LOG_INVALID)
+			rc = -EINVAL;
+		break;
+	case MIO_LOG_FILE:
+		assert(mio_instance != NULL && value != NULL);
+		rc = conf_copy_str(&mio_instance->m_log_file, value);
+		break;
+	case MERO_CLOVIS_INST_ADDR:
+		rc = conf_copy_str(&mero_conf->mc_clovis_local_addr, value);
+		break;
+	case MERO_HA_ADDR:
+		rc = conf_copy_str(&mero_conf->mc_ha_addr, value);
+		break;
+	case MERO_PROFILE:
+		rc = conf_copy_str(&mero_conf->mc_profile, value);
+		break;
+	case MERO_PROCESS_FID:
+		rc = conf_copy_str(&mero_conf->mc_process_fid, value);
+		break;
+	case MERO_TM_RECV_QUEUE_MIN_LEN:
+		mero_conf->mc_tm_recv_queue_min_len = atoi(value);
+		break;
+	case MERO_MAX_RPC_MSG_SIZE:
+		mero_conf->mc_max_rpc_msg_size = atoi(value);
+		break;
+	case MERO_DEFAULT_UNIT_SIZE:
+		mero_conf->mc_unit_size = atoi(value);
+		mero_conf->mc_default_layout_id =
+		  m0_clovis_obj_unit_size_to_layout_id(mero_conf->mc_unit_size);
+		break;
+	case MERO_IS_OOSTORE:
+		mero_conf->mc_is_oostore = atoi(value);
+		break;
+	case MERO_IS_READ_VERIFY:
+		mero_conf->mc_is_read_verify = atoi(value);
+		break;
+	default:
+		break;
+	}
+
+	return rc;
+}
+
+int mio_conf_init(const char *config_file)
+{
+	int  rc;
+	FILE *fh;
+	bool is_key = true;
+	enum conf_key key = MIO_CONF_INVALID;
+	char *scalar_value;
+	bool eof;
+	yaml_parser_t parser;
+	yaml_token_t token;
+
+	if (!yaml_parser_initialize(&parser)) {
+		/* MIO logger has not been initialised yet, so use fprintf. */
+		fprintf(stderr, "Failed to initialize parser!\n");
+		return -1;
+	}
+
+	fh = fopen(config_file, "r");
+	if (fh == NULL) {
+		fprintf(stderr, "Failed to open file!\n");
+		return -1;
+	}
+
+	/* Scan the yaml file and retrieve configuration values. */
+	rc = 0;
+	eof = false;
+	yaml_parser_set_input_file(&parser, fh);
+
+	while(!eof) {
+		yaml_parser_scan(&parser, &token);
+
+		switch (token.type) {
+		case YAML_KEY_TOKEN:
+			is_key = true;
+			break;
+		case YAML_VALUE_TOKEN:
+			is_key = false;
+			break;
+		case YAML_SCALAR_TOKEN:
+			scalar_value = (char *)token.data.scalar.value;
+			if (is_key)
+				rc = conf_extract_key(&key, scalar_value);
+			else
+				rc = conf_extract_value(key, scalar_value);
+			break;
+		case YAML_STREAM_END_TOKEN:				
+			eof = true;
+			break;
+		default:
+			break;
+		}
+
+		yaml_token_delete(&token);
+
+		if (rc < 0)
+			break;
+	}
+	if (rc < 0) {
+		conf_free_drivers();
+		goto exit;
+	}
+
+	/* Set driver properly. */	
+	mio_instance->m_driver_id = mio_inst_drv_id;
+	mio_instance->m_driver = mio_driver_get(mio_inst_drv_id);
+	mio_instance->m_driver_confs = mio_driver_confs[mio_inst_drv_id];
+
+exit:
+	yaml_parser_delete(&parser);
+	fclose(fh);
+	return rc;
+}
+
+void mio_conf_fini()
+{
+	conf_free_drivers();
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/src/utils.c b/deps/mio/src/utils.c
new file mode 100644
index 0000000000000000000000000000000000000000..cb7ab412db601e9a8a333293b7f6d0e24177d677
--- /dev/null
+++ b/deps/mio/src/utils.c
@@ -0,0 +1,77 @@
+/* -*- C -*- */
+/*
+ * Copyright: (c) 2020 - 2021 Seagate Technology LLC and/or its its Affiliates,
+ * All Rights Reserved
+ *
+ * This software is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdlib.h>
+#include <sys/time.h>
+#include <asm/byteorder.h>
+
+#include "mio_internal.h"
+
+void *mio_mem_alloc(size_t size)
+{
+	void *p;
+
+	p = malloc(size);
+	if (p != NULL)
+		memset(p, 0, size);
+
+	return p;
+}
+
+void mio_mem_free(void *p)
+{
+	free(p);
+}
+
+void mio_memset(void *p, int c, size_t size)
+{
+	memset(p, c, size);
+}
+
+void mio_mem_copy(void *to, void *from, size_t size)
+{
+	memcpy(to, from, size);
+}
+
+enum {
+        TIME_ONE_SECOND = 1000000000ULL,
+        TIME_ONE_MSEC   = TIME_ONE_SECOND / 1000
+};
+
+uint64_t mio_now()
+{
+        struct timeval tv;
+
+        gettimeofday(&tv, NULL);
+        return tv.tv_sec * TIME_ONE_SECOND + tv.tv_usec * 1000;
+}
+
+uint64_t mio_byteorder_cpu_to_be64(uint64_t cpu_64bits)
+{
+        return __cpu_to_be64(cpu_64bits);
+}
+
+uint64_t mio_byteorder_be64_to_cpu(uint64_t big_endian_64bits)
+{
+        return __be64_to_cpu(big_endian_64bits);
+}
+
+/*
+ *  Local variables:
+ *  c-indentation-style: "K&R"
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ *  fill-column: 80
+ *  scroll-step: 1
+ *  End:
+ */
+/*
+ * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
+ */
diff --git a/deps/mio/tests/mio_config.yaml b/deps/mio/tests/mio_config.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..362ed73fc229d5f64c04c44d73d88540d7f91121
--- /dev/null
+++ b/deps/mio/tests/mio_config.yaml
@@ -0,0 +1,18 @@
+# Sample MIO configuration Yaml file. 
+
+#MIO_Config_Sections: [MIO_CONFIG, MERO_CONFIG]
+MIO_CONFIG:
+  MIO_LOG_FILE:
+  MIO_LOG_LEVEL: MIO_DEBUG 
+  MIO_DRIVER: MERO
+
+MERO_CONFIG:
+  MERO_CLOVIS_INST_ADDR: 192.168.0.23@tcp:12345:34:101
+  MERO_HA_ADDR: 192.168.0.23@tcp:12345:34:1
+  MERO_PROFILE: <0x7000000000000001:0>
+  MERO_PROCESS_FID: <0x7200000000000000:0>
+  MERO_DEFAULT_UNIT_SIZE: 1048576
+  MERO_IS_OOSTORE: 1
+  MERO_IS_READ_VERIFY: 0
+  MERO_TM_RECV_QUEUE_MIN_LEN: 2
+  MERO_MAX_RPC_MSG_SIZE: 131072