Project import
diff --git a/f2fs-tools/AUTHORS b/f2fs-tools/AUTHORS
new file mode 100644
index 0000000..6ec1861
--- /dev/null
+++ b/f2fs-tools/AUTHORS
@@ -0,0 +1 @@
+This package has been developed by Praesto Team at Samsung Electronics Co., Ltd.
diff --git a/f2fs-tools/Android.mk b/f2fs-tools/Android.mk
new file mode 100644
index 0000000..55f4a4e
--- /dev/null
+++ b/f2fs-tools/Android.mk
@@ -0,0 +1,128 @@
+LOCAL_PATH:= $(call my-dir)
+
+# f2fs-tools depends on Linux kernel headers being in the system include path.
+ifeq ($(HOST_OS),linux)
+
+# The versions depend on $(LOCAL_PATH)/VERSION
+version_CFLAGS := -DF2FS_MAJOR_VERSION=1 -DF2FS_MINOR_VERSION=4 -DF2FS_TOOLS_VERSION=\"1.4.0\" -DF2FS_TOOLS_DATE=\"2014-10-18\"
+
+# external/e2fsprogs/lib is needed for uuid/uuid.h
+common_C_INCLUDES := $(LOCAL_PATH)/include external/e2fsprogs/lib/
+
+#----------------------------------------------------------
+include $(CLEAR_VARS)
+LOCAL_MODULE := libf2fs_fmt
+LOCAL_SRC_FILES := \
+	lib/libf2fs.c \
+	mkfs/f2fs_format.c \
+	mkfs/f2fs_format_utils.c \
+
+LOCAL_C_INCLUDES := $(common_C_INCLUDES)
+LOCAL_CFLAGS := $(version_CFLAGS)
+LOCAL_EXPORT_CFLAGS := $(version_CFLAGS)
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/mkfs
+include $(BUILD_STATIC_LIBRARY)
+
+#----------------------------------------------------------
+include $(CLEAR_VARS)
+LOCAL_MODULE := libf2fs_fmt_host
+LOCAL_SRC_FILES := \
+	lib/libf2fs.c \
+	mkfs/f2fs_format.c \
+	mkfs/f2fs_format_utils.c \
+
+LOCAL_C_INCLUDES := $(common_C_INCLUDES)
+LOCAL_CFLAGS := $(version_CFLAGS)
+LOCAL_EXPORT_CFLAGS := $(version_CFLAGS)
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/mkfs
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+#----------------------------------------------------------
+include $(CLEAR_VARS)
+LOCAL_MODULE := libf2fs_fmt_host_dyn
+LOCAL_SRC_FILES := \
+	lib/libf2fs.c \
+	mkfs/f2fs_format.c \
+
+LOCAL_C_INCLUDES := $(common_C_INCLUDES)
+LOCAL_CFLAGS := $(version_CFLAGS)
+LOCAL_EXPORT_CFLAGS := $(version_CFLAGS)
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/mkfs
+LOCAL_STATIC_LIBRARIES := \
+     libf2fs_ioutils_host \
+     libext2_uuid-host \
+     libsparse_host \
+     libz
+# LOCAL_LDLIBS := -ldl
+include $(BUILD_HOST_SHARED_LIBRARY)
+
+#----------------------------------------------------------
+include $(CLEAR_VARS)
+# The LOCAL_MODULE name is referenced by the code. Don't change it.
+LOCAL_MODULE := mkfs.f2fs
+
+# mkfs.f2fs is used in recovery: must be static.
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
+
+LOCAL_SRC_FILES := \
+	lib/libf2fs_io.c \
+	mkfs/f2fs_format_main.c
+LOCAL_C_INCLUDES := $(common_C_INCLUDES)
+LOCAL_CFLAGS := $(version_CFLAGS)
+LOCAL_STATIC_LIBRARIES := libc libf2fs_fmt libext2_uuid_static
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_EXECUTABLE)
+
+#----------------------------------------------------------
+include $(CLEAR_VARS)
+LOCAL_MODULE := make_f2fs
+
+LOCAL_SRC_FILES := \
+	lib/libf2fs_io.c \
+	mkfs/f2fs_format_main.c
+LOCAL_C_INCLUDES := $(common_C_INCLUDES)
+LOCAL_CFLAGS := $(version_CFLAGS)
+LOCAL_STATIC_LIBRARIES := libf2fs_fmt
+LOCAL_SHARED_LIBRARIES := libext2_uuid
+LOCAL_SYSTEM_SHARED_LIBRARIES := libc
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_EXECUTABLE)
+
+#----------------------------------------------------------
+include $(CLEAR_VARS)
+# The LOCAL_MODULE name is referenced by the code. Don't change it.
+LOCAL_MODULE := fsck.f2fs
+LOCAL_SRC_FILES := \
+	fsck/dump.c \
+	fsck/fsck.c \
+	fsck/main.c \
+	fsck/mount.c \
+	lib/libf2fs.c \
+	lib/libf2fs_io.c \
+
+LOCAL_C_INCLUDES := $(common_C_INCLUDES)
+LOCAL_CFLAGS := $(version_CFLAGS)
+LOCAL_SHARED_LIBRARIES := libext2_uuid
+LOCAL_SYSTEM_SHARED_LIBRARIES := libc
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_EXECUTABLE)
+
+#----------------------------------------------------------
+include $(CLEAR_VARS)
+LOCAL_MODULE := fsck.f2fs
+LOCAL_SRC_FILES := \
+	fsck/dump.c \
+	fsck/fsck.c \
+	fsck/main.c \
+	fsck/mount.c \
+	lib/libf2fs.c \
+	lib/libf2fs_io.c \
+
+LOCAL_C_INCLUDES := $(common_C_INCLUDES)
+LOCAL_CFLAGS := $(version_CFLAGS)
+LOCAL_HOST_SHARED_LIBRARIES :=  libext2_uuid_host
+include $(BUILD_HOST_EXECUTABLE)
+
+endif
diff --git a/f2fs-tools/COPYING b/f2fs-tools/COPYING
new file mode 100644
index 0000000..52f956d
--- /dev/null
+++ b/f2fs-tools/COPYING
@@ -0,0 +1,864 @@
+The tools for F2FS are covered by GNU Public License version 2.
+Exceptionally, the following files are also covered by the GNU Lesser General
+Public License Version 2.1 as the dual licenses.
+- include/f2fs_fs.h
+- lib/libf2fs.c
+- lib/libf2fs_io.c
+- mkfs/f2fs_format.c
+- mkfs/f2fs_format_main.c
+- mkfs/f2fs_format_utils.c
+- mkfs/f2fs_format_utils.h
+
+================================================================================
+Copyright (c) 2012 Samsung Electronics Co., Ltd.
+             http://www.samsung.com/
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2 as
+published by the Free Software Foundation.
+
+================================================================================
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+================================================================================
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/f2fs-tools/ChangeLog b/f2fs-tools/ChangeLog
new file mode 100644
index 0000000..9739e99
--- /dev/null
+++ b/f2fs-tools/ChangeLog
@@ -0,0 +1,4 @@
+f2fs-tools-1.0.0 Tue Aug 14, 2012 KST
+    * The first release of f2fs-tools.
+f2fs-tools-1.0.1 Tue Jun 04, 2013 KST
+    * Added fsck and dump for f2fs-tools.
diff --git a/f2fs-tools/MODULE_LICENSE_LGPL b/f2fs-tools/MODULE_LICENSE_LGPL
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/f2fs-tools/MODULE_LICENSE_LGPL
diff --git a/f2fs-tools/Makefile.am b/f2fs-tools/Makefile.am
new file mode 100644
index 0000000..d2921d6
--- /dev/null
+++ b/f2fs-tools/Makefile.am
@@ -0,0 +1,5 @@
+## Makefile.am
+
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS = man lib mkfs fsck tools
diff --git a/f2fs-tools/NOTICE b/f2fs-tools/NOTICE
new file mode 100644
index 0000000..52f956d
--- /dev/null
+++ b/f2fs-tools/NOTICE
@@ -0,0 +1,864 @@
+The tools for F2FS are covered by GNU Public License version 2.
+Exceptionally, the following files are also covered by the GNU Lesser General
+Public License Version 2.1 as the dual licenses.
+- include/f2fs_fs.h
+- lib/libf2fs.c
+- lib/libf2fs_io.c
+- mkfs/f2fs_format.c
+- mkfs/f2fs_format_main.c
+- mkfs/f2fs_format_utils.c
+- mkfs/f2fs_format_utils.h
+
+================================================================================
+Copyright (c) 2012 Samsung Electronics Co., Ltd.
+             http://www.samsung.com/
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2 as
+published by the Free Software Foundation.
+
+================================================================================
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+================================================================================
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/f2fs-tools/README b/f2fs-tools/README
new file mode 100644
index 0000000..222cbc3
--- /dev/null
+++ b/f2fs-tools/README
@@ -0,0 +1,48 @@
+F2FS format utilility
+---------------------
+
+To use f2fs filesystem, you should format the storage partition
+with this utilility. Otherwise, you cannot mount f2fs.
+
+Before compilation
+------------------
+
+Your should install the following packages.
+ - libuuid-devel or uuid-dev
+ - pkg-config
+ - autoconf
+ - libtool
+
+Initial compilation
+-------------------
+
+Before compilation initially, autoconf/automake tools should be run.
+
+ # autoreconf --install
+
+How to compile
+--------------
+
+ # ./configure
+ # make
+
+How to cross-compile (e.g., for ARM)
+------------------------------------
+
+ 1. Add the below line into mkfs/Makefile.am:
+ mkfs_f2fs_LDFLAGS = -all-static
+
+ 2. Add the below line into fsck/Makefile.am:
+ fsck_f2fs_LDFLAGS = -all-static
+
+ 3. then, do:
+ # LDFLAGS=--static ./configure \
+	--host=arm-none-linux-gnueabi --target=arm-none-linux-gnueabi
+ # make
+
+How to run by default
+---------------------
+
+ $ ./mkfs.f2fs -l [LABEL] $DEV
+
+For more mkfs options, see man page.
diff --git a/f2fs-tools/VERSION b/f2fs-tools/VERSION
new file mode 100644
index 0000000..0e58c09
--- /dev/null
+++ b/f2fs-tools/VERSION
@@ -0,0 +1,2 @@
+1.4.1
+2015-03-04
diff --git a/f2fs-tools/configure.ac b/f2fs-tools/configure.ac
new file mode 100644
index 0000000..ae451b8
--- /dev/null
+++ b/f2fs-tools/configure.ac
@@ -0,0 +1,92 @@
+#                                               -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ([2.68])
+
+# Get version from file VERSION
+m4_define([f2fs_tools_version], m4_esyscmd([sed -n '1p' VERSION | tr -d '\n']))
+m4_define([f2fs_tools_date], m4_esyscmd([sed -n '2p' VERSION | tr -d '\n']))
+m4_define([f2fs_tools_gitdate],
+		m4_esyscmd([git log -1 --pretty=format:%ci 2> /dev/null]))
+
+AC_INIT([F2FS tools], [f2fs_tools_version],
+			[linux-f2fs-devel@lists.sourceforge.net])
+
+AC_DEFINE([F2FS_TOOLS_VERSION], "f2fs_tools_version", [f2fs-tools version])
+AC_DEFINE([F2FS_MAJOR_VERSION], m4_bpatsubst(f2fs_tools_version,
+				[\([0-9]*\)\(\w\|\W\)*], [\1]),
+				[Major version for f2fs-tools])
+AC_DEFINE([F2FS_MINOR_VERSION], m4_bpatsubst(f2fs_tools_version,
+				[\([0-9]*\).\([0-9]*\)\(\w\|\W\)*], [\2]),
+				[Minor version for f2fs-tools])
+
+AC_CHECK_FILE(.git,
+	AC_DEFINE([F2FS_TOOLS_DATE],
+		"m4_bpatsubst(f2fs_tools_gitdate,
+		[\([0-9-]*\)\(\w\|\W\)*], [\1])",
+		[f2fs-tools date based on Git commits]),
+	AC_DEFINE([F2FS_TOOLS_DATE],
+		"f2fs_tools_date",
+		[f2fs-tools date based on Source releases]))
+
+AC_CONFIG_SRCDIR([config.h.in])
+AC_CONFIG_HEADER([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_AUX_DIR([build-aux])
+AM_INIT_AUTOMAKE([foreign tar-pax dist-xz])
+
+AC_CHECK_HEADERS_ONCE([
+	fcntl.h
+	mntent.h
+	stdlib.h
+	string.h
+	unistd.h
+	sys/ioctl.h
+	sys/mount.h
+])
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_LIBTOOL
+AC_PATH_PROG([LDCONFIG], [ldconfig],
+       [AC_MSG_ERROR([ldconfig not found])],
+       [$PATH:/sbin])
+
+# Checks for libraries.
+PKG_CHECK_MODULES([libuuid], [uuid])
+
+# Checks for header files.
+AC_CHECK_HEADERS([linux/fs.h fcntl.h mntent.h stdlib.h string.h \
+		sys/ioctl.h sys/mount.h unistd.h linux/falloc.h byteswap.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_INLINE
+AC_TYPE_INT32_T
+AC_TYPE_INT8_T
+AC_TYPE_SIZE_T
+
+# Checks for library functions.
+AC_FUNC_GETMNTENT
+AC_CHECK_FUNCS_ONCE([
+	getmntent
+	memset
+])
+
+AS_IF([test "$ac_cv_header_byteswap_h" = "yes"],
+      [AC_CHECK_DECLS([bswap_64],,,[#include <byteswap.h>])])
+
+# Install directories
+AC_PREFIX_DEFAULT([/usr])
+AC_SUBST([sbindir], [/sbin])
+AC_SUBST([sysconfdir], [/etc])
+AC_SUBST([localstatedir], [/var])
+AC_CONFIG_FILES([
+	Makefile
+	man/Makefile
+	lib/Makefile
+	mkfs/Makefile
+	fsck/Makefile
+	tools/Makefile
+])
+
+AC_OUTPUT
diff --git a/f2fs-tools/fsck/Makefile.am b/f2fs-tools/fsck/Makefile.am
new file mode 100644
index 0000000..3258e47
--- /dev/null
+++ b/f2fs-tools/fsck/Makefile.am
@@ -0,0 +1,10 @@
+## Makefile.am
+
+AM_CPPFLAGS = ${libuuid_CFLAGS} -I$(top_srcdir)/include
+AM_CFLAGS = -Wall
+sbin_PROGRAMS = fsck.f2fs
+fsck_f2fs_SOURCES = main.c fsck.c dump.c mount.c
+fsck_f2fs_LDADD = ${libuuid_LIBS} $(top_builddir)/lib/libf2fs.la
+
+install-data-hook:
+	ln -sf fsck.f2fs $(DESTDIR)/$(sbindir)/dump.f2fs
diff --git a/f2fs-tools/fsck/dump.c b/f2fs-tools/fsck/dump.c
new file mode 100644
index 0000000..3c4a8d1
--- /dev/null
+++ b/f2fs-tools/fsck/dump.c
@@ -0,0 +1,466 @@
+/**
+ * dump.c
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <inttypes.h>
+
+#include "fsck.h"
+#include <locale.h>
+
+#define BUF_SZ	80
+
+const char *seg_type_name[SEG_TYPE_MAX] = {
+	"SEG_TYPE_DATA",
+	"SEG_TYPE_CUR_DATA",
+	"SEG_TYPE_NODE",
+	"SEG_TYPE_CUR_NODE",
+};
+
+void sit_dump(struct f2fs_sb_info *sbi, int start_sit, int end_sit)
+{
+	struct seg_entry *se;
+	int segno;
+	char buf[BUF_SZ];
+	u32 free_segs = 0;;
+	u64 valid_blocks = 0;
+	int ret;
+	int fd;
+
+	fd = open("dump_sit", O_CREAT|O_WRONLY|O_TRUNC, 0666);
+	ASSERT(fd >= 0);
+
+	for (segno = start_sit; segno < end_sit; segno++) {
+		se = get_seg_entry(sbi, segno);
+
+		memset(buf, 0, BUF_SZ);
+		snprintf(buf, BUF_SZ, "%5d %8d\n", segno, se->valid_blocks);
+
+		ret = write(fd, buf, strlen(buf));
+		ASSERT(ret >= 0);
+
+		DBG(4, "SIT[0x%3x] : 0x%x\n", segno, se->valid_blocks);
+		if (se->valid_blocks == 0x0) {
+			free_segs++;
+		} else {
+			ASSERT(se->valid_blocks <= 512);
+			valid_blocks += se->valid_blocks;
+		}
+	}
+
+	memset(buf, 0, BUF_SZ);
+	snprintf(buf, BUF_SZ, "valid_segs:%d\t free_segs:%d\n",
+			SM_I(sbi)->main_segments - free_segs, free_segs);
+	ret = write(fd, buf, strlen(buf));
+	ASSERT(ret >= 0);
+
+	close(fd);
+	DBG(1, "Blocks [0x%" PRIx64 "] Free Segs [0x%x]\n", valid_blocks, free_segs);
+}
+
+void ssa_dump(struct f2fs_sb_info *sbi, int start_ssa, int end_ssa)
+{
+	struct f2fs_summary_block sum_blk;
+	char buf[BUF_SZ];
+	int segno, i, ret;
+	int fd;
+
+	fd = open("dump_ssa", O_CREAT|O_WRONLY|O_TRUNC, 0666);
+	ASSERT(fd >= 0);
+
+	snprintf(buf, BUF_SZ, "Note: dump.f2fs -b blkaddr = 0x%x + segno * "
+				" 0x200 + offset\n",
+				sbi->sm_info->main_blkaddr);
+	ret = write(fd, buf, strlen(buf));
+	ASSERT(ret >= 0);
+
+	for (segno = start_ssa; segno < end_ssa; segno++) {
+		ret = get_sum_block(sbi, segno, &sum_blk);
+
+		memset(buf, 0, BUF_SZ);
+		switch (ret) {
+		case SEG_TYPE_CUR_NODE:
+			snprintf(buf, BUF_SZ, "\n\nsegno: %x, Current Node\n", segno);
+			break;
+		case SEG_TYPE_CUR_DATA:
+			snprintf(buf, BUF_SZ, "\n\nsegno: %x, Current Data\n", segno);
+			break;
+		case SEG_TYPE_NODE:
+			snprintf(buf, BUF_SZ, "\n\nsegno: %x, Node\n", segno);
+			break;
+		case SEG_TYPE_DATA:
+			snprintf(buf, BUF_SZ, "\n\nsegno: %x, Data\n", segno);
+			break;
+		}
+		ret = write(fd, buf, strlen(buf));
+		ASSERT(ret >= 0);
+
+		for (i = 0; i < ENTRIES_IN_SUM; i++) {
+			memset(buf, 0, BUF_SZ);
+			if (i % 10 == 0) {
+				buf[0] = '\n';
+				ret = write(fd, buf, strlen(buf));
+				ASSERT(ret >= 0);
+			}
+			snprintf(buf, BUF_SZ, "[%3d: %6x]", i,
+					le32_to_cpu(sum_blk.entries[i].nid));
+			ret = write(fd, buf, strlen(buf));
+			ASSERT(ret >= 0);
+		}
+	}
+	close(fd);
+}
+
+static void dump_data_blk(__u64 offset, u32 blkaddr)
+{
+	char buf[F2FS_BLKSIZE];
+
+	if (blkaddr == NULL_ADDR)
+		return;
+
+	/* get data */
+	if (blkaddr == NEW_ADDR) {
+		memset(buf, 0, F2FS_BLKSIZE);
+	} else {
+		int ret;
+		ret = dev_read_block(buf, blkaddr);
+		ASSERT(ret >= 0);
+	}
+
+	/* write blkaddr */
+	dev_write_dump(buf, offset, F2FS_BLKSIZE);
+}
+
+static void dump_node_blk(struct f2fs_sb_info *sbi, int ntype,
+						u32 nid, u64 *ofs)
+{
+	struct node_info ni;
+	struct f2fs_node *node_blk;
+	u32 skip = 0;
+	u32 i, idx;
+
+	switch (ntype) {
+	case TYPE_DIRECT_NODE:
+		skip = idx = ADDRS_PER_BLOCK;
+		break;
+	case TYPE_INDIRECT_NODE:
+		idx = NIDS_PER_BLOCK;
+		skip = idx * ADDRS_PER_BLOCK;
+		break;
+	case TYPE_DOUBLE_INDIRECT_NODE:
+		skip = 0;
+		idx = NIDS_PER_BLOCK;
+		break;
+	}
+
+	if (nid == 0) {
+		*ofs += skip;
+		return;
+	}
+
+	get_node_info(sbi, nid, &ni);
+
+	node_blk = calloc(BLOCK_SZ, 1);
+	dev_read_block(node_blk, ni.blk_addr);
+
+	for (i = 0; i < idx; i++, (*ofs)++) {
+		switch (ntype) {
+		case TYPE_DIRECT_NODE:
+			dump_data_blk(*ofs * F2FS_BLKSIZE,
+					le32_to_cpu(node_blk->dn.addr[i]));
+			break;
+		case TYPE_INDIRECT_NODE:
+			dump_node_blk(sbi, TYPE_DIRECT_NODE,
+					le32_to_cpu(node_blk->in.nid[i]), ofs);
+			break;
+		case TYPE_DOUBLE_INDIRECT_NODE:
+			dump_node_blk(sbi, TYPE_INDIRECT_NODE,
+					le32_to_cpu(node_blk->in.nid[i]), ofs);
+			break;
+		}
+	}
+	free(node_blk);
+}
+
+static void dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
+					struct f2fs_node *node_blk)
+{
+	u32 i = 0;
+	u64 ofs = 0;
+
+	/* TODO: need to dump xattr */
+
+	if((node_blk->i.i_inline & F2FS_INLINE_DATA)){
+		DBG(3, "ino[0x%x] has inline data!\n", nid);
+		/* recover from inline data */
+		dev_write_dump(((unsigned char *)node_blk) + INLINE_DATA_OFFSET,
+							0, MAX_INLINE_DATA);
+		return;
+	}
+
+	/* check data blocks in inode */
+	for (i = 0; i < ADDRS_PER_INODE(&node_blk->i); i++, ofs++)
+		dump_data_blk(ofs * F2FS_BLKSIZE,
+				le32_to_cpu(node_blk->i.i_addr[i]));
+
+	/* check node blocks in inode */
+	for (i = 0; i < 5; i++) {
+		if (i == 0 || i == 1)
+			dump_node_blk(sbi, TYPE_DIRECT_NODE,
+					node_blk->i.i_nid[i], &ofs);
+		else if (i == 2 || i == 3)
+			dump_node_blk(sbi, TYPE_INDIRECT_NODE,
+					node_blk->i.i_nid[i], &ofs);
+		else if (i == 4)
+			dump_node_blk(sbi, TYPE_DOUBLE_INDIRECT_NODE,
+					node_blk->i.i_nid[i], &ofs);
+		else
+			ASSERT(0);
+	}
+}
+
+void dump_file(struct f2fs_sb_info *sbi, struct node_info *ni,
+					struct f2fs_node *node_blk)
+{
+	struct f2fs_inode *inode = &node_blk->i;
+	u32 imode = le32_to_cpu(inode->i_mode);
+	char name[255] = {0};
+	char path[1024] = {0};
+	char ans[255] = {0};
+	int ret;
+
+	if (!S_ISREG(imode)) {
+		MSG(0, "Not a regular file\n\n");
+		return;
+	}
+
+	printf("Do you want to dump this file into ./lost_found/? [Y/N] ");
+	ret = scanf("%s", ans);
+	ASSERT(ret >= 0);
+
+	if (!strcasecmp(ans, "y")) {
+		ret = system("mkdir -p ./lost_found");
+		ASSERT(ret >= 0);
+
+		/* make a file */
+		strncpy(name, (const char *)inode->i_name,
+					le32_to_cpu(inode->i_namelen));
+		name[le32_to_cpu(inode->i_namelen)] = 0;
+		sprintf(path, "./lost_found/%s", name);
+
+		config.dump_fd = open(path, O_TRUNC|O_CREAT|O_RDWR, 0666);
+		ASSERT(config.dump_fd >= 0);
+
+		/* dump file's data */
+		dump_inode_blk(sbi, ni->ino, node_blk);
+
+		/* adjust file size */
+		ret = ftruncate(config.dump_fd, le32_to_cpu(inode->i_size));
+		ASSERT(ret >= 0);
+
+		close(config.dump_fd);
+	}
+}
+
+void dump_node(struct f2fs_sb_info *sbi, nid_t nid)
+{
+	struct node_info ni;
+	struct f2fs_node *node_blk;
+
+	get_node_info(sbi, nid, &ni);
+
+	node_blk = calloc(BLOCK_SZ, 1);
+	dev_read_block(node_blk, ni.blk_addr);
+
+	DBG(1, "Node ID               [0x%x]\n", nid);
+	DBG(1, "nat_entry.block_addr  [0x%x]\n", ni.blk_addr);
+	DBG(1, "nat_entry.version     [0x%x]\n", ni.version);
+	DBG(1, "nat_entry.ino         [0x%x]\n", ni.ino);
+
+	if (ni.blk_addr == 0x0)
+		MSG(0, "Invalid nat entry\n\n");
+
+	DBG(1, "node_blk.footer.ino [0x%x]\n", le32_to_cpu(node_blk->footer.ino));
+	DBG(1, "node_blk.footer.nid [0x%x]\n", le32_to_cpu(node_blk->footer.nid));
+
+	if (le32_to_cpu(node_blk->footer.ino) == ni.ino &&
+			le32_to_cpu(node_blk->footer.nid) == ni.nid) {
+		print_node_info(node_blk);
+		dump_file(sbi, &ni, node_blk);
+	} else {
+		MSG(0, "Invalid node block\n\n");
+	}
+
+	free(node_blk);
+}
+
+static void dump_node_from_blkaddr(u32 blk_addr)
+{
+	struct f2fs_node *node_blk;
+	int ret;
+
+	node_blk = calloc(BLOCK_SZ, 1);
+	ASSERT(node_blk);
+
+	ret = dev_read_block(node_blk, blk_addr);
+	ASSERT(ret >= 0);
+
+	if (config.dbg_lv > 0)
+		print_node_info(node_blk);
+	else
+		print_inode_info(&node_blk->i, 1);
+
+	free(node_blk);
+}
+
+static void dump_data_offset(u32 blk_addr, int ofs_in_node)
+{
+	struct f2fs_node *node_blk;
+	unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4;
+	unsigned int bidx = 0;
+	unsigned int node_ofs;
+	int ret;
+
+	node_blk = calloc(BLOCK_SZ, 1);
+	ASSERT(node_blk);
+
+	ret = dev_read_block(node_blk, blk_addr);
+	ASSERT(ret >= 0);
+
+	node_ofs = ofs_of_node(node_blk);
+
+	if (node_ofs == 0)
+		goto got_it;
+
+	if (node_ofs > 0 && node_ofs <= 2) {
+		bidx = node_ofs - 1;
+	} else if (node_ofs <= indirect_blks) {
+		int dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1);
+		bidx = node_ofs - 2 - dec;
+	} else {
+		int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1);
+		bidx = node_ofs - 5 - dec;
+	}
+	bidx = bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE(&node_blk->i);
+got_it:
+	bidx +=  ofs_in_node;
+
+	setlocale(LC_ALL, "");
+	MSG(0, " - Data offset       : 0x%x (4KB), %'u (bytes)\n",
+				bidx, bidx * 4096);
+	free(node_blk);
+}
+
+static void dump_node_offset(u32 blk_addr)
+{
+	struct f2fs_node *node_blk;
+	int ret;
+
+	node_blk = calloc(BLOCK_SZ, 1);
+	ASSERT(node_blk);
+
+	ret = dev_read_block(node_blk, blk_addr);
+	ASSERT(ret >= 0);
+
+	MSG(0, " - Node offset       : 0x%x\n", ofs_of_node(node_blk));
+	free(node_blk);
+}
+
+int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
+{
+	nid_t nid;
+	int type;
+	struct f2fs_summary sum_entry;
+	struct node_info ni, ino_ni;
+	int ret = 0;
+
+	MSG(0, "\n== Dump data from block address ==\n\n");
+
+	if (blk_addr < SM_I(sbi)->seg0_blkaddr) {
+		MSG(0, "\nFS Reserved Area for SEG #0: ");
+		ret = -EINVAL;
+	} else if (blk_addr < SIT_I(sbi)->sit_base_addr) {
+		MSG(0, "\nFS Metadata Area: ");
+		ret = -EINVAL;
+	} else if (blk_addr < NM_I(sbi)->nat_blkaddr) {
+		MSG(0, "\nFS SIT Area: ");
+		ret = -EINVAL;
+	} else if (blk_addr < SM_I(sbi)->ssa_blkaddr) {
+		MSG(0, "\nFS NAT Area: ");
+		ret = -EINVAL;
+	} else if (blk_addr < SM_I(sbi)->main_blkaddr) {
+		MSG(0, "\nFS SSA Area: ");
+		ret = -EINVAL;
+	} else if (blk_addr > __end_block_addr(sbi)) {
+		MSG(0, "\nOut of address space: ");
+		ret = -EINVAL;
+	}
+
+	if (ret) {
+		MSG(0, "User data is from 0x%x to 0x%x\n\n",
+			SM_I(sbi)->main_blkaddr,
+			__end_block_addr(sbi));
+		return ret;
+	}
+
+	type = get_sum_entry(sbi, blk_addr, &sum_entry);
+	nid = le32_to_cpu(sum_entry.nid);
+
+	get_node_info(sbi, nid, &ni);
+
+	DBG(1, "Note: blkaddr = main_blkaddr + segno * 512 + offset\n");
+	DBG(1, "Block_addr            [0x%x]\n", blk_addr);
+	DBG(1, " - Segno              [0x%x]\n", GET_SEGNO(sbi, blk_addr));
+	DBG(1, " - Offset             [0x%x]\n", OFFSET_IN_SEG(sbi, blk_addr));
+	DBG(1, "SUM.nid               [0x%x]\n", nid);
+	DBG(1, "SUM.type              [%s]\n", seg_type_name[type]);
+	DBG(1, "SUM.version           [%d]\n", sum_entry.version);
+	DBG(1, "SUM.ofs_in_node       [0x%x]\n", sum_entry.ofs_in_node);
+	DBG(1, "NAT.blkaddr           [0x%x]\n", ni.blk_addr);
+	DBG(1, "NAT.ino               [0x%x]\n", ni.ino);
+
+	get_node_info(sbi, ni.ino, &ino_ni);
+
+	/* inode block address */
+	if (ni.blk_addr == NULL_ADDR || ino_ni.blk_addr == NULL_ADDR) {
+		MSG(0, "FS Userdata Area: Obsolete block from 0x%x\n",
+			blk_addr);
+		return -EINVAL;
+	}
+
+	/* print inode */
+	if (config.dbg_lv > 0)
+		dump_node_from_blkaddr(ino_ni.blk_addr);
+
+	if (type == SEG_TYPE_CUR_DATA || type == SEG_TYPE_DATA) {
+		MSG(0, "FS Userdata Area: Data block from 0x%x\n", blk_addr);
+		MSG(0, " - Direct node block : id = 0x%x from 0x%x\n",
+					nid, ni.blk_addr);
+		MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
+					ni.ino, ino_ni.blk_addr);
+		dump_node_from_blkaddr(ino_ni.blk_addr);
+		dump_data_offset(ni.blk_addr,
+			le16_to_cpu(sum_entry.ofs_in_node));
+	} else {
+		MSG(0, "FS Userdata Area: Node block from 0x%x\n", blk_addr);
+		if (ni.ino == ni.nid) {
+			MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
+					ni.ino, ino_ni.blk_addr);
+			dump_node_from_blkaddr(ino_ni.blk_addr);
+		} else {
+			MSG(0, " - Node block        : id = 0x%x from 0x%x\n",
+					nid, ni.blk_addr);
+			MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
+					ni.ino, ino_ni.blk_addr);
+			dump_node_from_blkaddr(ino_ni.blk_addr);
+			dump_node_offset(ni.blk_addr);
+		}
+	}
+
+	return 0;
+}
diff --git a/f2fs-tools/fsck/f2fs.h b/f2fs-tools/fsck/f2fs.h
new file mode 100644
index 0000000..c268f15
--- /dev/null
+++ b/f2fs-tools/fsck/f2fs.h
@@ -0,0 +1,387 @@
+/**
+ * f2fs.h
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _F2FS_H_
+#define _F2FS_H_
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <mntent.h>
+#include <linux/types.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <assert.h>
+
+#include <f2fs_fs.h>
+
+#define EXIT_ERR_CODE		(-1)
+#define ver_after(a, b) (typecheck(unsigned long long, a) &&            \
+		typecheck(unsigned long long, b) &&                     \
+		((long long)((a) - (b)) > 0))
+
+struct list_head {
+	struct list_head *next, *prev;
+};
+
+enum {
+	NAT_BITMAP,
+	SIT_BITMAP
+};
+
+struct node_info {
+	nid_t nid;
+	nid_t ino;
+	u32 blk_addr;
+	unsigned char version;
+};
+
+struct f2fs_nm_info {
+	block_t nat_blkaddr;
+	nid_t max_nid;
+	nid_t init_scan_nid;
+	nid_t next_scan_nid;
+
+	unsigned int nat_cnt;
+	unsigned int fcnt;
+
+	char *nat_bitmap;
+	int bitmap_size;
+};
+
+struct seg_entry {
+	unsigned short valid_blocks;    /* # of valid blocks */
+	unsigned char *cur_valid_map;   /* validity bitmap of blocks */
+	/*
+	 * # of valid blocks and the validity bitmap stored in the the last
+	 * checkpoint pack. This information is used by the SSR mode.
+	 */
+	unsigned short ckpt_valid_blocks;
+	unsigned char *ckpt_valid_map;
+	unsigned char type;             /* segment type like CURSEG_XXX_TYPE */
+	unsigned char orig_type;        /* segment type like CURSEG_XXX_TYPE */
+	unsigned long long mtime;       /* modification time of the segment */
+};
+
+struct sec_entry {
+	unsigned int valid_blocks;      /* # of valid blocks in a section */
+};
+
+struct sit_info {
+
+	block_t sit_base_addr;          /* start block address of SIT area */
+	block_t sit_blocks;             /* # of blocks used by SIT area */
+	block_t written_valid_blocks;   /* # of valid blocks in main area */
+	char *sit_bitmap;               /* SIT bitmap pointer */
+	unsigned int bitmap_size;       /* SIT bitmap size */
+
+	unsigned long *dirty_sentries_bitmap;   /* bitmap for dirty sentries */
+	unsigned int dirty_sentries;            /* # of dirty sentries */
+	unsigned int sents_per_block;           /* # of SIT entries per block */
+	struct seg_entry *sentries;             /* SIT segment-level cache */
+	struct sec_entry *sec_entries;          /* SIT section-level cache */
+
+	unsigned long long elapsed_time;        /* elapsed time after mount */
+	unsigned long long mounted_time;        /* mount time */
+	unsigned long long min_mtime;           /* min. modification time */
+	unsigned long long max_mtime;           /* max. modification time */
+};
+
+struct curseg_info {
+	struct f2fs_summary_block *sum_blk;     /* cached summary block */
+	unsigned char alloc_type;               /* current allocation type */
+	unsigned int segno;                     /* current segment number */
+	unsigned short next_blkoff;             /* next block offset to write */
+	unsigned int zone;                      /* current zone number */
+	unsigned int next_segno;                /* preallocated segment */
+};
+
+struct f2fs_sm_info {
+	struct sit_info *sit_info;
+	struct curseg_info *curseg_array;
+
+	block_t seg0_blkaddr;
+	block_t main_blkaddr;
+	block_t ssa_blkaddr;
+
+	unsigned int segment_count;
+	unsigned int main_segments;
+	unsigned int reserved_segments;
+	unsigned int ovp_segments;
+};
+
+struct f2fs_sb_info {
+	struct f2fs_fsck *fsck;
+
+	struct f2fs_super_block *raw_super;
+	struct f2fs_nm_info *nm_info;
+	struct f2fs_sm_info *sm_info;
+	struct f2fs_checkpoint *ckpt;
+	int cur_cp;
+
+	struct list_head orphan_inode_list;
+	unsigned int n_orphans;
+
+	/* basic file system units */
+	unsigned int log_sectors_per_block;     /* log2 sectors per block */
+	unsigned int log_blocksize;             /* log2 block size */
+	unsigned int blocksize;                 /* block size */
+	unsigned int root_ino_num;              /* root inode number*/
+	unsigned int node_ino_num;              /* node inode number*/
+	unsigned int meta_ino_num;              /* meta inode number*/
+	unsigned int log_blocks_per_seg;        /* log2 blocks per segment */
+	unsigned int blocks_per_seg;            /* blocks per segment */
+	unsigned int segs_per_sec;              /* segments per section */
+	unsigned int secs_per_zone;             /* sections per zone */
+	unsigned int total_sections;            /* total section count */
+	unsigned int total_node_count;          /* total node block count */
+	unsigned int total_valid_node_count;    /* valid node block count */
+	unsigned int total_valid_inode_count;   /* valid inode count */
+	int active_logs;                        /* # of active logs */
+
+	block_t user_block_count;               /* # of user blocks */
+	block_t total_valid_block_count;        /* # of valid blocks */
+	block_t alloc_valid_block_count;        /* # of allocated blocks */
+	block_t last_valid_block_count;         /* for recovery */
+	u32 s_next_generation;                  /* for NFS support */
+
+	unsigned int cur_victim_sec;            /* current victim section num */
+
+};
+
+static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info *sbi)
+{
+	return (struct f2fs_super_block *)(sbi->raw_super);
+}
+
+static inline struct f2fs_checkpoint *F2FS_CKPT(struct f2fs_sb_info *sbi)
+{
+	return (struct f2fs_checkpoint *)(sbi->ckpt);
+}
+
+static inline struct f2fs_fsck *F2FS_FSCK(struct f2fs_sb_info *sbi)
+{
+	return (struct f2fs_fsck *)(sbi->fsck);
+}
+
+static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi)
+{
+	return (struct f2fs_nm_info *)(sbi->nm_info);
+}
+
+static inline struct f2fs_sm_info *SM_I(struct f2fs_sb_info *sbi)
+{
+	return (struct f2fs_sm_info *)(sbi->sm_info);
+}
+
+static inline struct sit_info *SIT_I(struct f2fs_sb_info *sbi)
+{
+	return (struct sit_info *)(SM_I(sbi)->sit_info);
+}
+
+static inline void *inline_data_addr(struct f2fs_node *node_blk)
+{
+	return (void *)&(node_blk->i.i_addr[1]);
+}
+
+static inline unsigned int ofs_of_node(struct f2fs_node *node_blk)
+{
+	unsigned flag = le32_to_cpu(node_blk->footer.flag);
+	return flag >> OFFSET_BIT_SHIFT;
+}
+
+static inline unsigned long __bitmap_size(struct f2fs_sb_info *sbi, int flag)
+{
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+
+	/* return NAT or SIT bitmap */
+	if (flag == NAT_BITMAP)
+		return le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
+	else if (flag == SIT_BITMAP)
+		return le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
+
+	return 0;
+}
+
+static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
+{
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	int offset;
+	if (le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload) > 0) {
+		if (flag == NAT_BITMAP)
+			return &ckpt->sit_nat_version_bitmap;
+		else
+			return ((char *)ckpt + F2FS_BLKSIZE);
+	} else {
+		offset = (flag == NAT_BITMAP) ?
+			le32_to_cpu(ckpt->sit_ver_bitmap_bytesize) : 0;
+		return &ckpt->sit_nat_version_bitmap + offset;
+	}
+}
+
+static inline bool is_set_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
+{
+	unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags);
+	return ckpt_flags & f;
+}
+
+static inline block_t __start_cp_addr(struct f2fs_sb_info *sbi)
+{
+	block_t start_addr;
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	unsigned long long ckpt_version = le64_to_cpu(ckpt->checkpoint_ver);
+
+	start_addr = le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_blkaddr);
+
+	/*
+	 * odd numbered checkpoint should at cp segment 0
+	 * and even segent must be at cp segment 1
+	 */
+	if (!(ckpt_version & 1))
+		start_addr += sbi->blocks_per_seg;
+
+	return start_addr;
+}
+
+static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi)
+{
+	return le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
+}
+
+static inline block_t __end_block_addr(struct f2fs_sb_info *sbi)
+{
+	block_t end = SM_I(sbi)->main_blkaddr;
+	return end + le64_to_cpu(F2FS_RAW_SUPER(sbi)->block_count);
+}
+
+#define GET_ZONENO_FROM_SEGNO(sbi, segno)                               \
+	((segno / sbi->segs_per_sec) / sbi->secs_per_zone)
+
+#define IS_DATASEG(t)                                                   \
+	((t == CURSEG_HOT_DATA) || (t == CURSEG_COLD_DATA) ||           \
+	 (t == CURSEG_WARM_DATA))
+
+#define IS_NODESEG(t)                                                   \
+	((t == CURSEG_HOT_NODE) || (t == CURSEG_COLD_NODE) ||           \
+	 (t == CURSEG_WARM_NODE))
+
+#define GET_SUM_BLKADDR(sbi, segno)					\
+	((sbi->sm_info->ssa_blkaddr) + segno)
+
+#define GET_SEGOFF_FROM_SEG0(sbi, blk_addr)				\
+	((blk_addr) - SM_I(sbi)->seg0_blkaddr)
+
+#define GET_SEGNO_FROM_SEG0(sbi, blk_addr)				\
+	(GET_SEGOFF_FROM_SEG0(sbi, blk_addr) >> sbi->log_blocks_per_seg)
+
+#define GET_BLKOFF_FROM_SEG0(sbi, blk_addr)				\
+	(GET_SEGOFF_FROM_SEG0(sbi, blk_addr) & (sbi->blocks_per_seg - 1))
+
+#define FREE_I_START_SEGNO(sbi)						\
+	GET_SEGNO_FROM_SEG0(sbi, SM_I(sbi)->main_blkaddr)
+#define GET_R2L_SEGNO(sbi, segno)	(segno + FREE_I_START_SEGNO(sbi))
+
+#define START_BLOCK(sbi, segno)	(SM_I(sbi)->main_blkaddr +		\
+	(segno << sbi->log_blocks_per_seg))
+
+static inline struct curseg_info *CURSEG_I(struct f2fs_sb_info *sbi, int type)
+{
+	return (struct curseg_info *)(SM_I(sbi)->curseg_array + type);
+}
+
+static inline block_t start_sum_block(struct f2fs_sb_info *sbi)
+{
+	return __start_cp_addr(sbi) + le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
+}
+
+static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type)
+{
+	return __start_cp_addr(sbi) + le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_total_block_count)
+		- (base + 1) + type;
+}
+
+
+#define nats_in_cursum(sum)             (le16_to_cpu(sum->n_nats))
+#define sits_in_cursum(sum)             (le16_to_cpu(sum->n_sits))
+
+#define nat_in_journal(sum, i)          (sum->nat_j.entries[i].ne)
+#define nid_in_journal(sum, i)          (sum->nat_j.entries[i].nid)
+#define sit_in_journal(sum, i)          (sum->sit_j.entries[i].se)
+#define segno_in_journal(sum, i)        (sum->sit_j.entries[i].segno)
+
+#define SIT_ENTRY_OFFSET(sit_i, segno)                                  \
+	(segno % sit_i->sents_per_block)
+#define SIT_BLOCK_OFFSET(sit_i, segno)                                  \
+	(segno / SIT_ENTRY_PER_BLOCK)
+#define TOTAL_SEGS(sbi) (SM_I(sbi)->main_segments)
+
+static inline bool IS_VALID_NID(struct f2fs_sb_info *sbi, u32 nid)
+{
+	return (nid <= (NAT_ENTRY_PER_BLOCK *
+			F2FS_RAW_SUPER(sbi)->segment_count_nat
+			<< (sbi->log_blocks_per_seg - 1)));
+}
+
+static inline bool IS_VALID_BLK_ADDR(struct f2fs_sb_info *sbi, u32 addr)
+{
+	int i;
+
+	if (addr >= F2FS_RAW_SUPER(sbi)->block_count ||
+				addr < SM_I(sbi)->main_blkaddr) {
+		ASSERT_MSG("block addr [0x%x]\n", addr);
+		return 0;
+	}
+
+	for (i = 0; i < NO_CHECK_TYPE; i++) {
+		struct curseg_info *curseg = CURSEG_I(sbi, i);
+
+		if (START_BLOCK(sbi, curseg->segno) +
+					curseg->next_blkoff == addr)
+			return 0;
+	}
+	return 1;
+}
+
+static inline u64 BLKOFF_FROM_MAIN(struct f2fs_sb_info *sbi, u64 blk_addr)
+{
+	ASSERT(blk_addr >= SM_I(sbi)->main_blkaddr);
+	return blk_addr - SM_I(sbi)->main_blkaddr;
+}
+
+static inline u32 GET_SEGNO(struct f2fs_sb_info *sbi, u64 blk_addr)
+{
+	return (u32)(BLKOFF_FROM_MAIN(sbi, blk_addr)
+			>> sbi->log_blocks_per_seg);
+}
+
+static inline u32 OFFSET_IN_SEG(struct f2fs_sb_info *sbi, u64 blk_addr)
+{
+	return (u32)(BLKOFF_FROM_MAIN(sbi, blk_addr)
+			% (1 << sbi->log_blocks_per_seg));
+}
+
+static inline void node_info_from_raw_nat(struct node_info *ni,
+		struct f2fs_nat_entry *raw_nat)
+{
+	ni->ino = le32_to_cpu(raw_nat->ino);
+	ni->blk_addr = le32_to_cpu(raw_nat->block_addr);
+	ni->version = raw_nat->version;
+}
+
+extern int lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid, struct f2fs_nat_entry *ne);
+#define IS_SUM_NODE_SEG(footer)		(footer.entry_type == SUM_TYPE_NODE)
+
+#endif /* _F2FS_H_ */
diff --git a/f2fs-tools/fsck/fsck.c b/f2fs-tools/fsck/fsck.c
new file mode 100644
index 0000000..1b27ae0
--- /dev/null
+++ b/f2fs-tools/fsck/fsck.c
@@ -0,0 +1,1210 @@
+/**
+ * fsck.c
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include "fsck.h"
+
+char *tree_mark;
+uint32_t tree_mark_size = 256;
+
+static inline int f2fs_set_main_bitmap(struct f2fs_sb_info *sbi, u32 blk,
+								int type)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	struct seg_entry *se;
+
+	se = get_seg_entry(sbi, GET_SEGNO(sbi, blk));
+	if (se->type != type) {
+		if (type == CURSEG_WARM_DATA) {
+			if (se->type != CURSEG_COLD_DATA) {
+				DBG(1, "Wrong segment type [0x%x] %x -> %x",
+						GET_SEGNO(sbi, blk), se->type,
+						CURSEG_WARM_DATA);
+				se->type = CURSEG_WARM_DATA;
+			}
+		} else {
+			DBG(1, "Wrong segment type [0x%x] %x -> %x",
+				GET_SEGNO(sbi, blk), se->type, type);
+			se->type = type;
+		}
+	}
+	return f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, blk), fsck->main_area_bitmap);
+}
+
+static inline int f2fs_test_main_bitmap(struct f2fs_sb_info *sbi, u32 blk)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+
+	return f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, blk),
+						fsck->main_area_bitmap);
+}
+
+static inline int f2fs_test_sit_bitmap(struct f2fs_sb_info *sbi, u32 blk)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+
+	return f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, blk), fsck->sit_area_bitmap);
+}
+
+static int add_into_hard_link_list(struct f2fs_sb_info *sbi,
+						u32 nid, u32 link_cnt)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	struct hard_link_node *node = NULL, *tmp = NULL, *prev = NULL;
+
+	node = calloc(sizeof(struct hard_link_node), 1);
+	ASSERT(node != NULL);
+
+	node->nid = nid;
+	node->links = link_cnt;
+	node->next = NULL;
+
+	if (fsck->hard_link_list_head == NULL) {
+		fsck->hard_link_list_head = node;
+		goto out;
+	}
+
+	tmp = fsck->hard_link_list_head;
+
+	/* Find insertion position */
+	while (tmp && (nid < tmp->nid)) {
+		ASSERT(tmp->nid != nid);
+		prev = tmp;
+		tmp = tmp->next;
+	}
+
+	if (tmp == fsck->hard_link_list_head) {
+		node->next = tmp;
+		fsck->hard_link_list_head = node;
+	} else {
+		prev->next = node;
+		node->next = tmp;
+	}
+
+out:
+	DBG(2, "ino[0x%x] has hard links [0x%x]\n", nid, link_cnt);
+	return 0;
+}
+
+static int find_and_dec_hard_link_list(struct f2fs_sb_info *sbi, u32 nid)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	struct hard_link_node *node = NULL, *prev = NULL;
+
+	if (fsck->hard_link_list_head == NULL)
+		return -EINVAL;
+
+	node = fsck->hard_link_list_head;
+
+	while (node && (nid < node->nid)) {
+		prev = node;
+		node = node->next;
+	}
+
+	if (node == NULL || (nid != node->nid))
+		return -EINVAL;
+
+	/* Decrease link count */
+	node->links = node->links - 1;
+
+	/* if link count becomes one, remove the node */
+	if (node->links == 1) {
+		if (fsck->hard_link_list_head == node)
+			fsck->hard_link_list_head = node->next;
+		else
+			prev->next = node->next;
+		free(node);
+	}
+	return 0;
+}
+
+static int is_valid_ssa_node_blk(struct f2fs_sb_info *sbi, u32 nid,
+							u32 blk_addr)
+{
+	int ret = 0;
+	struct f2fs_summary sum_entry;
+
+	ret = get_sum_entry(sbi, blk_addr, &sum_entry);
+
+	if (ret != SEG_TYPE_NODE && ret != SEG_TYPE_CUR_NODE) {
+		ASSERT_MSG("Summary footer is not for node segment");
+		return -EINVAL;
+	}
+
+	if (le32_to_cpu(sum_entry.nid) != nid) {
+		DBG(0, "nid                       [0x%x]\n", nid);
+		DBG(0, "target blk_addr           [0x%x]\n", blk_addr);
+		DBG(0, "summary blk_addr          [0x%x]\n",
+					GET_SUM_BLKADDR(sbi,
+					GET_SEGNO(sbi, blk_addr)));
+		DBG(0, "seg no / offset           [0x%x / 0x%x]\n",
+					GET_SEGNO(sbi, blk_addr),
+					OFFSET_IN_SEG(sbi, blk_addr));
+		DBG(0, "summary_entry.nid         [0x%x]\n",
+					le32_to_cpu(sum_entry.nid));
+		DBG(0, "--> node block's nid      [0x%x]\n", nid);
+		ASSERT_MSG("Invalid node seg summary\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int is_valid_ssa_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
+		u32 parent_nid, u16 idx_in_node, u8 version)
+{
+	int ret = 0;
+	struct f2fs_summary sum_entry;
+
+	ret = get_sum_entry(sbi, blk_addr, &sum_entry);
+
+	if (ret != SEG_TYPE_DATA && ret != SEG_TYPE_CUR_DATA) {
+		ASSERT_MSG("Summary footer is not for data segment");
+		return -EINVAL;
+	}
+
+	if (le32_to_cpu(sum_entry.nid) != parent_nid ||
+			sum_entry.version != version ||
+			le16_to_cpu(sum_entry.ofs_in_node) != idx_in_node) {
+
+		DBG(0, "summary_entry.nid         [0x%x]\n",
+					le32_to_cpu(sum_entry.nid));
+		DBG(0, "summary_entry.version     [0x%x]\n",
+					sum_entry.version);
+		DBG(0, "summary_entry.ofs_in_node [0x%x]\n",
+					le16_to_cpu(sum_entry.ofs_in_node));
+		DBG(0, "parent nid                [0x%x]\n", parent_nid);
+		DBG(0, "version from nat          [0x%x]\n", version);
+		DBG(0, "idx in parent node        [0x%x]\n", idx_in_node);
+
+		DBG(0, "Target data block addr    [0x%x]\n", blk_addr);
+		ASSERT_MSG("Invalid data seg summary\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid,
+			struct f2fs_node *node_blk,
+			enum FILE_TYPE ftype, enum NODE_TYPE ntype,
+			struct node_info *ni)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	int ret;
+
+	if (!IS_VALID_NID(sbi, nid)) {
+		ASSERT_MSG("nid is not valid. [0x%x]", nid);
+		return -EINVAL;
+	}
+
+	get_node_info(sbi, nid, ni);
+	if (ni->blk_addr == NEW_ADDR) {
+		ASSERT_MSG("nid is NEW_ADDR. [0x%x]", nid);
+		return -EINVAL;
+	}
+
+	if (!IS_VALID_BLK_ADDR(sbi, ni->blk_addr)) {
+		ASSERT_MSG("blkaddres is not valid. [0x%x]", ni->blk_addr);
+		return -EINVAL;
+	}
+
+	if (is_valid_ssa_node_blk(sbi, nid, ni->blk_addr)) {
+		ASSERT_MSG("summary node block is not valid. [0x%x]", nid);
+		return -EINVAL;
+	}
+
+	ret = dev_read_block(node_blk, ni->blk_addr);
+	ASSERT(ret >= 0);
+
+	if (ntype == TYPE_INODE &&
+			node_blk->footer.nid != node_blk->footer.ino) {
+		ASSERT_MSG("nid[0x%x] footer.nid[0x%x] footer.ino[0x%x]",
+				nid, le32_to_cpu(node_blk->footer.nid),
+				le32_to_cpu(node_blk->footer.ino));
+		return -EINVAL;
+	}
+	if (ntype != TYPE_INODE &&
+			node_blk->footer.nid == node_blk->footer.ino) {
+		ASSERT_MSG("nid[0x%x] footer.nid[0x%x] footer.ino[0x%x]",
+				nid, le32_to_cpu(node_blk->footer.nid),
+				le32_to_cpu(node_blk->footer.ino));
+		return -EINVAL;
+	}
+
+	if (le32_to_cpu(node_blk->footer.nid) != nid) {
+		ASSERT_MSG("nid[0x%x] blk_addr[0x%x] footer.nid[0x%x]",
+				nid, ni->blk_addr,
+				le32_to_cpu(node_blk->footer.nid));
+		return -EINVAL;
+	}
+
+	if (ntype == TYPE_XATTR) {
+		u32 flag = le32_to_cpu(node_blk->footer.flag);
+
+		if ((flag >> OFFSET_BIT_SHIFT) != XATTR_NODE_OFFSET) {
+			ASSERT_MSG("xnid[0x%x] has wrong ofs:[0x%x]",
+					nid, flag);
+			return -EINVAL;
+		}
+	}
+
+	if ((ntype == TYPE_INODE && ftype == F2FS_FT_DIR) ||
+			(ntype == TYPE_XATTR && ftype == F2FS_FT_XATTR)) {
+		/* not included '.' & '..' */
+		if (f2fs_test_main_bitmap(sbi, ni->blk_addr) != 0) {
+			ASSERT_MSG("Duplicated node blk. nid[0x%x][0x%x]\n",
+					nid, ni->blk_addr);
+			return -EINVAL;
+		}
+	}
+
+	/* workaround to fix later */
+	if (ftype != F2FS_FT_ORPHAN ||
+			f2fs_test_bit(nid, fsck->nat_area_bitmap) != 0)
+		f2fs_clear_bit(nid, fsck->nat_area_bitmap);
+	else
+		ASSERT_MSG("orphan or xattr nid is duplicated [0x%x]\n",
+				nid);
+
+	if (f2fs_test_sit_bitmap(sbi, ni->blk_addr) == 0)
+		ASSERT_MSG("SIT bitmap is 0x0. blk_addr[0x%x]",
+				ni->blk_addr);
+
+	if (f2fs_test_main_bitmap(sbi, ni->blk_addr) == 0) {
+		fsck->chk.valid_blk_cnt++;
+		fsck->chk.valid_node_cnt++;
+	}
+	return 0;
+}
+
+static int fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino,
+					u32 x_nid, u32 *blk_cnt)
+{
+	struct f2fs_node *node_blk = NULL;
+	struct node_info ni;
+	int ret = 0;
+
+	if (x_nid == 0x0)
+		return 0;
+
+	node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1);
+	ASSERT(node_blk != NULL);
+
+	/* Sanity check */
+	if (sanity_check_nid(sbi, x_nid, node_blk,
+				F2FS_FT_XATTR, TYPE_XATTR, &ni)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	*blk_cnt = *blk_cnt + 1;
+	f2fs_set_main_bitmap(sbi, ni.blk_addr, CURSEG_COLD_NODE);
+	DBG(2, "ino[0x%x] x_nid[0x%x]\n", ino, x_nid);
+out:
+	free(node_blk);
+	return ret;
+}
+
+int fsck_chk_node_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
+		u32 nid, enum FILE_TYPE ftype, enum NODE_TYPE ntype,
+		u32 *blk_cnt)
+{
+	struct node_info ni;
+	struct f2fs_node *node_blk = NULL;
+
+	node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1);
+	ASSERT(node_blk != NULL);
+
+	if (sanity_check_nid(sbi, nid, node_blk, ftype, ntype, &ni))
+		goto err;
+
+	if (ntype == TYPE_INODE) {
+		fsck_chk_inode_blk(sbi, nid, ftype, node_blk, blk_cnt, &ni);
+	} else {
+		switch (ntype) {
+		case TYPE_DIRECT_NODE:
+			f2fs_set_main_bitmap(sbi, ni.blk_addr,
+							CURSEG_WARM_NODE);
+			fsck_chk_dnode_blk(sbi, inode, nid, ftype, node_blk,
+					blk_cnt, &ni);
+			break;
+		case TYPE_INDIRECT_NODE:
+			f2fs_set_main_bitmap(sbi, ni.blk_addr,
+							CURSEG_COLD_NODE);
+			fsck_chk_idnode_blk(sbi, inode, ftype, node_blk,
+					blk_cnt);
+			break;
+		case TYPE_DOUBLE_INDIRECT_NODE:
+			f2fs_set_main_bitmap(sbi, ni.blk_addr,
+							CURSEG_COLD_NODE);
+			fsck_chk_didnode_blk(sbi, inode, ftype, node_blk,
+					blk_cnt);
+			break;
+		default:
+			ASSERT(0);
+		}
+	}
+	free(node_blk);
+	return 0;
+err:
+	free(node_blk);
+	return -EINVAL;
+}
+
+/* start with valid nid and blkaddr */
+void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
+		enum FILE_TYPE ftype, struct f2fs_node *node_blk,
+		u32 *blk_cnt, struct node_info *ni)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	u32 child_cnt = 0, child_files = 0;
+	enum NODE_TYPE ntype;
+	u32 i_links = le32_to_cpu(node_blk->i.i_links);
+	u64 i_blocks = le64_to_cpu(node_blk->i.i_blocks);
+	unsigned int idx = 0;
+	int need_fix = 0;
+	int ret;
+
+	if (f2fs_test_main_bitmap(sbi, ni->blk_addr) == 0)
+		fsck->chk.valid_inode_cnt++;
+
+	if (ftype == F2FS_FT_DIR) {
+		f2fs_set_main_bitmap(sbi, ni->blk_addr, CURSEG_HOT_NODE);
+	} else {
+		if (f2fs_test_main_bitmap(sbi, ni->blk_addr) == 0) {
+			f2fs_set_main_bitmap(sbi, ni->blk_addr,
+							CURSEG_WARM_NODE);
+			if (i_links > 1) {
+				/* First time. Create new hard link node */
+				add_into_hard_link_list(sbi, nid, i_links);
+				fsck->chk.multi_hard_link_files++;
+			}
+		} else {
+			DBG(3, "[0x%x] has hard links [0x%x]\n", nid, i_links);
+			if (find_and_dec_hard_link_list(sbi, nid)) {
+				ASSERT_MSG("[0x%x] needs more i_links=0x%x",
+						nid, i_links);
+				if (config.fix_on) {
+					node_blk->i.i_links =
+						cpu_to_le32(i_links + 1);
+					need_fix = 1;
+					FIX_MSG("File: 0x%x "
+						"i_links= 0x%x -> 0x%x",
+						nid, i_links, i_links + 1);
+				}
+				goto check;
+			}
+			/* No need to go deep into the node */
+			return;
+		}
+	}
+
+	if (fsck_chk_xattr_blk(sbi, nid,
+			le32_to_cpu(node_blk->i.i_xattr_nid), blk_cnt) &&
+			config.fix_on) {
+		node_blk->i.i_xattr_nid = 0;
+		need_fix = 1;
+		FIX_MSG("Remove xattr block: 0x%x, x_nid = 0x%x",
+				nid, le32_to_cpu(node_blk->i.i_xattr_nid));
+	}
+
+	if (ftype == F2FS_FT_CHRDEV || ftype == F2FS_FT_BLKDEV ||
+			ftype == F2FS_FT_FIFO || ftype == F2FS_FT_SOCK)
+		goto check;
+
+	if((node_blk->i.i_inline & F2FS_INLINE_DATA)) {
+		if (le32_to_cpu(node_blk->i.i_addr[0]) != 0) {
+			/* should fix this bug all the time */
+			FIX_MSG("inline_data has wrong 0'th block = %x",
+					le32_to_cpu(node_blk->i.i_addr[0]));
+			node_blk->i.i_addr[0] = 0;
+			node_blk->i.i_blocks = cpu_to_le64(*blk_cnt);
+			need_fix = 1;
+		}
+		if (!(node_blk->i.i_inline & F2FS_DATA_EXIST)) {
+			char buf[MAX_INLINE_DATA];
+			memset(buf, 0, MAX_INLINE_DATA);
+
+			if (memcmp(buf, &node_blk->i.i_addr[1],
+							MAX_INLINE_DATA)) {
+				FIX_MSG("inline_data has DATA_EXIST");
+				node_blk->i.i_inline |= F2FS_DATA_EXIST;
+				need_fix = 1;
+			}
+		}
+		DBG(3, "ino[0x%x] has inline data!\n", nid);
+		goto check;
+	}
+	if((node_blk->i.i_inline & F2FS_INLINE_DENTRY)) {
+		DBG(3, "ino[0x%x] has inline dentry!\n", nid);
+		ret = fsck_chk_inline_dentries(sbi, node_blk,
+					&child_cnt, &child_files);
+		if (ret < 0) {
+			/* should fix this bug all the time */
+			need_fix = 1;
+		}
+		goto check;
+	}
+
+	/* readahead node blocks */
+	for (idx = 0; idx < 5; idx++) {
+		u32 nid = le32_to_cpu(node_blk->i.i_nid[idx]);
+
+		if (nid != 0) {
+			struct node_info ni;
+
+			get_node_info(sbi, nid, &ni);
+			if (IS_VALID_BLK_ADDR(sbi, ni.blk_addr))
+				dev_reada_block(ni.blk_addr);
+		}
+	}
+
+	/* check data blocks in inode */
+	for (idx = 0; idx < ADDRS_PER_INODE(&node_blk->i); idx++) {
+		if (le32_to_cpu(node_blk->i.i_addr[idx]) != 0) {
+			ret = fsck_chk_data_blk(sbi,
+					le32_to_cpu(node_blk->i.i_addr[idx]),
+					&child_cnt, &child_files,
+					(i_blocks == *blk_cnt),
+					ftype, nid, idx, ni->version);
+			if (!ret) {
+				*blk_cnt = *blk_cnt + 1;
+			} else if (config.fix_on) {
+				node_blk->i.i_addr[idx] = 0;
+				need_fix = 1;
+				FIX_MSG("[0x%x] i_addr[%d] = 0", nid, idx);
+			}
+		}
+	}
+
+	/* check node blocks in inode */
+	for (idx = 0; idx < 5; idx++) {
+		if (idx == 0 || idx == 1)
+			ntype = TYPE_DIRECT_NODE;
+		else if (idx == 2 || idx == 3)
+			ntype = TYPE_INDIRECT_NODE;
+		else if (idx == 4)
+			ntype = TYPE_DOUBLE_INDIRECT_NODE;
+		else
+			ASSERT(0);
+
+		if (le32_to_cpu(node_blk->i.i_nid[idx]) != 0) {
+			ret = fsck_chk_node_blk(sbi, &node_blk->i,
+					le32_to_cpu(node_blk->i.i_nid[idx]),
+					ftype, ntype, blk_cnt);
+			if (!ret) {
+				*blk_cnt = *blk_cnt + 1;
+			} else if (config.fix_on) {
+				node_blk->i.i_nid[idx] = 0;
+				need_fix = 1;
+				FIX_MSG("[0x%x] i_nid[%d] = 0", nid, idx);
+			}
+		}
+	}
+check:
+	if (ftype == F2FS_FT_DIR)
+		DBG(1, "Directory Inode: 0x%x [%s] depth: %d has %d files\n\n",
+				le32_to_cpu(node_blk->footer.ino),
+				node_blk->i.i_name,
+				le32_to_cpu(node_blk->i.i_current_depth),
+				child_files);
+	if (ftype == F2FS_FT_ORPHAN)
+		DBG(1, "Orphan Inode: 0x%x [%s] i_blocks: %u\n\n",
+				le32_to_cpu(node_blk->footer.ino),
+				node_blk->i.i_name,
+				(u32)i_blocks);
+
+	if (i_blocks != *blk_cnt) {
+		ASSERT_MSG("ino: 0x%x has i_blocks: %08"PRIx64", "
+				"but has %u blocks",
+				nid, i_blocks, *blk_cnt);
+		if (config.fix_on) {
+			node_blk->i.i_blocks = cpu_to_le64(*blk_cnt);
+			need_fix = 1;
+			FIX_MSG("[0x%x] i_blocks=0x%08"PRIx64" -> 0x%x",
+					nid, i_blocks, *blk_cnt);
+		}
+	}
+	if (ftype == F2FS_FT_DIR && i_links != child_cnt) {
+		ASSERT_MSG("ino: 0x%x has i_links: %u but real links: %u",
+				nid, i_links, child_cnt);
+		if (config.fix_on) {
+			node_blk->i.i_links = cpu_to_le32(child_cnt);
+			need_fix = 1;
+			FIX_MSG("Dir: 0x%x i_links= 0x%x -> 0x%x",
+						nid, i_links, child_cnt);
+		}
+	}
+
+	if (ftype == F2FS_FT_ORPHAN && i_links)
+		ASSERT_MSG("ino: 0x%x is orphan inode, but has i_links: %u",
+				nid, i_links);
+	if (need_fix) {
+		ret = dev_write_block(node_blk, ni->blk_addr);
+		ASSERT(ret >= 0);
+	}
+}
+
+int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
+		u32 nid, enum FILE_TYPE ftype, struct f2fs_node *node_blk,
+		u32 *blk_cnt, struct node_info *ni)
+{
+	int idx, ret;
+	u32 child_cnt = 0, child_files = 0;
+	int need_fix = 0;
+
+	for (idx = 0; idx < ADDRS_PER_BLOCK; idx++) {
+		if (le32_to_cpu(node_blk->dn.addr[idx]) == 0x0)
+			continue;
+		ret = fsck_chk_data_blk(sbi,
+			le32_to_cpu(node_blk->dn.addr[idx]),
+			&child_cnt, &child_files,
+			le64_to_cpu(inode->i_blocks) == *blk_cnt, ftype,
+			nid, idx, ni->version);
+		if (!ret) {
+			*blk_cnt = *blk_cnt + 1;
+		} else if (config.fix_on) {
+			node_blk->dn.addr[idx] = 0;
+			need_fix = 1;
+			FIX_MSG("[0x%x] dn.addr[%d] = 0", nid, idx);
+		}
+	}
+	if (need_fix) {
+		ret = dev_write_block(node_blk, ni->blk_addr);
+		ASSERT(ret >= 0);
+	}
+	return 0;
+}
+
+int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
+		enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt)
+{
+	int ret;
+	int i = 0;
+
+	for (i = 0 ; i < NIDS_PER_BLOCK; i++) {
+		if (le32_to_cpu(node_blk->in.nid[i]) == 0x0)
+			continue;
+		ret = fsck_chk_node_blk(sbi, inode,
+				le32_to_cpu(node_blk->in.nid[i]),
+				ftype, TYPE_DIRECT_NODE, blk_cnt);
+		if (!ret)
+			*blk_cnt = *blk_cnt + 1;
+		else if (ret == -EINVAL)
+			printf("delete in.nid[i] = 0;\n");
+	}
+	return 0;
+}
+
+int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
+		enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt)
+{
+	int i = 0;
+	int ret = 0;
+
+	for (i = 0; i < NIDS_PER_BLOCK; i++) {
+		if (le32_to_cpu(node_blk->in.nid[i]) == 0x0)
+			continue;
+		ret = fsck_chk_node_blk(sbi, inode,
+				le32_to_cpu(node_blk->in.nid[i]),
+				ftype, TYPE_INDIRECT_NODE, blk_cnt);
+		if (!ret)
+			*blk_cnt = *blk_cnt + 1;
+		else if (ret == -EINVAL)
+			printf("delete in.nid[i] = 0;\n");
+	}
+	return 0;
+}
+
+static void print_dentry(__u32 depth, __u8 *name,
+		unsigned long *bitmap,
+		struct f2fs_dir_entry *dentry,
+		int max, int idx, int last_blk)
+{
+	int last_de = 0;
+	int next_idx = 0;
+	int name_len;
+	unsigned int i;
+	int bit_offset;
+
+	if (config.dbg_lv != -1)
+		return;
+
+	name_len = le16_to_cpu(dentry[idx].name_len);
+	next_idx = idx + (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN;
+
+	bit_offset = find_next_bit(bitmap, max, next_idx);
+	if (bit_offset >= max && last_blk)
+		last_de = 1;
+
+	if (tree_mark_size <= depth) {
+		tree_mark_size *= 2;
+		tree_mark = realloc(tree_mark, tree_mark_size);
+	}
+
+	if (last_de)
+		tree_mark[depth] = '`';
+	else
+		tree_mark[depth] = '|';
+
+	if (tree_mark[depth - 1] == '`')
+		tree_mark[depth - 1] = ' ';
+
+
+	for (i = 1; i < depth; i++)
+		printf("%c   ", tree_mark[i]);
+	printf("%c-- %s 0x%x\n", last_de ? '`' : '|',
+				name, le32_to_cpu(dentry[idx].ino));
+}
+
+static int __chk_dentries(struct f2fs_sb_info *sbi, u32 *child_cnt,
+			u32* child_files,
+			unsigned long *bitmap,
+			struct f2fs_dir_entry *dentry,
+			__u8 (*filenames)[F2FS_SLOT_LEN],
+			int max, int last_blk)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	enum FILE_TYPE ftype;
+	int dentries = 0;
+	u32 blk_cnt;
+	u8 *name;
+	u32 hash_code, ino;
+	u16 name_len;;
+	int ret = 0;
+	int fixed = 0;
+	int i;
+
+	/* readahead inode blocks */
+	for (i = 0; i < max;) {
+		if (test_bit(i, bitmap) == 0) {
+			i++;
+			continue;
+		}
+		ino = le32_to_cpu(dentry[i].ino);
+
+		if (IS_VALID_NID(sbi, ino)) {
+			struct node_info ni;
+
+			get_node_info(sbi, ino, &ni);
+			if (IS_VALID_BLK_ADDR(sbi, ni.blk_addr))
+				dev_reada_block(ni.blk_addr);
+		}
+		name_len = le16_to_cpu(dentry[i].name_len);
+		i += (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN;
+	}
+
+	for (i = 0; i < max;) {
+		if (test_bit(i, bitmap) == 0) {
+			i++;
+			continue;
+		}
+		if (!IS_VALID_NID(sbi, le32_to_cpu(dentry[i].ino))) {
+			DBG(1, "Bad dentry 0x%x with invalid NID/ino 0x%x",
+			    i, le32_to_cpu(dentry[i].ino));
+			if (config.fix_on) {
+				FIX_MSG("Clear bad dentry 0x%x with bad ino 0x%x",
+					i, le32_to_cpu(dentry[i].ino));
+				clear_bit(i, bitmap);
+				i++;
+				fixed = 1;
+				continue;
+			}
+		}
+		ftype = dentry[i].file_type;
+		if ((ftype <= F2FS_FT_UNKNOWN || ftype > F2FS_FT_LAST_FILE_TYPE) && config.fix_on) {
+			DBG(1, "Bad dentry 0x%x with unexpected ftype 0x%x",
+			    i, ftype);
+			if (config.fix_on) {
+				FIX_MSG("Clear bad dentry 0x%x with bad ftype 0x%x",
+					i, ftype);
+				clear_bit(i, bitmap);
+				i++;
+				fixed = 1;
+				continue;
+			}
+		}
+		name_len = le16_to_cpu(dentry[i].name_len);
+		name = calloc(name_len + 1, 1);
+		memcpy(name, filenames[i], name_len);
+		hash_code = f2fs_dentry_hash((const unsigned char *)name,
+								name_len);
+
+		/* fix hash_code made by old buggy code */
+		if (le32_to_cpu(dentry[i].hash_code) != hash_code) {
+			dentry[i].hash_code = hash_code;
+			fixed = 1;
+			FIX_MSG("hash_code[%d] of %s", i, name);
+		}
+
+		/* Becareful. 'dentry.file_type' is not imode. */
+		if (ftype == F2FS_FT_DIR) {
+			*child_cnt = *child_cnt + 1;
+			if ((name[0] == '.' && name_len == 1) ||
+				(name[0] == '.' && name[1] == '.' &&
+							name_len == 2)) {
+				i++;
+				free(name);
+				continue;
+			}
+		}
+
+		DBG(1, "[%3u]-[0x%x] name[%s] len[0x%x] ino[0x%x] type[0x%x]\n",
+				fsck->dentry_depth, i, name, name_len,
+				le32_to_cpu(dentry[i].ino),
+				dentry[i].file_type);
+
+		print_dentry(fsck->dentry_depth, name, bitmap,
+						dentry, max, i, last_blk);
+
+		blk_cnt = 1;
+		ret = fsck_chk_node_blk(sbi,
+				NULL, le32_to_cpu(dentry[i].ino),
+				ftype, TYPE_INODE, &blk_cnt);
+
+		if (ret && config.fix_on) {
+			int j;
+			int slots = (name_len + F2FS_SLOT_LEN - 1) /
+				F2FS_SLOT_LEN;
+			for (j = 0; j < slots; j++)
+				clear_bit(i + j, bitmap);
+			FIX_MSG("Unlink [0x%x] - %s len[0x%x], type[0x%x]",
+					le32_to_cpu(dentry[i].ino),
+					name, name_len,
+					dentry[i].file_type);
+			i += slots;
+			free(name);
+			fixed = 1;
+			continue;
+		}
+
+		i += (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN;
+		dentries++;
+		*child_files = *child_files + 1;
+		free(name);
+	}
+	return fixed ? -1 : dentries;
+}
+
+int fsck_chk_inline_dentries(struct f2fs_sb_info *sbi,
+		struct f2fs_node *node_blk, u32 *child_cnt, u32 *child_files)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	struct f2fs_inline_dentry *de_blk;
+	int dentries;
+
+	de_blk = inline_data_addr(node_blk);
+	ASSERT(de_blk != NULL);
+
+	fsck->dentry_depth++;
+	dentries = __chk_dentries(sbi, child_cnt, child_files,
+			(unsigned long *)de_blk->dentry_bitmap,
+			de_blk->dentry, de_blk->filename,
+			NR_INLINE_DENTRY, 1);
+	if (dentries < 0) {
+		DBG(1, "[%3d] Inline Dentry Block Fixed hash_codes\n\n",
+			fsck->dentry_depth);
+	} else {
+		DBG(1, "[%3d] Inline Dentry Block Done : "
+				"dentries:%d in %d slots (len:%d)\n\n",
+			fsck->dentry_depth, dentries,
+			(int)NR_INLINE_DENTRY, F2FS_NAME_LEN);
+	}
+	fsck->dentry_depth--;
+	return dentries;
+}
+
+int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
+		u32 *child_cnt, u32 *child_files, int last_blk)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	struct f2fs_dentry_block *de_blk;
+	int dentries, ret;
+
+	de_blk = (struct f2fs_dentry_block *)calloc(BLOCK_SZ, 1);
+	ASSERT(de_blk != NULL);
+
+	ret = dev_read_block(de_blk, blk_addr);
+	ASSERT(ret >= 0);
+
+	fsck->dentry_depth++;
+	dentries = __chk_dentries(sbi, child_cnt, child_files,
+			(unsigned long *)de_blk->dentry_bitmap,
+			de_blk->dentry, de_blk->filename,
+			NR_DENTRY_IN_BLOCK, last_blk);
+
+	if (dentries < 0) {
+		ret = dev_write_block(de_blk, blk_addr);
+		ASSERT(ret >= 0);
+		DBG(1, "[%3d] Dentry Block [0x%x] Fixed hash_codes\n\n",
+			fsck->dentry_depth, blk_addr);
+	} else {
+		DBG(1, "[%3d] Dentry Block [0x%x] Done : "
+				"dentries:%d in %d slots (len:%d)\n\n",
+			fsck->dentry_depth, blk_addr, dentries,
+			NR_DENTRY_IN_BLOCK, F2FS_NAME_LEN);
+	}
+	fsck->dentry_depth--;
+	free(de_blk);
+	return 0;
+}
+
+int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
+		u32 *child_cnt, u32 *child_files, int last_blk,
+		enum FILE_TYPE ftype, u32 parent_nid, u16 idx_in_node, u8 ver)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+
+	/* Is it reserved block? */
+	if (blk_addr == NEW_ADDR) {
+		fsck->chk.valid_blk_cnt++;
+		return 0;
+	}
+
+	if (!IS_VALID_BLK_ADDR(sbi, blk_addr)) {
+		ASSERT_MSG("blkaddres is not valid. [0x%x]", blk_addr);
+		return -EINVAL;
+	}
+
+	if (is_valid_ssa_data_blk(sbi, blk_addr, parent_nid,
+						idx_in_node, ver)) {
+		ASSERT_MSG("summary data block is not valid. [0x%x]",
+						parent_nid);
+		return -EINVAL;
+	}
+
+	if (f2fs_test_sit_bitmap(sbi, blk_addr) == 0)
+		ASSERT_MSG("SIT bitmap is 0x0. blk_addr[0x%x]", blk_addr);
+
+	if (f2fs_test_main_bitmap(sbi, blk_addr) != 0)
+		ASSERT_MSG("Duplicated data [0x%x]. pnid[0x%x] idx[0x%x]",
+				blk_addr, parent_nid, idx_in_node);
+
+
+	fsck->chk.valid_blk_cnt++;
+
+	if (ftype == F2FS_FT_DIR) {
+		f2fs_set_main_bitmap(sbi, blk_addr, CURSEG_HOT_DATA);
+		return fsck_chk_dentry_blk(sbi, blk_addr, child_cnt,
+				child_files, last_blk);
+	} else {
+		f2fs_set_main_bitmap(sbi, blk_addr, CURSEG_WARM_DATA);
+	}
+	return 0;
+}
+
+void fsck_chk_orphan_node(struct f2fs_sb_info *sbi)
+{
+	u32 blk_cnt = 0;
+	block_t start_blk, orphan_blkaddr, i, j;
+	struct f2fs_orphan_block *orphan_blk;
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+
+	if (!is_set_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG))
+		return;
+
+	start_blk = __start_cp_addr(sbi) + 1 +
+		le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload);
+	orphan_blkaddr = __start_sum_addr(sbi) - 1;
+	orphan_blk = calloc(BLOCK_SZ, 1);
+
+	for (i = 0; i < orphan_blkaddr; i++) {
+		int ret = dev_read_block(orphan_blk, start_blk + i);
+
+		ASSERT(ret >= 0);
+
+		for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) {
+			nid_t ino = le32_to_cpu(orphan_blk->ino[j]);
+			DBG(1, "[%3d] ino [0x%x]\n", i, ino);
+			if (config.fix_on) {
+				FIX_MSG("Discard orphan inodes: ino [0x%x]",
+									ino);
+				continue;
+			}
+			blk_cnt = 1;
+			fsck_chk_node_blk(sbi, NULL, ino,
+					F2FS_FT_ORPHAN, TYPE_INODE, &blk_cnt);
+		}
+		memset(orphan_blk, 0, BLOCK_SZ);
+	}
+	free(orphan_blk);
+}
+
+void fsck_init(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	struct f2fs_sm_info *sm_i = SM_I(sbi);
+
+	/*
+	 * We build three bitmap for main/sit/nat so that may check consistency
+	 * of filesystem.
+	 * 1. main_area_bitmap will be used to check whether all blocks of main
+	 *    area is used or not.
+	 * 2. nat_area_bitmap has bitmap information of used nid in NAT.
+	 * 3. sit_area_bitmap has bitmap information of used main block.
+	 * At Last sequence, we compare main_area_bitmap with sit_area_bitmap.
+	 */
+	fsck->nr_main_blks = sm_i->main_segments << sbi->log_blocks_per_seg;
+	fsck->main_area_bitmap_sz = (fsck->nr_main_blks + 7) / 8;
+	fsck->main_area_bitmap = calloc(fsck->main_area_bitmap_sz, 1);
+	ASSERT(fsck->main_area_bitmap != NULL);
+
+	build_nat_area_bitmap(sbi);
+
+	build_sit_area_bitmap(sbi);
+
+	tree_mark = calloc(tree_mark_size, 1);
+	ASSERT(tree_mark != NULL);
+}
+
+static void fix_nat_entries(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	u32 i;
+
+	for (i = 0; i < fsck->nr_nat_entries; i++)
+		if (f2fs_test_bit(i, fsck->nat_area_bitmap) != 0)
+			nullify_nat_entry(sbi, i);
+}
+
+static void fix_checkpoint(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	struct f2fs_super_block *raw_sb = sbi->raw_super;
+	struct f2fs_checkpoint *ckp = F2FS_CKPT(sbi);
+	unsigned long long cp_blk_no;
+	u32 i;
+	int ret;
+	u_int32_t crc = 0;
+
+	ckp->ckpt_flags = cpu_to_le32(CP_UMOUNT_FLAG);
+	ckp->cp_pack_total_block_count =
+		cpu_to_le32(8 + le32_to_cpu(raw_sb->cp_payload));
+	ckp->cp_pack_start_sum = cpu_to_le32(1 +
+				le32_to_cpu(raw_sb->cp_payload));
+
+	ckp->free_segment_count = cpu_to_le32(fsck->chk.free_segs);
+	ckp->valid_block_count = cpu_to_le32(fsck->chk.valid_blk_cnt);
+	ckp->valid_node_count = cpu_to_le32(fsck->chk.valid_node_cnt);
+	ckp->valid_inode_count = cpu_to_le32(fsck->chk.valid_inode_cnt);
+
+	crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, ckp, CHECKSUM_OFFSET);
+	*((__le32 *)((unsigned char *)ckp + CHECKSUM_OFFSET)) =
+							cpu_to_le32(crc);
+
+	cp_blk_no = le32_to_cpu(raw_sb->cp_blkaddr);
+	if (sbi->cur_cp == 2)
+		cp_blk_no += 1 << le32_to_cpu(raw_sb->log_blocks_per_seg);
+
+	ret = dev_write_block(ckp, cp_blk_no++);
+	ASSERT(ret >= 0);
+
+	for (i = 0; i < le32_to_cpu(raw_sb->cp_payload); i++) {
+		ret = dev_write_block(((unsigned char *)ckp) + i * F2FS_BLKSIZE,
+								cp_blk_no++);
+		ASSERT(ret >= 0);
+	}
+
+	for (i = 0; i < NO_CHECK_TYPE; i++) {
+		struct curseg_info *curseg = CURSEG_I(sbi, i);
+
+		ret = dev_write_block(curseg->sum_blk, cp_blk_no++);
+		ASSERT(ret >= 0);
+	}
+
+	ret = dev_write_block(ckp, cp_blk_no++);
+	ASSERT(ret >= 0);
+}
+
+int check_curseg_offset(struct f2fs_sb_info *sbi)
+{
+	int i;
+
+	for (i = 0; i < NO_CHECK_TYPE; i++) {
+		struct curseg_info *curseg = CURSEG_I(sbi, i);
+		struct seg_entry *se;
+
+		se = get_seg_entry(sbi, curseg->segno);
+		if (f2fs_test_bit(curseg->next_blkoff,
+				(const char *)se->cur_valid_map) == 1) {
+			ASSERT_MSG("Next block offset is not free, type:%d", i);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+int check_sit_types(struct f2fs_sb_info *sbi)
+{
+	unsigned int i;
+	int err = 0;
+
+	for (i = 0; i < TOTAL_SEGS(sbi); i++) {
+		struct seg_entry *se;
+
+		se = get_seg_entry(sbi, i);
+		if (se->orig_type != se->type) {
+			if (se->orig_type == CURSEG_COLD_DATA) {
+				se->type = se->orig_type;
+			} else {
+				FIX_MSG("Wrong segment type [0x%x] %x -> %x",
+						i, se->orig_type, se->type);
+				err = -EINVAL;
+			}
+		}
+	}
+	return err;
+}
+
+int fsck_verify(struct f2fs_sb_info *sbi)
+{
+	unsigned int i = 0;
+	int ret = 0;
+	int force = 0;
+	u32 nr_unref_nid = 0;
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	struct hard_link_node *node = NULL;
+
+	printf("\n");
+
+	for (i = 0; i < fsck->nr_nat_entries; i++) {
+		if (f2fs_test_bit(i, fsck->nat_area_bitmap) != 0) {
+			printf("NID[0x%x] is unreachable\n", i);
+			nr_unref_nid++;
+		}
+	}
+
+	if (fsck->hard_link_list_head != NULL) {
+		node = fsck->hard_link_list_head;
+		while (node) {
+			printf("NID[0x%x] has [0x%x] more unreachable links\n",
+					node->nid, node->links);
+			node = node->next;
+		}
+		config.bug_on = 1;
+	}
+
+	printf("[FSCK] Unreachable nat entries                       ");
+	if (nr_unref_nid == 0x0) {
+		printf(" [Ok..] [0x%x]\n", nr_unref_nid);
+	} else {
+		printf(" [Fail] [0x%x]\n", nr_unref_nid);
+		ret = EXIT_ERR_CODE;
+		config.bug_on = 1;
+	}
+
+	printf("[FSCK] SIT valid block bitmap checking                ");
+	if (memcmp(fsck->sit_area_bitmap, fsck->main_area_bitmap,
+					fsck->sit_area_bitmap_sz) == 0x0) {
+		printf("[Ok..]\n");
+	} else {
+		printf("[Fail]\n");
+		ret = EXIT_ERR_CODE;
+		config.bug_on = 1;
+	}
+
+	printf("[FSCK] Hard link checking for regular file           ");
+	if (fsck->hard_link_list_head == NULL) {
+		printf(" [Ok..] [0x%x]\n", fsck->chk.multi_hard_link_files);
+	} else {
+		printf(" [Fail] [0x%x]\n", fsck->chk.multi_hard_link_files);
+		ret = EXIT_ERR_CODE;
+		config.bug_on = 1;
+	}
+
+	printf("[FSCK] valid_block_count matching with CP            ");
+	if (sbi->total_valid_block_count == fsck->chk.valid_blk_cnt) {
+		printf(" [Ok..] [0x%x]\n", (u32)fsck->chk.valid_blk_cnt);
+	} else {
+		printf(" [Fail] [0x%x]\n", (u32)fsck->chk.valid_blk_cnt);
+		ret = EXIT_ERR_CODE;
+		config.bug_on = 1;
+	}
+
+	printf("[FSCK] valid_node_count matcing with CP (de lookup)  ");
+	if (sbi->total_valid_node_count == fsck->chk.valid_node_cnt) {
+		printf(" [Ok..] [0x%x]\n", fsck->chk.valid_node_cnt);
+	} else {
+		printf(" [Fail] [0x%x]\n", fsck->chk.valid_node_cnt);
+		ret = EXIT_ERR_CODE;
+		config.bug_on = 1;
+	}
+
+	printf("[FSCK] valid_node_count matcing with CP (nat lookup) ");
+	if (sbi->total_valid_node_count == fsck->chk.valid_nat_entry_cnt) {
+		printf(" [Ok..] [0x%x]\n", fsck->chk.valid_nat_entry_cnt);
+	} else {
+		printf(" [Fail] [0x%x]\n", fsck->chk.valid_nat_entry_cnt);
+		ret = EXIT_ERR_CODE;
+		config.bug_on = 1;
+	}
+
+	printf("[FSCK] valid_inode_count matched with CP             ");
+	if (sbi->total_valid_inode_count == fsck->chk.valid_inode_cnt) {
+		printf(" [Ok..] [0x%x]\n", fsck->chk.valid_inode_cnt);
+	} else {
+		printf(" [Fail] [0x%x]\n", fsck->chk.valid_inode_cnt);
+		ret = EXIT_ERR_CODE;
+		config.bug_on = 1;
+	}
+
+	printf("[FSCK] free segment_count matched with CP            ");
+	if (le32_to_cpu(F2FS_CKPT(sbi)->free_segment_count) ==
+						fsck->chk.sit_free_segs) {
+		printf(" [Ok..] [0x%x]\n", fsck->chk.sit_free_segs);
+	} else {
+		printf(" [Fail] [0x%x]\n", fsck->chk.sit_free_segs);
+		ret = EXIT_ERR_CODE;
+		config.bug_on = 1;
+	}
+
+	printf("[FSCK] next block offset is free                     ");
+	if (check_curseg_offset(sbi) == 0) {
+		printf(" [Ok..]\n");
+	} else {
+		printf(" [Fail]\n");
+		ret = EXIT_ERR_CODE;
+		config.bug_on = 1;
+	}
+
+	printf("[FSCK] fixing SIT types\n");
+	if (check_sit_types(sbi) != 0)
+		force = 1;
+
+	printf("[FSCK] other corrupted bugs                          ");
+	if (config.bug_on == 0) {
+		printf(" [Ok..]\n");
+	} else {
+		printf(" [Fail]\n");
+		ret = EXIT_ERR_CODE;
+	}
+
+	/* fix global metadata */
+	if (force || (config.bug_on && config.fix_on)) {
+		fix_nat_entries(sbi);
+		rewrite_sit_area_bitmap(sbi);
+		fix_checkpoint(sbi);
+	}
+	return ret;
+}
+
+void fsck_free(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	if (fsck->main_area_bitmap)
+		free(fsck->main_area_bitmap);
+
+	if (fsck->nat_area_bitmap)
+		free(fsck->nat_area_bitmap);
+
+	if (fsck->sit_area_bitmap)
+		free(fsck->sit_area_bitmap);
+
+	if (tree_mark)
+		free(tree_mark);
+}
diff --git a/f2fs-tools/fsck/fsck.h b/f2fs-tools/fsck/fsck.h
new file mode 100644
index 0000000..9cad013
--- /dev/null
+++ b/f2fs-tools/fsck/fsck.h
@@ -0,0 +1,131 @@
+/**
+ * fsck.h
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _FSCK_H_
+#define _FSCK_H_
+
+#include "f2fs.h"
+
+/* fsck.c */
+struct orphan_info {
+	u32 nr_inodes;
+	u32 *ino_list;
+};
+
+struct f2fs_fsck {
+	struct f2fs_sb_info sbi;
+
+	struct orphan_info orphani;
+	struct chk_result {
+		u64 valid_blk_cnt;
+		u32 valid_nat_entry_cnt;
+		u32 valid_node_cnt;
+		u32 valid_inode_cnt;
+		u32 multi_hard_link_files;
+		u64 sit_valid_blocks;
+		u32 sit_free_segs;
+		u32 free_segs;
+	} chk;
+
+	struct hard_link_node *hard_link_list_head;
+
+	char *main_seg_usage;
+	char *main_area_bitmap;
+	char *nat_area_bitmap;
+	char *sit_area_bitmap;
+
+	u64 main_area_bitmap_sz;
+	u32 nat_area_bitmap_sz;
+	u32 sit_area_bitmap_sz;
+
+	u64 nr_main_blks;
+	u32 nr_nat_entries;
+
+	u32 dentry_depth;
+};
+
+#define BLOCK_SZ		4096
+struct block {
+	unsigned char buf[BLOCK_SZ];
+};
+
+enum NODE_TYPE {
+	TYPE_INODE = 37,
+	TYPE_DIRECT_NODE = 43,
+	TYPE_INDIRECT_NODE = 53,
+	TYPE_DOUBLE_INDIRECT_NODE = 67,
+	TYPE_XATTR = 77
+};
+
+struct hard_link_node {
+	u32 nid;
+	u32 links;
+	struct hard_link_node *next;
+};
+
+enum seg_type {
+	SEG_TYPE_DATA,
+	SEG_TYPE_CUR_DATA,
+	SEG_TYPE_NODE,
+	SEG_TYPE_CUR_NODE,
+	SEG_TYPE_MAX,
+};
+
+extern void fsck_chk_orphan_node(struct f2fs_sb_info *);
+extern int fsck_chk_node_blk(struct f2fs_sb_info *, struct f2fs_inode *, u32,
+		enum FILE_TYPE, enum NODE_TYPE, u32 *);
+extern void fsck_chk_inode_blk(struct f2fs_sb_info *, u32, enum FILE_TYPE,
+		struct f2fs_node *, u32 *, struct node_info *);
+extern int fsck_chk_dnode_blk(struct f2fs_sb_info *, struct f2fs_inode *,
+		u32, enum FILE_TYPE, struct f2fs_node *, u32 *,
+		struct node_info *);
+extern int fsck_chk_idnode_blk(struct f2fs_sb_info *, struct f2fs_inode *,
+		enum FILE_TYPE, struct f2fs_node *, u32 *);
+extern int fsck_chk_didnode_blk(struct f2fs_sb_info *, struct f2fs_inode *,
+		enum FILE_TYPE, struct f2fs_node *, u32 *);
+extern int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32, u32 *, u32 *,
+		int, enum FILE_TYPE, u32, u16, u8);
+extern int fsck_chk_dentry_blk(struct f2fs_sb_info *, u32, u32 *, u32 *, int);
+int fsck_chk_inline_dentries(struct f2fs_sb_info *, struct f2fs_node *,
+		u32 *, u32 *);
+
+extern void print_node_info(struct f2fs_node *);
+extern void print_inode_info(struct f2fs_inode *, int);
+extern struct seg_entry *get_seg_entry(struct f2fs_sb_info *, unsigned int);
+extern int get_sum_block(struct f2fs_sb_info *, unsigned int,
+				struct f2fs_summary_block *);
+extern int get_sum_entry(struct f2fs_sb_info *, u32, struct f2fs_summary *);
+extern void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *);
+extern void nullify_nat_entry(struct f2fs_sb_info *, u32);
+extern void rewrite_sit_area_bitmap(struct f2fs_sb_info *);
+extern void build_nat_area_bitmap(struct f2fs_sb_info *);
+extern void build_sit_area_bitmap(struct f2fs_sb_info *);
+extern void fsck_init(struct f2fs_sb_info *);
+extern int fsck_verify(struct f2fs_sb_info *);
+extern void fsck_free(struct f2fs_sb_info *);
+extern int f2fs_do_mount(struct f2fs_sb_info *);
+extern void f2fs_do_umount(struct f2fs_sb_info *);
+
+/* dump.c */
+struct dump_option {
+	nid_t nid;
+	int start_sit;
+	int end_sit;
+	int start_ssa;
+	int end_ssa;
+	int32_t blk_addr;
+};
+
+extern void sit_dump(struct f2fs_sb_info *, int, int);
+extern void ssa_dump(struct f2fs_sb_info *, int, int);
+extern void dump_node(struct f2fs_sb_info *, nid_t);
+extern int dump_info_from_blkaddr(struct f2fs_sb_info *, u32);
+
+#endif /* _FSCK_H_ */
diff --git a/f2fs-tools/fsck/main.c b/f2fs-tools/fsck/main.c
new file mode 100644
index 0000000..3606f62
--- /dev/null
+++ b/f2fs-tools/fsck/main.c
@@ -0,0 +1,261 @@
+/**
+ * main.c
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include "fsck.h"
+#include <libgen.h>
+
+struct f2fs_fsck gfsck;
+
+void fsck_usage()
+{
+	MSG(0, "\nUsage: fsck.f2fs [options] device\n");
+	MSG(0, "[options]:\n");
+	MSG(0, "  -a check/fix potential corruption, reported by f2fs\n");
+	MSG(0, "  -d debug level [default:0]\n");
+	MSG(0, "  -f check/fix entire partition\n");
+	MSG(0, "  -t show directory tree [-d -1]\n");
+	exit(1);
+}
+
+void dump_usage()
+{
+	MSG(0, "\nUsage: dump.f2fs [options] device\n");
+	MSG(0, "[options]:\n");
+	MSG(0, "  -d debug level [default:0]\n");
+	MSG(0, "  -i inode no (hex)\n");
+	MSG(0, "  -s [SIT dump segno from #1~#2 (decimal), for all 0~-1]\n");
+	MSG(0, "  -a [SSA dump segno from #1~#2 (decimal), for all 0~-1]\n");
+	MSG(0, "  -b blk_addr (in 4KB)\n");
+
+	exit(1);
+}
+
+void f2fs_parse_options(int argc, char *argv[])
+{
+	int option = 0;
+	char *prog = basename(argv[0]);
+
+	if (!strcmp("fsck.f2fs", prog)) {
+		const char *option_string = "ad:ft";
+
+		config.func = FSCK;
+		while ((option = getopt(argc, argv, option_string)) != EOF) {
+			switch (option) {
+			case 'a':
+				config.auto_fix = 1;
+				MSG(0, "Info: Fix the reported corruption.\n");
+				break;
+			case 'd':
+				config.dbg_lv = atoi(optarg);
+				MSG(0, "Info: Debug level = %d\n",
+							config.dbg_lv);
+				break;
+			case 'f':
+				config.fix_on = 1;
+				MSG(0, "Info: Force to fix corruption\n");
+				break;
+			case 't':
+				config.dbg_lv = -1;
+				break;
+			default:
+				MSG(0, "\tError: Unknown option %c\n", option);
+				fsck_usage();
+				break;
+			}
+		}
+	} else if (!strcmp("dump.f2fs", prog)) {
+		const char *option_string = "d:i:s:a:b:";
+		static struct dump_option dump_opt = {
+			.nid = 3,	/* default root ino */
+			.start_sit = -1,
+			.end_sit = -1,
+			.start_ssa = -1,
+			.end_ssa = -1,
+			.blk_addr = -1,
+		};
+
+		config.func = DUMP;
+		while ((option = getopt(argc, argv, option_string)) != EOF) {
+			int ret = 0;
+
+			switch (option) {
+			case 'd':
+				config.dbg_lv = atoi(optarg);
+				MSG(0, "Info: Debug level = %d\n",
+							config.dbg_lv);
+				break;
+			case 'i':
+				if (strncmp(optarg, "0x", 2))
+					ret = sscanf(optarg, "%d",
+							&dump_opt.nid);
+				else
+					ret = sscanf(optarg, "%x",
+							&dump_opt.nid);
+				break;
+			case 's':
+				ret = sscanf(optarg, "%d~%d",
+							&dump_opt.start_sit,
+							&dump_opt.end_sit);
+				break;
+			case 'a':
+				ret = sscanf(optarg, "%d~%d",
+							&dump_opt.start_ssa,
+							&dump_opt.end_ssa);
+				break;
+			case 'b':
+				if (strncmp(optarg, "0x", 2))
+					ret = sscanf(optarg, "%d",
+							&dump_opt.blk_addr);
+				else
+					ret = sscanf(optarg, "%x",
+							&dump_opt.blk_addr);
+				break;
+			default:
+				MSG(0, "\tError: Unknown option %c\n", option);
+				dump_usage();
+				break;
+			}
+			ASSERT(ret >= 0);
+		}
+
+		config.private = &dump_opt;
+	}
+
+	if ((optind + 1) != argc) {
+		MSG(0, "\tError: Device not specified\n");
+		if (config.func == FSCK)
+			fsck_usage();
+		else if (config.func == DUMP)
+			dump_usage();
+	}
+	config.device_name = argv[optind];
+}
+
+static void do_fsck(struct f2fs_sb_info *sbi)
+{
+	u32 blk_cnt;
+
+	fsck_init(sbi);
+
+	fsck_chk_orphan_node(sbi);
+
+	/* Traverse all block recursively from root inode */
+	blk_cnt = 1;
+	fsck_chk_node_blk(sbi, NULL, sbi->root_ino_num,
+			F2FS_FT_DIR, TYPE_INODE, &blk_cnt);
+	fsck_verify(sbi);
+	fsck_free(sbi);
+}
+
+static void do_dump(struct f2fs_sb_info *sbi)
+{
+	struct dump_option *opt = (struct dump_option *)config.private;
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	u32 flag = le32_to_cpu(ckpt->ckpt_flags);
+
+	fsck_init(sbi);
+
+	if (opt->end_sit == -1)
+		opt->end_sit = SM_I(sbi)->main_segments;
+	if (opt->end_ssa == -1)
+		opt->end_ssa = SM_I(sbi)->main_segments;
+	if (opt->start_sit != -1)
+		sit_dump(sbi, opt->start_sit, opt->end_sit);
+	if (opt->start_ssa != -1)
+		ssa_dump(sbi, opt->start_ssa, opt->end_ssa);
+	if (opt->blk_addr != -1) {
+		dump_info_from_blkaddr(sbi, opt->blk_addr);
+		goto cleanup;
+	}
+
+	MSG(0, "Info: checkpoint state = %x : ", flag);
+	if (flag & CP_FSCK_FLAG)
+		MSG(0, "%s", " fsck");
+	if (flag & CP_ERROR_FLAG)
+		MSG(0, "%s", " error");
+	if (flag & CP_COMPACT_SUM_FLAG)
+		MSG(0, "%s", " compacted_summary");
+	if (flag & CP_ORPHAN_PRESENT_FLAG)
+		MSG(0, "%s", " orphan_inodes");
+	if (flag & CP_FASTBOOT_FLAG)
+		MSG(0, "%s", " fastboot");
+	if (flag & CP_UMOUNT_FLAG)
+		MSG(0, "%s", " unmount");
+	else
+		MSG(0, "%s", " sudden-power-off");
+	MSG(0, "\n");
+
+	dump_node(sbi, opt->nid);
+cleanup:
+	fsck_free(sbi);
+}
+
+int main(int argc, char **argv)
+{
+	struct f2fs_sb_info *sbi;
+	int ret = 0;
+
+	f2fs_init_configuration(&config);
+
+	f2fs_parse_options(argc, argv);
+
+	if (f2fs_dev_is_umounted(&config) < 0)
+		return -1;
+
+	/* Get device */
+	if (f2fs_get_device_info(&config) < 0)
+		return -1;
+fsck_again:
+	memset(&gfsck, 0, sizeof(gfsck));
+	gfsck.sbi.fsck = &gfsck;
+	sbi = &gfsck.sbi;
+
+	ret = f2fs_do_mount(sbi);
+	if (ret == 1) {
+		free(sbi->ckpt);
+		free(sbi->raw_super);
+		goto out;
+	} else if (ret < 0)
+		return -1;
+
+	switch (config.func) {
+	case FSCK:
+		do_fsck(sbi);
+		break;
+	case DUMP:
+		do_dump(sbi);
+		break;
+	}
+
+	f2fs_do_umount(sbi);
+out:
+	if (config.func == FSCK && config.bug_on) {
+		if (config.fix_on == 0 && config.auto_fix == 0) {
+			char ans[255] = {0};
+retry:
+			printf("Do you want to fix this partition? [Y/N] ");
+			ret = scanf("%s", ans);
+			ASSERT(ret >= 0);
+			if (!strcasecmp(ans, "y"))
+				config.fix_on = 1;
+			else if (!strcasecmp(ans, "n"))
+				config.fix_on = 0;
+			else
+				goto retry;
+
+			if (config.fix_on)
+				goto fsck_again;
+		}
+	}
+	f2fs_finalize_device(&config);
+
+	printf("\nDone.\n");
+	return 0;
+}
diff --git a/f2fs-tools/fsck/mount.c b/f2fs-tools/fsck/mount.c
new file mode 100644
index 0000000..6d96db8
--- /dev/null
+++ b/f2fs-tools/fsck/mount.c
@@ -0,0 +1,1326 @@
+/**
+ * mount.c
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include "fsck.h"
+#include <locale.h>
+
+void print_inode_info(struct f2fs_inode *inode, int name)
+{
+	unsigned int i = 0;
+	int namelen = le32_to_cpu(inode->i_namelen);
+
+	if (name && namelen) {
+		inode->i_name[namelen] = '\0';
+		MSG(0, " - File name         : %s\n", inode->i_name);
+		setlocale(LC_ALL, "");
+		MSG(0, " - File size         : %'llu (bytes)\n",
+				le64_to_cpu(inode->i_size));
+		return;
+	}
+
+	DISP_u32(inode, i_mode);
+	DISP_u32(inode, i_uid);
+	DISP_u32(inode, i_gid);
+	DISP_u32(inode, i_links);
+	DISP_u64(inode, i_size);
+	DISP_u64(inode, i_blocks);
+
+	DISP_u64(inode, i_atime);
+	DISP_u32(inode, i_atime_nsec);
+	DISP_u64(inode, i_ctime);
+	DISP_u32(inode, i_ctime_nsec);
+	DISP_u64(inode, i_mtime);
+	DISP_u32(inode, i_mtime_nsec);
+
+	DISP_u32(inode, i_generation);
+	DISP_u32(inode, i_current_depth);
+	DISP_u32(inode, i_xattr_nid);
+	DISP_u32(inode, i_flags);
+	DISP_u32(inode, i_inline);
+	DISP_u32(inode, i_pino);
+
+	if (namelen) {
+		DISP_u32(inode, i_namelen);
+		inode->i_name[namelen] = '\0';
+		DISP_utf(inode, i_name);
+	}
+
+	printf("i_ext: fofs:%x blkaddr:%x len:%x\n",
+			inode->i_ext.fofs,
+			inode->i_ext.blk_addr,
+			inode->i_ext.len);
+
+	DISP_u32(inode, i_addr[0]);	/* Pointers to data blocks */
+	DISP_u32(inode, i_addr[1]);	/* Pointers to data blocks */
+	DISP_u32(inode, i_addr[2]);	/* Pointers to data blocks */
+	DISP_u32(inode, i_addr[3]);	/* Pointers to data blocks */
+
+	for (i = 4; i < ADDRS_PER_INODE(inode); i++) {
+		if (inode->i_addr[i] != 0x0) {
+			printf("i_addr[0x%x] points data block\r\t\t[0x%4x]\n",
+					i, inode->i_addr[i]);
+			break;
+		}
+	}
+
+	DISP_u32(inode, i_nid[0]);	/* direct */
+	DISP_u32(inode, i_nid[1]);	/* direct */
+	DISP_u32(inode, i_nid[2]);	/* indirect */
+	DISP_u32(inode, i_nid[3]);	/* indirect */
+	DISP_u32(inode, i_nid[4]);	/* double indirect */
+
+	printf("\n");
+}
+
+void print_node_info(struct f2fs_node *node_block)
+{
+	nid_t ino = le32_to_cpu(node_block->footer.ino);
+	nid_t nid = le32_to_cpu(node_block->footer.nid);
+	/* Is this inode? */
+	if (ino == nid) {
+		DBG(0, "Node ID [0x%x:%u] is inode\n", nid, nid);
+		print_inode_info(&node_block->i, 0);
+	} else {
+		int i;
+		u32 *dump_blk = (u32 *)node_block;
+		DBG(0, "Node ID [0x%x:%u] is direct node or indirect node.\n",
+								nid, nid);
+		for (i = 0; i <= 10; i++)
+			MSG(0, "[%d]\t\t\t[0x%8x : %d]\n",
+						i, dump_blk[i], dump_blk[i]);
+	}
+}
+
+void print_raw_sb_info(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
+
+	if (!config.dbg_lv)
+		return;
+
+	printf("\n");
+	printf("+--------------------------------------------------------+\n");
+	printf("| Super block                                            |\n");
+	printf("+--------------------------------------------------------+\n");
+
+	DISP_u32(sb, magic);
+	DISP_u32(sb, major_ver);
+	DISP_u32(sb, minor_ver);
+	DISP_u32(sb, log_sectorsize);
+	DISP_u32(sb, log_sectors_per_block);
+
+	DISP_u32(sb, log_blocksize);
+	DISP_u32(sb, log_blocks_per_seg);
+	DISP_u32(sb, segs_per_sec);
+	DISP_u32(sb, secs_per_zone);
+	DISP_u32(sb, checksum_offset);
+	DISP_u64(sb, block_count);
+
+	DISP_u32(sb, section_count);
+	DISP_u32(sb, segment_count);
+	DISP_u32(sb, segment_count_ckpt);
+	DISP_u32(sb, segment_count_sit);
+	DISP_u32(sb, segment_count_nat);
+
+	DISP_u32(sb, segment_count_ssa);
+	DISP_u32(sb, segment_count_main);
+	DISP_u32(sb, segment0_blkaddr);
+
+	DISP_u32(sb, cp_blkaddr);
+	DISP_u32(sb, sit_blkaddr);
+	DISP_u32(sb, nat_blkaddr);
+	DISP_u32(sb, ssa_blkaddr);
+	DISP_u32(sb, main_blkaddr);
+
+	DISP_u32(sb, root_ino);
+	DISP_u32(sb, node_ino);
+	DISP_u32(sb, meta_ino);
+	DISP_u32(sb, cp_payload);
+	DISP("%s", sb, version);
+	printf("\n");
+}
+
+void print_ckpt_info(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
+
+	if (!config.dbg_lv)
+		return;
+
+	printf("\n");
+	printf("+--------------------------------------------------------+\n");
+	printf("| Checkpoint                                             |\n");
+	printf("+--------------------------------------------------------+\n");
+
+	DISP_u64(cp, checkpoint_ver);
+	DISP_u64(cp, user_block_count);
+	DISP_u64(cp, valid_block_count);
+	DISP_u32(cp, rsvd_segment_count);
+	DISP_u32(cp, overprov_segment_count);
+	DISP_u32(cp, free_segment_count);
+
+	DISP_u32(cp, alloc_type[CURSEG_HOT_NODE]);
+	DISP_u32(cp, alloc_type[CURSEG_WARM_NODE]);
+	DISP_u32(cp, alloc_type[CURSEG_COLD_NODE]);
+	DISP_u32(cp, cur_node_segno[0]);
+	DISP_u32(cp, cur_node_segno[1]);
+	DISP_u32(cp, cur_node_segno[2]);
+
+	DISP_u32(cp, cur_node_blkoff[0]);
+	DISP_u32(cp, cur_node_blkoff[1]);
+	DISP_u32(cp, cur_node_blkoff[2]);
+
+
+	DISP_u32(cp, alloc_type[CURSEG_HOT_DATA]);
+	DISP_u32(cp, alloc_type[CURSEG_WARM_DATA]);
+	DISP_u32(cp, alloc_type[CURSEG_COLD_DATA]);
+	DISP_u32(cp, cur_data_segno[0]);
+	DISP_u32(cp, cur_data_segno[1]);
+	DISP_u32(cp, cur_data_segno[2]);
+
+	DISP_u32(cp, cur_data_blkoff[0]);
+	DISP_u32(cp, cur_data_blkoff[1]);
+	DISP_u32(cp, cur_data_blkoff[2]);
+
+	DISP_u32(cp, ckpt_flags);
+	DISP_u32(cp, cp_pack_total_block_count);
+	DISP_u32(cp, cp_pack_start_sum);
+	DISP_u32(cp, valid_node_count);
+	DISP_u32(cp, valid_inode_count);
+	DISP_u32(cp, next_free_nid);
+	DISP_u32(cp, sit_ver_bitmap_bytesize);
+	DISP_u32(cp, nat_ver_bitmap_bytesize);
+	DISP_u32(cp, checksum_offset);
+	DISP_u64(cp, elapsed_time);
+
+	DISP_u32(cp, sit_nat_version_bitmap[0]);
+	printf("\n\n");
+}
+
+int sanity_check_raw_super(struct f2fs_super_block *raw_super)
+{
+	unsigned int blocksize;
+
+	if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) {
+		return -1;
+	}
+
+	if (F2FS_BLKSIZE != PAGE_CACHE_SIZE) {
+		return -1;
+	}
+
+	blocksize = 1 << le32_to_cpu(raw_super->log_blocksize);
+	if (F2FS_BLKSIZE != blocksize) {
+		return -1;
+	}
+
+	if (le32_to_cpu(raw_super->log_sectorsize) > F2FS_MAX_LOG_SECTOR_SIZE ||
+		le32_to_cpu(raw_super->log_sectorsize) <
+						F2FS_MIN_LOG_SECTOR_SIZE) {
+		return -1;
+	}
+
+	if (le32_to_cpu(raw_super->log_sectors_per_block) +
+				le32_to_cpu(raw_super->log_sectorsize) !=
+						F2FS_MAX_LOG_SECTOR_SIZE) {
+		return -1;
+	}
+
+	return 0;
+}
+
+int validate_super_block(struct f2fs_sb_info *sbi, int block)
+{
+	u64 offset;
+
+	sbi->raw_super = malloc(sizeof(struct f2fs_super_block));
+
+	if (block == 0)
+		offset = F2FS_SUPER_OFFSET;
+	else
+		offset = F2FS_BLKSIZE + F2FS_SUPER_OFFSET;
+
+	if (dev_read(sbi->raw_super, offset, sizeof(struct f2fs_super_block)))
+		return -1;
+
+	if (!sanity_check_raw_super(sbi->raw_super)) {
+		/* get kernel version */
+		if (config.kd >= 0) {
+			dev_read_version(config.version, 0, VERSION_LEN);
+			get_kernel_version(config.version);
+		} else {
+			memset(config.version, 0, VERSION_LEN);
+		}
+
+		/* build sb version */
+		memcpy(config.sb_version, sbi->raw_super->version, VERSION_LEN);
+		get_kernel_version(config.sb_version);
+		memcpy(config.init_version, sbi->raw_super->init_version, VERSION_LEN);
+		get_kernel_version(config.init_version);
+
+		MSG(0, "Info: MKFS version\n  \"%s\"\n", config.init_version);
+		MSG(0, "Info: FSCK version\n  from \"%s\"\n    to \"%s\"\n",
+					config.sb_version, config.version);
+		if (memcmp(config.sb_version, config.version, VERSION_LEN)) {
+			int ret;
+
+			memcpy(sbi->raw_super->version,
+						config.version, VERSION_LEN);
+			ret = dev_write(sbi->raw_super, offset,
+					sizeof(struct f2fs_super_block));
+			ASSERT(ret >= 0);
+
+			config.auto_fix = 0;
+			config.fix_on = 1;
+		}
+		return 0;
+	}
+
+	free(sbi->raw_super);
+	MSG(0, "\tCan't find a valid F2FS superblock at 0x%x\n", block);
+
+	return -EINVAL;
+}
+
+int init_sb_info(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_super_block *raw_super = sbi->raw_super;
+
+	sbi->log_sectors_per_block =
+		le32_to_cpu(raw_super->log_sectors_per_block);
+	sbi->log_blocksize = le32_to_cpu(raw_super->log_blocksize);
+	sbi->blocksize = 1 << sbi->log_blocksize;
+	sbi->log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
+	sbi->blocks_per_seg = 1 << sbi->log_blocks_per_seg;
+	sbi->segs_per_sec = le32_to_cpu(raw_super->segs_per_sec);
+	sbi->secs_per_zone = le32_to_cpu(raw_super->secs_per_zone);
+	sbi->total_sections = le32_to_cpu(raw_super->section_count);
+	sbi->total_node_count =
+		(le32_to_cpu(raw_super->segment_count_nat) / 2)
+		* sbi->blocks_per_seg * NAT_ENTRY_PER_BLOCK;
+	sbi->root_ino_num = le32_to_cpu(raw_super->root_ino);
+	sbi->node_ino_num = le32_to_cpu(raw_super->node_ino);
+	sbi->meta_ino_num = le32_to_cpu(raw_super->meta_ino);
+	sbi->cur_victim_sec = NULL_SEGNO;
+	return 0;
+}
+
+void *validate_checkpoint(struct f2fs_sb_info *sbi, block_t cp_addr,
+				unsigned long long *version)
+{
+	void *cp_page_1, *cp_page_2;
+	struct f2fs_checkpoint *cp_block;
+	unsigned long blk_size = sbi->blocksize;
+	unsigned long long cur_version = 0, pre_version = 0;
+	unsigned int crc = 0;
+	size_t crc_offset;
+
+	/* Read the 1st cp block in this CP pack */
+	cp_page_1 = malloc(PAGE_SIZE);
+	if (dev_read_block(cp_page_1, cp_addr) < 0)
+		return NULL;
+
+	cp_block = (struct f2fs_checkpoint *)cp_page_1;
+	crc_offset = le32_to_cpu(cp_block->checksum_offset);
+	if (crc_offset >= blk_size)
+		goto invalid_cp1;
+
+	crc = *(unsigned int *)((unsigned char *)cp_block + crc_offset);
+	if (f2fs_crc_valid(crc, cp_block, crc_offset))
+		goto invalid_cp1;
+
+	pre_version = le64_to_cpu(cp_block->checkpoint_ver);
+
+	/* Read the 2nd cp block in this CP pack */
+	cp_page_2 = malloc(PAGE_SIZE);
+	cp_addr += le32_to_cpu(cp_block->cp_pack_total_block_count) - 1;
+
+	if (dev_read_block(cp_page_2, cp_addr) < 0)
+		goto invalid_cp2;
+
+	cp_block = (struct f2fs_checkpoint *)cp_page_2;
+	crc_offset = le32_to_cpu(cp_block->checksum_offset);
+	if (crc_offset >= blk_size)
+		goto invalid_cp2;
+
+	crc = *(unsigned int *)((unsigned char *)cp_block + crc_offset);
+	if (f2fs_crc_valid(crc, cp_block, crc_offset))
+		goto invalid_cp2;
+
+	cur_version = le64_to_cpu(cp_block->checkpoint_ver);
+
+	if (cur_version == pre_version) {
+		*version = cur_version;
+		free(cp_page_2);
+		return cp_page_1;
+	}
+
+invalid_cp2:
+	free(cp_page_2);
+invalid_cp1:
+	free(cp_page_1);
+	return NULL;
+}
+
+int get_valid_checkpoint(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_super_block *raw_sb = sbi->raw_super;
+	void *cp1, *cp2, *cur_page;
+	unsigned long blk_size = sbi->blocksize;
+	unsigned long long cp1_version = 0, cp2_version = 0;
+	unsigned long long cp_start_blk_no;
+	unsigned int cp_blks = 1 + le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload);
+	int ret;
+
+	sbi->ckpt = malloc(cp_blks * blk_size);
+	if (!sbi->ckpt)
+		return -ENOMEM;
+	/*
+	 * Finding out valid cp block involves read both
+	 * sets( cp pack1 and cp pack 2)
+	 */
+	cp_start_blk_no = le32_to_cpu(raw_sb->cp_blkaddr);
+	cp1 = validate_checkpoint(sbi, cp_start_blk_no, &cp1_version);
+
+	/* The second checkpoint pack should start at the next segment */
+	cp_start_blk_no += 1 << le32_to_cpu(raw_sb->log_blocks_per_seg);
+	cp2 = validate_checkpoint(sbi, cp_start_blk_no, &cp2_version);
+
+	if (cp1 && cp2) {
+		if (ver_after(cp2_version, cp1_version)) {
+			cur_page = cp2;
+			sbi->cur_cp = 2;
+		} else {
+			cur_page = cp1;
+			sbi->cur_cp = 1;
+		}
+	} else if (cp1) {
+		cur_page = cp1;
+		sbi->cur_cp = 1;
+	} else if (cp2) {
+		cur_page = cp2;
+		sbi->cur_cp = 2;
+	} else {
+		free(cp1);
+		free(cp2);
+		goto fail_no_cp;
+	}
+
+	memcpy(sbi->ckpt, cur_page, blk_size);
+
+	if (cp_blks > 1) {
+		unsigned int i;
+		unsigned long long cp_blk_no;
+
+		cp_blk_no = le32_to_cpu(raw_sb->cp_blkaddr);
+		if (cur_page == cp2)
+			cp_blk_no += 1 <<
+				le32_to_cpu(raw_sb->log_blocks_per_seg);
+		/* copy sit bitmap */
+		for (i = 1; i < cp_blks; i++) {
+			unsigned char *ckpt = (unsigned char *)sbi->ckpt;
+			ret = dev_read_block(cur_page, cp_blk_no + i);
+			ASSERT(ret >= 0);
+			memcpy(ckpt + i * blk_size, cur_page, blk_size);
+		}
+	}
+	free(cp1);
+	free(cp2);
+	return 0;
+
+fail_no_cp:
+	free(sbi->ckpt);
+	return -EINVAL;
+}
+
+int sanity_check_ckpt(struct f2fs_sb_info *sbi)
+{
+	unsigned int total, fsmeta;
+	struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+
+	total = le32_to_cpu(raw_super->segment_count);
+	fsmeta = le32_to_cpu(raw_super->segment_count_ckpt);
+	fsmeta += le32_to_cpu(raw_super->segment_count_sit);
+	fsmeta += le32_to_cpu(raw_super->segment_count_nat);
+	fsmeta += le32_to_cpu(ckpt->rsvd_segment_count);
+	fsmeta += le32_to_cpu(raw_super->segment_count_ssa);
+
+	if (fsmeta >= total)
+		return 1;
+
+	return 0;
+}
+
+int init_node_manager(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_super_block *sb_raw = F2FS_RAW_SUPER(sbi);
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	unsigned char *version_bitmap;
+	unsigned int nat_segs, nat_blocks;
+
+	nm_i->nat_blkaddr = le32_to_cpu(sb_raw->nat_blkaddr);
+
+	/* segment_count_nat includes pair segment so divide to 2. */
+	nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1;
+	nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg);
+	nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks;
+	nm_i->fcnt = 0;
+	nm_i->nat_cnt = 0;
+	nm_i->init_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid);
+	nm_i->next_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid);
+
+	nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP);
+
+	nm_i->nat_bitmap = malloc(nm_i->bitmap_size);
+	if (!nm_i->nat_bitmap)
+		return -ENOMEM;
+	version_bitmap = __bitmap_ptr(sbi, NAT_BITMAP);
+	if (!version_bitmap)
+		return -EFAULT;
+
+	/* copy version bitmap */
+	memcpy(nm_i->nat_bitmap, version_bitmap, nm_i->bitmap_size);
+	return 0;
+}
+
+int build_node_manager(struct f2fs_sb_info *sbi)
+{
+	int err;
+	sbi->nm_info = malloc(sizeof(struct f2fs_nm_info));
+	if (!sbi->nm_info)
+		return -ENOMEM;
+
+	err = init_node_manager(sbi);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+int build_sit_info(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_super_block *raw_sb = F2FS_RAW_SUPER(sbi);
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	struct sit_info *sit_i;
+	unsigned int sit_segs, start;
+	char *src_bitmap, *dst_bitmap;
+	unsigned int bitmap_size;
+
+	sit_i = malloc(sizeof(struct sit_info));
+	if (!sit_i)
+		return -ENOMEM;
+
+	SM_I(sbi)->sit_info = sit_i;
+
+	sit_i->sentries = calloc(TOTAL_SEGS(sbi) * sizeof(struct seg_entry), 1);
+
+	for (start = 0; start < TOTAL_SEGS(sbi); start++) {
+		sit_i->sentries[start].cur_valid_map
+			= calloc(SIT_VBLOCK_MAP_SIZE, 1);
+		sit_i->sentries[start].ckpt_valid_map
+			= calloc(SIT_VBLOCK_MAP_SIZE, 1);
+		if (!sit_i->sentries[start].cur_valid_map
+				|| !sit_i->sentries[start].ckpt_valid_map)
+			return -ENOMEM;
+	}
+
+	sit_segs = le32_to_cpu(raw_sb->segment_count_sit) >> 1;
+	bitmap_size = __bitmap_size(sbi, SIT_BITMAP);
+	src_bitmap = __bitmap_ptr(sbi, SIT_BITMAP);
+
+	dst_bitmap = malloc(bitmap_size);
+	memcpy(dst_bitmap, src_bitmap, bitmap_size);
+
+	sit_i->sit_base_addr = le32_to_cpu(raw_sb->sit_blkaddr);
+	sit_i->sit_blocks = sit_segs << sbi->log_blocks_per_seg;
+	sit_i->written_valid_blocks = le64_to_cpu(ckpt->valid_block_count);
+	sit_i->sit_bitmap = dst_bitmap;
+	sit_i->bitmap_size = bitmap_size;
+	sit_i->dirty_sentries = 0;
+	sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK;
+	sit_i->elapsed_time = le64_to_cpu(ckpt->elapsed_time);
+	return 0;
+}
+
+void reset_curseg(struct f2fs_sb_info *sbi, int type)
+{
+	struct curseg_info *curseg = CURSEG_I(sbi, type);
+	struct summary_footer *sum_footer;
+	struct seg_entry *se;
+
+	sum_footer = &(curseg->sum_blk->footer);
+	memset(sum_footer, 0, sizeof(struct summary_footer));
+	if (IS_DATASEG(type))
+		SET_SUM_TYPE(sum_footer, SUM_TYPE_DATA);
+	if (IS_NODESEG(type))
+		SET_SUM_TYPE(sum_footer, SUM_TYPE_NODE);
+	se = get_seg_entry(sbi, curseg->segno);
+	se->type = type;
+}
+
+static void read_compacted_summaries(struct f2fs_sb_info *sbi)
+{
+	struct curseg_info *curseg;
+	unsigned int i, j, offset;
+	block_t start;
+	char *kaddr;
+	int ret;
+
+	start = start_sum_block(sbi);
+
+	kaddr = (char *)malloc(PAGE_SIZE);
+	ret = dev_read_block(kaddr, start++);
+	ASSERT(ret >= 0);
+
+	curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
+	memcpy(&curseg->sum_blk->n_nats, kaddr, SUM_JOURNAL_SIZE);
+
+	curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
+	memcpy(&curseg->sum_blk->n_sits, kaddr + SUM_JOURNAL_SIZE,
+						SUM_JOURNAL_SIZE);
+
+	offset = 2 * SUM_JOURNAL_SIZE;
+	for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
+		unsigned short blk_off;
+		struct curseg_info *curseg = CURSEG_I(sbi, i);
+
+		reset_curseg(sbi, i);
+
+		if (curseg->alloc_type == SSR)
+			blk_off = sbi->blocks_per_seg;
+		else
+			blk_off = curseg->next_blkoff;
+
+		for (j = 0; j < blk_off; j++) {
+			struct f2fs_summary *s;
+			s = (struct f2fs_summary *)(kaddr + offset);
+			curseg->sum_blk->entries[j] = *s;
+			offset += SUMMARY_SIZE;
+			if (offset + SUMMARY_SIZE <=
+					PAGE_CACHE_SIZE - SUM_FOOTER_SIZE)
+				continue;
+			memset(kaddr, 0, PAGE_SIZE);
+			ret = dev_read_block(kaddr, start++);
+			ASSERT(ret >= 0);
+			offset = 0;
+		}
+	}
+	free(kaddr);
+}
+
+static void restore_node_summary(struct f2fs_sb_info *sbi,
+		unsigned int segno, struct f2fs_summary_block *sum_blk)
+{
+	struct f2fs_node *node_blk;
+	struct f2fs_summary *sum_entry;
+	block_t addr;
+	unsigned int i;
+	int ret;
+
+	node_blk = malloc(F2FS_BLKSIZE);
+	ASSERT(node_blk);
+
+	/* scan the node segment */
+	addr = START_BLOCK(sbi, segno);
+	sum_entry = &sum_blk->entries[0];
+
+	for (i = 0; i < sbi->blocks_per_seg; i++, sum_entry++) {
+		ret = dev_read_block(node_blk, addr);
+		ASSERT(ret >= 0);
+		sum_entry->nid = node_blk->footer.nid;
+		addr++;
+	}
+	free(node_blk);
+}
+
+static void read_normal_summaries(struct f2fs_sb_info *sbi, int type)
+{
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	struct f2fs_summary_block *sum_blk;
+	struct curseg_info *curseg;
+	unsigned int segno = 0;
+	block_t blk_addr = 0;
+	int ret;
+
+	if (IS_DATASEG(type)) {
+		segno = le32_to_cpu(ckpt->cur_data_segno[type]);
+		if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG))
+			blk_addr = sum_blk_addr(sbi, NR_CURSEG_TYPE, type);
+		else
+			blk_addr = sum_blk_addr(sbi, NR_CURSEG_DATA_TYPE, type);
+	} else {
+		segno = le32_to_cpu(ckpt->cur_node_segno[type -
+							CURSEG_HOT_NODE]);
+		if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG))
+			blk_addr = sum_blk_addr(sbi, NR_CURSEG_NODE_TYPE,
+							type - CURSEG_HOT_NODE);
+		else
+			blk_addr = GET_SUM_BLKADDR(sbi, segno);
+	}
+
+	sum_blk = (struct f2fs_summary_block *)malloc(PAGE_SIZE);
+	ret = dev_read_block(sum_blk, blk_addr);
+	ASSERT(ret >= 0);
+
+	if (IS_NODESEG(type) && !is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG))
+		restore_node_summary(sbi, segno, sum_blk);
+
+	curseg = CURSEG_I(sbi, type);
+	memcpy(curseg->sum_blk, sum_blk, PAGE_CACHE_SIZE);
+	reset_curseg(sbi, type);
+	free(sum_blk);
+}
+
+static void restore_curseg_summaries(struct f2fs_sb_info *sbi)
+{
+	int type = CURSEG_HOT_DATA;
+
+	if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_COMPACT_SUM_FLAG)) {
+		read_compacted_summaries(sbi);
+		type = CURSEG_HOT_NODE;
+	}
+
+	for (; type <= CURSEG_COLD_NODE; type++)
+		read_normal_summaries(sbi, type);
+}
+
+static void build_curseg(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	struct curseg_info *array;
+	unsigned short blk_off;
+	unsigned int segno;
+	int i;
+
+	array = malloc(sizeof(*array) * NR_CURSEG_TYPE);
+	ASSERT(array);
+
+	SM_I(sbi)->curseg_array = array;
+
+	for (i = 0; i < NR_CURSEG_TYPE; i++) {
+		array[i].sum_blk = malloc(PAGE_CACHE_SIZE);
+		ASSERT(array[i].sum_blk);
+		if (i <= CURSEG_COLD_DATA) {
+			blk_off = le16_to_cpu(ckpt->cur_data_blkoff[i]);
+			segno = le32_to_cpu(ckpt->cur_data_segno[i]);
+		}
+		if (i > CURSEG_COLD_DATA) {
+			blk_off = le16_to_cpu(ckpt->cur_node_blkoff[i -
+							CURSEG_HOT_NODE]);
+			segno = le32_to_cpu(ckpt->cur_node_segno[i -
+							CURSEG_HOT_NODE]);
+		}
+		array[i].segno = segno;
+		array[i].zone = GET_ZONENO_FROM_SEGNO(sbi, segno);
+		array[i].next_segno = NULL_SEGNO;
+		array[i].next_blkoff = blk_off;
+		array[i].alloc_type = ckpt->alloc_type[i];
+	}
+	restore_curseg_summaries(sbi);
+}
+
+inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno)
+{
+	unsigned int end_segno = SM_I(sbi)->segment_count - 1;
+	ASSERT(segno <= end_segno);
+}
+
+static struct f2fs_sit_block *get_current_sit_page(struct f2fs_sb_info *sbi,
+						unsigned int segno)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	unsigned int offset = SIT_BLOCK_OFFSET(sit_i, segno);
+	block_t blk_addr = sit_i->sit_base_addr + offset;
+	struct f2fs_sit_block *sit_blk = calloc(BLOCK_SZ, 1);
+	int ret;
+
+	check_seg_range(sbi, segno);
+
+	/* calculate sit block address */
+	if (f2fs_test_bit(offset, sit_i->sit_bitmap))
+		blk_addr += sit_i->sit_blocks;
+
+	ret = dev_read_block(sit_blk, blk_addr);
+	ASSERT(ret >= 0);
+
+	return sit_blk;
+}
+
+void rewrite_current_sit_page(struct f2fs_sb_info *sbi,
+			unsigned int segno, struct f2fs_sit_block *sit_blk)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	unsigned int offset = SIT_BLOCK_OFFSET(sit_i, segno);
+	block_t blk_addr = sit_i->sit_base_addr + offset;
+	int ret;
+
+	/* calculate sit block address */
+	if (f2fs_test_bit(offset, sit_i->sit_bitmap))
+		blk_addr += sit_i->sit_blocks;
+
+	ret = dev_write_block(sit_blk, blk_addr);
+	ASSERT(ret >= 0);
+}
+
+void check_block_count(struct f2fs_sb_info *sbi,
+		unsigned int segno, struct f2fs_sit_entry *raw_sit)
+{
+	struct f2fs_sm_info *sm_info = SM_I(sbi);
+	unsigned int end_segno = sm_info->segment_count - 1;
+	int valid_blocks = 0;
+	unsigned int i;
+
+	/* check segment usage */
+	if (GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg)
+		ASSERT_MSG("Invalid SIT vblocks: segno=0x%x, %u",
+				segno, GET_SIT_VBLOCKS(raw_sit));
+
+	/* check boundary of a given segment number */
+	if (segno > end_segno)
+		ASSERT_MSG("Invalid SEGNO: 0x%x", segno);
+
+	/* check bitmap with valid block count */
+	for (i = 0; i < SIT_VBLOCK_MAP_SIZE; i++)
+		valid_blocks += get_bits_in_byte(raw_sit->valid_map[i]);
+
+	if (GET_SIT_VBLOCKS(raw_sit) != valid_blocks)
+		ASSERT_MSG("Wrong SIT valid blocks: segno=0x%x, %u vs. %u",
+				segno, GET_SIT_VBLOCKS(raw_sit), valid_blocks);
+
+	if (GET_SIT_TYPE(raw_sit) >= NO_CHECK_TYPE)
+		ASSERT_MSG("Wrong SIT type: segno=0x%x, %u",
+				segno, GET_SIT_TYPE(raw_sit));
+}
+
+void seg_info_from_raw_sit(struct seg_entry *se,
+		struct f2fs_sit_entry *raw_sit)
+{
+	se->valid_blocks = GET_SIT_VBLOCKS(raw_sit);
+	se->ckpt_valid_blocks = GET_SIT_VBLOCKS(raw_sit);
+	memcpy(se->cur_valid_map, raw_sit->valid_map, SIT_VBLOCK_MAP_SIZE);
+	memcpy(se->ckpt_valid_map, raw_sit->valid_map, SIT_VBLOCK_MAP_SIZE);
+	se->type = GET_SIT_TYPE(raw_sit);
+	se->orig_type = GET_SIT_TYPE(raw_sit);
+	se->mtime = le64_to_cpu(raw_sit->mtime);
+}
+
+struct seg_entry *get_seg_entry(struct f2fs_sb_info *sbi,
+		unsigned int segno)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	return &sit_i->sentries[segno];
+}
+
+int get_sum_block(struct f2fs_sb_info *sbi, unsigned int segno,
+				struct f2fs_summary_block *sum_blk)
+{
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	struct curseg_info *curseg;
+	int type, ret;
+	u64 ssa_blk;
+
+	ssa_blk = GET_SUM_BLKADDR(sbi, segno);
+	for (type = 0; type < NR_CURSEG_NODE_TYPE; type++) {
+		if (segno == ckpt->cur_node_segno[type]) {
+			curseg = CURSEG_I(sbi, CURSEG_HOT_NODE + type);
+			if (!IS_SUM_NODE_SEG(curseg->sum_blk->footer)) {
+				ASSERT_MSG("segno [0x%x] indicates a data "
+						"segment, but should be node",
+						segno);
+				return -EINVAL;
+			}
+			memcpy(sum_blk, curseg->sum_blk, BLOCK_SZ);
+			return SEG_TYPE_CUR_NODE;
+		}
+	}
+
+	for (type = 0; type < NR_CURSEG_DATA_TYPE; type++) {
+		if (segno == ckpt->cur_data_segno[type]) {
+			curseg = CURSEG_I(sbi, type);
+			if (IS_SUM_NODE_SEG(curseg->sum_blk->footer)) {
+				ASSERT_MSG("segno [0x%x] indicates a node "
+						"segment, but should be data",
+						segno);
+				return -EINVAL;
+			}
+			DBG(2, "segno [0x%x] is current data seg[0x%x]\n",
+								segno, type);
+			memcpy(sum_blk, curseg->sum_blk, BLOCK_SZ);
+			return SEG_TYPE_CUR_DATA;
+		}
+	}
+
+	ret = dev_read_block(sum_blk, ssa_blk);
+	ASSERT(ret >= 0);
+
+	if (IS_SUM_NODE_SEG(sum_blk->footer))
+		return SEG_TYPE_NODE;
+	else
+		return SEG_TYPE_DATA;
+
+}
+
+int get_sum_entry(struct f2fs_sb_info *sbi, u32 blk_addr,
+				struct f2fs_summary *sum_entry)
+{
+	struct f2fs_summary_block *sum_blk;
+	u32 segno, offset;
+	int ret;
+
+	segno = GET_SEGNO(sbi, blk_addr);
+	offset = OFFSET_IN_SEG(sbi, blk_addr);
+
+	sum_blk = calloc(BLOCK_SZ, 1);
+
+	ret = get_sum_block(sbi, segno, sum_blk);
+	memcpy(sum_entry, &(sum_blk->entries[offset]),
+				sizeof(struct f2fs_summary));
+	free(sum_blk);
+	return ret;
+}
+
+static void get_nat_entry(struct f2fs_sb_info *sbi, nid_t nid,
+				struct f2fs_nat_entry *raw_nat)
+{
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	struct f2fs_nat_block *nat_block;
+	pgoff_t block_off;
+	pgoff_t block_addr;
+	int seg_off, entry_off;
+	int ret;
+
+	if (lookup_nat_in_journal(sbi, nid, raw_nat) >= 0)
+		return;
+
+	nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1);
+
+	block_off = nid / NAT_ENTRY_PER_BLOCK;
+	entry_off = nid % NAT_ENTRY_PER_BLOCK;
+
+	seg_off = block_off >> sbi->log_blocks_per_seg;
+	block_addr = (pgoff_t)(nm_i->nat_blkaddr +
+			(seg_off << sbi->log_blocks_per_seg << 1) +
+			(block_off & ((1 << sbi->log_blocks_per_seg) - 1)));
+
+	if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
+		block_addr += sbi->blocks_per_seg;
+
+	ret = dev_read_block(nat_block, block_addr);
+	ASSERT(ret >= 0);
+
+	memcpy(raw_nat, &nat_block->entries[entry_off],
+					sizeof(struct f2fs_nat_entry));
+	free(nat_block);
+}
+
+void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni)
+{
+	struct f2fs_nat_entry raw_nat;
+	get_nat_entry(sbi, nid, &raw_nat);
+	ni->nid = nid;
+	node_info_from_raw_nat(ni, &raw_nat);
+}
+
+void build_sit_entries(struct f2fs_sb_info *sbi)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
+	struct f2fs_summary_block *sum = curseg->sum_blk;
+	unsigned int segno;
+
+	for (segno = 0; segno < TOTAL_SEGS(sbi); segno++) {
+		struct seg_entry *se = &sit_i->sentries[segno];
+		struct f2fs_sit_block *sit_blk;
+		struct f2fs_sit_entry sit;
+		int i;
+
+		for (i = 0; i < sits_in_cursum(sum); i++) {
+			if (le32_to_cpu(segno_in_journal(sum, i)) == segno) {
+				sit = sit_in_journal(sum, i);
+				goto got_it;
+			}
+		}
+		sit_blk = get_current_sit_page(sbi, segno);
+		sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, segno)];
+		free(sit_blk);
+got_it:
+		check_block_count(sbi, segno, &sit);
+		seg_info_from_raw_sit(se, &sit);
+	}
+
+}
+
+int build_segment_manager(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	struct f2fs_sm_info *sm_info;
+
+	sm_info = malloc(sizeof(struct f2fs_sm_info));
+	if (!sm_info)
+		return -ENOMEM;
+
+	/* init sm info */
+	sbi->sm_info = sm_info;
+	sm_info->seg0_blkaddr = le32_to_cpu(raw_super->segment0_blkaddr);
+	sm_info->main_blkaddr = le32_to_cpu(raw_super->main_blkaddr);
+	sm_info->segment_count = le32_to_cpu(raw_super->segment_count);
+	sm_info->reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
+	sm_info->ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
+	sm_info->main_segments = le32_to_cpu(raw_super->segment_count_main);
+	sm_info->ssa_blkaddr = le32_to_cpu(raw_super->ssa_blkaddr);
+
+	build_sit_info(sbi);
+
+	build_curseg(sbi);
+
+	build_sit_entries(sbi);
+
+	return 0;
+}
+
+void build_sit_area_bitmap(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	struct f2fs_sm_info *sm_i = SM_I(sbi);
+	unsigned int segno = 0;
+	char *ptr = NULL;
+	u32 sum_vblocks = 0;
+	u32 free_segs = 0;
+	struct seg_entry *se;
+
+	fsck->sit_area_bitmap_sz = sm_i->main_segments * SIT_VBLOCK_MAP_SIZE;
+	fsck->sit_area_bitmap = calloc(1, fsck->sit_area_bitmap_sz);
+	ptr = fsck->sit_area_bitmap;
+
+	ASSERT(fsck->sit_area_bitmap_sz == fsck->main_area_bitmap_sz);
+
+	for (segno = 0; segno < TOTAL_SEGS(sbi); segno++) {
+		se = get_seg_entry(sbi, segno);
+
+		memcpy(ptr, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE);
+		ptr += SIT_VBLOCK_MAP_SIZE;
+
+		if (se->valid_blocks == 0x0) {
+			if (sbi->ckpt->cur_node_segno[0] == segno ||
+					sbi->ckpt->cur_data_segno[0] == segno ||
+					sbi->ckpt->cur_node_segno[1] == segno ||
+					sbi->ckpt->cur_data_segno[1] == segno ||
+					sbi->ckpt->cur_node_segno[2] == segno ||
+					sbi->ckpt->cur_data_segno[2] == segno) {
+				continue;
+			} else {
+				free_segs++;
+			}
+		} else {
+			sum_vblocks += se->valid_blocks;
+		}
+	}
+	fsck->chk.sit_valid_blocks = sum_vblocks;
+	fsck->chk.sit_free_segs = free_segs;
+
+	DBG(1, "Blocks [0x%x : %d] Free Segs [0x%x : %d]\n\n",
+			sum_vblocks, sum_vblocks,
+			free_segs, free_segs);
+}
+
+void rewrite_sit_area_bitmap(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
+	struct sit_info *sit_i = SIT_I(sbi);
+	unsigned int segno = 0;
+	struct f2fs_summary_block *sum = curseg->sum_blk;
+	char *ptr = NULL;
+
+	/* remove sit journal */
+	sum->n_sits = 0;
+
+	fsck->chk.free_segs = 0;
+
+	ptr = fsck->main_area_bitmap;
+
+	for (segno = 0; segno < TOTAL_SEGS(sbi); segno++) {
+		struct f2fs_sit_block *sit_blk;
+		struct f2fs_sit_entry *sit;
+		struct seg_entry *se;
+		u16 valid_blocks = 0;
+		u16 type;
+		int i;
+
+		sit_blk = get_current_sit_page(sbi, segno);
+		sit = &sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, segno)];
+		memcpy(sit->valid_map, ptr, SIT_VBLOCK_MAP_SIZE);
+
+		/* update valid block count */
+		for (i = 0; i < SIT_VBLOCK_MAP_SIZE; i++)
+			valid_blocks += get_bits_in_byte(sit->valid_map[i]);
+
+		se = get_seg_entry(sbi, segno);
+		type = se->type;
+		if (type >= NO_CHECK_TYPE) {
+			ASSERT_MSG("Invalide type and valid blocks=%x,%x",
+					segno, valid_blocks);
+			type = 0;
+		}
+		sit->vblocks = cpu_to_le16((type << SIT_VBLOCKS_SHIFT) |
+								valid_blocks);
+		rewrite_current_sit_page(sbi, segno, sit_blk);
+		free(sit_blk);
+
+		if (valid_blocks == 0 &&
+				sbi->ckpt->cur_node_segno[0] != segno &&
+				sbi->ckpt->cur_data_segno[0] != segno &&
+				sbi->ckpt->cur_node_segno[1] != segno &&
+				sbi->ckpt->cur_data_segno[1] != segno &&
+				sbi->ckpt->cur_node_segno[2] != segno &&
+				sbi->ckpt->cur_data_segno[2] != segno)
+			fsck->chk.free_segs++;
+
+		ptr += SIT_VBLOCK_MAP_SIZE;
+	}
+}
+
+int lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid,
+					struct f2fs_nat_entry *raw_nat)
+{
+	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
+	struct f2fs_summary_block *sum = curseg->sum_blk;
+	int i = 0;
+
+	for (i = 0; i < nats_in_cursum(sum); i++) {
+		if (le32_to_cpu(nid_in_journal(sum, i)) == nid) {
+			memcpy(raw_nat, &nat_in_journal(sum, i),
+						sizeof(struct f2fs_nat_entry));
+			DBG(3, "==> Found nid [0x%x] in nat cache\n", nid);
+			return i;
+		}
+	}
+	return -1;
+}
+
+void nullify_nat_entry(struct f2fs_sb_info *sbi, u32 nid)
+{
+	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
+	struct f2fs_summary_block *sum = curseg->sum_blk;
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	struct f2fs_nat_block *nat_block;
+	pgoff_t block_off;
+	pgoff_t block_addr;
+	int seg_off, entry_off;
+	int ret;
+	int i = 0;
+
+	/* check in journal */
+	for (i = 0; i < nats_in_cursum(sum); i++) {
+		if (le32_to_cpu(nid_in_journal(sum, i)) == nid) {
+			memset(&nat_in_journal(sum, i), 0,
+					sizeof(struct f2fs_nat_entry));
+			FIX_MSG("Remove nid [0x%x] in nat journal\n", nid);
+			return;
+		}
+	}
+	nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1);
+
+	block_off = nid / NAT_ENTRY_PER_BLOCK;
+	entry_off = nid % NAT_ENTRY_PER_BLOCK;
+
+	seg_off = block_off >> sbi->log_blocks_per_seg;
+	block_addr = (pgoff_t)(nm_i->nat_blkaddr +
+			(seg_off << sbi->log_blocks_per_seg << 1) +
+			(block_off & ((1 << sbi->log_blocks_per_seg) - 1)));
+
+	if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
+		block_addr += sbi->blocks_per_seg;
+
+	ret = dev_read_block(nat_block, block_addr);
+	ASSERT(ret >= 0);
+
+	memset(&nat_block->entries[entry_off], 0,
+					sizeof(struct f2fs_nat_entry));
+
+	ret = dev_write_block(nat_block, block_addr);
+	ASSERT(ret >= 0);
+	free(nat_block);
+}
+
+void build_nat_area_bitmap(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	struct f2fs_super_block *raw_sb = F2FS_RAW_SUPER(sbi);
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	struct f2fs_nat_block *nat_block;
+	u32 nid, nr_nat_blks;
+	pgoff_t block_off;
+	pgoff_t block_addr;
+	int seg_off;
+	int ret;
+	unsigned int i;
+
+	nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1);
+	ASSERT(nat_block);
+
+	/* Alloc & build nat entry bitmap */
+	nr_nat_blks = (le32_to_cpu(raw_sb->segment_count_nat) / 2) <<
+						sbi->log_blocks_per_seg;
+
+	fsck->nr_nat_entries = nr_nat_blks * NAT_ENTRY_PER_BLOCK;
+	fsck->nat_area_bitmap_sz = (fsck->nr_nat_entries + 7) / 8;
+	fsck->nat_area_bitmap = calloc(fsck->nat_area_bitmap_sz, 1);
+	ASSERT(fsck->nat_area_bitmap != NULL);
+
+	for (block_off = 0; block_off < nr_nat_blks; block_off++) {
+
+		seg_off = block_off >> sbi->log_blocks_per_seg;
+		block_addr = (pgoff_t)(nm_i->nat_blkaddr +
+			(seg_off << sbi->log_blocks_per_seg << 1) +
+			(block_off & ((1 << sbi->log_blocks_per_seg) - 1)));
+
+		if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
+			block_addr += sbi->blocks_per_seg;
+
+		ret = dev_read_block(nat_block, block_addr);
+		ASSERT(ret >= 0);
+
+		nid = block_off * NAT_ENTRY_PER_BLOCK;
+		for (i = 0; i < NAT_ENTRY_PER_BLOCK; i++) {
+			struct f2fs_nat_entry raw_nat;
+			struct node_info ni;
+			ni.nid = nid + i;
+
+			if ((nid + i) == F2FS_NODE_INO(sbi) ||
+					(nid + i) == F2FS_META_INO(sbi)) {
+				ASSERT(nat_block->entries[i].block_addr != 0x0);
+				continue;
+			}
+
+			if (lookup_nat_in_journal(sbi, nid + i,
+							&raw_nat) >= 0) {
+				node_info_from_raw_nat(&ni, &raw_nat);
+				if (ni.blk_addr != 0x0) {
+					f2fs_set_bit(nid + i,
+							fsck->nat_area_bitmap);
+					fsck->chk.valid_nat_entry_cnt++;
+					DBG(3, "nid[0x%x] in nat cache\n",
+								nid + i);
+				}
+			} else {
+				node_info_from_raw_nat(&ni,
+						&nat_block->entries[i]);
+				if (ni.blk_addr == 0)
+					continue;
+				ASSERT(nid + i != 0x0);
+
+				DBG(3, "nid[0x%8x] addr[0x%16x] ino[0x%8x]\n",
+					nid + i, ni.blk_addr, ni.ino);
+				f2fs_set_bit(nid + i, fsck->nat_area_bitmap);
+				fsck->chk.valid_nat_entry_cnt++;
+			}
+		}
+	}
+	free(nat_block);
+
+	DBG(1, "valid nat entries (block_addr != 0x0) [0x%8x : %u]\n",
+			fsck->chk.valid_nat_entry_cnt,
+			fsck->chk.valid_nat_entry_cnt);
+}
+
+int f2fs_do_mount(struct f2fs_sb_info *sbi)
+{
+	int ret;
+
+	sbi->active_logs = NR_CURSEG_TYPE;
+	ret = validate_super_block(sbi, 0);
+	if (ret) {
+		ret = validate_super_block(sbi, 1);
+		if (ret)
+			return -1;
+	}
+
+	print_raw_sb_info(sbi);
+
+	init_sb_info(sbi);
+
+	ret = get_valid_checkpoint(sbi);
+	if (ret) {
+		ERR_MSG("Can't find valid checkpoint\n");
+		return -1;
+	}
+
+	if (sanity_check_ckpt(sbi)) {
+		ERR_MSG("Checkpoint is polluted\n");
+		return -1;
+	}
+
+	print_ckpt_info(sbi);
+
+	if (config.auto_fix) {
+		u32 flag = le32_to_cpu(sbi->ckpt->ckpt_flags);
+
+		if (flag & CP_FSCK_FLAG)
+			config.fix_on = 1;
+		else
+			return 1;
+	}
+
+	config.bug_on = 0;
+
+	sbi->total_valid_node_count = le32_to_cpu(sbi->ckpt->valid_node_count);
+	sbi->total_valid_inode_count =
+			le32_to_cpu(sbi->ckpt->valid_inode_count);
+	sbi->user_block_count = le64_to_cpu(sbi->ckpt->user_block_count);
+	sbi->total_valid_block_count =
+			le64_to_cpu(sbi->ckpt->valid_block_count);
+	sbi->last_valid_block_count = sbi->total_valid_block_count;
+	sbi->alloc_valid_block_count = 0;
+
+	if (build_segment_manager(sbi)) {
+		ERR_MSG("build_segment_manager failed\n");
+		return -1;
+	}
+
+	if (build_node_manager(sbi)) {
+		ERR_MSG("build_segment_manager failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+void f2fs_do_umount(struct f2fs_sb_info *sbi)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	struct f2fs_sm_info *sm_i = SM_I(sbi);
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	unsigned int i;
+
+	/* free nm_info */
+	free(nm_i->nat_bitmap);
+	free(sbi->nm_info);
+
+	/* free sit_info */
+	for (i = 0; i < TOTAL_SEGS(sbi); i++) {
+		free(sit_i->sentries[i].cur_valid_map);
+		free(sit_i->sentries[i].ckpt_valid_map);
+	}
+	free(sit_i->sit_bitmap);
+	free(sm_i->sit_info);
+
+	/* free sm_info */
+	for (i = 0; i < NR_CURSEG_TYPE; i++)
+		free(sm_i->curseg_array[i].sum_blk);
+
+	free(sm_i->curseg_array);
+	free(sbi->sm_info);
+
+	free(sbi->ckpt);
+	free(sbi->raw_super);
+}
diff --git a/f2fs-tools/include/f2fs_fs.h b/f2fs-tools/include/f2fs_fs.h
new file mode 100644
index 0000000..6ce58c2
--- /dev/null
+++ b/f2fs-tools/include/f2fs_fs.h
@@ -0,0 +1,797 @@
+/**
+ * f2fs_fs.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Dual licensed under the GPL or LGPL version 2 licenses.
+ *
+ * The byteswap codes are copied from:
+ *   samba_3_master/lib/ccan/endian/endian.h under LGPL 2.1
+ */
+#ifndef __F2FS_FS_H__
+#define __F2FS_FS_H__
+
+#include <inttypes.h>
+#include <linux/types.h>
+#include <sys/types.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+typedef u_int64_t	u64;
+typedef u_int32_t	u32;
+typedef u_int16_t	u16;
+typedef u_int8_t	u8;
+typedef u32		block_t;
+typedef u32		nid_t;
+typedef u8		bool;
+typedef unsigned long	pgoff_t;
+
+#if HAVE_BYTESWAP_H
+#include <byteswap.h>
+#else
+/**
+ * bswap_16 - reverse bytes in a uint16_t value.
+ * @val: value whose bytes to swap.
+ *
+ * Example:
+ *	// Output contains "1024 is 4 as two bytes reversed"
+ *	printf("1024 is %u as two bytes reversed\n", bswap_16(1024));
+ */
+static inline uint16_t bswap_16(uint16_t val)
+{
+	return ((val & (uint16_t)0x00ffU) << 8)
+		| ((val & (uint16_t)0xff00U) >> 8);
+}
+
+/**
+ * bswap_32 - reverse bytes in a uint32_t value.
+ * @val: value whose bytes to swap.
+ *
+ * Example:
+ *	// Output contains "1024 is 262144 as four bytes reversed"
+ *	printf("1024 is %u as four bytes reversed\n", bswap_32(1024));
+ */
+static inline uint32_t bswap_32(uint32_t val)
+{
+	return ((val & (uint32_t)0x000000ffUL) << 24)
+		| ((val & (uint32_t)0x0000ff00UL) <<  8)
+		| ((val & (uint32_t)0x00ff0000UL) >>  8)
+		| ((val & (uint32_t)0xff000000UL) >> 24);
+}
+#endif /* !HAVE_BYTESWAP_H */
+
+#if defined HAVE_DECL_BSWAP_64 && !HAVE_DECL_BSWAP_64
+/**
+ * bswap_64 - reverse bytes in a uint64_t value.
+ * @val: value whose bytes to swap.
+ *
+ * Example:
+ *	// Output contains "1024 is 1125899906842624 as eight bytes reversed"
+ *	printf("1024 is %llu as eight bytes reversed\n",
+ *		(unsigned long long)bswap_64(1024));
+ */
+static inline uint64_t bswap_64(uint64_t val)
+{
+	return ((val & (uint64_t)0x00000000000000ffULL) << 56)
+		| ((val & (uint64_t)0x000000000000ff00ULL) << 40)
+		| ((val & (uint64_t)0x0000000000ff0000ULL) << 24)
+		| ((val & (uint64_t)0x00000000ff000000ULL) <<  8)
+		| ((val & (uint64_t)0x000000ff00000000ULL) >>  8)
+		| ((val & (uint64_t)0x0000ff0000000000ULL) >> 24)
+		| ((val & (uint64_t)0x00ff000000000000ULL) >> 40)
+		| ((val & (uint64_t)0xff00000000000000ULL) >> 56);
+}
+#endif
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define le16_to_cpu(x)	((__u16)(x))
+#define le32_to_cpu(x)	((__u32)(x))
+#define le64_to_cpu(x)	((__u64)(x))
+#define cpu_to_le16(x)	((__u16)(x))
+#define cpu_to_le32(x)	((__u32)(x))
+#define cpu_to_le64(x)	((__u64)(x))
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define le16_to_cpu(x)	bswap_16(x)
+#define le32_to_cpu(x)	bswap_32(x)
+#define le64_to_cpu(x)	bswap_64(x)
+#define cpu_to_le16(x)	bswap_16(x)
+#define cpu_to_le32(x)	bswap_32(x)
+#define cpu_to_le64(x)	bswap_64(x)
+#endif
+
+#define typecheck(type,x) \
+	({	type __dummy; \
+		typeof(x) __dummy2; \
+		(void)(&__dummy == &__dummy2); \
+		1; \
+	 })
+
+#define NULL_SEGNO	((unsigned int)~0)
+
+/*
+ * Debugging interfaces
+ */
+#define FIX_MSG(fmt, ...)						\
+	do {								\
+		printf("[FIX] (%s:%4d) ", __func__, __LINE__);		\
+		printf(" --> "fmt"\n", ##__VA_ARGS__);			\
+	} while (0)
+
+#define ASSERT_MSG(fmt, ...)						\
+	do {								\
+		printf("[ASSERT] (%s:%4d) ", __func__, __LINE__);	\
+		printf(" --> "fmt"\n", ##__VA_ARGS__);			\
+		config.bug_on = 1;					\
+	} while (0)
+
+#define ASSERT(exp)							\
+	do {								\
+		if (!(exp)) {						\
+			printf("[ASSERT] (%s:%4d) " #exp"\n",		\
+					__func__, __LINE__);		\
+			exit(-1);					\
+		}							\
+	} while (0)
+
+#define ERR_MSG(fmt, ...)						\
+	do {								\
+		printf("[%s:%d] " fmt, __func__, __LINE__, ##__VA_ARGS__); \
+	} while (0)
+
+#define MSG(n, fmt, ...)						\
+	do {								\
+		if (config.dbg_lv >= n) {				\
+			printf(fmt, ##__VA_ARGS__);			\
+		}							\
+	} while (0)
+
+#define DBG(n, fmt, ...)						\
+	do {								\
+		if (config.dbg_lv >= n) {				\
+			printf("[%s:%4d] " fmt,				\
+				__func__, __LINE__, ##__VA_ARGS__);	\
+		}							\
+	} while (0)
+
+/* Display on console */
+#define DISP(fmt, ptr, member)				\
+	do {						\
+		printf("%-30s" fmt, #member, ((ptr)->member));	\
+	} while (0)
+
+#define DISP_u32(ptr, member)						\
+	do {								\
+		assert(sizeof((ptr)->member) <= 4);			\
+		printf("%-30s" "\t\t[0x%8x : %u]\n",		\
+			#member, ((ptr)->member), ((ptr)->member));	\
+	} while (0)
+
+#define DISP_u64(ptr, member)						\
+	do {								\
+		assert(sizeof((ptr)->member) == 8);			\
+		printf("%-30s" "\t\t[0x%8llx : %llu]\n",		\
+			#member, ((ptr)->member), ((ptr)->member));	\
+	} while (0)
+
+#define DISP_utf(ptr, member)						\
+	do {								\
+		printf("%-30s" "\t\t[%s]\n", #member, ((ptr)->member)); \
+	} while (0)
+
+/* Display to buffer */
+#define BUF_DISP_u32(buf, data, len, ptr, member)			\
+	do {								\
+		assert(sizeof((ptr)->member) <= 4);			\
+		snprintf(buf, len, #member);				\
+		snprintf(data, len, "0x%x : %u", ((ptr)->member),	\
+						((ptr)->member));	\
+	} while (0)
+
+#define BUF_DISP_u64(buf, data, len, ptr, member)			\
+	do {								\
+		assert(sizeof((ptr)->member) == 8);			\
+		snprintf(buf, len, #member);				\
+		snprintf(data, len, "0x%llx : %llu", ((ptr)->member),	\
+						((ptr)->member));	\
+	} while (0)
+
+#define BUF_DISP_utf(buf, data, len, ptr, member)			\
+		snprintf(buf, len, #member)
+
+/* these are defined in kernel */
+#define PAGE_SIZE		4096
+#define PAGE_CACHE_SIZE		4096
+#define BITS_PER_BYTE		8
+#define F2FS_SUPER_MAGIC	0xF2F52010	/* F2FS Magic Number */
+#define CHECKSUM_OFFSET		4092
+
+/* for mkfs */
+#define F2FS_MIN_VOLUME_SIZE	104857600
+#define	F2FS_NUMBER_OF_CHECKPOINT_PACK	2
+#define	DEFAULT_SECTOR_SIZE		512
+#define	DEFAULT_SECTORS_PER_BLOCK	8
+#define	DEFAULT_BLOCKS_PER_SEGMENT	512
+#define DEFAULT_SEGMENTS_PER_SECTION	1
+
+#define VERSION_LEN	256
+
+enum f2fs_config_func {
+	FSCK,
+	DUMP,
+};
+
+struct f2fs_configuration {
+	u_int32_t sector_size;
+	u_int32_t reserved_segments;
+	u_int32_t overprovision;
+	u_int32_t cur_seg[6];
+	u_int32_t segs_per_sec;
+	u_int32_t secs_per_zone;
+	u_int32_t segs_per_zone;
+	u_int32_t start_sector;
+	u_int64_t total_sectors;
+	u_int32_t sectors_per_blk;
+	u_int32_t blks_per_seg;
+	__u8 init_version[VERSION_LEN + 1];
+	__u8 sb_version[VERSION_LEN + 1];
+	__u8 version[VERSION_LEN + 1];
+	char *vol_label;
+	int heap;
+	int32_t fd, kd;
+	int32_t dump_fd;
+	char *device_name;
+	char *extension_list;
+	int dbg_lv;
+	int trim;
+	int func;
+	void *private;
+	int fix_on;
+	int bug_on;
+	int auto_fix;
+} __attribute__((packed));
+
+#ifdef CONFIG_64BIT
+#define BITS_PER_LONG	64
+#else
+#define BITS_PER_LONG	32
+#endif
+
+#define BIT_MASK(nr)	(1 << (nr % BITS_PER_LONG))
+#define BIT_WORD(nr)	(nr / BITS_PER_LONG)
+
+/*
+ * Copied from fs/f2fs/f2fs.h
+ */
+#define	NR_CURSEG_DATA_TYPE	(3)
+#define NR_CURSEG_NODE_TYPE	(3)
+#define NR_CURSEG_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
+
+enum {
+	CURSEG_HOT_DATA	= 0,	/* directory entry blocks */
+	CURSEG_WARM_DATA,	/* data blocks */
+	CURSEG_COLD_DATA,	/* multimedia or GCed data blocks */
+	CURSEG_HOT_NODE,	/* direct node blocks of directory files */
+	CURSEG_WARM_NODE,	/* direct node blocks of normal files */
+	CURSEG_COLD_NODE,	/* indirect node blocks */
+	NO_CHECK_TYPE
+};
+
+/*
+ * Copied from fs/f2fs/segment.h
+ */
+#define GET_SUM_TYPE(footer) ((footer)->entry_type)
+#define SET_SUM_TYPE(footer, type) ((footer)->entry_type = type)
+
+/*
+ * Copied from include/linux/f2fs_sb.h
+ */
+#define F2FS_SUPER_OFFSET		1024	/* byte-size offset */
+#define F2FS_MIN_LOG_SECTOR_SIZE	9	/* 9 bits for 512 bytes */
+#define F2FS_MAX_LOG_SECTOR_SIZE	12	/* 12 bits for 4096 bytes */
+#define F2FS_BLKSIZE			4096	/* support only 4KB block */
+#define F2FS_MAX_EXTENSION		64	/* # of extension entries */
+#define F2FS_BLK_ALIGN(x)	(((x) + F2FS_BLKSIZE - 1) / F2FS_BLKSIZE)
+
+#define NULL_ADDR		0x0U
+#define NEW_ADDR		-1U
+
+#define F2FS_ROOT_INO(sbi)	(sbi->root_ino_num)
+#define F2FS_NODE_INO(sbi)	(sbi->node_ino_num)
+#define F2FS_META_INO(sbi)	(sbi->meta_ino_num)
+
+/* This flag is used by node and meta inodes, and by recovery */
+#define GFP_F2FS_ZERO	(GFP_NOFS | __GFP_ZERO)
+
+/*
+ * For further optimization on multi-head logs, on-disk layout supports maximum
+ * 16 logs by default. The number, 16, is expected to cover all the cases
+ * enoughly. The implementaion currently uses no more than 6 logs.
+ * Half the logs are used for nodes, and the other half are used for data.
+ */
+#define MAX_ACTIVE_LOGS	16
+#define MAX_ACTIVE_NODE_LOGS	8
+#define MAX_ACTIVE_DATA_LOGS	8
+
+/*
+ * For superblock
+ */
+struct f2fs_super_block {
+	__le32 magic;			/* Magic Number */
+	__le16 major_ver;		/* Major Version */
+	__le16 minor_ver;		/* Minor Version */
+	__le32 log_sectorsize;		/* log2 sector size in bytes */
+	__le32 log_sectors_per_block;	/* log2 # of sectors per block */
+	__le32 log_blocksize;		/* log2 block size in bytes */
+	__le32 log_blocks_per_seg;	/* log2 # of blocks per segment */
+	__le32 segs_per_sec;		/* # of segments per section */
+	__le32 secs_per_zone;		/* # of sections per zone */
+	__le32 checksum_offset;		/* checksum offset inside super block */
+	__le64 block_count;		/* total # of user blocks */
+	__le32 section_count;		/* total # of sections */
+	__le32 segment_count;		/* total # of segments */
+	__le32 segment_count_ckpt;	/* # of segments for checkpoint */
+	__le32 segment_count_sit;	/* # of segments for SIT */
+	__le32 segment_count_nat;	/* # of segments for NAT */
+	__le32 segment_count_ssa;	/* # of segments for SSA */
+	__le32 segment_count_main;	/* # of segments for main area */
+	__le32 segment0_blkaddr;	/* start block address of segment 0 */
+	__le32 cp_blkaddr;		/* start block address of checkpoint */
+	__le32 sit_blkaddr;		/* start block address of SIT */
+	__le32 nat_blkaddr;		/* start block address of NAT */
+	__le32 ssa_blkaddr;		/* start block address of SSA */
+	__le32 main_blkaddr;		/* start block address of main area */
+	__le32 root_ino;		/* root inode number */
+	__le32 node_ino;		/* node inode number */
+	__le32 meta_ino;		/* meta inode number */
+	__u8 uuid[16];			/* 128-bit uuid for volume */
+	__le16 volume_name[512];	/* volume name */
+	__le32 extension_count;		/* # of extensions below */
+	__u8 extension_list[F2FS_MAX_EXTENSION][8];	/* extension array */
+	__le32 cp_payload;
+	__u8 version[VERSION_LEN];	/* the kernel version */
+	__u8 init_version[VERSION_LEN];	/* the initial kernel version */
+} __attribute__((packed));
+
+/*
+ * For checkpoint
+ */
+#define CP_FASTBOOT_FLAG	0x00000020
+#define CP_FSCK_FLAG		0x00000010
+#define CP_ERROR_FLAG		0x00000008
+#define CP_COMPACT_SUM_FLAG	0x00000004
+#define CP_ORPHAN_PRESENT_FLAG	0x00000002
+#define CP_UMOUNT_FLAG		0x00000001
+
+struct f2fs_checkpoint {
+	__le64 checkpoint_ver;		/* checkpoint block version number */
+	__le64 user_block_count;	/* # of user blocks */
+	__le64 valid_block_count;	/* # of valid blocks in main area */
+	__le32 rsvd_segment_count;	/* # of reserved segments for gc */
+	__le32 overprov_segment_count;	/* # of overprovision segments */
+	__le32 free_segment_count;	/* # of free segments in main area */
+
+	/* information of current node segments */
+	__le32 cur_node_segno[MAX_ACTIVE_NODE_LOGS];
+	__le16 cur_node_blkoff[MAX_ACTIVE_NODE_LOGS];
+	/* information of current data segments */
+	__le32 cur_data_segno[MAX_ACTIVE_DATA_LOGS];
+	__le16 cur_data_blkoff[MAX_ACTIVE_DATA_LOGS];
+	__le32 ckpt_flags;		/* Flags : umount and journal_present */
+	__le32 cp_pack_total_block_count;	/* total # of one cp pack */
+	__le32 cp_pack_start_sum;	/* start block number of data summary */
+	__le32 valid_node_count;	/* Total number of valid nodes */
+	__le32 valid_inode_count;	/* Total number of valid inodes */
+	__le32 next_free_nid;		/* Next free node number */
+	__le32 sit_ver_bitmap_bytesize;	/* Default value 64 */
+	__le32 nat_ver_bitmap_bytesize; /* Default value 256 */
+	__le32 checksum_offset;		/* checksum offset inside cp block */
+	__le64 elapsed_time;		/* mounted time */
+	/* allocation type of current segment */
+	unsigned char alloc_type[MAX_ACTIVE_LOGS];
+
+	/* SIT and NAT version bitmap */
+	unsigned char sit_nat_version_bitmap[1];
+} __attribute__((packed));
+
+/*
+ * For orphan inode management
+ */
+#define F2FS_ORPHANS_PER_BLOCK	1020
+
+struct f2fs_orphan_block {
+	__le32 ino[F2FS_ORPHANS_PER_BLOCK];	/* inode numbers */
+	__le32 reserved;	/* reserved */
+	__le16 blk_addr;	/* block index in current CP */
+	__le16 blk_count;	/* Number of orphan inode blocks in CP */
+	__le32 entry_count;	/* Total number of orphan nodes in current CP */
+	__le32 check_sum;	/* CRC32 for orphan inode block */
+} __attribute__((packed));
+
+/*
+ * For NODE structure
+ */
+struct f2fs_extent {
+	__le32 fofs;		/* start file offset of the extent */
+	__le32 blk_addr;	/* start block address of the extent */
+	__le32 len;		/* lengh of the extent */
+} __attribute__((packed));
+
+#define F2FS_NAME_LEN		255
+#define F2FS_INLINE_XATTR_ADDRS	50	/* 200 bytes for inline xattrs */
+#define DEF_ADDRS_PER_INODE	923	/* Address Pointers in an Inode */
+#define ADDRS_PER_INODE(fi)	addrs_per_inode(fi)
+#define ADDRS_PER_BLOCK         1018	/* Address Pointers in a Direct Block */
+#define NIDS_PER_BLOCK          1018	/* Node IDs in an Indirect Block */
+
+#define	NODE_DIR1_BLOCK		(DEF_ADDRS_PER_INODE + 1)
+#define	NODE_DIR2_BLOCK		(DEF_ADDRS_PER_INODE + 2)
+#define	NODE_IND1_BLOCK		(DEF_ADDRS_PER_INODE + 3)
+#define	NODE_IND2_BLOCK		(DEF_ADDRS_PER_INODE + 4)
+#define	NODE_DIND_BLOCK		(DEF_ADDRS_PER_INODE + 5)
+
+#define F2FS_INLINE_XATTR	0x01	/* file inline xattr flag */
+#define F2FS_INLINE_DATA	0x02	/* file inline data flag */
+#define F2FS_INLINE_DENTRY	0x04	/* file inline dentry flag */
+#define F2FS_DATA_EXIST		0x08	/* file inline data exist flag */
+
+#define MAX_INLINE_DATA		(sizeof(__le32) * (DEF_ADDRS_PER_INODE - \
+						F2FS_INLINE_XATTR_ADDRS - 1))
+
+#define INLINE_DATA_OFFSET	(PAGE_CACHE_SIZE - sizeof(struct node_footer) \
+				- sizeof(__le32)*(DEF_ADDRS_PER_INODE + 5 - 1))
+
+#define DEF_DIR_LEVEL		0
+
+struct f2fs_inode {
+	__le16 i_mode;			/* file mode */
+	__u8 i_advise;			/* file hints */
+	__u8 i_inline;			/* file inline flags */
+	__le32 i_uid;			/* user ID */
+	__le32 i_gid;			/* group ID */
+	__le32 i_links;			/* links count */
+	__le64 i_size;			/* file size in bytes */
+	__le64 i_blocks;		/* file size in blocks */
+	__le64 i_atime;			/* access time */
+	__le64 i_ctime;			/* change time */
+	__le64 i_mtime;			/* modification time */
+	__le32 i_atime_nsec;		/* access time in nano scale */
+	__le32 i_ctime_nsec;		/* change time in nano scale */
+	__le32 i_mtime_nsec;		/* modification time in nano scale */
+	__le32 i_generation;		/* file version (for NFS) */
+	__le32 i_current_depth;		/* only for directory depth */
+	__le32 i_xattr_nid;		/* nid to save xattr */
+	__le32 i_flags;			/* file attributes */
+	__le32 i_pino;			/* parent inode number */
+	__le32 i_namelen;		/* file name length */
+	__u8 i_name[F2FS_NAME_LEN];	/* file name for SPOR */
+	__u8 i_dir_level;		/* dentry_level for large dir */
+
+	struct f2fs_extent i_ext;	/* caching a largest extent */
+
+	__le32 i_addr[DEF_ADDRS_PER_INODE];	/* Pointers to data blocks */
+
+	__le32 i_nid[5];		/* direct(2), indirect(2),
+						double_indirect(1) node id */
+} __attribute__((packed));
+
+struct direct_node {
+	__le32 addr[ADDRS_PER_BLOCK];	/* array of data block address */
+} __attribute__((packed));
+
+struct indirect_node {
+	__le32 nid[NIDS_PER_BLOCK];	/* array of data block address */
+} __attribute__((packed));
+
+enum {
+	COLD_BIT_SHIFT = 0,
+	FSYNC_BIT_SHIFT,
+	DENT_BIT_SHIFT,
+	OFFSET_BIT_SHIFT
+};
+
+#define XATTR_NODE_OFFSET	((((unsigned int)-1) << OFFSET_BIT_SHIFT) \
+				>> OFFSET_BIT_SHIFT)
+
+struct node_footer {
+	__le32 nid;		/* node id */
+	__le32 ino;		/* inode nunmber */
+	__le32 flag;		/* include cold/fsync/dentry marks and offset */
+	__le64 cp_ver;		/* checkpoint version */
+	__le32 next_blkaddr;	/* next node page block address */
+} __attribute__((packed));
+
+struct f2fs_node {
+	/* can be one of three types: inode, direct, and indirect types */
+	union {
+		struct f2fs_inode i;
+		struct direct_node dn;
+		struct indirect_node in;
+	};
+	struct node_footer footer;
+} __attribute__((packed));
+
+/*
+ * For NAT entries
+ */
+#define NAT_ENTRY_PER_BLOCK (PAGE_CACHE_SIZE / sizeof(struct f2fs_nat_entry))
+
+struct f2fs_nat_entry {
+	__u8 version;		/* latest version of cached nat entry */
+	__le32 ino;		/* inode number */
+	__le32 block_addr;	/* block address */
+} __attribute__((packed));
+
+struct f2fs_nat_block {
+	struct f2fs_nat_entry entries[NAT_ENTRY_PER_BLOCK];
+} __attribute__((packed));
+
+/*
+ * For SIT entries
+ *
+ * Each segment is 2MB in size by default so that a bitmap for validity of
+ * there-in blocks should occupy 64 bytes, 512 bits.
+ * Not allow to change this.
+ */
+#define SIT_VBLOCK_MAP_SIZE 64
+#define SIT_ENTRY_PER_BLOCK (PAGE_CACHE_SIZE / sizeof(struct f2fs_sit_entry))
+
+/*
+ * F2FS uses 4 bytes to represent block address. As a result, supported size of
+ * disk is 16 TB and it equals to 16 * 1024 * 1024 / 2 segments.
+ */
+#define F2FS_MAX_SEGMENT       ((16 * 1024 * 1024) / 2)
+#define MAX_SIT_BITMAP_SIZE    ((F2FS_MAX_SEGMENT / SIT_ENTRY_PER_BLOCK) / 8)
+
+/*
+ * Note that f2fs_sit_entry->vblocks has the following bit-field information.
+ * [15:10] : allocation type such as CURSEG_XXXX_TYPE
+ * [9:0] : valid block count
+ */
+#define SIT_VBLOCKS_SHIFT	10
+#define SIT_VBLOCKS_MASK	((1 << SIT_VBLOCKS_SHIFT) - 1)
+#define GET_SIT_VBLOCKS(raw_sit)				\
+	(le16_to_cpu((raw_sit)->vblocks) & SIT_VBLOCKS_MASK)
+#define GET_SIT_TYPE(raw_sit)					\
+	((le16_to_cpu((raw_sit)->vblocks) & ~SIT_VBLOCKS_MASK)	\
+	 >> SIT_VBLOCKS_SHIFT)
+
+struct f2fs_sit_entry {
+	__le16 vblocks;				/* reference above */
+	__u8 valid_map[SIT_VBLOCK_MAP_SIZE];	/* bitmap for valid blocks */
+	__le64 mtime;				/* segment age for cleaning */
+} __attribute__((packed));
+
+struct f2fs_sit_block {
+	struct f2fs_sit_entry entries[SIT_ENTRY_PER_BLOCK];
+} __attribute__((packed));
+
+/*
+ * For segment summary
+ *
+ * One summary block contains exactly 512 summary entries, which represents
+ * exactly 2MB segment by default. Not allow to change the basic units.
+ *
+ * NOTE: For initializing fields, you must use set_summary
+ *
+ * - If data page, nid represents dnode's nid
+ * - If node page, nid represents the node page's nid.
+ *
+ * The ofs_in_node is used by only data page. It represents offset
+ * from node's page's beginning to get a data block address.
+ * ex) data_blkaddr = (block_t)(nodepage_start_address + ofs_in_node)
+ */
+#define ENTRIES_IN_SUM		512
+#define	SUMMARY_SIZE		(7)	/* sizeof(struct summary) */
+#define	SUM_FOOTER_SIZE		(5)	/* sizeof(struct summary_footer) */
+#define SUM_ENTRIES_SIZE	(SUMMARY_SIZE * ENTRIES_IN_SUM)
+
+/* a summary entry for a 4KB-sized block in a segment */
+struct f2fs_summary {
+	__le32 nid;		/* parent node id */
+	union {
+		__u8 reserved[3];
+		struct {
+			__u8 version;		/* node version number */
+			__le16 ofs_in_node;	/* block index in parent node */
+		} __attribute__((packed));
+	};
+} __attribute__((packed));
+
+/* summary block type, node or data, is stored to the summary_footer */
+#define SUM_TYPE_NODE		(1)
+#define SUM_TYPE_DATA		(0)
+
+struct summary_footer {
+	unsigned char entry_type;	/* SUM_TYPE_XXX */
+	__u32 check_sum;		/* summary checksum */
+} __attribute__((packed));
+
+#define SUM_JOURNAL_SIZE	(F2FS_BLKSIZE - SUM_FOOTER_SIZE -\
+				SUM_ENTRIES_SIZE)
+#define NAT_JOURNAL_ENTRIES	((SUM_JOURNAL_SIZE - 2) /\
+				sizeof(struct nat_journal_entry))
+#define NAT_JOURNAL_RESERVED	((SUM_JOURNAL_SIZE - 2) %\
+				sizeof(struct nat_journal_entry))
+#define SIT_JOURNAL_ENTRIES	((SUM_JOURNAL_SIZE - 2) /\
+				sizeof(struct sit_journal_entry))
+#define SIT_JOURNAL_RESERVED	((SUM_JOURNAL_SIZE - 2) %\
+				sizeof(struct sit_journal_entry))
+/*
+ * frequently updated NAT/SIT entries can be stored in the spare area in
+ * summary blocks
+ */
+enum {
+	NAT_JOURNAL = 0,
+	SIT_JOURNAL
+};
+
+struct nat_journal_entry {
+	__le32 nid;
+	struct f2fs_nat_entry ne;
+} __attribute__((packed));
+
+struct nat_journal {
+	struct nat_journal_entry entries[NAT_JOURNAL_ENTRIES];
+	__u8 reserved[NAT_JOURNAL_RESERVED];
+} __attribute__((packed));
+
+struct sit_journal_entry {
+	__le32 segno;
+	struct f2fs_sit_entry se;
+} __attribute__((packed));
+
+struct sit_journal {
+	struct sit_journal_entry entries[SIT_JOURNAL_ENTRIES];
+	__u8 reserved[SIT_JOURNAL_RESERVED];
+} __attribute__((packed));
+
+/* 4KB-sized summary block structure */
+struct f2fs_summary_block {
+	struct f2fs_summary entries[ENTRIES_IN_SUM];
+	union {
+		__le16 n_nats;
+		__le16 n_sits;
+	};
+	/* spare area is used by NAT or SIT journals */
+	union {
+		struct nat_journal nat_j;
+		struct sit_journal sit_j;
+	};
+	struct summary_footer footer;
+} __attribute__((packed));
+
+/*
+ * For directory operations
+ */
+#define F2FS_DOT_HASH		0
+#define F2FS_DDOT_HASH		F2FS_DOT_HASH
+#define F2FS_MAX_HASH		(~((0x3ULL) << 62))
+#define F2FS_HASH_COL_BIT	((0x1ULL) << 63)
+
+typedef __le32	f2fs_hash_t;
+
+/* One directory entry slot covers 8bytes-long file name */
+#define F2FS_SLOT_LEN		8
+#define F2FS_SLOT_LEN_BITS	3
+
+#define GET_DENTRY_SLOTS(x)	((x + F2FS_SLOT_LEN - 1) >> F2FS_SLOT_LEN_BITS)
+
+/* the number of dentry in a block */
+#define NR_DENTRY_IN_BLOCK	214
+
+/* MAX level for dir lookup */
+#define MAX_DIR_HASH_DEPTH	63
+
+#define SIZE_OF_DIR_ENTRY	11	/* by byte */
+#define SIZE_OF_DENTRY_BITMAP	((NR_DENTRY_IN_BLOCK + BITS_PER_BYTE - 1) / \
+					BITS_PER_BYTE)
+#define SIZE_OF_RESERVED	(PAGE_SIZE - ((SIZE_OF_DIR_ENTRY + \
+				F2FS_SLOT_LEN) * \
+				NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP))
+
+/* One directory entry slot representing F2FS_SLOT_LEN-sized file name */
+struct f2fs_dir_entry {
+	__le32 hash_code;	/* hash code of file name */
+	__le32 ino;		/* inode number */
+	__le16 name_len;	/* lengh of file name */
+	__u8 file_type;		/* file type */
+} __attribute__((packed));
+
+/* 4KB-sized directory entry block */
+struct f2fs_dentry_block {
+	/* validity bitmap for directory entries in each block */
+	__u8 dentry_bitmap[SIZE_OF_DENTRY_BITMAP];
+	__u8 reserved[SIZE_OF_RESERVED];
+	struct f2fs_dir_entry dentry[NR_DENTRY_IN_BLOCK];
+	__u8 filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN];
+} __attribute__((packed));
+
+/* for inline dir */
+#define NR_INLINE_DENTRY	(MAX_INLINE_DATA * BITS_PER_BYTE / \
+				((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
+				BITS_PER_BYTE + 1))
+#define INLINE_DENTRY_BITMAP_SIZE	((NR_INLINE_DENTRY + \
+					BITS_PER_BYTE - 1) / BITS_PER_BYTE)
+#define INLINE_RESERVED_SIZE	(MAX_INLINE_DATA - \
+				((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
+				NR_INLINE_DENTRY + INLINE_DENTRY_BITMAP_SIZE))
+
+/* inline directory entry structure */
+struct f2fs_inline_dentry {
+	__u8 dentry_bitmap[INLINE_DENTRY_BITMAP_SIZE];
+	__u8 reserved[INLINE_RESERVED_SIZE];
+	struct f2fs_dir_entry dentry[NR_INLINE_DENTRY];
+	__u8 filename[NR_INLINE_DENTRY][F2FS_SLOT_LEN];
+} __packed;
+
+/* file types used in inode_info->flags */
+enum FILE_TYPE {
+	F2FS_FT_UNKNOWN,
+	F2FS_FT_REG_FILE,
+	F2FS_FT_DIR,
+	F2FS_FT_CHRDEV,
+	F2FS_FT_BLKDEV,
+	F2FS_FT_FIFO,
+	F2FS_FT_SOCK,
+	F2FS_FT_SYMLINK,
+	F2FS_FT_MAX,
+	/* added for fsck */
+	F2FS_FT_ORPHAN,
+	F2FS_FT_XATTR,
+	F2FS_FT_LAST_FILE_TYPE = F2FS_FT_XATTR,
+};
+
+/* from f2fs/segment.h */
+enum {
+	LFS = 0,
+	SSR
+};
+
+extern void ASCIIToUNICODE(u_int16_t *, u_int8_t *);
+extern int log_base_2(u_int32_t);
+extern unsigned int addrs_per_inode(struct f2fs_inode *);
+
+extern int get_bits_in_byte(unsigned char n);
+extern int set_bit(unsigned int nr,void * addr);
+extern int clear_bit(unsigned int nr, void * addr);
+extern int test_bit(unsigned int nr, const void * addr);
+extern int f2fs_test_bit(unsigned int, const char *);
+extern int f2fs_set_bit(unsigned int, char *);
+extern int f2fs_clear_bit(unsigned int, char *);
+extern unsigned long find_next_bit(const unsigned long *,
+				unsigned long, unsigned long);
+
+extern u_int32_t f2fs_cal_crc32(u_int32_t, void *, int);
+extern int f2fs_crc_valid(u_int32_t blk_crc, void *buf, int len);
+
+extern void f2fs_init_configuration(struct f2fs_configuration *);
+extern int f2fs_dev_is_umounted(struct f2fs_configuration *);
+extern int f2fs_get_device_info(struct f2fs_configuration *);
+extern void f2fs_finalize_device(struct f2fs_configuration *);
+
+extern int dev_read(void *, __u64, size_t);
+extern int dev_write(void *, __u64, size_t);
+extern int dev_write_block(void *, __u64);
+extern int dev_write_dump(void *, __u64, size_t);
+/* All bytes in the buffer must be 0 use dev_fill(). */
+extern int dev_fill(void *, __u64, size_t);
+
+extern int dev_read_block(void *, __u64);
+extern int dev_read_blocks(void *, __u64, __u32 );
+extern int dev_reada_block(__u64);
+
+extern int dev_read_version(void *, __u64, size_t);
+extern void get_kernel_version(__u8 *);
+f2fs_hash_t f2fs_dentry_hash(const unsigned char *, int);
+
+extern struct f2fs_configuration config;
+
+#define ALIGN(val, size)	((val) + (size) - 1) / (size)
+#define SEG_ALIGN(blks)		ALIGN(blks, config.blks_per_seg)
+#define ZONE_ALIGN(blks)	ALIGN(blks, config.blks_per_seg * \
+					config.segs_per_zone)
+
+#endif	/*__F2FS_FS_H */
diff --git a/f2fs-tools/include/list.h b/f2fs-tools/include/list.h
new file mode 100644
index 0000000..571cd5c
--- /dev/null
+++ b/f2fs-tools/include/list.h
@@ -0,0 +1,88 @@
+
+#define POISON_POINTER_DELTA 0
+#define LIST_POISON1  ((void *) (0x00100100 + POISON_POINTER_DELTA))
+#define LIST_POISON2  ((void *) (0x00200200 + POISON_POINTER_DELTA))
+
+#if !defined(offsetof)
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+#define container_of(ptr, type, member) ({                      \
+		const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+		(type *)( (char *)__mptr - offsetof(type,member) );})
+
+struct list_head {
+	struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+	struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+	list->next = list;
+	list->prev = list;
+}
+
+static inline void __list_add(struct list_head *new,
+		struct list_head *prev,
+		struct list_head *next)
+{
+	next->prev = new;
+	new->next = next;
+	new->prev = prev;
+	prev->next = new;
+}
+
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head, head->next);
+}
+
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head->prev, head);
+}
+
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+	next->prev = prev;
+	prev->next = next;
+}
+
+static inline void __list_del_entry(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+}
+
+static inline void list_del(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+	entry->next = LIST_POISON1;
+	entry->prev = LIST_POISON2;
+}
+
+static inline int list_empty(const struct list_head *head)
+{
+	return head->next == head;
+}
+
+#define list_entry(ptr, type, member) \
+	container_of(ptr, type, member)
+
+#define list_for_each(pos, head) \
+	for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#define list_for_each_safe(pos, n, head) \
+	for (pos = (head)->next, n = pos->next; pos != (head); \
+			pos = n, n = pos->next)
+#define list_for_each_entry(pos, head, member)                          \
+	for (pos = list_entry((head)->next, typeof(*pos), member);      \
+			&pos->member != (head);    \
+			pos = list_entry(pos->member.next, typeof(*pos), member))
+#define list_for_each_entry_safe(pos, n, head, member)                  \
+	for (pos = list_entry((head)->next, typeof(*pos), member),      \
+			n = list_entry(pos->member.next, typeof(*pos), member); \
+			&pos->member != (head);                                    \
+			pos = n, n = list_entry(n->member.next, typeof(*n), member))
diff --git a/f2fs-tools/lib/Makefile.am b/f2fs-tools/lib/Makefile.am
new file mode 100644
index 0000000..a6b304c
--- /dev/null
+++ b/f2fs-tools/lib/Makefile.am
@@ -0,0 +1,7 @@
+## Makefile.am
+
+lib_LTLIBRARIES = libf2fs.la
+
+libf2fs_la_SOURCES = libf2fs.c libf2fs_io.c
+libf2fs_la_CFLAGS = -Wall
+libf2fs_la_CPPFLAGS = -I$(top_srcdir)/include
diff --git a/f2fs-tools/lib/libf2fs.c b/f2fs-tools/lib/libf2fs.c
new file mode 100644
index 0000000..9e19e9b
--- /dev/null
+++ b/f2fs-tools/lib/libf2fs.c
@@ -0,0 +1,511 @@
+/**
+ * libf2fs.c
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Dual licensed under the GPL or LGPL version 2 licenses.
+ */
+#define _LARGEFILE64_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <mntent.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <sys/ioctl.h>
+#include <linux/hdreg.h>
+
+#include <f2fs_fs.h>
+
+void ASCIIToUNICODE(u_int16_t *out_buf, u_int8_t *in_buf)
+{
+	u_int8_t *pchTempPtr = in_buf;
+	u_int16_t *pwTempPtr = out_buf;
+
+	while (*pchTempPtr != '\0') {
+		*pwTempPtr = (u_int16_t)*pchTempPtr;
+		pchTempPtr++;
+		pwTempPtr++;
+	}
+	*pwTempPtr = '\0';
+	return;
+}
+
+int log_base_2(u_int32_t num)
+{
+	int ret = 0;
+	if (num <= 0 || (num & (num - 1)) != 0)
+		return -1;
+
+	while (num >>= 1)
+		ret++;
+	return ret;
+}
+
+/*
+ * f2fs bit operations
+ */
+static const int bits_in_byte[256] = {
+	0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+	4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
+};
+
+int get_bits_in_byte(unsigned char n)
+{
+	return bits_in_byte[n];
+}
+
+int set_bit(unsigned int nr,void * addr)
+{
+	int             mask, retval;
+	unsigned char   *ADDR = (unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << ((nr & 0x07));
+	retval = mask & *ADDR;
+	*ADDR |= mask;
+	return retval;
+}
+
+int clear_bit(unsigned int nr, void * addr)
+{
+	int             mask, retval;
+	unsigned char   *ADDR = (unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << ((nr & 0x07));
+	retval = mask & *ADDR;
+	*ADDR &= ~mask;
+	return retval;
+}
+
+int test_bit(unsigned int nr, const void * addr)
+{
+	const __u32 *p = (const __u32 *)addr;
+
+	nr = nr ^ 0;
+
+	return ((1 << (nr & 31)) & (p[nr >> 5])) != 0;
+}
+
+int f2fs_test_bit(unsigned int nr, const char *p)
+{
+	int mask;
+	char *addr = (char *)p;
+
+	addr += (nr >> 3);
+	mask = 1 << (7 - (nr & 0x07));
+	return (mask & *addr) != 0;
+}
+
+int f2fs_set_bit(unsigned int nr, char *addr)
+{
+	int mask;
+	int ret;
+
+	addr += (nr >> 3);
+	mask = 1 << (7 - (nr & 0x07));
+	ret = mask & *addr;
+	*addr |= mask;
+	return ret;
+}
+
+int f2fs_clear_bit(unsigned int nr, char *addr)
+{
+	int mask;
+	int ret;
+
+	addr += (nr >> 3);
+	mask = 1 << (7 - (nr & 0x07));
+	ret = mask & *addr;
+	*addr &= ~mask;
+	return ret;
+}
+
+static inline unsigned long __ffs(unsigned long word)
+{
+	int num = 0;
+
+#if BITS_PER_LONG == 64
+	if ((word & 0xffffffff) == 0) {
+		num += 32;
+		word >>= 32;
+	}
+#endif
+	if ((word & 0xffff) == 0) {
+		num += 16;
+		word >>= 16;
+	}
+	if ((word & 0xff) == 0) {
+		num += 8;
+		word >>= 8;
+	}
+	if ((word & 0xf) == 0) {
+		num += 4;
+		word >>= 4;
+	}
+	if ((word & 0x3) == 0) {
+		num += 2;
+		word >>= 2;
+	}
+	if ((word & 0x1) == 0)
+		num += 1;
+	return num;
+}
+
+unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
+                unsigned long offset)
+{
+        const unsigned long *p = addr + BIT_WORD(offset);
+        unsigned long result = offset & ~(BITS_PER_LONG-1);
+        unsigned long tmp;
+
+        if (offset >= size)
+                return size;
+        size -= result;
+        offset %= BITS_PER_LONG;
+        if (offset) {
+                tmp = *(p++);
+                tmp &= (~0UL << offset);
+                if (size < BITS_PER_LONG)
+                        goto found_first;
+                if (tmp)
+                        goto found_middle;
+                size -= BITS_PER_LONG;
+                result += BITS_PER_LONG;
+        }
+        while (size & ~(BITS_PER_LONG-1)) {
+                if ((tmp = *(p++)))
+                        goto found_middle;
+                result += BITS_PER_LONG;
+                size -= BITS_PER_LONG;
+        }
+        if (!size)
+                return result;
+        tmp = *p;
+
+found_first:
+        tmp &= (~0UL >> (BITS_PER_LONG - size));
+        if (tmp == 0UL)		/* Are any bits set? */
+                return result + size;   /* Nope. */
+found_middle:
+        return result + __ffs(tmp);
+}
+
+/*
+ * Hashing code adapted from ext3
+ */
+#define DELTA 0x9E3779B9
+
+static void TEA_transform(unsigned int buf[4], unsigned int const in[])
+{
+	__u32 sum = 0;
+	__u32 b0 = buf[0], b1 = buf[1];
+	__u32 a = in[0], b = in[1], c = in[2], d = in[3];
+	int     n = 16;
+
+	do {
+		sum += DELTA;
+		b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
+		b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
+	} while (--n);
+
+	buf[0] += b0;
+	buf[1] += b1;
+
+}
+
+static void str2hashbuf(const unsigned char *msg, int len,
+					unsigned int *buf, int num)
+{
+	unsigned pad, val;
+	int i;
+
+	pad = (__u32)len | ((__u32)len << 8);
+	pad |= pad << 16;
+
+	val = pad;
+	if (len > num * 4)
+		len = num * 4;
+	for (i = 0; i < len; i++) {
+		if ((i % 4) == 0)
+			val = pad;
+		val = msg[i] + (val << 8);
+		if ((i % 4) == 3) {
+			*buf++ = val;
+			val = pad;
+			num--;
+		}
+	}
+	if (--num >= 0)
+		*buf++ = val;
+	while (--num >= 0)
+		*buf++ = pad;
+
+}
+
+/**
+ * Return hash value of directory entry
+ * @param name          dentry name
+ * @param len           name lenth
+ * @return              return on success hash value, errno on failure
+ */
+f2fs_hash_t f2fs_dentry_hash(const unsigned char *name, int len)
+{
+	__u32 hash;
+	f2fs_hash_t	f2fs_hash;
+	const unsigned char	*p;
+	__u32 in[8], buf[4];
+
+	/* special hash codes for special dentries */
+	if ((len <= 2) && (name[0] == '.') &&
+		(name[1] == '.' || name[1] == '\0'))
+		return 0;
+
+	/* Initialize the default seed for the hash checksum functions */
+	buf[0] = 0x67452301;
+	buf[1] = 0xefcdab89;
+	buf[2] = 0x98badcfe;
+	buf[3] = 0x10325476;
+
+	p = name;
+	while (1) {
+		str2hashbuf(p, len, in, 4);
+		TEA_transform(buf, in);
+		p += 16;
+		if (len <= 16)
+			break;
+		len -= 16;
+	}
+	hash = buf[0];
+
+	f2fs_hash = cpu_to_le32(hash & ~F2FS_HASH_COL_BIT);
+	return f2fs_hash;
+}
+
+unsigned int addrs_per_inode(struct f2fs_inode *i)
+{
+	if (i->i_inline & F2FS_INLINE_XATTR)
+		return DEF_ADDRS_PER_INODE - F2FS_INLINE_XATTR_ADDRS;
+	return DEF_ADDRS_PER_INODE;
+}
+
+/*
+ * CRC32
+ */
+#define CRCPOLY_LE 0xedb88320
+
+u_int32_t f2fs_cal_crc32(u_int32_t crc, void *buf, int len)
+{
+	int i;
+	unsigned char *p = (unsigned char *)buf;
+	while (len--) {
+		crc ^= *p++;
+		for (i = 0; i < 8; i++)
+			crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
+	}
+	return crc;
+}
+
+int f2fs_crc_valid(u_int32_t blk_crc, void *buf, int len)
+{
+	u_int32_t cal_crc = 0;
+
+	cal_crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, buf, len);
+
+	if (cal_crc != blk_crc)	{
+		DBG(0,"CRC validation failed: cal_crc = %u, "
+			"blk_crc = %u buff_size = 0x%x\n",
+			cal_crc, blk_crc, len);
+		return -1;
+	}
+	return 0;
+}
+
+/*
+ * device information
+ */
+void f2fs_init_configuration(struct f2fs_configuration *c)
+{
+	c->total_sectors = 0;
+	c->sector_size = DEFAULT_SECTOR_SIZE;
+	c->sectors_per_blk = DEFAULT_SECTORS_PER_BLOCK;
+	c->blks_per_seg = DEFAULT_BLOCKS_PER_SEGMENT;
+
+	/* calculated by overprovision ratio */
+	c->reserved_segments = 48;
+	c->overprovision = 5;
+	c->segs_per_sec = 1;
+	c->secs_per_zone = 1;
+	c->segs_per_zone = 1;
+	c->heap = 1;
+	c->vol_label = "";
+	c->device_name = NULL;
+	c->trim = 1;
+}
+
+static int is_mounted(const char *mpt, const char *device)
+{
+	FILE *file = NULL;
+	struct mntent *mnt = NULL;
+
+	file = setmntent(mpt, "r");
+	if (file == NULL)
+		return 0;
+
+	while ((mnt = getmntent(file)) != NULL) {
+		if (!strcmp(device, mnt->mnt_fsname))
+			break;
+	}
+	endmntent(file);
+	return mnt ? 1 : 0;
+}
+
+int f2fs_dev_is_umounted(struct f2fs_configuration *c)
+{
+	struct stat st_buf;
+	int ret = 0;
+
+	ret = is_mounted(MOUNTED, c->device_name);
+	if (ret) {
+		MSG(0, "\tError: Not available on mounted device!\n");
+		return -1;
+	}
+
+	/*
+	 * if failed due to /etc/mtab file not present
+	 * try with /proc/mounts.
+	 */
+	ret = is_mounted("/proc/mounts", c->device_name);
+	if (ret) {
+		MSG(0, "\tError: Not available on mounted device!\n");
+		return -1;
+	}
+
+	/*
+	 * If f2fs is umounted with -l, the process can still use
+	 * the file system. In this case, we should not format.
+	 */
+	if (stat(c->device_name, &st_buf) == 0 && S_ISBLK(st_buf.st_mode)) {
+		int fd = open(c->device_name, O_RDONLY | O_EXCL);
+
+		if (fd >= 0) {
+			close(fd);
+		} else if (errno == EBUSY) {
+			MSG(0, "\tError: In use by the system!\n");
+			return -1;
+		}
+	}
+	return 0;
+}
+
+void get_kernel_version(__u8 *version)
+{
+	int i;
+	for (i = 0; i < VERSION_LEN; i++) {
+		if (version[i] == '\n')
+			break;
+	}
+	memset(version + i, 0, VERSION_LEN + 1 - i);
+}
+
+int f2fs_get_device_info(struct f2fs_configuration *c)
+{
+	int32_t fd = 0;
+	uint32_t sector_size;
+#ifndef BLKGETSIZE64
+	uint32_t total_sectors;
+#endif
+	struct stat stat_buf;
+	struct hd_geometry geom;
+	u_int64_t wanted_total_sectors = c->total_sectors;
+
+	fd = open(c->device_name, O_RDWR);
+	if (fd < 0) {
+		MSG(0, "\tError: Failed to open the device!\n");
+		return -1;
+	}
+	c->fd = fd;
+
+	c->kd = open("/proc/version", O_RDONLY);
+	if (c->kd < 0)
+		MSG(0, "\tInfo: No support kernel version!\n");
+
+	if (fstat(fd, &stat_buf) < 0 ) {
+		MSG(0, "\tError: Failed to get the device stat!\n");
+		return -1;
+	}
+
+	if (S_ISREG(stat_buf.st_mode)) {
+		c->total_sectors = stat_buf.st_size / c->sector_size;
+	} else if (S_ISBLK(stat_buf.st_mode)) {
+		if (ioctl(fd, BLKSSZGET, &sector_size) < 0) {
+			MSG(0, "\tError: Using the default sector size\n");
+		} else {
+			if (c->sector_size < sector_size) {
+				c->sector_size = sector_size;
+				c->sectors_per_blk = PAGE_SIZE / sector_size;
+			}
+		}
+
+#ifdef BLKGETSIZE64
+		if (ioctl(fd, BLKGETSIZE64, &c->total_sectors) < 0) {
+			MSG(0, "\tError: Cannot get the device size\n");
+			return -1;
+		}
+		c->total_sectors /= c->sector_size;
+#else
+		if (ioctl(fd, BLKGETSIZE, &total_sectors) < 0) {
+			MSG(0, "\tError: Cannot get the device size\n");
+			return -1;
+		}
+		total_sectors /= c->sector_size;
+		c->total_sectors = total_sectors;
+#endif
+		if (ioctl(fd, HDIO_GETGEO, &geom) < 0)
+			c->start_sector = 0;
+		else
+			c->start_sector = geom.start;
+	} else {
+		MSG(0, "\tError: Volume type is not supported!!!\n");
+		return -1;
+	}
+	if (wanted_total_sectors && wanted_total_sectors < c->total_sectors) {
+		MSG(0, "Info: total device sectors = %"PRIu64" (in %u bytes)\n",
+					c->total_sectors, c->sector_size);
+		c->total_sectors = wanted_total_sectors;
+
+	}
+	MSG(0, "Info: sector size = %u\n", c->sector_size);
+	MSG(0, "Info: total sectors = %"PRIu64" (in %u bytes)\n",
+					c->total_sectors, c->sector_size);
+	if (c->total_sectors <
+			(F2FS_MIN_VOLUME_SIZE / c->sector_size)) {
+		MSG(0, "Error: Min volume size supported is %d\n",
+				F2FS_MIN_VOLUME_SIZE);
+		return -1;
+	}
+
+	return 0;
+}
+
diff --git a/f2fs-tools/lib/libf2fs_io.c b/f2fs-tools/lib/libf2fs_io.c
new file mode 100644
index 0000000..afa345f
--- /dev/null
+++ b/f2fs-tools/lib/libf2fs_io.c
@@ -0,0 +1,121 @@
+/**
+ * libf2fs.c
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Dual licensed under the GPL or LGPL version 2 licenses.
+ */
+#define _LARGEFILE64_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <mntent.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <sys/ioctl.h>
+#include <linux/hdreg.h>
+
+#include <f2fs_fs.h>
+
+struct f2fs_configuration config;
+
+/*
+ * IO interfaces
+ */
+int dev_read_version(void *buf, __u64 offset, size_t len)
+{
+	if (lseek64(config.kd, (off64_t)offset, SEEK_SET) < 0)
+		return -1;
+	if (read(config.kd, buf, len) < 0)
+		return -1;
+	return 0;
+}
+
+int dev_read(void *buf, __u64 offset, size_t len)
+{
+	if (lseek64(config.fd, (off64_t)offset, SEEK_SET) < 0)
+		return -1;
+	if (read(config.fd, buf, len) < 0)
+		return -1;
+	return 0;
+}
+
+int dev_readahead(__u64 offset, size_t len)
+{
+#ifdef POSIX_FADV_WILLNEED
+	return posix_fadvise(config.fd, offset, len, POSIX_FADV_WILLNEED);
+#else
+	return 0;
+#endif
+}
+
+int dev_write(void *buf, __u64 offset, size_t len)
+{
+	if (lseek64(config.fd, (off64_t)offset, SEEK_SET) < 0)
+		return -1;
+	if (write(config.fd, buf, len) < 0)
+		return -1;
+	return 0;
+}
+
+int dev_write_block(void *buf, __u64 blk_addr)
+{
+	return dev_write(buf, blk_addr * F2FS_BLKSIZE, F2FS_BLKSIZE);
+}
+
+int dev_write_dump(void *buf, __u64 offset, size_t len)
+{
+	if (lseek64(config.dump_fd, (off64_t)offset, SEEK_SET) < 0)
+		return -1;
+	if (write(config.dump_fd, buf, len) < 0)
+		return -1;
+	return 0;
+}
+
+int dev_fill(void *buf, __u64 offset, size_t len)
+{
+	/* Only allow fill to zero */
+	if (*((__u8*)buf))
+		return -1;
+	if (lseek64(config.fd, (off64_t)offset, SEEK_SET) < 0)
+		return -1;
+	if (write(config.fd, buf, len) < 0)
+		return -1;
+	return 0;
+}
+
+int dev_read_block(void *buf, __u64 blk_addr)
+{
+	return dev_read(buf, blk_addr * F2FS_BLKSIZE, F2FS_BLKSIZE);
+}
+
+int dev_read_blocks(void *buf, __u64 addr, __u32 nr_blks)
+{
+	return dev_read(buf, addr * F2FS_BLKSIZE, nr_blks * F2FS_BLKSIZE);
+}
+
+int dev_reada_block(__u64 blk_addr)
+{
+	return dev_readahead(blk_addr * F2FS_BLKSIZE, F2FS_BLKSIZE);
+}
+
+void f2fs_finalize_device(struct f2fs_configuration *c)
+{
+	/*
+	 * We should call fsync() to flush out all the dirty pages
+	 * in the block device page cache.
+	 */
+	if (fsync(c->fd) < 0)
+		MSG(0, "\tError: Could not conduct fsync!!!\n");
+
+	if (close(c->fd) < 0)
+		MSG(0, "\tError: Failed to close device file!!!\n");
+
+	close(c->kd);
+}
diff --git a/f2fs-tools/man/Makefile.am b/f2fs-tools/man/Makefile.am
new file mode 100644
index 0000000..477d654
--- /dev/null
+++ b/f2fs-tools/man/Makefile.am
@@ -0,0 +1,3 @@
+## Makefile.am
+
+dist_man_MANS = mkfs.f2fs.8
diff --git a/f2fs-tools/man/mkfs.f2fs.8 b/f2fs-tools/man/mkfs.f2fs.8
new file mode 100644
index 0000000..f386ac6
--- /dev/null
+++ b/f2fs-tools/man/mkfs.f2fs.8
@@ -0,0 +1,91 @@
+.\" Copyright (c) 2012 Samsung Electronics Co., Ltd.
+.\"             http://www.samsung.com/
+.\"  Written by Jaegeuk Kim <jaegeuk.kim@samsung.com>
+.\"
+.TH MKFS.F2FS 8 "January 2013" "f2fs-tools version 1.2.0"
+.SH NAME
+mkfs.f2fs \- create an F2FS file system
+.SH SYNOPSIS
+.B mkfs.f2fs
+[
+.B \-a
+.I heap-based-allocation
+]
+[
+.B \-l
+.I volume-label
+]
+[
+.B \-o
+.I overprovision-ratio-percentage
+]
+[
+.B \-s
+.I log-based-#-of-segments-per-section
+]
+[
+.B \-z
+.I #-of-sections-per-zone
+]
+[
+.B \-e
+.I extenstion-list
+]
+[
+.B \-d
+.I debugging-level
+]
+.I device
+.SH DESCRIPTION
+.B mkfs.f2fs
+is used to create a f2fs file system (usually in a disk partition).
+\fIdevice\fP is the special file corresponding to the device (e.g.
+\fI/dev/sdXX\fP).
+.PP
+The exit code returned by
+.B mkfs.f2fs
+is 0 on success and 1 on failure.
+.SH OPTIONS
+.TP
+.BI \-a " heap-based-allocation"
+Specify 1 or 0 to enable/disable heap based block allocation policy.
+If the value is equal to 1, each of active log areas are initially
+assigned separately according to the whole volume size.
+The default value is 1.
+.TP
+.BI \-l " volume-label"
+Specify the volume label to the partition mounted as F2FS.
+.TP
+.BI \-o " overprovision-ratio-percentage"
+Specify the percentage over the volume size for overprovision area. This area
+is hidden to users, and utilized by F2FS cleaner. The default percentage is 5%.
+.TP
+.BI \-s " log-based-#-of-segments-per-section"
+Specify the log-based number of segments per section. A section consists of
+multiple consecutive segments, and is the unit of garbage collection.
+The default number is 0, which means one segment is assigned to a section.
+.TP
+.BI \-z " #-of-sections-per-zone"
+Specify the number of sections per zone. A zone consists of multiple sections.
+F2FS allocates segments for active logs with separated zones as much as possible.
+The default number is 1, which means a zone consists of one section.
+.TP
+.BI \-e " extension-list"
+Specify a file extension list in order f2fs to treat them as cold files.
+The data of files having those extensions will be stored to the cold log.
+The default list includes most of multimedia file extensions such as jpg, gif,
+mpeg, mkv, and so on.
+.TP
+.BI \-d " debug-level"
+Specify the level of debugging options.
+The default number is 0, which shows basic debugging messages.
+.TP
+.SH AUTHOR
+This version of
+.B mkfs.f2fs
+has been written by Jaegeuk Kim <jaegeuk.kim@samsung.com>.
+.SH AVAILABILITY
+.B mkfs.f2fs
+is available from git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs-tools.git.
+.SH SEE ALSO
+.BR mkfs (8).
diff --git a/f2fs-tools/mkfs/Makefile.am b/f2fs-tools/mkfs/Makefile.am
new file mode 100644
index 0000000..fa48699
--- /dev/null
+++ b/f2fs-tools/mkfs/Makefile.am
@@ -0,0 +1,7 @@
+## Makefile.am
+
+AM_CPPFLAGS = ${libuuid_CFLAGS} -I$(top_srcdir)/include
+AM_CFLAGS = -Wall -DWITH_BLKDISCARD
+sbin_PROGRAMS = mkfs.f2fs
+mkfs_f2fs_SOURCES = f2fs_format_main.c f2fs_format.c f2fs_format_utils.c
+mkfs_f2fs_LDADD = ${libuuid_LIBS} $(top_builddir)/lib/libf2fs.la
diff --git a/f2fs-tools/mkfs/f2fs_format.c b/f2fs-tools/mkfs/f2fs_format.c
new file mode 100644
index 0000000..094afa3
--- /dev/null
+++ b/f2fs-tools/mkfs/f2fs_format.c
@@ -0,0 +1,963 @@
+/**
+ * f2fs_format.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Dual licensed under the GPL or LGPL version 2 licenses.
+ */
+#define _LARGEFILE64_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <time.h>
+#include <uuid/uuid.h>
+
+#include "f2fs_fs.h"
+#include "f2fs_format_utils.h"
+
+extern struct f2fs_configuration config;
+struct f2fs_super_block sb;
+struct f2fs_checkpoint *cp;
+
+/* Return first segment number of each area */
+#define prev_zone(cur)		(config.cur_seg[cur] - config.segs_per_zone)
+#define next_zone(cur)		(config.cur_seg[cur] + config.segs_per_zone)
+#define last_zone(cur)		((cur - 1) * config.segs_per_zone)
+#define last_section(cur)	(cur + (config.secs_per_zone - 1) * config.segs_per_sec)
+
+#define set_sb_le64(member, val)		(sb.member = cpu_to_le64(val))
+#define set_sb_le32(member, val)		(sb.member = cpu_to_le32(val))
+#define set_sb_le16(member, val)		(sb.member = cpu_to_le16(val))
+#define get_sb_le64(member)			le64_to_cpu(sb.member)
+#define get_sb_le32(member)			le32_to_cpu(sb.member)
+#define get_sb_le16(member)			le16_to_cpu(sb.member)
+
+#define set_sb(member, val)	\
+			do {						\
+				typeof(sb.member) t;			\
+				switch (sizeof(t)) {			\
+				case 8: set_sb_le64(member, val); break; \
+				case 4: set_sb_le32(member, val); break; \
+				case 2: set_sb_le16(member, val); break; \
+				} \
+			} while(0)
+
+#define get_sb(member)		\
+			({						\
+				typeof(sb.member) t;			\
+				switch (sizeof(t)) {			\
+				case 8: t = get_sb_le64(member); break; \
+				case 4: t = get_sb_le32(member); break; \
+				case 2: t = get_sb_le16(member); break; \
+				} 					\
+				t; \
+			})
+
+#define set_cp_le64(member, val)		(cp->member = cpu_to_le64(val))
+#define set_cp_le32(member, val)		(cp->member = cpu_to_le32(val))
+#define set_cp_le16(member, val)		(cp->member = cpu_to_le16(val))
+#define get_cp_le64(member)			le64_to_cpu(cp->member)
+#define get_cp_le32(member)			le32_to_cpu(cp->member)
+#define get_cp_le16(member)			le16_to_cpu(cp->member)
+
+#define set_cp(member, val)	\
+			do {						\
+				typeof(cp->member) t;			\
+				switch (sizeof(t)) {			\
+				case 8: set_cp_le64(member, val); break; \
+				case 4: set_cp_le32(member, val); break; \
+				case 2: set_cp_le16(member, val); break; \
+				} \
+			} while(0)
+
+#define get_cp(member)		\
+			({						\
+				typeof(cp->member) t;			\
+				switch (sizeof(t)) {			\
+				case 8: t = get_cp_le64(member); break; \
+				case 4: t = get_cp_le32(member); break; \
+				case 2: t = get_cp_le16(member); break; \
+				} 					\
+				t; \
+			})
+
+
+const char *media_ext_lists[] = {
+	"jpg",
+	"gif",
+	"png",
+	"avi",
+	"divx",
+	"mp4",
+	"mp3",
+	"3gp",
+	"wmv",
+	"wma",
+	"mpeg",
+	"mkv",
+	"mov",
+	"asx",
+	"asf",
+	"wmx",
+	"svi",
+	"wvx",
+	"wm",
+	"mpg",
+	"mpe",
+	"rm",
+	"ogg",
+	"jpeg",
+	"video",
+	"apk",	/* for android system */
+	NULL
+};
+
+static void configure_extension_list(void)
+{
+	const char **extlist = media_ext_lists;
+	char *ext_str = config.extension_list;
+	char *ue;
+	int name_len;
+	int i = 0;
+
+	sb.extension_count = 0;
+	memset(sb.extension_list, 0,
+			sizeof(sb.extension_list));
+
+	while (*extlist) {
+		name_len = strlen(*extlist);
+		memcpy(sb.extension_list[i++], *extlist, name_len);
+		extlist++;
+	}
+	set_sb(extension_count, i);
+
+	if (!ext_str)
+		return;
+
+	/* add user ext list */
+	ue = strtok(ext_str, ",");
+	while (ue != NULL) {
+		name_len = strlen(ue);
+		memcpy(sb.extension_list[i++], ue, name_len);
+		ue = strtok(NULL, ",");
+		if (i >= F2FS_MAX_EXTENSION)
+			break;
+	}
+
+	set_sb(extension_count, i);
+
+	free(config.extension_list);
+}
+
+static int f2fs_prepare_super_block(void)
+{
+	u_int32_t blk_size_bytes;
+	u_int32_t log_sectorsize, log_sectors_per_block;
+	u_int32_t log_blocksize, log_blks_per_seg;
+	u_int32_t segment_size_bytes, zone_size_bytes;
+	u_int32_t sit_segments;
+	u_int32_t blocks_for_sit, blocks_for_nat, blocks_for_ssa;
+	u_int32_t total_valid_blks_available;
+	u_int64_t zone_align_start_offset, diff, total_meta_segments;
+	u_int32_t sit_bitmap_size, max_sit_bitmap_size;
+	u_int32_t max_nat_bitmap_size, max_nat_segments;
+	u_int32_t total_zones;
+
+	set_sb(magic, F2FS_SUPER_MAGIC);
+	set_sb(major_ver, F2FS_MAJOR_VERSION);
+	set_sb(minor_ver, F2FS_MINOR_VERSION);
+
+	log_sectorsize = log_base_2(config.sector_size);
+	log_sectors_per_block = log_base_2(config.sectors_per_blk);
+	log_blocksize = log_sectorsize + log_sectors_per_block;
+	log_blks_per_seg = log_base_2(config.blks_per_seg);
+
+	set_sb(log_sectorsize, log_sectorsize);
+	set_sb(log_sectors_per_block, log_sectors_per_block);
+
+	set_sb(log_blocksize, log_blocksize);
+	set_sb(log_blocks_per_seg, log_blks_per_seg);
+
+	set_sb(segs_per_sec, config.segs_per_sec);
+	set_sb(secs_per_zone, config.secs_per_zone);
+
+	blk_size_bytes = 1 << log_blocksize;
+	segment_size_bytes = blk_size_bytes * config.blks_per_seg;
+	zone_size_bytes =
+		blk_size_bytes * config.secs_per_zone *
+		config.segs_per_sec * config.blks_per_seg;
+
+	sb.checksum_offset = 0;
+
+	set_sb(block_count, config.total_sectors >> log_sectors_per_block);
+
+	zone_align_start_offset =
+		(config.start_sector * config.sector_size +
+		2 * F2FS_BLKSIZE + zone_size_bytes - 1) /
+		zone_size_bytes * zone_size_bytes -
+		config.start_sector * config.sector_size;
+
+	if (config.start_sector % config.sectors_per_blk) {
+		MSG(1, "\tWARN: Align start sector number to the page unit\n");
+		MSG(1, "\ti.e., start sector: %d, ofs:%d (sects/page: %d)\n",
+				config.start_sector,
+				config.start_sector % config.sectors_per_blk,
+				config.sectors_per_blk);
+	}
+
+	set_sb(segment_count, (config.total_sectors * config.sector_size -
+				zone_align_start_offset) / segment_size_bytes);
+
+	set_sb(segment0_blkaddr, zone_align_start_offset / blk_size_bytes);
+	sb.cp_blkaddr = sb.segment0_blkaddr;
+
+	MSG(0, "Info: zone aligned segment0 blkaddr: %u\n", get_sb(segment0_blkaddr));
+
+	set_sb(segment_count_ckpt, F2FS_NUMBER_OF_CHECKPOINT_PACK);
+
+	set_sb(sit_blkaddr, get_sb(segment0_blkaddr) + get_sb(segment_count_ckpt) *
+			config.blks_per_seg);
+
+	blocks_for_sit = ALIGN(get_sb(segment_count), SIT_ENTRY_PER_BLOCK);
+
+	sit_segments = SEG_ALIGN(blocks_for_sit);
+
+	set_sb(segment_count_sit, sit_segments * 2);
+
+	set_sb(nat_blkaddr, get_sb(sit_blkaddr) + get_sb(segment_count_sit) *
+			config.blks_per_seg);
+
+	total_valid_blks_available = (get_sb(segment_count) -
+			(get_sb(segment_count_ckpt) + get_sb(segment_count_sit))) *
+			config.blks_per_seg;
+
+	blocks_for_nat = ALIGN(total_valid_blks_available, NAT_ENTRY_PER_BLOCK);
+
+	set_sb(segment_count_nat, SEG_ALIGN(blocks_for_nat));
+	/*
+	 * The number of node segments should not be exceeded a "Threshold".
+	 * This number resizes NAT bitmap area in a CP page.
+	 * So the threshold is determined not to overflow one CP page
+	 */
+	sit_bitmap_size = ((get_sb(segment_count_sit) / 2) <<
+				log_blks_per_seg) / 8;
+
+	if (sit_bitmap_size > MAX_SIT_BITMAP_SIZE)
+		max_sit_bitmap_size = MAX_SIT_BITMAP_SIZE;
+	else
+		max_sit_bitmap_size = sit_bitmap_size;
+
+	/*
+	 * It should be reserved minimum 1 segment for nat.
+	 * When sit is too large, we should expand cp area. It requires more pages for cp.
+	 */
+	if (max_sit_bitmap_size >
+			(CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 65)) {
+		max_nat_bitmap_size = CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1;
+		set_sb(cp_payload, F2FS_BLK_ALIGN(max_sit_bitmap_size));
+	} else {
+		max_nat_bitmap_size = CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1
+			- max_sit_bitmap_size;
+		sb.cp_payload = 0;
+	}
+
+	max_nat_segments = (max_nat_bitmap_size * 8) >> log_blks_per_seg;
+
+	if (get_sb(segment_count_nat) > max_nat_segments)
+		set_sb(segment_count_nat, max_nat_segments);
+
+	set_sb(segment_count_nat, get_sb(segment_count_nat) * 2);
+
+	set_sb(ssa_blkaddr, get_sb(nat_blkaddr) + get_sb(segment_count_nat) *
+			config.blks_per_seg);
+
+	total_valid_blks_available = (get_sb(segment_count) -
+			(get_sb(segment_count_ckpt) +
+			get_sb(segment_count_sit) +
+			get_sb(segment_count_nat))) *
+			config.blks_per_seg;
+
+	blocks_for_ssa = total_valid_blks_available /
+				config.blks_per_seg + 1;
+
+	set_sb(segment_count_ssa, SEG_ALIGN(blocks_for_ssa));
+
+	total_meta_segments = get_sb(segment_count_ckpt) +
+		get_sb(segment_count_sit) +
+		get_sb(segment_count_nat) +
+		get_sb(segment_count_ssa);
+	diff = total_meta_segments % (config.segs_per_zone);
+	if (diff)
+		set_sb(segment_count_ssa, get_sb(segment_count_ssa) +
+			(config.segs_per_zone - diff));
+
+	set_sb(main_blkaddr, get_sb(ssa_blkaddr) + get_sb(segment_count_ssa) *
+			 config.blks_per_seg);
+
+	set_sb(segment_count_main, get_sb(segment_count) -
+			(get_sb(segment_count_ckpt) +
+			 get_sb(segment_count_sit) +
+			 get_sb(segment_count_nat) +
+			 get_sb(segment_count_ssa)));
+
+	set_sb(section_count, get_sb(segment_count_main) / config.segs_per_sec);
+
+	set_sb(segment_count_main, get_sb(section_count) * config.segs_per_sec);
+
+	if ((get_sb(segment_count_main) - 2) <
+					config.reserved_segments) {
+		MSG(1, "\tError: Device size is not sufficient for F2FS volume,\
+			more segment needed =%u",
+			config.reserved_segments -
+			(get_sb(segment_count_main) - 2));
+		return -1;
+	}
+
+	uuid_generate(sb.uuid);
+
+	ASCIIToUNICODE(sb.volume_name, (u_int8_t *)config.vol_label);
+
+	set_sb(node_ino, 1);
+	set_sb(meta_ino, 2);
+	set_sb(root_ino, 3);
+
+	total_zones = get_sb(segment_count_main) / (config.segs_per_zone);
+	if (total_zones <= 6) {
+		MSG(1, "\tError: %d zones: Need more zones \
+			by shrinking zone size\n", total_zones);
+		return -1;
+	}
+
+	if (config.heap) {
+		config.cur_seg[CURSEG_HOT_NODE] = last_section(last_zone(total_zones));
+		config.cur_seg[CURSEG_WARM_NODE] = prev_zone(CURSEG_HOT_NODE);
+		config.cur_seg[CURSEG_COLD_NODE] = prev_zone(CURSEG_WARM_NODE);
+		config.cur_seg[CURSEG_HOT_DATA] = prev_zone(CURSEG_COLD_NODE);
+		config.cur_seg[CURSEG_COLD_DATA] = 0;
+		config.cur_seg[CURSEG_WARM_DATA] = next_zone(CURSEG_COLD_DATA);
+	} else {
+		config.cur_seg[CURSEG_HOT_NODE] = 0;
+		config.cur_seg[CURSEG_WARM_NODE] = next_zone(CURSEG_HOT_NODE);
+		config.cur_seg[CURSEG_COLD_NODE] = next_zone(CURSEG_WARM_NODE);
+		config.cur_seg[CURSEG_HOT_DATA] = next_zone(CURSEG_COLD_NODE);
+		config.cur_seg[CURSEG_COLD_DATA] = next_zone(CURSEG_HOT_DATA);
+		config.cur_seg[CURSEG_WARM_DATA] = next_zone(CURSEG_COLD_DATA);
+	}
+
+	configure_extension_list();
+
+	/* get kernel version */
+	if (config.kd >= 0) {
+		dev_read_version(config.version, 0, VERSION_LEN);
+		get_kernel_version(config.version);
+		MSG(0, "Info: format version with\n  \"%s\"\n", config.version);
+	} else {
+		memset(config.version, 0, VERSION_LEN);
+	}
+
+	memcpy(sb.version, config.version, VERSION_LEN);
+	memcpy(sb.init_version, config.version, VERSION_LEN);
+
+	return 0;
+}
+
+static int f2fs_init_sit_area(void)
+{
+	u_int32_t blk_size, seg_size;
+	u_int32_t index = 0;
+	u_int64_t sit_seg_addr = 0;
+	u_int8_t *zero_buf = NULL;
+
+	blk_size = 1 << get_sb(log_blocksize);
+	seg_size = (1 << get_sb(log_blocks_per_seg)) * blk_size;
+
+	zero_buf = calloc(sizeof(u_int8_t), seg_size);
+	if(zero_buf == NULL) {
+		MSG(1, "\tError: Calloc Failed for sit_zero_buf!!!\n");
+		return -1;
+	}
+
+	sit_seg_addr = get_sb(sit_blkaddr);
+	sit_seg_addr *= blk_size;
+
+	DBG(1, "\tFilling sit area at offset 0x%08"PRIx64"\n", sit_seg_addr);
+	for (index = 0; index < (get_sb(segment_count_sit) / 2); index++) {
+		if (dev_fill(zero_buf, sit_seg_addr, seg_size)) {
+			MSG(1, "\tError: While zeroing out the sit area \
+					on disk!!!\n");
+			free(zero_buf);
+			return -1;
+		}
+		sit_seg_addr += seg_size;
+	}
+
+	free(zero_buf);
+	return 0 ;
+}
+
+static int f2fs_init_nat_area(void)
+{
+	u_int32_t blk_size, seg_size;
+	u_int32_t index = 0;
+	u_int64_t nat_seg_addr = 0;
+	u_int8_t *nat_buf = NULL;
+
+	blk_size = 1 << get_sb(log_blocksize);
+	seg_size = (1 << get_sb(log_blocks_per_seg)) * blk_size;
+
+	nat_buf = calloc(sizeof(u_int8_t), seg_size);
+	if (nat_buf == NULL) {
+		MSG(1, "\tError: Calloc Failed for nat_zero_blk!!!\n");
+		return -1;
+	}
+
+	nat_seg_addr = get_sb(nat_blkaddr);
+	nat_seg_addr *= blk_size;
+
+	DBG(1, "\tFilling nat area at offset 0x%08"PRIx64"\n", nat_seg_addr);
+	for (index = 0; index < get_sb(segment_count_nat) / 2; index++) {
+		if (dev_fill(nat_buf, nat_seg_addr, seg_size)) {
+			MSG(1, "\tError: While zeroing out the nat area \
+					on disk!!!\n");
+			free(nat_buf);
+			return -1;
+		}
+		nat_seg_addr = nat_seg_addr + (2 * seg_size);
+	}
+
+	free(nat_buf);
+	return 0 ;
+}
+
+static int f2fs_write_check_point_pack(void)
+{
+	struct f2fs_summary_block *sum = NULL;
+	u_int32_t blk_size_bytes;
+	u_int64_t cp_seg_blk_offset = 0;
+	u_int32_t crc = 0;
+	unsigned int i;
+	char *cp_payload = NULL;
+	char *sum_compact, *sum_compact_p;
+	struct f2fs_summary *sum_entry;
+	int ret = -1;
+
+	cp = calloc(F2FS_BLKSIZE, 1);
+	if (cp == NULL) {
+		MSG(1, "\tError: Calloc Failed for f2fs_checkpoint!!!\n");
+		return ret;
+	}
+
+	sum = calloc(F2FS_BLKSIZE, 1);
+	if (sum == NULL) {
+		MSG(1, "\tError: Calloc Failed for summay_node!!!\n");
+		goto free_cp;
+	}
+
+	sum_compact = calloc(F2FS_BLKSIZE, 1);
+	if (sum == NULL) {
+		MSG(1, "\tError: Calloc Failed for summay buffer!!!\n");
+		goto free_sum;
+	}
+	sum_compact_p = sum_compact;
+
+	cp_payload = calloc(F2FS_BLKSIZE, 1);
+	if (cp_payload == NULL) {
+		MSG(1, "\tError: Calloc Failed for cp_payload!!!\n");
+		goto free_sum_compact;
+	}
+
+	/* 1. cp page 1 of checkpoint pack 1 */
+	set_cp(checkpoint_ver, 1);
+	set_cp(cur_node_segno[0], config.cur_seg[CURSEG_HOT_NODE]);
+	set_cp(cur_node_segno[1], config.cur_seg[CURSEG_WARM_NODE]);
+	set_cp(cur_node_segno[2], config.cur_seg[CURSEG_COLD_NODE]);
+	set_cp(cur_data_segno[0], config.cur_seg[CURSEG_HOT_DATA]);
+	set_cp(cur_data_segno[1], config.cur_seg[CURSEG_WARM_DATA]);
+	set_cp(cur_data_segno[2], config.cur_seg[CURSEG_COLD_DATA]);
+	for (i = 3; i < MAX_ACTIVE_NODE_LOGS; i++) {
+		set_cp(cur_node_segno[i], 0xffffffff);
+		set_cp(cur_data_segno[i], 0xffffffff);
+	}
+
+	set_cp(cur_node_blkoff[0], 1);
+	set_cp(cur_data_blkoff[0], 1);
+	set_cp(valid_block_count, 2);
+	set_cp(rsvd_segment_count, config.reserved_segments);
+	set_cp(overprov_segment_count, (get_sb(segment_count_main) -
+			get_cp(rsvd_segment_count)) *
+			config.overprovision / 100);
+	set_cp(overprov_segment_count, get_cp(overprov_segment_count) +
+			get_cp(rsvd_segment_count));
+
+	/* main segments - reserved segments - (node + data segments) */
+	set_cp(free_segment_count, get_sb(segment_count_main) - 6);
+	set_cp(user_block_count, ((get_cp(free_segment_count) + 6 -
+			get_cp(overprov_segment_count)) * config.blks_per_seg));
+	/* cp page (2), data summaries (1), node summaries (3) */
+	set_cp(cp_pack_total_block_count, 6 + get_sb(cp_payload));
+	set_cp(ckpt_flags, CP_UMOUNT_FLAG | CP_COMPACT_SUM_FLAG);
+	set_cp(cp_pack_start_sum, 1 + get_sb(cp_payload));
+	set_cp(valid_node_count, 1);
+	set_cp(valid_inode_count, 1);
+	set_cp(next_free_nid, get_sb(root_ino) + 1);
+	set_cp(sit_ver_bitmap_bytesize, ((get_sb(segment_count_sit) / 2) <<
+			get_sb(log_blocks_per_seg)) / 8);
+
+	set_cp(nat_ver_bitmap_bytesize, ((get_sb(segment_count_nat) / 2) <<
+			 get_sb(log_blocks_per_seg)) / 8);
+
+	set_cp(checksum_offset, CHECKSUM_OFFSET);
+
+	crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, cp, CHECKSUM_OFFSET);
+	*((__le32 *)((unsigned char *)cp + CHECKSUM_OFFSET)) =
+							cpu_to_le32(crc);
+
+	blk_size_bytes = 1 << get_sb(log_blocksize);
+	cp_seg_blk_offset = get_sb(segment0_blkaddr);
+	cp_seg_blk_offset *= blk_size_bytes;
+
+	DBG(1, "\tWriting main segments, cp at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
+	if (dev_write(cp, cp_seg_blk_offset, blk_size_bytes)) {
+		MSG(1, "\tError: While writing the cp to disk!!!\n");
+		goto free_cp_payload;
+	}
+
+	for (i = 0; i < get_sb(cp_payload); i++) {
+		cp_seg_blk_offset += blk_size_bytes;
+		if (dev_fill(cp_payload, cp_seg_blk_offset, blk_size_bytes)) {
+			MSG(1, "\tError: While zeroing out the sit bitmap area \
+					on disk!!!\n");
+			goto free_cp_payload;
+		}
+	}
+
+	/* Prepare and write Segment summary for HOT/WARM/COLD DATA
+	 *
+	 * The structure of compact summary
+	 * +-------------------+
+	 * | nat_journal       |
+	 * +-------------------+
+	 * | sit_journal       |
+	 * +-------------------+
+	 * | hot data summary  |
+	 * +-------------------+
+	 * | warm data summary |
+	 * +-------------------+
+	 * | cold data summary |
+	 * +-------------------+
+	*/
+	memset(sum, 0, sizeof(struct f2fs_summary_block));
+	SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA);
+
+	sum->n_nats = cpu_to_le16(1);
+	sum->nat_j.entries[0].nid = sb.root_ino;
+	sum->nat_j.entries[0].ne.version = 0;
+	sum->nat_j.entries[0].ne.ino = sb.root_ino;
+	sum->nat_j.entries[0].ne.block_addr = cpu_to_le32(
+			get_sb(main_blkaddr) +
+			get_cp(cur_node_segno[0]) * config.blks_per_seg);
+
+	memcpy(sum_compact_p, &sum->n_nats, SUM_JOURNAL_SIZE);
+	sum_compact_p += SUM_JOURNAL_SIZE;
+
+	memset(sum, 0, sizeof(struct f2fs_summary_block));
+	/* inode sit for root */
+	sum->n_sits = cpu_to_le16(6);
+	sum->sit_j.entries[0].segno = cp->cur_node_segno[0];
+	sum->sit_j.entries[0].se.vblocks = cpu_to_le16((CURSEG_HOT_NODE << 10) | 1);
+	f2fs_set_bit(0, (char *)sum->sit_j.entries[0].se.valid_map);
+	sum->sit_j.entries[1].segno = cp->cur_node_segno[1];
+	sum->sit_j.entries[1].se.vblocks = cpu_to_le16((CURSEG_WARM_NODE << 10));
+	sum->sit_j.entries[2].segno = cp->cur_node_segno[2];
+	sum->sit_j.entries[2].se.vblocks = cpu_to_le16((CURSEG_COLD_NODE << 10));
+
+	/* data sit for root */
+	sum->sit_j.entries[3].segno = cp->cur_data_segno[0];
+	sum->sit_j.entries[3].se.vblocks = cpu_to_le16((CURSEG_HOT_DATA << 10) | 1);
+	f2fs_set_bit(0, (char *)sum->sit_j.entries[3].se.valid_map);
+	sum->sit_j.entries[4].segno = cp->cur_data_segno[1];
+	sum->sit_j.entries[4].se.vblocks = cpu_to_le16((CURSEG_WARM_DATA << 10));
+	sum->sit_j.entries[5].segno = cp->cur_data_segno[2];
+	sum->sit_j.entries[5].se.vblocks = cpu_to_le16((CURSEG_COLD_DATA << 10));
+
+	memcpy(sum_compact_p, &sum->n_sits, SUM_JOURNAL_SIZE);
+	sum_compact_p += SUM_JOURNAL_SIZE;
+
+	/* hot data summary */
+	sum_entry = (struct f2fs_summary *)sum_compact_p;
+	sum_entry->nid = sb.root_ino;
+	sum_entry->ofs_in_node = 0;
+	/* warm data summary, nothing to do */
+	/* cold data summary, nothing to do */
+
+	cp_seg_blk_offset += blk_size_bytes;
+	DBG(1, "\tWriting Segment summary for HOT/WARM/COLD_DATA, at offset 0x%08"PRIx64"\n",
+			cp_seg_blk_offset);
+	if (dev_write(sum_compact, cp_seg_blk_offset, blk_size_bytes)) {
+		MSG(1, "\tError: While writing the sum_blk to disk!!!\n");
+		goto free_cp_payload;
+	}
+
+	/* Prepare and write Segment summary for HOT_NODE */
+	memset(sum, 0, sizeof(struct f2fs_summary_block));
+	SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE);
+
+	sum->entries[0].nid = sb.root_ino;
+	sum->entries[0].ofs_in_node = 0;
+
+	cp_seg_blk_offset += blk_size_bytes;
+	DBG(1, "\tWriting Segment summary for HOT_NODE, at offset 0x%08"PRIx64"\n",
+			cp_seg_blk_offset);
+	if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) {
+		MSG(1, "\tError: While writing the sum_blk to disk!!!\n");
+		goto free_cp_payload;
+	}
+
+	/* Fill segment summary for WARM_NODE to zero. */
+	memset(sum, 0, sizeof(struct f2fs_summary_block));
+	SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE);
+
+	cp_seg_blk_offset += blk_size_bytes;
+	DBG(1, "\tWriting Segment summary for WARM_NODE, at offset 0x%08"PRIx64"\n",
+			cp_seg_blk_offset);
+	if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) {
+		MSG(1, "\tError: While writing the sum_blk to disk!!!\n");
+		goto free_cp_payload;
+	}
+
+	/* Fill segment summary for COLD_NODE to zero. */
+	memset(sum, 0, sizeof(struct f2fs_summary_block));
+	SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE);
+	cp_seg_blk_offset += blk_size_bytes;
+	DBG(1, "\tWriting Segment summary for COLD_NODE, at offset 0x%08"PRIx64"\n",
+			cp_seg_blk_offset);
+	if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) {
+		MSG(1, "\tError: While writing the sum_blk to disk!!!\n");
+		goto free_cp_payload;
+	}
+
+	/* cp page2 */
+	cp_seg_blk_offset += blk_size_bytes;
+	DBG(1, "\tWriting cp page2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
+	if (dev_write(cp, cp_seg_blk_offset, blk_size_bytes)) {
+		MSG(1, "\tError: While writing the cp to disk!!!\n");
+		goto free_cp_payload;
+	}
+
+	/* cp page 1 of check point pack 2
+	 * Initiatialize other checkpoint pack with version zero
+	 */
+	cp->checkpoint_ver = 0;
+
+	crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, cp, CHECKSUM_OFFSET);
+	*((__le32 *)((unsigned char *)cp + CHECKSUM_OFFSET)) =
+							cpu_to_le32(crc);
+	cp_seg_blk_offset = (get_sb(segment0_blkaddr) +
+				config.blks_per_seg) *
+				blk_size_bytes;
+	DBG(1, "\tWriting cp page 1 of checkpoint pack 2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
+	if (dev_write(cp, cp_seg_blk_offset, blk_size_bytes)) {
+		MSG(1, "\tError: While writing the cp to disk!!!\n");
+		goto free_cp_payload;
+	}
+
+	for (i = 0; i < get_sb(cp_payload); i++) {
+		cp_seg_blk_offset += blk_size_bytes;
+		if (dev_fill(cp_payload, cp_seg_blk_offset, blk_size_bytes)) {
+			MSG(1, "\tError: While zeroing out the sit bitmap area \
+					on disk!!!\n");
+			goto free_cp_payload;
+		}
+	}
+
+	/* cp page 2 of check point pack 2 */
+	cp_seg_blk_offset += blk_size_bytes * (le32_to_cpu(cp->cp_pack_total_block_count)
+			- get_sb(cp_payload) - 1);
+	DBG(1, "\tWriting cp page 2 of checkpoint pack 2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
+	if (dev_write(cp, cp_seg_blk_offset, blk_size_bytes)) {
+		MSG(1, "\tError: While writing the cp to disk!!!\n");
+		goto free_cp_payload;
+	}
+
+	ret = 0;
+
+free_cp_payload:
+	free(cp_payload);
+free_sum_compact:
+	free(sum_compact);
+free_sum:
+	free(sum);
+free_cp:
+	free(cp);
+	return ret;
+}
+
+static int f2fs_write_super_block(void)
+{
+	int index;
+	u_int8_t *zero_buff;
+
+	zero_buff = calloc(F2FS_BLKSIZE, 1);
+
+	memcpy(zero_buff + F2FS_SUPER_OFFSET, &sb,
+						sizeof(sb));
+	DBG(1, "\tWriting super block, at offset 0x%08x\n", 0);
+	for (index = 0; index < 2; index++) {
+		if (dev_write(zero_buff, index * F2FS_BLKSIZE, F2FS_BLKSIZE)) {
+			MSG(1, "\tError: While while writing supe_blk \
+					on disk!!! index : %d\n", index);
+			free(zero_buff);
+			return -1;
+		}
+	}
+
+	free(zero_buff);
+	return 0;
+}
+
+static int f2fs_write_root_inode(void)
+{
+	struct f2fs_node *raw_node = NULL;
+	u_int64_t blk_size_bytes, data_blk_nor;
+	u_int64_t main_area_node_seg_blk_offset = 0;
+
+	raw_node = calloc(F2FS_BLKSIZE, 1);
+	if (raw_node == NULL) {
+		MSG(1, "\tError: Calloc Failed for raw_node!!!\n");
+		return -1;
+	}
+
+	raw_node->footer.nid = sb.root_ino;
+	raw_node->footer.ino = sb.root_ino;
+	raw_node->footer.cp_ver = cpu_to_le64(1);
+	raw_node->footer.next_blkaddr = cpu_to_le32(
+			get_sb(main_blkaddr) +
+			config.cur_seg[CURSEG_HOT_NODE] *
+			config.blks_per_seg + 1);
+
+	raw_node->i.i_mode = cpu_to_le16(0x41ed);
+	raw_node->i.i_links = cpu_to_le32(2);
+	raw_node->i.i_uid = cpu_to_le32(getuid());
+	raw_node->i.i_gid = cpu_to_le32(getgid());
+
+	blk_size_bytes = 1 << get_sb(log_blocksize);
+	raw_node->i.i_size = cpu_to_le64(1 * blk_size_bytes); /* dentry */
+	raw_node->i.i_blocks = cpu_to_le64(2);
+
+	raw_node->i.i_atime = cpu_to_le32(time(NULL));
+	raw_node->i.i_atime_nsec = 0;
+	raw_node->i.i_ctime = cpu_to_le32(time(NULL));
+	raw_node->i.i_ctime_nsec = 0;
+	raw_node->i.i_mtime = cpu_to_le32(time(NULL));
+	raw_node->i.i_mtime_nsec = 0;
+	raw_node->i.i_generation = 0;
+	raw_node->i.i_xattr_nid = 0;
+	raw_node->i.i_flags = 0;
+	raw_node->i.i_current_depth = cpu_to_le32(1);
+	raw_node->i.i_dir_level = DEF_DIR_LEVEL;
+
+	data_blk_nor = get_sb(main_blkaddr) +
+		config.cur_seg[CURSEG_HOT_DATA] * config.blks_per_seg;
+	raw_node->i.i_addr[0] = cpu_to_le32(data_blk_nor);
+
+	raw_node->i.i_ext.fofs = 0;
+	raw_node->i.i_ext.blk_addr = cpu_to_le32(data_blk_nor);
+	raw_node->i.i_ext.len = cpu_to_le32(1);
+
+	main_area_node_seg_blk_offset = get_sb(main_blkaddr);
+	main_area_node_seg_blk_offset += config.cur_seg[CURSEG_HOT_NODE] *
+					config.blks_per_seg;
+        main_area_node_seg_blk_offset *= blk_size_bytes;
+
+	DBG(1, "\tWriting root inode (hot node), at offset 0x%08"PRIx64"\n", main_area_node_seg_blk_offset);
+	if (dev_write(raw_node, main_area_node_seg_blk_offset, F2FS_BLKSIZE)) {
+		MSG(1, "\tError: While writing the raw_node to disk!!!\n");
+		free(raw_node);
+		return -1;
+	}
+
+	memset(raw_node, 0xff, sizeof(struct f2fs_node));
+
+	/* avoid power-off-recovery based on roll-forward policy */
+	main_area_node_seg_blk_offset = get_sb(main_blkaddr);
+	main_area_node_seg_blk_offset += config.cur_seg[CURSEG_WARM_NODE] *
+					config.blks_per_seg;
+        main_area_node_seg_blk_offset *= blk_size_bytes;
+
+	DBG(1, "\tWriting root inode (warm node), at offset 0x%08"PRIx64"\n", main_area_node_seg_blk_offset);
+	if (dev_write(raw_node, main_area_node_seg_blk_offset, F2FS_BLKSIZE)) {
+		MSG(1, "\tError: While writing the raw_node to disk!!!\n");
+		free(raw_node);
+		return -1;
+	}
+	free(raw_node);
+	return 0;
+}
+
+static int f2fs_update_nat_root(void)
+{
+	struct f2fs_nat_block *nat_blk = NULL;
+	u_int64_t blk_size_bytes, nat_seg_blk_offset = 0;
+
+	nat_blk = calloc(F2FS_BLKSIZE, 1);
+	if(nat_blk == NULL) {
+		MSG(1, "\tError: Calloc Failed for nat_blk!!!\n");
+		return -1;
+	}
+
+	/* update root */
+	nat_blk->entries[get_sb(root_ino)].block_addr = cpu_to_le32(
+		get_sb(main_blkaddr) +
+		config.cur_seg[CURSEG_HOT_NODE] * config.blks_per_seg);
+	nat_blk->entries[get_sb(root_ino)].ino = sb.root_ino;
+
+	/* update node nat */
+	nat_blk->entries[get_sb(node_ino)].block_addr = cpu_to_le32(1);
+	nat_blk->entries[get_sb(node_ino)].ino = sb.node_ino;
+
+	/* update meta nat */
+	nat_blk->entries[get_sb(meta_ino)].block_addr = cpu_to_le32(1);
+	nat_blk->entries[get_sb(meta_ino)].ino = sb.meta_ino;
+
+	blk_size_bytes = 1 << get_sb(log_blocksize);
+	nat_seg_blk_offset = get_sb(nat_blkaddr);
+	nat_seg_blk_offset *= blk_size_bytes;
+
+	DBG(1, "\tWriting nat root, at offset 0x%08"PRIx64"\n", nat_seg_blk_offset);
+	if (dev_write(nat_blk, nat_seg_blk_offset, F2FS_BLKSIZE)) {
+		MSG(1, "\tError: While writing the nat_blk set0 to disk!\n");
+		free(nat_blk);
+		return -1;
+	}
+
+	free(nat_blk);
+	return 0;
+}
+
+static int f2fs_add_default_dentry_root(void)
+{
+	struct f2fs_dentry_block *dent_blk = NULL;
+	u_int64_t blk_size_bytes, data_blk_offset = 0;
+
+	dent_blk = calloc(F2FS_BLKSIZE, 1);
+	if(dent_blk == NULL) {
+		MSG(1, "\tError: Calloc Failed for dent_blk!!!\n");
+		return -1;
+	}
+
+	dent_blk->dentry[0].hash_code = 0;
+	dent_blk->dentry[0].ino = sb.root_ino;
+	dent_blk->dentry[0].name_len = cpu_to_le16(1);
+	dent_blk->dentry[0].file_type = F2FS_FT_DIR;
+	memcpy(dent_blk->filename[0], ".", 1);
+
+	dent_blk->dentry[1].hash_code = 0;
+	dent_blk->dentry[1].ino = sb.root_ino;
+	dent_blk->dentry[1].name_len = cpu_to_le16(2);
+	dent_blk->dentry[1].file_type = F2FS_FT_DIR;
+	memcpy(dent_blk->filename[1], "..", 2);
+
+	/* bitmap for . and .. */
+	dent_blk->dentry_bitmap[0] = (1 << 1) | (1 << 0);
+	blk_size_bytes = 1 << get_sb(log_blocksize);
+	data_blk_offset = get_sb(main_blkaddr);
+	data_blk_offset += config.cur_seg[CURSEG_HOT_DATA] *
+				config.blks_per_seg;
+	data_blk_offset *= blk_size_bytes;
+
+	DBG(1, "\tWriting default dentry root, at offset 0x%08"PRIx64"\n", data_blk_offset);
+	if (dev_write(dent_blk, data_blk_offset, F2FS_BLKSIZE)) {
+		MSG(1, "\tError: While writing the dentry_blk to disk!!!\n");
+		free(dent_blk);
+		return -1;
+	}
+
+	free(dent_blk);
+	return 0;
+}
+
+static int f2fs_create_root_dir(void)
+{
+	int err = 0;
+
+	err = f2fs_write_root_inode();
+	if (err < 0) {
+		MSG(1, "\tError: Failed to write root inode!!!\n");
+		goto exit;
+	}
+
+	err = f2fs_update_nat_root();
+	if (err < 0) {
+		MSG(1, "\tError: Failed to update NAT for root!!!\n");
+		goto exit;
+	}
+
+	err = f2fs_add_default_dentry_root();
+	if (err < 0) {
+		MSG(1, "\tError: Failed to add default dentries for root!!!\n");
+		goto exit;
+	}
+exit:
+	if (err)
+		MSG(1, "\tError: Could not create the root directory!!!\n");
+
+	return err;
+}
+
+int f2fs_format_device(void)
+{
+	int err = 0;
+
+	err= f2fs_prepare_super_block();
+	if (err < 0) {
+		MSG(0, "\tError: Failed to prepare a super block!!!\n");
+		goto exit;
+	}
+
+	err = f2fs_trim_device();
+	if (err < 0) {
+		MSG(0, "\tError: Failed to trim whole device!!!\n");
+		goto exit;
+	}
+
+	err = f2fs_init_sit_area();
+	if (err < 0) {
+		MSG(0, "\tError: Failed to Initialise the SIT AREA!!!\n");
+		goto exit;
+	}
+
+	err = f2fs_init_nat_area();
+	if (err < 0) {
+		MSG(0, "\tError: Failed to Initialise the NAT AREA!!!\n");
+		goto exit;
+	}
+
+	err = f2fs_create_root_dir();
+	if (err < 0) {
+		MSG(0, "\tError: Failed to create the root directory!!!\n");
+		goto exit;
+	}
+
+	err = f2fs_write_check_point_pack();
+	if (err < 0) {
+		MSG(0, "\tError: Failed to write the check point pack!!!\n");
+		goto exit;
+	}
+
+	err = f2fs_write_super_block();
+	if (err < 0) {
+		MSG(0, "\tError: Failed to write the Super Block!!!\n");
+		goto exit;
+	}
+exit:
+	if (err)
+		MSG(0, "\tError: Could not format the device!!!\n");
+
+	return err;
+}
diff --git a/f2fs-tools/mkfs/f2fs_format_main.c b/f2fs-tools/mkfs/f2fs_format_main.c
new file mode 100644
index 0000000..bba2085
--- /dev/null
+++ b/f2fs-tools/mkfs/f2fs_format_main.c
@@ -0,0 +1,139 @@
+/**
+ * f2fs_format.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Dual licensed under the GPL or LGPL version 2 licenses.
+ */
+#define _LARGEFILE64_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <time.h>
+//#include <linux/fs.h>
+#include <uuid/uuid.h>
+
+#include "f2fs_fs.h"
+#include "f2fs_format_utils.h"
+
+extern struct f2fs_configuration config;
+
+static void mkfs_usage()
+{
+	MSG(0, "\nUsage: mkfs.f2fs [options] device [sectors]\n");
+	MSG(0, "[options]:\n");
+	MSG(0, "  -a heap-based allocation [default:1]\n");
+	MSG(0, "  -d debug level [default:0]\n");
+	MSG(0, "  -e [extension list] e.g. \"mp3,gif,mov\"\n");
+	MSG(0, "  -l label\n");
+	MSG(0, "  -o overprovision ratio [default:5]\n");
+	MSG(0, "  -s # of segments per section [default:1]\n");
+	MSG(0, "  -z # of sections per zone [default:1]\n");
+	MSG(0, "  -t 0: nodiscard, 1: discard [default:1]\n");
+	MSG(0, "sectors: number of sectors. [default: determined by device size]\n");
+	exit(1);
+}
+
+static void f2fs_parse_options(int argc, char *argv[])
+{
+	static const char *option_string = "a:d:e:l:o:s:z:t:";
+	int32_t option=0;
+
+	while ((option = getopt(argc,argv,option_string)) != EOF) {
+		switch (option) {
+		case 'a':
+			config.heap = atoi(optarg);
+			if (config.heap == 0)
+				MSG(0, "Info: Disable heap-based policy\n");
+			break;
+		case 'd':
+			config.dbg_lv = atoi(optarg);
+			MSG(0, "Info: Debug level = %d\n", config.dbg_lv);
+			break;
+		case 'e':
+			config.extension_list = strdup(optarg);
+			MSG(0, "Info: Add new extension list\n");
+			break;
+		case 'l':		/*v: volume label */
+			if (strlen(optarg) > 512) {
+				MSG(0, "Error: Volume Label should be less than\
+						512 characters\n");
+				mkfs_usage();
+			}
+			config.vol_label = optarg;
+			MSG(0, "Info: Label = %s\n", config.vol_label);
+			break;
+		case 'o':
+			config.overprovision = atoi(optarg);
+			MSG(0, "Info: Overprovision ratio = %u%%\n",
+								atoi(optarg));
+			break;
+		case 's':
+			config.segs_per_sec = atoi(optarg);
+			MSG(0, "Info: Segments per section = %d\n",
+								atoi(optarg));
+			break;
+		case 'z':
+			config.secs_per_zone = atoi(optarg);
+			MSG(0, "Info: Sections per zone = %d\n", atoi(optarg));
+			break;
+		case 't':
+			config.trim = atoi(optarg);
+			MSG(0, "Info: Trim is %s\n", config.trim ? "enabled": "disabled");
+			break;
+		default:
+			MSG(0, "\tError: Unknown option %c\n",option);
+			mkfs_usage();
+			break;
+		}
+	}
+
+	if (optind >= argc) {
+		MSG(0, "\tError: Device not specified\n");
+		mkfs_usage();
+	}
+	config.device_name = argv[optind];
+
+	if ((optind + 1) < argc) {
+		/* We have a sector count. */
+		config.total_sectors = atoll(argv[optind+1]);
+		MSG(0, "\ttotal_sectors=%08"PRIx64" (%s bytes)\n",
+				config.total_sectors, argv[optind+1]);
+	}
+
+	config.reserved_segments  =
+			(2 * (100 / config.overprovision + 1) + 6)
+			* config.segs_per_sec;
+	config.segs_per_zone = config.segs_per_sec * config.secs_per_zone;
+}
+
+int main(int argc, char *argv[])
+{
+	MSG(0, "\n\tF2FS-tools: mkfs.f2fs Ver: %s (%s)\n\n",
+				F2FS_TOOLS_VERSION,
+				F2FS_TOOLS_DATE);
+	f2fs_init_configuration(&config);
+
+	f2fs_parse_options(argc, argv);
+
+	if (f2fs_dev_is_umounted(&config) < 0)
+		return -1;
+
+	if (f2fs_get_device_info(&config) < 0)
+		return -1;
+
+	if (f2fs_format_device() < 0)
+		return -1;
+
+	f2fs_finalize_device(&config);
+
+	MSG(0, "Info: format successful\n");
+
+	return 0;
+}
diff --git a/f2fs-tools/mkfs/f2fs_format_utils.c b/f2fs-tools/mkfs/f2fs_format_utils.c
new file mode 100644
index 0000000..a0f85f5
--- /dev/null
+++ b/f2fs-tools/mkfs/f2fs_format_utils.c
@@ -0,0 +1,68 @@
+/**
+ * f2fs_format_utils.c
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Dual licensed under the GPL or LGPL version 2 licenses.
+ */
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "f2fs_fs.h"
+
+#ifdef HAVE_LINUX_FS_H
+#include <linux/fs.h>
+#endif
+#ifdef HAVE_LINUX_FALLOC_H
+#include <linux/falloc.h>
+#endif
+
+int f2fs_trim_device()
+{
+	unsigned long long range[2];
+	struct stat stat_buf;
+
+	if (!config.trim)
+		return 0;
+
+	range[0] = 0;
+	range[1] = config.total_sectors * config.sector_size;
+
+	if (fstat(config.fd, &stat_buf) < 0 ) {
+		MSG(1, "\tError: Failed to get the device stat!!!\n");
+		return -1;
+	}
+
+#if defined(WITH_BLKDISCARD) && defined(BLKDISCARD)
+	MSG(0, "Info: Discarding device\n");
+	if (S_ISREG(stat_buf.st_mode)) {
+#ifdef FALLOC_FL_PUNCH_HOLE
+		if (fallocate(config.fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+				range[0], range[1]) < 0) {
+			MSG(0, "Info: fallocate(PUNCH_HOLE|KEEP_SIZE) is failed\n");
+		}
+#endif
+		return 0;
+	} else if (S_ISBLK(stat_buf.st_mode)) {
+		if (ioctl(config.fd, BLKDISCARD, &range) < 0) {
+			MSG(0, "Info: This device doesn't support TRIM\n");
+		} else {
+			MSG(0, "Info: Discarded %lu sectors\n",
+						config.total_sectors);
+		}
+	} else
+		return -1;
+#endif
+	return 0;
+}
+
diff --git a/f2fs-tools/mkfs/f2fs_format_utils.h b/f2fs-tools/mkfs/f2fs_format_utils.h
new file mode 100644
index 0000000..9eb2cea
--- /dev/null
+++ b/f2fs-tools/mkfs/f2fs_format_utils.h
@@ -0,0 +1,16 @@
+/**
+ * f2fs_format_utils.c
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Dual licensed under the GPL or LGPL version 2 licenses.
+ */
+#define _LARGEFILE64_SOURCE
+
+#include "f2fs_fs.h"
+
+extern struct f2fs_configuration config;
+
+int f2fs_trim_device(void);
+int f2fs_format_device(void);
diff --git a/f2fs-tools/scripts/dumpf2fs.sh b/f2fs-tools/scripts/dumpf2fs.sh
new file mode 100755
index 0000000..2c2a273
--- /dev/null
+++ b/f2fs-tools/scripts/dumpf2fs.sh
@@ -0,0 +1,61 @@
+#!/system/bin/sh
+DEV=/dev/block/mmcblk0p16
+
+CMD=$1
+BASE=0x200000
+BASE_MAIN=0xac00000
+
+case $CMD in
+cp1)
+	echo dump cp1
+	let addr=$BASE
+	echo $addr
+	hexdump -s $addr -n 4096 $DEV;;
+cp2)
+	echo dump cp2
+	let addr=$BASE+0x200000
+	hexdump -s $addr -n 4096 $DEV;;
+cp)
+	echo dump cp1 and cp2
+	let addr=$BASE
+	hexdump -s $addr -n 409 $DEV
+	let addr=$BASE+0x200000
+	hexdump -s $addr -n 4096 $DEV;;
+cp1_all)
+	echo dump cp1 all
+	let addr=$BASE
+	hexdump -s $addr -n 20480 $DEV;;
+cp2_all)
+	echo dump cp2 all
+	let addr=$BASE+0x200000
+	hexdump -s $addr -n 20480 $DEV;;
+cp_all)
+	echo dump cp1 and cp2 all
+	let addr=$BASE
+	hexdump -s $addr -n 20480 $DEV
+	let addr=$BASE+0x200000
+	hexdump -s $addr -n 20480 $DEV;;
+blk)
+	let addr=$BASE_MAIN+$2*0x200000+$3*0x1000
+	hexdump -s $addr -n 4096 $DEV
+	echo ;;
+inode)
+	let addr=$BASE_MAIN+$2*0x200000+$3*0x1000
+	for i in `seq $3 511`
+	do
+		hexdump -s $addr -n 8 $DEV
+		let end=$addr+0x0ff0
+		hexdump -s $end -n 16 $DEV
+		let addr=$addr+0x1000
+	done
+	echo ;;
+*)
+	let addr=$1*0x1000
+	let segno=$addr-$BASE_MAIN
+	let segno=$segno/0x200000
+	let off=$addr-$BASE_MAIN
+	let off=$off%0x200000/0x1000
+	echo $segno, $off
+	hexdump -s $addr -n 4096 $DEV
+	echo ;;
+esac
diff --git a/f2fs-tools/scripts/spo_test.sh b/f2fs-tools/scripts/spo_test.sh
new file mode 100755
index 0000000..2191214
--- /dev/null
+++ b/f2fs-tools/scripts/spo_test.sh
@@ -0,0 +1,70 @@
+#!/bin/bash
+
+MNT=/mnt/f2fs
+DEV=/dev/sdb1
+USER_DIR=/home/zeus
+F2FS_DIR=$USER_DIR/f2fs_test
+
+check_stop() {
+	stop=`cat /tmp/stop`
+	if [ $stop -eq 1 ]; then
+		exit
+	fi
+}
+
+case $1 in
+start)
+	echo 0 > /tmp/stop
+	umount /mnt/*
+	echo 3 > /proc/sys/vm/drop_caches
+	echo 8 > /proc/sys/kernel/printk
+
+	date >> $USER_DIR/por_result
+	sync
+
+	insmod $F2FS_DIR/src/fs/f2fs/f2fs.ko || exit
+
+	echo Start checking F2FS without fsync
+	check_stop
+	fsck.f2fs $DEV -d 0 || exit
+	mount -t f2fs -o disable_roll_forward $DEV $MNT || exit
+	umount $MNT
+	echo 3 > /proc/sys/vm/drop_caches
+
+	echo Start checking F2FS with fsync
+	check_stop
+	fsck.f2fs $DEV -d 0 || exit
+	mount -t f2fs $DEV $MNT || exit
+	umount $MNT
+
+	check_stop
+	fsck.f2fs $DEV -d 0 || exit
+	mount -t f2fs $DEV $MNT || exit
+
+	count=`cat $USER_DIR/por_time`
+	if [ $count -eq 20 ]; then
+		echo Start rm all
+		time rm -rf $MNT/* || exit
+		echo 0 > $USER_DIR/por_time
+		sync
+	else
+		echo $((count+1)) > $USER_DIR/por_time
+	fi
+	echo 8 > /proc/sys/kernel/printk
+	echo Start fsstress
+	date
+	$F2FS_DIR/stress_test/fsstress/fsstress -z -f link=0 -f mkdir=3 -f mknod=3 -f rmdir=2 -f symlink=3 -f truncate=4 -f write=10 -f creat=10 -f unlink=5 -f rename=5 -f fsync=10 -p 10 -n 10000 -l 0 -d $MNT &
+	RANDOM=`date '+%s'`
+	rand=$[($RANDOM % 540) + 60]
+	echo Start sleep: $rand seconds
+	sleep $rand
+
+	echo Reboot now
+	check_stop
+	echo b > /proc/sysrq-trigger
+	;;
+stop)
+	killall -9 fsstress
+	echo 1 > /tmp/stop
+	;;
+esac
diff --git a/f2fs-tools/scripts/tracepoint.sh b/f2fs-tools/scripts/tracepoint.sh
new file mode 100755
index 0000000..15588d7
--- /dev/null
+++ b/f2fs-tools/scripts/tracepoint.sh
@@ -0,0 +1,71 @@
+#!/system/bin/sh
+
+TRACE=/sys/kernel/debug/tracing/
+dev=$(((8<<20) + 17)) # sdb1 (8,17)
+
+echo 1 > $TRACE/tracing_on
+
+# mmc tracepoints
+echo 0 > $TRACE/events/mmc/enable
+
+# block tracepoints
+#echo "dev == $dev" > $TRACE/events/block/block_rq_complete/filter
+echo 0 > $TRACE/events/block/block_rq_complete/enable
+echo 0 > $TRACE/events/block/block_bio_complete/enable
+
+# GC
+G=0
+echo $G > $TRACE/events/f2fs/f2fs_get_victim/enable
+
+# block allocation
+A=0
+echo $A > $TRACE/events/f2fs/f2fs_reserve_new_block/enable
+
+# block truncation
+T=0
+echo $T > $TRACE/events/f2fs/f2fs_truncate/enable
+echo $T > $TRACE/events/f2fs/f2fs_truncate_inode_blocks_enter/enable
+echo $T > $TRACE/events/f2fs/f2fs_truncate_inode_blocks_exit/enable
+echo $T > $TRACE/events/f2fs/f2fs_truncate_blocks_enter/enable
+echo $T > $TRACE/events/f2fs/f2fs_truncate_blocks_exit/enable
+echo $T > $TRACE/events/f2fs/f2fs_truncate_nodes_enter/enable
+echo $T > $TRACE/events/f2fs/f2fs_truncate_nodes_exit/enable
+echo $T > $TRACE/events/f2fs/f2fs_truncate_data_blocks_range/enable
+echo $T > $TRACE/events/f2fs/f2fs_truncate_node/enable
+echo $T > $TRACE/events/f2fs/f2fs_truncate_partial_nodes/enable
+
+# syscalls
+S=0
+echo $S > $TRACE/events/f2fs/f2fs_unlink_enter/enable
+echo $S > $TRACE/events/f2fs/f2fs_unlink_exit/enable
+echo $S > $TRACE/events/f2fs/f2fs_fallocate/enable
+echo $S > $TRACE/events/f2fs/f2fs_get_data_block/enable
+
+# IOs
+R=0
+W=0
+echo $R > $TRACE/events/f2fs/f2fs_readpage/enable
+echo $W > $TRACE/events/f2fs/f2fs_writepage/enable
+echo $W > $TRACE/events/f2fs/f2fs_write_begin/enable
+echo $W > $TRACE/events/f2fs/f2fs_write_end/enable
+
+echo 0 > $TRACE/events/f2fs/f2fs_submit_page_bio/enable
+echo 0 > $TRACE/events/f2fs/f2fs_submit_page_mbio/enable
+echo $R > $TRACE/events/f2fs/f2fs_submit_read_bio/enable
+echo $W > $TRACE/events/f2fs/f2fs_submit_write_bio/enable
+
+echo 0 > $TRACE/events/f2fs/f2fs_issue_discard/enable
+echo 0 > $TRACE/events/f2fs/f2fs_issue_flush/enable
+
+# VFS interfaces
+V=0
+echo $V > $TRACE/events/f2fs/f2fs_iget/enable
+echo $V > $TRACE/events/f2fs/f2fs_iget_exit/enable
+echo $V > $TRACE/events/f2fs/f2fs_new_inode/enable
+echo $V > $TRACE/events/f2fs/f2fs_evict_inode/enable
+echo $V > $TRACE/events/f2fs/f2fs_sync_file_enter/enable
+echo $V > $TRACE/events/f2fs/f2fs_sync_file_exit/enable
+echo $V > $TRACE/events/f2fs/f2fs_write_checkpoint/enable
+echo $V > $TRACE/events/f2fs/f2fs_sync_fs/enable
+
+cat $TRACE/trace_pipe
diff --git a/f2fs-tools/tools/Makefile.am b/f2fs-tools/tools/Makefile.am
new file mode 100644
index 0000000..69a0bb1
--- /dev/null
+++ b/f2fs-tools/tools/Makefile.am
@@ -0,0 +1,8 @@
+## Makefile.am
+
+AM_CPPFLAGS = ${libuuid_CFLAGS} -I$(top_srcdir)/include
+AM_CFLAGS = -Wall
+sbin_PROGRAMS = f2fstat fibmap.f2fs parse.f2fs
+f2fstat_SOURCES = f2fstat.c
+fibmap_f2fs_SOURCES = fibmap.c
+parse_f2fs_SOURCES = f2fs_io_parse.c
diff --git a/f2fs-tools/tools/f2fs_io_parse.c b/f2fs-tools/tools/f2fs_io_parse.c
new file mode 100644
index 0000000..7f97270
--- /dev/null
+++ b/f2fs-tools/tools/f2fs_io_parse.c
@@ -0,0 +1,322 @@
+/*
+ * f2fs IO tracer
+ *
+ * Copyright (c) 2014 Motorola Mobility
+ * Copyright (c) 2014 Jaegeuk Kim <jaegeuk@kernel.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#define _LARGEFILE64_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <assert.h>
+#include <locale.h>
+
+#define P_NAMELEN	16
+
+/* For global trace methods */
+enum show_type {
+	SHOW_PID,
+	SHOW_FTYPE,
+	SHOW_ALL,
+};
+
+enum trace_types {
+	TP_PID,
+	TP_IOS,
+	TP_MAX,
+};
+
+struct tps {
+	enum trace_types type;
+	const char *name;
+};
+
+struct tps trace_points[] = {
+	{ TP_PID,	"f2fs_trace_pid" },
+	{ TP_IOS,	"f2fs_trace_ios" },
+};
+
+/* For f2fs_trace_pid and f2fs_trace_ios */
+enum rw_type {
+	READ,
+	WRITE,
+	MAX_RW,
+};
+
+enum file_type {
+	__NORMAL_FILE,
+	__DIR_FILE,
+	__NODE_FILE,
+	__META_FILE,
+	__ATOMIC_FILE,
+	__VOLATILE_FILE,
+	__MISC_FILE,
+	__NR_FILES,
+};
+
+char *file_type_string[] = {
+	"User      ",
+	"Dir       ",
+	"Node      ",
+	"Meta      ",
+	"Atomic    ",
+	"Voltile   ",
+	"Misc      ",
+};
+
+struct pid_ent {
+	int pid;
+	char name[P_NAMELEN];
+	unsigned long long io[__NR_FILES][MAX_RW];
+	unsigned long long total_io[MAX_RW];
+	LIST_ENTRY(pid_ent) ptr;
+};
+
+/* global variables */
+int major = 0, minor = 0;
+int show_option = SHOW_ALL;
+unsigned long long total_io[__NR_FILES][MAX_RW];
+
+LIST_HEAD(plist, pid_ent) pid_info;
+
+/* Functions */
+static inline int atoh(char *str)
+{
+	int val;
+	sscanf(str, "%x", &val);
+	return val;
+}
+
+static void do_init()
+{
+	struct pid_ent *misc;
+
+	misc = calloc(1, sizeof(struct pid_ent));
+	assert(misc);
+
+	LIST_INIT(&pid_info);
+	LIST_INSERT_HEAD(&pid_info, misc, ptr);
+}
+
+void show_usage()
+{
+	printf("\nUsage: parse.f2fs [options] log_file\n");
+	printf("[options]:\n");
+	printf("  -a RW sorted by pid & file types\n");
+	printf("  -f RW sorted by file types\n");
+	printf("  -p RW sorted by pid\n");
+	printf("  -m major number\n");
+	printf("  -n minor number\n");
+	exit(1);
+}
+
+static int parse_options(int argc, char *argv[])
+{
+	const char *option_string = "fm:n:p";
+	int option = 0;
+
+	while ((option = getopt(argc, argv, option_string)) != EOF) {
+		switch (option) {
+		case 'f':
+			show_option = SHOW_FTYPE;
+			break;
+		case 'm':
+			major = atoh(optarg);
+			break;
+		case 'n':
+			minor = atoh(optarg);
+			break;
+		case 'p':
+			show_option = SHOW_PID;
+			break;
+		default:
+			printf("\tError: Unknown option %c\n", option);
+			show_usage();
+			break;
+		}
+	}
+	if ((optind + 1) != argc) {
+		printf("\tError: Log file is not specified.\n");
+		show_usage();
+	}
+	return optind;
+}
+
+struct pid_ent *get_pid_entry(int pid)
+{
+	struct pid_ent *entry;
+
+	LIST_FOREACH(entry, &pid_info, ptr) {
+		if (entry->pid == pid)
+			return entry;
+	}
+	return LIST_FIRST(&pid_info);
+}
+
+static void handle_tp_pid(char *ptr)
+{
+	struct pid_ent *pent;
+
+	pent = calloc(1, sizeof(struct pid_ent));
+	assert(pent);
+
+	ptr = strtok(NULL, " ");
+	pent->pid = atoh(ptr);
+
+	ptr = strtok(NULL, " ");
+	strcpy(pent->name, ptr);
+
+	LIST_INSERT_HEAD(&pid_info, pent, ptr);
+}
+
+static void handle_tp_ios(char *ptr)
+{
+	int pid, type, rw, len;
+	struct pid_ent *p;
+
+	ptr = strtok(NULL, " ");
+	pid = atoh(ptr);
+
+	ptr = strtok(NULL, " ");
+	ptr = strtok(NULL, " ");
+	type = atoh(ptr);
+
+	ptr = strtok(NULL, " ");
+	rw = atoh(ptr);
+
+	ptr = strtok(NULL, " ");
+	/* unsigned long long blkaddr = atoh(ptr); */
+
+	ptr = strtok(NULL, " ");
+	len = atoh(ptr);
+
+	/* update per-pid stat */
+	p = get_pid_entry(pid);
+	p->io[type][rw & 0x1] += len;
+	p->total_io[rw & 0x1] += len;
+
+	/* update total stat */
+	total_io[type][rw & 0x1] += len;
+}
+
+static void do_parse(FILE *file)
+{
+	char line[300];
+	char *ptr;
+	int i;
+
+	while (fgets(line, sizeof(line), file) != NULL) {
+		ptr = strtok(line, ":");
+
+		ptr = strtok(NULL, " :");
+
+		for (i = 0; i < TP_MAX; i++) {
+			if (!strcmp(ptr, trace_points[i].name))
+				break;
+		}
+		if (i == TP_MAX)
+			continue;
+		ptr = strtok(NULL, " :");
+		if (major && major != atoh(ptr))
+			continue;
+		ptr = strtok(NULL, " :");
+		if (minor && minor != atoh(ptr))
+			continue;
+
+		switch (i) {
+		case TP_PID:
+			handle_tp_pid(ptr);
+			break;
+		case TP_IOS:
+			handle_tp_ios(ptr);
+			break;
+		}
+	}
+}
+
+static void __print_pid()
+{
+	struct pid_ent *entry;
+	int i;
+
+	setlocale(LC_ALL, "");
+	printf("%8s %16s %17s ||", "PID", "NAME", "R/W in 4KB");
+	for (i = 0; i < __NR_FILES; i++)
+		printf(" %17s |", file_type_string[i]);
+	printf("\n");
+
+	LIST_FOREACH(entry, &pid_info, ptr) {
+		printf("%8x %16s %'8lld %'8lld ||",
+				entry->pid, entry->name,
+				entry->total_io[READ],
+				entry->total_io[WRITE]);
+		for (i = 0; i < __NR_FILES; i++)
+			printf(" %'8lld %'8lld |",
+				entry->io[i][READ],
+				entry->io[i][WRITE]);
+		printf("\n");
+	}
+}
+
+static void __print_ftype()
+{
+	int i;
+
+	setlocale(LC_ALL, "");
+	printf("\n===== Data R/W in 4KB accoring to File types =====\n");
+	for (i = 0; i < __NR_FILES; i++)
+		printf(" %17s |", file_type_string[i]);
+	printf("\n");
+
+	for (i = 0; i < __NR_FILES; i++)
+		printf(" %'8lld %'8lld |",
+				total_io[i][READ],
+				total_io[i][WRITE]);
+	printf("\n");
+}
+
+static void do_print()
+{
+	switch (show_option) {
+	case SHOW_PID:
+		__print_pid();
+		break;
+	case SHOW_FTYPE:
+		__print_ftype();
+		break;
+	case SHOW_ALL:
+		__print_pid();
+		printf("\n\n");
+		__print_ftype();
+		break;
+	}
+}
+
+int main(int argc, char **argv)
+{
+	FILE *file;
+	int opt;
+
+	opt = parse_options(argc, argv);
+
+	file = fopen(argv[opt], "r");
+	if (!file) {
+		perror("open log file");
+		exit(EXIT_FAILURE);
+	}
+
+	do_init();
+
+	do_parse(file);
+
+	do_print();
+
+	fclose(file);
+	return 0;
+}
diff --git a/f2fs-tools/tools/f2fstat.c b/f2fs-tools/tools/f2fstat.c
new file mode 100644
index 0000000..7f485b0
--- /dev/null
+++ b/f2fs-tools/tools/f2fstat.c
@@ -0,0 +1,311 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <libgen.h>
+
+#ifdef DEBUG
+#define dbg(fmt, args...)	printf(fmt, __VA_ARGS__);
+#else
+#define dbg(fmt, args...)
+#endif
+
+/*
+ * f2fs status
+ */
+#define F2FS_STATUS	"/sys/kernel/debug/f2fs/status"
+
+#define KEY_NODE	0x00000001
+#define KEY_META	0x00000010
+
+unsigned long util;
+unsigned long used_node_blks;
+unsigned long used_data_blks;
+//unsigned long inline_inode;
+
+unsigned long free_segs;
+unsigned long valid_segs;
+unsigned long dirty_segs;
+unsigned long prefree_segs;
+
+unsigned long gc, bg_gc;
+unsigned long cp;
+unsigned long gc_data_blks;
+unsigned long gc_node_blks;
+
+//unsigned long extent_hit_ratio;
+
+unsigned long dirty_node, node_kb;
+unsigned long dirty_dents;
+unsigned long dirty_meta, meta_kb;
+unsigned long nat_caches;
+unsigned long dirty_sit;
+
+unsigned long free_nids;
+
+unsigned long ssr_blks;
+unsigned long lfs_blks;
+unsigned long memory_kb;
+
+struct options {
+	int delay;
+	int interval;
+	char partname[32];
+};
+
+struct mm_table {
+	const char *name;
+	unsigned long *val;
+	int flag;
+};
+
+static int compare_mm_table(const void *a, const void *b)
+{
+	dbg("[COMPARE] %s, %s\n", ((struct mm_table *)a)->name, ((struct mm_table *)b)->name);
+	return strcmp(((struct mm_table *)a)->name, ((struct mm_table *)b)->name);
+}
+
+static inline void remove_newline(char **head)
+{
+again:
+	if (**head == '\n') {
+		*head = *head + 1;
+		goto again;
+	}
+}
+
+void f2fstat(struct options *opt)
+{
+	int fd;
+	int ret;
+	char keyname[32];
+	char buf[4096];
+	struct mm_table key = { keyname, NULL };
+	struct mm_table *found;
+	int f2fstat_table_cnt;
+	char *head, *tail;
+	int found_cnt = 0;
+
+	static struct mm_table f2fstat_table[] = {
+		{ "  - Data",		&used_data_blks,	0 },
+		{ "  - Dirty",		&dirty_segs,		0 },
+		{ "  - Free",		&free_segs,		0 },
+		{ "  - NATs",		&nat_caches,		0 },
+		{ "  - Node",		&used_node_blks,	0 },
+		{ "  - Prefree",	&prefree_segs,		0 },
+		{ "  - SITs",		&dirty_sit,		0 },
+		{ "  - Valid",		&valid_segs,		0 },
+		{ "  - dents",		&dirty_dents,		0 },
+		{ "  - free_nids",	&free_nids,		0 },
+		{ "  - meta",		&dirty_meta,		KEY_META },
+		{ "  - nodes",		&dirty_node,		KEY_NODE },
+		{ "CP calls",		&cp,			0 },
+		{ "GC calls",		&gc,			0 },
+		{ "LFS",		&lfs_blks,		0 },
+		{ "Memory",		&memory_kb,		0 },
+		{ "SSR",		&ssr_blks,		0 },
+		{ "Utilization",	&util,			0 },
+	};
+
+	f2fstat_table_cnt = sizeof(f2fstat_table)/sizeof(struct mm_table);
+
+	fd = open(F2FS_STATUS, O_RDONLY);
+	if (fd < 0) {
+		perror("open " F2FS_STATUS);
+		exit(EXIT_FAILURE);
+	}
+
+	ret = read(fd, buf, 4096);
+	if (ret < 0) {
+		perror("read " F2FS_STATUS);
+		exit(EXIT_FAILURE);
+	}
+	buf[ret] = '\0';
+
+	head = buf;
+
+	if (opt->partname[0] != '\0') {
+		head = strstr(buf, opt->partname);
+		if (head == NULL)
+			exit(EXIT_FAILURE);
+	}
+
+	for (;;) {
+		remove_newline(&head);
+		tail = strchr(head, ':');
+		if (!tail)
+			break;
+		*tail = '\0';
+		if (strlen(head) >= sizeof(keyname)) {
+			dbg("[OVER] %s\n", head);
+			*tail = ':';
+			tail = strchr(head, '\n');
+			head = tail + 1;
+			continue;
+		}
+
+		strcpy(keyname, head);
+
+		found = bsearch(&key, f2fstat_table, f2fstat_table_cnt, sizeof(struct mm_table), compare_mm_table);
+		dbg("[RESULT] %s (%s)\n", head, (found) ? "O" : "X");
+		head = tail + 1;
+		if (!found)
+			goto nextline;
+
+		*(found->val) = strtoul(head, &tail, 10);
+		if (found->flag) {
+			int npages;
+			tail = strstr(head, "in");
+			head = tail + 2;
+			npages = strtoul(head, &tail, 10);
+			switch (found->flag & (KEY_NODE | KEY_META)) {
+			case KEY_NODE:
+				node_kb = npages * 4;
+				break;
+			case KEY_META:
+				meta_kb = npages * 4;
+				break;
+			}
+		}
+		if (++found_cnt == f2fstat_table_cnt)
+			break;
+nextline:
+		tail = strchr(head, '\n');
+		if (!tail)
+			break;
+		head =  tail + 1;
+	}
+
+	close(fd);
+}
+
+void usage(void)
+{
+	printf("Usage: f2fstat [option]\n"
+			"    -d    delay (secs)\n"
+			"    -i    interval of head info\n"
+			"    -p    partition name (e.g. /dev/sda3)\n");
+	exit(EXIT_FAILURE);
+}
+
+void parse_option(int argc, char *argv[], struct options *opt)
+{
+	int option;
+	const char *option_string = "d:i:p:h";
+
+	while ((option = getopt(argc, argv, option_string)) != EOF) {
+		switch (option) {
+		case 'd':
+			opt->delay = atoi(optarg);
+			break;
+		case 'i':
+			opt->interval = atoi(optarg);
+			break;
+		case 'p':
+			strcpy(opt->partname, basename(optarg));
+			break;
+		default:
+			usage();
+			break;
+		}
+	}
+}
+
+void __make_head(char *head, int index, int i, int len)
+{
+	char name_h[5][20] = {"main segments", "page/slab caches", "cp/gc", "blks", "memory"};
+	int half = (len - strlen(name_h[i])) / 2;
+
+	*(head + index) = '|';
+	index++;
+	memset(head + index, '-', half);
+	index += half;
+	strcpy(head + index, name_h[i]);
+	index += strlen(name_h[i]);
+	memset(head + index, '-', half);
+}
+
+void print_head(char *res)
+{
+	char *ptr, *ptr_buf;
+	char buf[1024], head[1024];
+	char name[20][10] = {"util", "node", "data", "free", "valid", "dirty", "prefree", "node", "dent", "meta",
+		"sit", "nat", "fnid", "cp", "gc", "ssr", "lfs", "total", "node", "meta"};
+	int i, len, prev_index = 0;
+
+	ptr_buf = buf;
+	memset(buf, ' ', 1024);
+	memset(head, ' ', 1024);
+
+	for (i = 0; i < 20; i++) {
+		ptr = (i == 0) ? strtok(res, " ") : strtok(NULL, " ");
+		strncpy(ptr_buf, name[i], strlen(name[i]));
+		if (i == 1) {
+			prev_index = ptr_buf - buf - 1;
+		} else if (i == 7) {
+			len = (ptr_buf - buf) - 1 - prev_index;
+			__make_head(head, prev_index, 0, len);
+			prev_index = ptr_buf - buf - 1;
+		} else if (i == 13) {
+			len = (ptr_buf - buf) - 1 - prev_index;
+			__make_head(head, prev_index, 1, len);
+			prev_index = ptr_buf - buf - 1;
+		} else if (i == 15) {
+			len = (ptr_buf - buf) - 1 - prev_index;
+			__make_head(head, prev_index, 2, len);
+			prev_index = ptr_buf - buf - 1;
+		} else if (i == 17) {
+			len = (ptr_buf - buf) - 1 - prev_index;
+			__make_head(head, prev_index, 3, len);
+			prev_index = ptr_buf - buf - 1;
+		}
+
+		len = strlen(ptr);
+		ptr_buf += (len > strlen(name[i]) ? len : strlen(name[i])) + 1;
+	}
+
+	len = (ptr_buf - buf) - 1 - prev_index;
+	__make_head(head, prev_index, 4, len);
+
+	*ptr_buf = 0;
+	*(head + (ptr_buf - buf - 1)) = '|';
+	*(head + (ptr_buf - buf)) = 0;
+	fprintf(stderr, "%s\n%s\n", head, buf);
+}
+
+int main(int argc, char *argv[])
+{
+	char format[] = "%4ld %4ld %4ld %4ld %5ld %5ld %7ld %4ld %4ld %4ld %3ld %3ld %4ld %2ld %2ld %3ld %3ld %5ld %4ld %4ld";
+	char buf[1024], tmp[1024];
+	int head_interval;
+	struct options opt = {
+		.delay = 1,
+		.interval = 20,
+		.partname = { 0, },
+	};
+
+	parse_option(argc, argv, &opt);
+	head_interval = opt.interval;
+
+	while (1) {
+		memset(buf, 0, 1024);
+		f2fstat(&opt);
+		sprintf(buf, format, util, used_node_blks, used_data_blks,
+			free_segs, valid_segs, dirty_segs, prefree_segs,
+			dirty_node, dirty_dents, dirty_meta, dirty_sit, nat_caches, free_nids,
+			cp, gc, ssr_blks, lfs_blks, memory_kb, node_kb, meta_kb);
+
+		strcpy(tmp, buf);
+		if (head_interval == opt.interval)
+			print_head(tmp);
+		if (head_interval-- == 0)
+			head_interval = opt.interval;
+
+		fprintf(stderr, "%s\n", buf);
+
+		sleep(opt.delay);
+	}
+
+	return 0;
+}
diff --git a/f2fs-tools/tools/fibmap.c b/f2fs-tools/tools/fibmap.c
new file mode 100644
index 0000000..224b233
--- /dev/null
+++ b/f2fs-tools/tools/fibmap.c
@@ -0,0 +1,165 @@
+#define _LARGEFILE64_SOURCE
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <libgen.h>
+#include <linux/hdreg.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <inttypes.h>
+
+struct file_ext {
+	__u32 f_pos;
+	__u32 start_blk;
+	__u32 end_blk;
+	__u32 blk_count;
+};
+
+void print_ext(struct file_ext *ext)
+{
+	if (ext->end_blk == 0)
+		printf("%8d    %8d    %8d    %8d\n", ext->f_pos, 0, 0, ext->blk_count);
+	else
+		printf("%8d    %8d    %8d    %8d\n", ext->f_pos, ext->start_blk,
+					ext->end_blk, ext->blk_count);
+}
+
+void print_stat(struct stat64 *st)
+{
+	printf("--------------------------------------------\n");
+	printf("dev       [%d:%d]\n", major(st->st_dev), minor(st->st_dev));
+	printf("ino       [0x%8"PRIx64" : %"PRIu64"]\n",
+						st->st_ino, st->st_ino);
+	printf("mode      [0x%8x : %d]\n", st->st_mode, st->st_mode);
+	printf("nlink     [0x%8lx : %ld]\n", st->st_nlink, st->st_nlink);
+	printf("uid       [0x%8x : %d]\n", st->st_uid, st->st_uid);
+	printf("gid       [0x%8x : %d]\n", st->st_gid, st->st_gid);
+	printf("size      [0x%8"PRIx64" : %"PRIu64"]\n",
+						st->st_size, st->st_size);
+	printf("blksize   [0x%8lx : %ld]\n", st->st_blksize, st->st_blksize);
+	printf("blocks    [0x%8"PRIx64" : %"PRIu64"]\n",
+					st->st_blocks, st->st_blocks);
+	printf("--------------------------------------------\n\n");
+}
+
+void stat_bdev(struct stat64 *st, unsigned int *start_lba)
+{
+	struct stat bdev_stat;
+	struct hd_geometry geom;
+	char devname[32] = { 0, };
+	char linkname[32] = { 0, };
+	int fd;
+
+	sprintf(devname, "/dev/block/%d:%d", major(st->st_dev), minor(st->st_dev));
+
+	fd = open(devname, O_RDONLY);
+	if (fd < 0)
+		return;
+
+	if (fstat(fd, &bdev_stat) < 0)
+		goto out;
+
+	if (S_ISBLK(bdev_stat.st_mode)) {
+		if (ioctl(fd, HDIO_GETGEO, &geom) < 0)
+			*start_lba = 0;
+		else
+			*start_lba = geom.start;
+	}
+
+	if (readlink(devname, linkname, sizeof(linkname)) < 0)
+		goto out;
+
+	printf("----------------bdev info-------------------\n");
+	printf("devname = %s\n", basename(linkname));
+	printf("start_lba = %u\n", *start_lba);
+
+out:
+	close(fd);
+
+}
+
+int main(int argc, char *argv[])
+{
+	int fd;
+	int ret = 0;
+	char *filename;
+	struct stat64 st;
+	int total_blks;
+	unsigned int i;
+	struct file_ext ext;
+	__u32 start_lba;
+	__u32 blknum;
+
+	if (argc != 2) {
+		fprintf(stderr, "No filename\n");
+		exit(-1);
+	}
+	filename = argv[1];
+
+	fd = open(filename, O_RDONLY|O_LARGEFILE);
+	if (fd < 0) {
+		ret = errno;
+		perror(filename);
+		exit(-1);
+	}
+
+	fsync(fd);
+
+	if (fstat64(fd, &st) < 0) {
+		ret = errno;
+		perror(filename);
+		goto out;
+	}
+
+	stat_bdev(&st, &start_lba);
+
+	total_blks = (st.st_size + st.st_blksize - 1) / st.st_blksize;
+
+	printf("\n----------------file info-------------------\n");
+	printf("%s :\n", filename);
+	print_stat(&st);
+	printf("file_pos   start_blk     end_blk        blks\n");
+
+	blknum = 0;
+	if (ioctl(fd, FIBMAP, &blknum) < 0) {
+		ret = errno;
+		perror("ioctl(FIBMAP)");
+		goto out;
+	}
+	ext.f_pos = 0;
+	ext.start_blk = blknum;
+	ext.end_blk = blknum;
+	ext.blk_count = 1;
+
+	for (i = 1; i < total_blks; i++) {
+		blknum = i;
+
+		if (ioctl(fd, FIBMAP, &blknum) < 0) {
+			ret = errno;
+			perror("ioctl(FIBMAP)");
+			goto out;
+		}
+
+		if ((blknum == 0 && blknum == ext.end_blk) || (ext.end_blk + 1) == blknum) {
+			ext.end_blk = blknum;
+			ext.blk_count++;
+		} else {
+			print_ext(&ext);
+			ext.f_pos = i * st.st_blksize;
+			ext.start_blk = blknum;
+			ext.end_blk = blknum;
+			ext.blk_count = 1;
+		}
+	}
+
+	print_ext(&ext);
+out:
+	close(fd);
+	return ret;
+}