File exfat-1.2.9-git.patch of Package exfat-kmp

diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d159169
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,339 @@
+                    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 Lesser 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 Lesser General
+Public License instead of this License.
diff --git a/Makefile b/Makefile
index 24e3654..711ed87 100644
--- a/Makefile
+++ b/Makefile
@@ -24,11 +24,9 @@ EXTRA_FLAGS += -I$(PWD)
 # any valid path to the directory in which the target kernel's source is located
 # can be provided on the command line.
 #
-KDIR	:= /lib/modules/$(shell uname -r)/build
-MDIR	:= /lib/modules/$(shell uname -r)
+KDIR	?= /lib/modules/$(shell uname -r)/build
+MDIR	?= /lib/modules/$(shell uname -r)
 PWD	:= $(shell pwd)
-KREL	:= $(shell cd ${KDIR} && make -s kernelrelease)
-MDIR	:= /lib/modules/${KREL}
 PWD	:= $(shell pwd)
 
 export CONFIG_EXFAT_FS := m
diff --git a/README.md b/README.md
index ad0462f..feab400 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,13 @@
 exfat-nofuse
 ============
 
-Android ARM Linux non-fuse read/write kernel driver for the exFAT, FAT12, FAT16 and vfat (FAT32) file systems.<br />
+Linux non-fuse read/write kernel driver for the exFAT, FAT12, FAT16 and vfat (FAT32) file systems.<br />
 Originally ported from Android kernel v3.0.
 
-Will not work on no ARM builds.
-Till someone can fix that :)
-
-
 Kudos to ksv1986 for the mutex patch!<br />
 Thanks to JackNorris for being awesome and providing the clear_inode() patch.<br />
 <br />
-Big thanks to lqs for completing the driver!
+Big thanks to lqs for completing the driver!<br />
 Big thanks to benpicco for fixing 3.11.y compatibility!
 
 
@@ -46,9 +42,9 @@ edit [linux]/fs/Kconfig
   source "fs/fat/Kconfig"
  +source "fs/exfat/Kconfig"
   source "fs/ntfs/Kconfig"
-```
-
   endmenu
+```
+  
 
 edit [linux]/fs/Makefile
 ```
@@ -74,5 +70,29 @@ build your kernel
 
 Have fun.
 
+
+Installing as a DKMS module:
+=================================
+
+You can have even more fun with exfat-nofuse by installing it as a DKMS module has the main advantage of being auto-compiled (and thus, possibly surviving) between kernel upgrades.
+
+First, get dkms. On Ubuntu this should be:
+
+	sudo apt install dkms
+
+Then copy the root of this repository to /usr/share:
+
+	sudo cp -R . /usr/src/exfat-1.2.8 (or whatever version number declared on dkms.conf is)
+	sudo dkms add -m exfat -v 1.2.8
+
+Build and load the module:
+
+	sudo dkms build -m exfat -v 1.2.8
+	sudo dkms install -m exfat -v 1.2.8
+
+Now you have a proper dkms module that will work for a long time... hopefully.
+
+
+
 Free Software for the Free Minds!
 =================================
diff --git a/dkms.conf b/dkms.conf
new file mode 100644
index 0000000..d873c0a
--- /dev/null
+++ b/dkms.conf
@@ -0,0 +1,7 @@
+PACKAGE_NAME="exfat"
+PACKAGE_VERSION="1.2.8"
+MAKE="KDIR=/lib/modules/$kernelver/build MDIR=/lib/modules/$kernelver make"
+CLEAN="make clean"
+BUILT_MODULE_NAME[0]="exfat"
+AUTOINSTALL="yes"
+DEST_MODULE_LOCATION="/extra"
diff --git a/exfat-km.mk b/exfat-km.mk
new file mode 100644
index 0000000..4e3ef07
--- /dev/null
+++ b/exfat-km.mk
@@ -0,0 +1,11 @@
+EXFAT_FOLDER ?= external/exfat-nofuse
+
+EXFAT_MODULE:
+	make clean -C $(EXFAT_FOLDER) KDIR=$(KERNEL_OUT)
+	make -j8 -C $(EXFAT_FOLDER) ARCH=arm KDIR=$(KERNEL_OUT) \
+		$(if $(ARM_CROSS_COMPILE),$(ARM_CROSS_COMPILE),$(KERNEL_CROSS_COMPILE))
+	mv $(EXFAT_FOLDER)/exfat.ko $(KERNEL_MODULES_OUT)
+	$(if $(ARM_EABI_TOOLCHAIN),$(ARM_EABI_TOOLCHAIN)/arm-eabi-strip, \
+		$(KERNEL_TOOLCHAIN_PATH)strip) --strip-unneeded $(KERNEL_MODULES_OUT)/exfat.ko
+
+TARGET_KERNEL_MODULES += EXFAT_MODULE
diff --git a/exfat_api.c b/exfat_api.c
index 3a9943b..32b29f0 100644
--- a/exfat_api.c
+++ b/exfat_api.c
@@ -526,5 +526,3 @@ EXPORT_SYMBOL(FsReleaseCache);
 /*======================================================================*/
 /*  Local Function Definitions                                          */
 /*======================================================================*/
-
-/* end of exfat_api.c */
diff --git a/exfat_api.h b/exfat_api.h
index a924e4d..84bdf61 100644
--- a/exfat_api.h
+++ b/exfat_api.h
@@ -204,5 +204,3 @@ typedef struct {
 s32 FsReleaseCache(struct super_block *sb);
 
 #endif /* _EXFAT_API_H */
-
-/* end of exfat_api.h */
diff --git a/exfat_blkdev.c b/exfat_blkdev.c
index b671b27..eaccfd8 100644
--- a/exfat_blkdev.c
+++ b/exfat_blkdev.c
@@ -94,7 +94,7 @@ s32 bdev_close(struct super_block *sb)
 	return FFS_SUCCESS;
 }
 
-s32 bdev_read(struct super_block *sb, u32 secno, struct buffer_head **bh, u32 num_secs, s32 read)
+s32 bdev_read(struct super_block *sb, sector_t secno, struct buffer_head **bh, u32 num_secs, s32 read)
 {
 	BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -126,7 +126,7 @@ s32 bdev_read(struct super_block *sb, u32 secno, struct buffer_head **bh, u32 nu
 	return FFS_MEDIAERR;
 }
 
-s32 bdev_write(struct super_block *sb, u32 secno, struct buffer_head *bh, u32 num_secs, s32 sync)
+s32 bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh, u32 num_secs, s32 sync)
 {
 	s32 count;
 	struct buffer_head *bh2;
@@ -195,5 +195,3 @@ s32 bdev_sync(struct super_block *sb)
 
 	return sync_blockdev(sb->s_bdev);
 }
-
-/* end of exfat_blkdev.c */
diff --git a/exfat_blkdev.h b/exfat_blkdev.h
index f10dfd4..3363b59 100644
--- a/exfat_blkdev.h
+++ b/exfat_blkdev.h
@@ -66,10 +66,8 @@ s32 bdev_init(void);
 s32 bdev_shutdown(void);
 s32 bdev_open(struct super_block *sb);
 s32 bdev_close(struct super_block *sb);
-s32 bdev_read(struct super_block *sb, u32 secno, struct buffer_head **bh, u32 num_secs, s32 read);
-s32 bdev_write(struct super_block *sb, u32 secno, struct buffer_head *bh, u32 num_secs, s32 sync);
+s32 bdev_read(struct super_block *sb, sector_t secno, struct buffer_head **bh, u32 num_secs, s32 read);
+s32 bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh, u32 num_secs, s32 sync);
 s32 bdev_sync(struct super_block *sb);
 
 #endif /* _EXFAT_BLKDEV_H */
-
-/* end of exfat_blkdev.h */
diff --git a/exfat_cache.c b/exfat_cache.c
index 36a9717..4130102 100644
--- a/exfat_cache.c
+++ b/exfat_cache.c
@@ -50,15 +50,15 @@
 static s32 __FAT_read(struct super_block *sb, u32 loc, u32 *content);
 static s32 __FAT_write(struct super_block *sb, u32 loc, u32 content);
 
-static BUF_CACHE_T *FAT_cache_find(struct super_block *sb, u32 sec);
-static BUF_CACHE_T *FAT_cache_get(struct super_block *sb, u32 sec);
+static BUF_CACHE_T *FAT_cache_find(struct super_block *sb, sector_t sec);
+static BUF_CACHE_T *FAT_cache_get(struct super_block *sb, sector_t sec);
 static void FAT_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp);
 static void FAT_cache_remove_hash(BUF_CACHE_T *bp);
 
-static u8 *__buf_getblk(struct super_block *sb, u32 sec);
+static u8 *__buf_getblk(struct super_block *sb, sector_t sec);
 
-static BUF_CACHE_T *buf_cache_find(struct super_block *sb, u32 sec);
-static BUF_CACHE_T *buf_cache_get(struct super_block *sb, u32 sec);
+static BUF_CACHE_T *buf_cache_find(struct super_block *sb, sector_t sec);
+static BUF_CACHE_T *buf_cache_get(struct super_block *sb, sector_t sec);
 static void buf_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp);
 static void buf_cache_remove_hash(BUF_CACHE_T *bp);
 
@@ -165,7 +165,8 @@ s32 FAT_write(struct super_block *sb, u32 loc, u32 content)
 static s32 __FAT_read(struct super_block *sb, u32 loc, u32 *content)
 {
 	s32 off;
-	u32 sec, _content;
+	u32 _content;
+	sector_t sec;
 	u8 *fat_sector, *fat_entry;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
 	BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
@@ -276,7 +277,7 @@ static s32 __FAT_read(struct super_block *sb, u32 loc, u32 *content)
 static s32 __FAT_write(struct super_block *sb, u32 loc, u32 content)
 {
 	s32 off;
-	u32 sec;
+	sector_t sec;
 	u8 *fat_sector, *fat_entry;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
 	BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
@@ -381,7 +382,7 @@ static s32 __FAT_write(struct super_block *sb, u32 loc, u32 content)
 	return 0;
 } /* end of __FAT_write */
 
-u8 *FAT_getblk(struct super_block *sb, u32 sec)
+u8 *FAT_getblk(struct super_block *sb, sector_t sec)
 {
 	BUF_CACHE_T *bp;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -416,7 +417,7 @@ u8 *FAT_getblk(struct super_block *sb, u32 sec)
 	return bp->buf_bh->b_data;
 } /* end of FAT_getblk */
 
-void FAT_modify(struct super_block *sb, u32 sec)
+void FAT_modify(struct super_block *sb, sector_t sec)
 {
 	BUF_CACHE_T *bp;
 
@@ -469,7 +470,7 @@ void FAT_sync(struct super_block *sb)
 	sm_V(&f_sem);
 } /* end of FAT_sync */
 
-static BUF_CACHE_T *FAT_cache_find(struct super_block *sb, u32 sec)
+static BUF_CACHE_T *FAT_cache_find(struct super_block *sb, sector_t sec)
 {
 	s32 off;
 	BUF_CACHE_T *bp, *hp;
@@ -491,7 +492,7 @@ static BUF_CACHE_T *FAT_cache_find(struct super_block *sb, u32 sec)
 	return NULL;
 } /* end of FAT_cache_find */
 
-static BUF_CACHE_T *FAT_cache_get(struct super_block *sb, u32 sec)
+static BUF_CACHE_T *FAT_cache_get(struct super_block *sb, sector_t sec)
 {
 	BUF_CACHE_T *bp;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -529,7 +530,7 @@ static void FAT_cache_remove_hash(BUF_CACHE_T *bp)
 /*  Buffer Read/Write Functions                                         */
 /*======================================================================*/
 
-u8 *buf_getblk(struct super_block *sb, u32 sec)
+u8 *buf_getblk(struct super_block *sb, sector_t sec)
 {
 	u8 *buf;
 
@@ -542,7 +543,7 @@ u8 *buf_getblk(struct super_block *sb, u32 sec)
 	return buf;
 } /* end of buf_getblk */
 
-static u8 *__buf_getblk(struct super_block *sb, u32 sec)
+static u8 *__buf_getblk(struct super_block *sb, sector_t sec)
 {
 	BUF_CACHE_T *bp;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -578,7 +579,7 @@ static u8 *__buf_getblk(struct super_block *sb, u32 sec)
 
 } /* end of __buf_getblk */
 
-void buf_modify(struct super_block *sb, u32 sec)
+void buf_modify(struct super_block *sb, sector_t sec)
 {
 	BUF_CACHE_T *bp;
 
@@ -588,12 +589,13 @@ void buf_modify(struct super_block *sb, u32 sec)
 	if (likely(bp != NULL))
 		sector_write(sb, sec, bp->buf_bh, 0);
 
-	WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%u).\n", sec);
+	WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
+	     (unsigned long long)sec);
 
 	sm_V(&b_sem);
 } /* end of buf_modify */
 
-void buf_lock(struct super_block *sb, u32 sec)
+void buf_lock(struct super_block *sb, sector_t sec)
 {
 	BUF_CACHE_T *bp;
 
@@ -603,12 +605,13 @@ void buf_lock(struct super_block *sb, u32 sec)
 	if (likely(bp != NULL))
 		bp->flag |= LOCKBIT;
 
-	WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%u).\n", sec);
+	WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
+	     (unsigned long long)sec);
 
 	sm_V(&b_sem);
 } /* end of buf_lock */
 
-void buf_unlock(struct super_block *sb, u32 sec)
+void buf_unlock(struct super_block *sb, sector_t sec)
 {
 	BUF_CACHE_T *bp;
 
@@ -618,12 +621,13 @@ void buf_unlock(struct super_block *sb, u32 sec)
 	if (likely(bp != NULL))
 		bp->flag &= ~(LOCKBIT);
 
-	WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%u).\n", sec);
+	WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
+	     (unsigned long long)sec);
 
 	sm_V(&b_sem);
 } /* end of buf_unlock */
 
-void buf_release(struct super_block *sb, u32 sec)
+void buf_release(struct super_block *sb, sector_t sec)
 {
 	BUF_CACHE_T *bp;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -691,7 +695,7 @@ void buf_sync(struct super_block *sb)
 	sm_V(&b_sem);
 } /* end of buf_sync */
 
-static BUF_CACHE_T *buf_cache_find(struct super_block *sb, u32 sec)
+static BUF_CACHE_T *buf_cache_find(struct super_block *sb, sector_t sec)
 {
 	s32 off;
 	BUF_CACHE_T *bp, *hp;
@@ -709,7 +713,7 @@ static BUF_CACHE_T *buf_cache_find(struct super_block *sb, u32 sec)
 	return NULL;
 } /* end of buf_cache_find */
 
-static BUF_CACHE_T *buf_cache_get(struct super_block *sb, u32 sec)
+static BUF_CACHE_T *buf_cache_get(struct super_block *sb, sector_t sec)
 {
 	BUF_CACHE_T *bp;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -778,5 +782,3 @@ static void move_to_lru(BUF_CACHE_T *bp, BUF_CACHE_T *list)
 	bp->next->prev = bp->prev;
 	push_to_lru(bp, list);
 } /* end of buf_cache_move_to_lru */
-
-/* end of exfat_cache.c */
diff --git a/exfat_cache.h b/exfat_cache.h
index 8d4b577..540e316 100644
--- a/exfat_cache.h
+++ b/exfat_cache.h
@@ -57,7 +57,7 @@ typedef struct __BUF_CACHE_T {
 	struct __BUF_CACHE_T *hash_next;
 	struct __BUF_CACHE_T *hash_prev;
 	s32                drv;
-	u32               sec;
+	sector_t          sec;
 	u32               flag;
 	struct buffer_head   *buf_bh;
 } BUF_CACHE_T;
@@ -70,18 +70,16 @@ s32  buf_init(struct super_block *sb);
 s32  buf_shutdown(struct super_block *sb);
 s32  FAT_read(struct super_block *sb, u32 loc, u32 *content);
 s32  FAT_write(struct super_block *sb, u32 loc, u32 content);
-u8 *FAT_getblk(struct super_block *sb, u32 sec);
-void   FAT_modify(struct super_block *sb, u32 sec);
+u8 *FAT_getblk(struct super_block *sb, sector_t sec);
+void   FAT_modify(struct super_block *sb, sector_t sec);
 void   FAT_release_all(struct super_block *sb);
 void   FAT_sync(struct super_block *sb);
-u8 *buf_getblk(struct super_block *sb, u32 sec);
-void   buf_modify(struct super_block *sb, u32 sec);
-void   buf_lock(struct super_block *sb, u32 sec);
-void   buf_unlock(struct super_block *sb, u32 sec);
-void   buf_release(struct super_block *sb, u32 sec);
+u8 *buf_getblk(struct super_block *sb, sector_t sec);
+void   buf_modify(struct super_block *sb, sector_t sec);
+void   buf_lock(struct super_block *sb, sector_t sec);
+void   buf_unlock(struct super_block *sb, sector_t sec);
+void   buf_release(struct super_block *sb, sector_t sec);
 void   buf_release_all(struct super_block *sb);
 void   buf_sync(struct super_block *sb);
 
 #endif /* _EXFAT_CACHE_H */
-
-/* end of exfat_cache.h */
diff --git a/exfat_config.h b/exfat_config.h
index fd8928e..33c6525 100644
--- a/exfat_config.h
+++ b/exfat_config.h
@@ -67,5 +67,3 @@
 #endif
 
 #endif /* _EXFAT_CONFIG_H */
-
-/* end of exfat_config.h */
diff --git a/exfat_core.c b/exfat_core.c
index c99897f..143b721 100644
--- a/exfat_core.c
+++ b/exfat_core.c
@@ -28,7 +28,7 @@
 /************************************************************************/
 /*                                                                      */
 /*  PROJECT : exFAT & FAT12/16/32 File System                           */
-/*  FILE    : exfat.c                                                   */
+/*  FILE    : exfat_core.c                                              */
 /*  PURPOSE : exFAT File Manager                                        */
 /*                                                                      */
 /*----------------------------------------------------------------------*/
@@ -57,6 +57,7 @@
 #include "exfat_core.h"
 
 #include <linux/blkdev.h>
+#include <linux/slab.h>
 
 static void __set_sb_dirty(struct super_block *sb)
 {
@@ -183,7 +184,7 @@ s32 ffsMountVol(struct super_block *sb)
 	if (sector_read(sb, 0, &tmp_bh, 1) != FFS_SUCCESS)
 		return FFS_MEDIAERR;
 
-		p_fs->PBR_sector = 0;
+	p_fs->PBR_sector = 0;
 
 	p_pbr = (PBR_SECTOR_T *) tmp_bh->b_data;
 
@@ -429,7 +430,8 @@ s32 ffsCreateFile(struct inode *inode, char *path, u8 mode, FILE_ID_T *fid)
 s32 ffsReadFile(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *rcount)
 {
 	s32 offset, sec_offset, clu_offset;
-	u32 clu, LogSector;
+	u32 clu;
+	sector_t LogSector;
 	u64 oneblkread, read_bytes;
 	struct buffer_head *tmp_bh = NULL;
 	struct super_block *sb = inode->i_sb;
@@ -522,7 +524,8 @@ s32 ffsWriteFile(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u
 {
 	s32 modified = FALSE, offset, sec_offset, clu_offset;
 	s32 num_clusters, num_alloc, num_alloced = (s32) ~0;
-	u32 clu, last_clu, LogSector, sector = 0;
+	u32 clu, last_clu;
+	sector_t LogSector, sector = 0;
 	u64 oneblkwrite, write_bytes;
 	CHAIN_T new_clu;
 	TIMESTAMP_T tm;
@@ -732,7 +735,8 @@ err_out:
 s32 ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
 {
 	s32 num_clusters;
-	u32 last_clu = CLUSTER_32(0), sector = 0;
+	u32 last_clu = CLUSTER_32(0);
+	sector_t sector = 0;
 	CHAIN_T clu;
 	TIMESTAMP_T tm;
 	DENTRY_T *ep, *ep2;
@@ -1011,7 +1015,8 @@ s32 ffsRemoveFile(struct inode *inode, FILE_ID_T *fid)
 /* ffsSetAttr : set the attribute of a given file */
 s32 ffsSetAttr(struct inode *inode, u32 attr)
 {
-	u32 type, sector = 0;
+	u32 type;
+	sector_t sector = 0;
 	DENTRY_T *ep;
 	struct super_block *sb = inode->i_sb;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -1087,7 +1092,7 @@ s32 ffsSetAttr(struct inode *inode, u32 attr)
 /* ffsGetStat : get the information of a given file */
 s32 ffsGetStat(struct inode *inode, DIR_ENTRY_T *info)
 {
-	u32 sector = 0;
+	sector_t sector = 0;
 	s32 count;
 	CHAIN_T dir;
 	UNI_NAME_T uni_name;
@@ -1171,7 +1176,7 @@ s32 ffsGetStat(struct inode *inode, DIR_ENTRY_T *info)
 	/* XXX this is very bad for exfat cuz name is already included in es.
 	 API should be revised */
 	p_fs->fs_func->get_uni_name_from_ext_entry(sb, &(fid->dir), fid->entry, uni_name.name);
-	if (*(uni_name.name) == 0x0)
+	if (*(uni_name.name) == 0x0 && p_fs->vol_type != EXFAT)
 		get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x1);
 	nls_uniname_to_cstring(sb, info->Name, &uni_name);
 
@@ -1212,7 +1217,7 @@ s32 ffsGetStat(struct inode *inode, DIR_ENTRY_T *info)
 /* ffsSetStat : set the information of a given file */
 s32 ffsSetStat(struct inode *inode, DIR_ENTRY_T *info)
 {
-	u32 sector = 0;
+	sector_t sector = 0;
 	TIMESTAMP_T tm;
 	DENTRY_T *ep, *ep2;
 	ENTRY_SET_CACHE_T *es = NULL;
@@ -1285,7 +1290,8 @@ s32 ffsSetStat(struct inode *inode, DIR_ENTRY_T *info)
 s32 ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
 {
 	s32 num_clusters, num_alloced, modified = FALSE;
-	u32 last_clu, sector = 0;
+	u32 last_clu;
+	sector_t sector = 0;
 	CHAIN_T new_clu;
 	DENTRY_T *ep;
 	ENTRY_SET_CACHE_T *es = NULL;
@@ -1445,7 +1451,8 @@ s32 ffsReadDir(struct inode *inode, DIR_ENTRY_T *dir_entry)
 {
 	int i, dentry, clu_offset;
 	s32 dentries_per_clu, dentries_per_clu_bits = 0;
-	u32 type, sector;
+	u32 type;
+	sector_t sector;
 	CHAIN_T dir, clu;
 	UNI_NAME_T uni_name;
 	TIMESTAMP_T tm;
@@ -1556,7 +1563,7 @@ s32 ffsReadDir(struct inode *inode, DIR_ENTRY_T *dir_entry)
 
 			*(uni_name.name) = 0x0;
 			p_fs->fs_func->get_uni_name_from_ext_entry(sb, &dir, dentry, uni_name.name);
-			if (*(uni_name.name) == 0x0)
+			if (*(uni_name.name) == 0x0 && p_fs->vol_type != EXFAT)
 				get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x1);
 			nls_uniname_to_cstring(sb, dir_entry->Name, &uni_name);
 			buf_unlock(sb, sector);
@@ -1762,7 +1769,7 @@ void fs_error(struct super_block *sb)
 
 s32 clear_cluster(struct super_block *sb, u32 clu)
 {
-	u32 s, n;
+	sector_t s, n;
 	s32 ret = FFS_SUCCESS;
 	struct buffer_head *tmp_bh = NULL;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -1926,7 +1933,7 @@ void fat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, s32 do_relse)
 	u32 clu, prev;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
 	int i;
-	u32 sector;
+	sector_t sector;
 
 	if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0)))
 		return;
@@ -1966,7 +1973,7 @@ void exfat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, s32 do_relse)
 	u32 clu;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
 	int i;
-	u32 sector;
+	sector_t sector;
 
 	if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0)))
 		return;
@@ -2125,7 +2132,8 @@ s32 load_alloc_bitmap(struct super_block *sb)
 {
 	int i, j, ret;
 	u32 map_size;
-	u32 type, sector;
+	u32 type;
+	sector_t sector;
 	CHAIN_T clu;
 	BMAP_DENTRY_T *ep;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -2208,7 +2216,7 @@ void free_alloc_bitmap(struct super_block *sb)
 s32 set_alloc_bitmap(struct super_block *sb, u32 clu)
 {
 	int i, b;
-	u32 sector;
+	sector_t sector;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
 	BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
 
@@ -2225,7 +2233,7 @@ s32 set_alloc_bitmap(struct super_block *sb, u32 clu)
 s32 clr_alloc_bitmap(struct super_block *sb, u32 clu)
 {
 	int i, b;
-	u32 sector;
+	sector_t sector;
 #ifdef CONFIG_EXFAT_DISCARD
 	struct exfat_sb_info *sbi = EXFAT_SB(sb);
 	struct exfat_mount_options *opts = &sbi->options;
@@ -2312,13 +2320,14 @@ void sync_alloc_bitmap(struct super_block *sb)
 /*
  *  Upcase table Management Functions
  */
-s32 __load_upcase_table(struct super_block *sb, u32 sector, u32 num_sectors, u32 utbl_checksum)
+s32 __load_upcase_table(struct super_block *sb, sector_t sector, u32 num_sectors, u32 utbl_checksum)
 {
 	int i, ret = FFS_ERROR;
 	u32 j;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
 	BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
 	struct buffer_head *tmp_bh = NULL;
+	sector_t end_sector = num_sectors + sector;
 
 	u8	skip = FALSE;
 	u32	index = 0;
@@ -2332,12 +2341,10 @@ s32 __load_upcase_table(struct super_block *sb, u32 sector, u32 num_sectors, u32
 		return FFS_MEMORYERR;
 	memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *));
 
-	num_sectors += sector;
-
-	while (sector < num_sectors) {
+	while (sector < end_sector) {
 		ret = sector_read(sb, sector, &tmp_bh, 1);
 		if (ret != FFS_SUCCESS) {
-			DPRINTK("sector read (0x%X)fail\n", sector);
+			DPRINTK("sector read (0x%llX)fail\n", (unsigned long long)sector);
 			goto error;
 		}
 		sector++;
@@ -2450,7 +2457,8 @@ s32 load_upcase_table(struct super_block *sb)
 {
 	int i;
 	u32 tbl_clu, tbl_size;
-	u32 type, sector, num_sectors;
+	sector_t sector;
+	u32 type, num_sectors;
 	CHAIN_T clu;
 	CASE_DENTRY_T *ep;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -2681,7 +2689,7 @@ void exfat_set_entry_flag(DENTRY_T *p_entry, u8 flags)
 u32 fat_get_entry_clu0(DENTRY_T *p_entry)
 {
 	DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
-	return (GET32_A(ep->start_clu_hi) << 16) | GET16_A(ep->start_clu_lo);
+	return ((u32) GET16_A(ep->start_clu_hi) << 16) | GET16_A(ep->start_clu_lo);
 } /* end of fat_get_entry_clu0 */
 
 u32 exfat_get_entry_clu0(DENTRY_T *p_entry)
@@ -2827,7 +2835,7 @@ void exfat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, u8 mode)
 s32 fat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 type,
 						 u32 start_clu, u64 size)
 {
-	u32 sector;
+	sector_t sector;
 	DOS_DENTRY_T *dos_ep;
 
 	dos_ep = (DOS_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, &sector);
@@ -2843,7 +2851,7 @@ s32 fat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 ty
 s32 exfat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 type,
 						   u32 start_clu, u64 size)
 {
-	u32 sector;
+	sector_t sector;
 	u8 flags;
 	FILE_DENTRY_T *file_ep;
 	STRM_DENTRY_T *strm_ep;
@@ -2872,7 +2880,7 @@ s32 fat_init_ext_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, s32 nu
 						 UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname)
 {
 	int i;
-	u32 sector;
+	sector_t sector;
 	u8 chksum;
 	u16 *uniname = p_uniname->name;
 	DOS_DENTRY_T *dos_ep;
@@ -2914,7 +2922,7 @@ s32 exfat_init_ext_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, s32
 						   UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname)
 {
 	int i;
-	u32 sector;
+	sector_t sector;
 	u16 *uniname = p_uniname->name;
 	FILE_DENTRY_T *file_ep;
 	STRM_DENTRY_T *strm_ep;
@@ -3056,7 +3064,7 @@ void init_name_entry(NAME_DENTRY_T *ep, u16 *uniname)
 void fat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, s32 order, s32 num_entries)
 {
 	int i;
-	u32 sector;
+	sector_t sector;
 	DENTRY_T *ep;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
 
@@ -3073,7 +3081,7 @@ void fat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, s32
 void exfat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, s32 order, s32 num_entries)
 {
 	int i;
-	u32 sector;
+	sector_t sector;
 	DENTRY_T *ep;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
 
@@ -3090,7 +3098,7 @@ void exfat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, s
 void update_dir_checksum(struct super_block *sb, CHAIN_T *p_dir, s32 entry)
 {
 	int i, num_entries;
-	u32 sector;
+	sector_t sector;
 	u16 chksum;
 	FILE_DENTRY_T *file_ep;
 	DENTRY_T *ep;
@@ -3161,7 +3169,7 @@ static s32 _walk_fat_chain(struct super_block *sb, CHAIN_T *p_dir, s32 byte_offs
 		*clu = cur_clu;
 	return FFS_SUCCESS;
 }
-s32 find_location(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 *sector, s32 *offset)
+s32 find_location(struct super_block *sb, CHAIN_T *p_dir, s32 entry, sector_t *sector, s32 *offset)
 {
 	s32 off, ret;
 	u32 clu = 0;
@@ -3188,7 +3196,7 @@ s32 find_location(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 *sector
 	return FFS_SUCCESS;
 } /* end of find_location */
 
-DENTRY_T *get_entry_with_sector(struct super_block *sb, u32 sector, s32 offset)
+DENTRY_T *get_entry_with_sector(struct super_block *sb, sector_t sector, s32 offset)
 {
 	u8 *buf;
 
@@ -3200,10 +3208,10 @@ DENTRY_T *get_entry_with_sector(struct super_block *sb, u32 sector, s32 offset)
 	return (DENTRY_T *)(buf + offset);
 } /* end of get_entry_with_sector */
 
-DENTRY_T *get_entry_in_dir(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 *sector)
+DENTRY_T *get_entry_in_dir(struct super_block *sb, CHAIN_T *p_dir, s32 entry, sector_t *sector)
 {
 	s32 off;
-	u32 sec;
+	sector_t sec;
 	u8 *buf;
 
 	if (find_location(sb, p_dir, entry, &sec, &off) != FFS_SUCCESS)
@@ -3242,7 +3250,8 @@ ENTRY_SET_CACHE_T *get_entry_set_in_dir(struct super_block *sb, CHAIN_T *p_dir,
 {
 	s32 off, ret, byte_offset;
 	u32 clu = 0;
-	u32 sec, entry_type;
+	sector_t sec;
+	u32 entry_type;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
 	BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
 	ENTRY_SET_CACHE_T *es = NULL;
@@ -3375,8 +3384,9 @@ ENTRY_SET_CACHE_T *get_entry_set_in_dir(struct super_block *sb, CHAIN_T *p_dir,
 	if (file_ep)
 		*file_ep = (DENTRY_T *)&(es->__buf);
 
-	DPRINTK("es sec %u offset %d flags %d, num_entries %u buf ptr %p\n",
-		   es->sector, es->offset, es->alloc_flag, es->num_entries, &(es->__buf));
+	DPRINTK("es sec %llu offset %d flags %d, num_entries %u buf ptr %p\n",
+		   (unsigned long long)es->sector, es->offset, es->alloc_flag,
+		   es->num_entries, &(es->__buf));
 	DPRINTK("get_entry_set_in_dir exited %p\n", es);
 	return es;
 err_out:
@@ -3394,7 +3404,7 @@ void release_entry_set(ENTRY_SET_CACHE_T *es)
 }
 
 
-static s32 __write_partial_entries_in_entry_set(struct super_block *sb, ENTRY_SET_CACHE_T *es, u32 sec, s32 off, u32 count)
+static s32 __write_partial_entries_in_entry_set(struct super_block *sb, ENTRY_SET_CACHE_T *es, sector_t sec, s32 off, u32 count)
 {
 	s32 num_entries, buf_off = (off - es->offset);
 	u32 remaining_byte_in_sector, copy_entries;
@@ -3404,7 +3414,7 @@ static s32 __write_partial_entries_in_entry_set(struct super_block *sb, ENTRY_SE
 	u8 *buf, *esbuf = (u8 *)&(es->__buf);
 
 	DPRINTK("__write_partial_entries_in_entry_set entered\n");
-	DPRINTK("es %p sec %u off %d count %d\n", es, sec, off, count);
+	DPRINTK("es %p sec %llu off %d count %d\n", es, (unsigned long long)sec, off, count);
 	num_entries = count;
 
 	while (num_entries) {
@@ -3415,7 +3425,7 @@ static s32 __write_partial_entries_in_entry_set(struct super_block *sb, ENTRY_SE
 		if (buf == NULL)
 			goto err_out;
 		DPRINTK("es->buf %p buf_off %u\n", esbuf, buf_off);
-		DPRINTK("copying %d entries from %p to sector %u\n", copy_entries, (esbuf + buf_off), sec);
+		DPRINTK("copying %d entries from %p to sector %llu\n", copy_entries, (esbuf + buf_off), (unsigned long long)sec);
 		memcpy(buf + off, esbuf + buf_off, copy_entries << DENTRY_SIZE_BITS);
 		buf_modify(sb, sec);
 		num_entries -= copy_entries;
@@ -3456,7 +3466,8 @@ s32 write_whole_entry_set(struct super_block *sb, ENTRY_SET_CACHE_T *es)
 s32 write_partial_entries_in_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es, DENTRY_T *ep, u32 count)
 {
 	s32 ret, byte_offset, off;
-	u32 clu=0, sec;
+	u32 clu=0;
+	sector_t sec;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
 	BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
 	CHAIN_T dir;
@@ -3579,7 +3590,8 @@ s32 search_deleted_or_unused_entry(struct super_block *sb, CHAIN_T *p_dir, s32 n
 s32 find_empty_entry(struct inode *inode, CHAIN_T *p_dir, s32 num_entries)
 {
 	s32 ret, dentry;
-	u32 last_clu, sector;
+	u32 last_clu;
+	sector_t sector;
 	u64 size = 0;
 	CHAIN_T clu;
 	DENTRY_T *ep = NULL;
@@ -3758,7 +3770,7 @@ s32 fat_find_dir_entry(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uni
    -2 : entry with the name does not exist */
 s32 exfat_find_dir_entry(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, s32 num_entries, DOS_NAME_T *p_dosname, u32 type)
 {
-	int i, dentry = 0, num_ext_entries = 0, len;
+	int i = 0, dentry = 0, num_ext_entries = 0, len, step;
 	s32 order = 0, is_feasible_entry = FALSE;
 	s32 dentries_per_clu, num_empty = 0;
 	u32 entry_type;
@@ -3792,12 +3804,13 @@ s32 exfat_find_dir_entry(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_u
 		if (p_fs->dev_ejected)
 			break;
 
-		for (i = 0; i < dentries_per_clu; i++, dentry++) {
+		while (i < dentries_per_clu) {
 			ep = get_entry_in_dir(sb, &clu, i, NULL);
 			if (!ep)
 				return -2;
 
 			entry_type = p_fs->fs_func->get_entry_type(ep);
+			step = 1;
 
 			if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) {
 				is_feasible_entry = FALSE;
@@ -3820,20 +3833,23 @@ s32 exfat_find_dir_entry(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_u
 				num_empty = 0;
 
 				if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) {
+					file_ep = (FILE_DENTRY_T *) ep;
 					if ((type == TYPE_ALL) || (type == entry_type)) {
-						file_ep = (FILE_DENTRY_T *) ep;
 						num_ext_entries = file_ep->num_ext;
 						is_feasible_entry = TRUE;
 					} else {
 						is_feasible_entry = FALSE;
+						step = file_ep->num_ext + 1;
 					}
 				} else if (entry_type == TYPE_STREAM) {
 					if (is_feasible_entry) {
 						strm_ep = (STRM_DENTRY_T *) ep;
-						if (p_uniname->name_len == strm_ep->name_len) {
+						if (p_uniname->name_hash == GET16_A(strm_ep->name_hash) &&
+						    p_uniname->name_len == strm_ep->name_len) {
 							order = 1;
 						} else {
 							is_feasible_entry = FALSE;
+							step = num_ext_entries;
 						}
 					}
 				} else if (entry_type == TYPE_EXTEND) {
@@ -3852,6 +3868,7 @@ s32 exfat_find_dir_entry(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_u
 
 						if (nls_uniname_cmp(sb, uniname, entry_uniname)) {
 							is_feasible_entry = FALSE;
+							step = num_ext_entries - order + 1;
 						} else if (order == num_ext_entries) {
 							p_fs->hint_uentry.dir = CLUSTER_32(~0);
 							p_fs->hint_uentry.entry = -1;
@@ -3864,8 +3881,13 @@ s32 exfat_find_dir_entry(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_u
 					is_feasible_entry = FALSE;
 				}
 			}
+
+			i += step;
+			dentry += step;
 		}
 
+		i -= dentries_per_clu;
+
 		if (p_dir->dir == CLUSTER_32(0))
 			break; /* FAT16 root_dir */
 
@@ -4806,7 +4828,7 @@ s32 create_file(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, u8 m
 void remove_file(struct inode *inode, CHAIN_T *p_dir, s32 entry)
 {
 	s32 num_entries;
-	u32 sector;
+	sector_t sector;
 	DENTRY_T *ep;
 	struct super_block *sb = inode->i_sb;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -4834,7 +4856,7 @@ void remove_file(struct inode *inode, CHAIN_T *p_dir, s32 entry)
 s32 rename_file(struct inode *inode, CHAIN_T *p_dir, s32 oldentry, UNI_NAME_T *p_uniname, FILE_ID_T *fid)
 {
 	s32 ret, newentry = -1, num_old_entries, num_new_entries;
-	u32 sector_old, sector_new;
+	sector_t sector_old, sector_new;
 	DOS_NAME_T dos_name;
 	DENTRY_T *epold, *epnew;
 	struct super_block *sb = inode->i_sb;
@@ -4923,7 +4945,7 @@ s32 rename_file(struct inode *inode, CHAIN_T *p_dir, s32 oldentry, UNI_NAME_T *p
 s32 move_file(struct inode *inode, CHAIN_T *p_olddir, s32 oldentry, CHAIN_T *p_newdir, UNI_NAME_T *p_uniname, FILE_ID_T *fid)
 {
 	s32 ret, newentry, num_new_entries, num_old_entries;
-	u32 sector_mov, sector_new;
+	sector_t sector_mov, sector_new;
 	CHAIN_T clu;
 	DOS_NAME_T dos_name;
 	DENTRY_T *epmov, *epnew;
@@ -5022,13 +5044,13 @@ s32 move_file(struct inode *inode, CHAIN_T *p_olddir, s32 oldentry, CHAIN_T *p_n
  *  Sector Read/Write Functions
  */
 
-s32 sector_read(struct super_block *sb, u32 sec, struct buffer_head **bh, s32 read)
+s32 sector_read(struct super_block *sb, sector_t sec, struct buffer_head **bh, s32 read)
 {
 	s32 ret = FFS_MEDIAERR;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
 
 	if ((sec >= (p_fs->PBR_sector+p_fs->num_sectors)) && (p_fs->num_sectors > 0)) {
-		printk("[EXFAT] sector_read: out of range error! (sec = %d)\n", sec);
+		printk("[EXFAT] sector_read: out of range error! (sec = %llu)\n", (unsigned long long)sec);
 		fs_error(sb);
 		return ret;
 	}
@@ -5042,13 +5064,13 @@ s32 sector_read(struct super_block *sb, u32 sec, struct buffer_head **bh, s32 re
 	return ret;
 } /* end of sector_read */
 
-s32 sector_write(struct super_block *sb, u32 sec, struct buffer_head *bh, s32 sync)
+s32 sector_write(struct super_block *sb, sector_t sec, struct buffer_head *bh, s32 sync)
 {
 	s32 ret = FFS_MEDIAERR;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
 
 	if (sec >= (p_fs->PBR_sector+p_fs->num_sectors) && (p_fs->num_sectors > 0)) {
-		printk("[EXFAT] sector_write: out of range error! (sec = %d)\n", sec);
+		printk("[EXFAT] sector_write: out of range error! (sec = %llu)\n", (unsigned long long)sec);
 		fs_error(sb);
 		return ret;
 	}
@@ -5068,13 +5090,14 @@ s32 sector_write(struct super_block *sb, u32 sec, struct buffer_head *bh, s32 sy
 	return ret;
 } /* end of sector_write */
 
-s32 multi_sector_read(struct super_block *sb, u32 sec, struct buffer_head **bh, s32 num_secs, s32 read)
+s32 multi_sector_read(struct super_block *sb, sector_t sec, struct buffer_head **bh, s32 num_secs, s32 read)
 {
 	s32 ret = FFS_MEDIAERR;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
 
 	if (((sec+num_secs) > (p_fs->PBR_sector+p_fs->num_sectors)) && (p_fs->num_sectors > 0)) {
-		printk("[EXFAT] multi_sector_read: out of range error! (sec = %d, num_secs = %d)\n", sec, num_secs);
+		printk("[EXFAT] multi_sector_read: out of range error! (sec = %llu, num_secs = %d)\n",
+		       (unsigned long long)sec, num_secs);
 		fs_error(sb);
 		return ret;
 	}
@@ -5088,13 +5111,14 @@ s32 multi_sector_read(struct super_block *sb, u32 sec, struct buffer_head **bh,
 	return ret;
 } /* end of multi_sector_read */
 
-s32 multi_sector_write(struct super_block *sb, u32 sec, struct buffer_head *bh, s32 num_secs, s32 sync)
+s32 multi_sector_write(struct super_block *sb, sector_t sec, struct buffer_head *bh, s32 num_secs, s32 sync)
 {
 	s32 ret = FFS_MEDIAERR;
 	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
 
 	if ((sec+num_secs) > (p_fs->PBR_sector+p_fs->num_sectors) && (p_fs->num_sectors > 0)) {
-		printk("[EXFAT] multi_sector_write: out of range error! (sec = %d, num_secs = %d)\n", sec, num_secs);
+		printk("[EXFAT] multi_sector_write: out of range error! (sec = %llu, num_secs = %d)\n",
+		       (unsigned long long)sec, num_secs);
 		fs_error(sb);
 		return ret;
 	}
@@ -5112,5 +5136,3 @@ s32 multi_sector_write(struct super_block *sb, u32 sec, struct buffer_head *bh,
 
 	return ret;
 } /* end of multi_sector_write */
-
-/* end of exfat_core.c */
diff --git a/exfat_core.h b/exfat_core.h
index 9724d61..52d05c7 100644
--- a/exfat_core.h
+++ b/exfat_core.h
@@ -19,7 +19,7 @@
 /************************************************************************/
 /*                                                                      */
 /*  PROJECT : exFAT & FAT12/16/32 File System                           */
-/*  FILE    : exfat.h                                                   */
+/*  FILE    : exfat_core.h                                              */
 /*  PURPOSE : Header File for exFAT File Manager                        */
 /*                                                                      */
 /*----------------------------------------------------------------------*/
@@ -127,13 +127,13 @@
 #define MAX(a, b)		(((a) > (b)) ? (a) : (b))
 
 #define START_SECTOR(x) \
-	((((x) - 2) << p_fs->sectors_per_clu_bits) + p_fs->data_start_sector)
+	((((sector_t)((x) - 2)) << p_fs->sectors_per_clu_bits) + p_fs->data_start_sector)
 
 #define IS_LAST_SECTOR_IN_CLUSTER(sec) \
 		((((sec) - p_fs->data_start_sector + 1) & ((1 <<  p_fs->sectors_per_clu_bits) - 1)) == 0)
 
 #define GET_CLUSTER_FROM_SECTOR(sec)			\
-		((((sec) - p_fs->data_start_sector) >> p_fs->sectors_per_clu_bits) + 2)
+		((u32)((((sec) - p_fs->data_start_sector) >> p_fs->sectors_per_clu_bits) + 2))
 
 #define GET16(p_src) \
 	(((u16)(p_src)[0]) | (((u16)(p_src)[1]) << 8))
@@ -449,7 +449,7 @@ typedef struct __FS_INFO_T {
 	u32      vol_type;               /* volume FAT type */
 	u32      vol_id;                 /* volume serial number */
 
-	u32      num_sectors;            /* num of sectors in volume */
+	u64      num_sectors;            /* num of sectors in volume */
 	u32      num_clusters;           /* num of clusters in volume */
 	u32      cluster_size;           /* cluster size in bytes */
 	u32      cluster_size_bits;
@@ -501,7 +501,7 @@ typedef struct __FS_INFO_T {
 #define ES_ALL_ENTRIES	0
 
 typedef struct {
-	u32	sector;		/* sector number that contains file_entry */
+	sector_t	sector;	/* sector number that contains file_entry */
 	s32	offset;		/* byte offset in the sector */
 	s32	alloc_flag;	/* flag in stream entry. 01 for cluster chain, 03 for contig. clusteres. */
 	u32 num_entries;
@@ -615,9 +615,9 @@ void   init_name_entry(NAME_DENTRY_T *ep, u16 *uniname);
 void   fat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, s32 order, s32 num_entries);
 void   exfat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, s32 order, s32 num_entries);
 
-s32   find_location(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 *sector, s32 *offset);
-DENTRY_T *get_entry_with_sector(struct super_block *sb, u32 sector, s32 offset);
-DENTRY_T *get_entry_in_dir(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 *sector);
+s32   find_location(struct super_block *sb, CHAIN_T *p_dir, s32 entry, sector_t *sector, s32 *offset);
+DENTRY_T *get_entry_with_sector(struct super_block *sb, sector_t sector, s32 offset);
+DENTRY_T *get_entry_in_dir(struct super_block *sb, CHAIN_T *p_dir, s32 entry, sector_t *sector);
 ENTRY_SET_CACHE_T *get_entry_set_in_dir(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 type, DENTRY_T **file_ep);
 void release_entry_set(ENTRY_SET_CACHE_T *es);
 s32 write_whole_entry_set(struct super_block *sb, ENTRY_SET_CACHE_T *es);
@@ -663,9 +663,9 @@ s32  rename_file(struct inode *inode, CHAIN_T *p_dir, s32 old_entry, UNI_NAME_T
 s32  move_file(struct inode *inode, CHAIN_T *p_olddir, s32 oldentry, CHAIN_T *p_newdir, UNI_NAME_T *p_uniname, FILE_ID_T *fid);
 
 /* sector read/write functions */
-s32   sector_read(struct super_block *sb, u32 sec, struct buffer_head **bh, s32 read);
-s32   sector_write(struct super_block *sb, u32 sec, struct buffer_head *bh, s32 sync);
-s32   multi_sector_read(struct super_block *sb, u32 sec, struct buffer_head **bh, s32 num_secs, s32 read);
-s32   multi_sector_write(struct super_block *sb, u32 sec, struct buffer_head *bh, s32 num_secs, s32 sync);
+s32   sector_read(struct super_block *sb, sector_t sec, struct buffer_head **bh, s32 read);
+s32   sector_write(struct super_block *sb, sector_t sec, struct buffer_head *bh, s32 sync);
+s32   multi_sector_read(struct super_block *sb, sector_t sec, struct buffer_head **bh, s32 num_secs, s32 read);
+s32   multi_sector_write(struct super_block *sb, sector_t sec, struct buffer_head *bh, s32 num_secs, s32 sync);
 
 #endif /* _EXFAT_H */
diff --git a/exfat_data.c b/exfat_data.c
index 41c74ec..65da07a 100644
--- a/exfat_data.c
+++ b/exfat_data.c
@@ -57,15 +57,21 @@
 /*----------------------------------------------------------------------*/
 
 /* FAT cache */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
+DECLARE_MUTEX(f_sem);
+#else
 DEFINE_SEMAPHORE(f_sem);
+#endif
 BUF_CACHE_T FAT_cache_array[FAT_CACHE_SIZE];
 BUF_CACHE_T FAT_cache_lru_list;
 BUF_CACHE_T FAT_cache_hash_list[FAT_CACHE_HASH_SIZE];
 
 /* buf cache */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
+DECLARE_MUTEX(b_sem);
+#else
 DEFINE_SEMAPHORE(b_sem);
+#endif
 BUF_CACHE_T buf_cache_array[BUF_CACHE_SIZE];
 BUF_CACHE_T buf_cache_lru_list;
 BUF_CACHE_T buf_cache_hash_list[BUF_CACHE_HASH_SIZE];
-
-/* end of exfat_data.c */
diff --git a/exfat_data.h b/exfat_data.h
index 317e827..53b0e39 100644
--- a/exfat_data.h
+++ b/exfat_data.h
@@ -56,5 +56,3 @@
 #define BUF_CACHE_HASH_SIZE     64
 
 #endif /* _EXFAT_DATA_H */
-
-/* end of exfat_data.h */
diff --git a/exfat_nls.c b/exfat_nls.c
index 382bdc3..a48b3d0 100644
--- a/exfat_nls.c
+++ b/exfat_nls.c
@@ -353,7 +353,11 @@ void nls_cstring_to_uniname(struct super_block *sb, UNI_NAME_T *p_uniname, u8 *p
 		lossy = TRUE;
 
 	if (nls == NULL) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,101)
+		i = utf8s_to_utf16s(p_cstring, MAX_NAME_LENGTH, uniname);
+#else
 		i = utf8s_to_utf16s(p_cstring, MAX_NAME_LENGTH, UTF16_HOST_ENDIAN, uniname, MAX_NAME_LENGTH);
+#endif
 		for (j = 0; j < i; j++)
 			SET16_A(upname + j * 2, nls_upper(sb, uniname[j]));
 		uniname[i] = '\0';
@@ -442,5 +446,3 @@ static s32 convert_uni_to_ch(struct nls_table *nls, u8 *ch, u16 uni, s32 *lossy)
 	return len;
 
 } /* end of convert_uni_to_ch */
-
-/* end of exfat_nls.c */
diff --git a/exfat_nls.h b/exfat_nls.h
index 69eedc9..bc516d7 100644
--- a/exfat_nls.h
+++ b/exfat_nls.h
@@ -89,5 +89,3 @@ void   nls_uniname_to_cstring(struct super_block *sb, u8 *p_cstring, UNI_NAME_T
 void   nls_cstring_to_uniname(struct super_block *sb, UNI_NAME_T *p_uniname, u8 *p_cstring, s32 *p_lossy);
 
 #endif /* _EXFAT_NLS_H */
-
-/* end of exfat_nls.h */
diff --git a/exfat_oal.c b/exfat_oal.c
index 814a919..7435442 100644
--- a/exfat_oal.c
+++ b/exfat_oal.c
@@ -55,7 +55,11 @@
 /*                                                                      */
 /*======================================================================*/
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
+DECLARE_MUTEX(z_sem);
+#else
 DEFINE_SEMAPHORE(z_sem);
+#endif
 
 s32 sm_init(struct semaphore *sm)
 {
@@ -124,10 +128,16 @@ static time_t accum_days_in_year[] = {
 
 TIMESTAMP_T *tm_current(TIMESTAMP_T *tp)
 {
-	struct timespec ts = CURRENT_TIME_SEC;
-	time_t second = ts.tv_sec;
-	time_t day, leap_day, month, year;
+	struct timespec ts;
+	time_t second, day, leap_day, month, year;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0)
+	ts = CURRENT_TIME_SEC;
+#else
+	ktime_get_real_ts(&ts);
+#endif
 
+	second = ts.tv_sec;
 	second -= sys_tz.tz_minuteswest * SECS_PER_MIN;
 
 	/* Jan 1 GMT 00:00:00 1980. But what about another time zone? */
@@ -184,5 +194,3 @@ TIMESTAMP_T *tm_current(TIMESTAMP_T *tp)
 
 	return tp;
 } /* end of tm_current */
-
-/* end of exfat_oal.c */
diff --git a/exfat_oal.h b/exfat_oal.h
index b9ad234..b6dd789 100644
--- a/exfat_oal.h
+++ b/exfat_oal.h
@@ -72,5 +72,3 @@ void  sm_V(struct semaphore *sm);
 TIMESTAMP_T *tm_current(TIMESTAMP_T *tm);
 
 #endif /* _EXFAT_OAL_H */
-
-/* end of exfat_oal.h */
diff --git a/exfat_super.c b/exfat_super.c
index 3950a99..ab828c3 100644
--- a/exfat_super.c
+++ b/exfat_super.c
@@ -95,6 +95,10 @@ static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET;
 
 extern struct timezone sys_tz;
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0)
+#define current_time(x)	(CURRENT_TIME_SEC)
+#endif
+
 #define CHECK_ERR(x)	BUG_ON(x)
 
 #define UNIX_SECS_1980    315532800L
@@ -218,7 +222,11 @@ static struct inode *exfat_build_inode(struct super_block *sb, FILE_ID_T *fid, l
 static void exfat_detach(struct inode *inode);
 static void exfat_attach(struct inode *inode, loff_t i_pos);
 static inline unsigned long exfat_hash(loff_t i_pos);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)
+static int exfat_write_inode(struct inode *inode, int wait);
+#else
 static int exfat_write_inode(struct inode *inode, struct writeback_control *wbc);
+#endif
 static void exfat_write_super(struct super_block *sb);
 
 static void __lock_super(struct super_block *sb)
@@ -294,15 +302,15 @@ static int exfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,00)
 	if (flags & LOOKUP_RCU)
 		return -ECHILD;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,00)
+#else
 	unsigned int flags;
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,00)
 	if (nd && nd->flags & LOOKUP_RCU)
 		return -ECHILD;
+#endif
 
 	flags = nd ? nd->flags : 0;
-#else
-	flags = nd ? nd->flags : 0;
 #endif
 
 	if (dentry->d_inode)
@@ -336,25 +344,33 @@ static unsigned int exfat_striptail_len(const struct qstr *qstr)
 	return __exfat_striptail_len(qstr->len, qstr->name);
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
 static int exfat_d_hash(const struct dentry *dentry, struct qstr *qstr)
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+static int exfat_d_hash(struct dentry *dentry, struct qstr *qstr)
 #else
 static int exfat_d_hash(const struct dentry *dentry, const struct inode *inode,
 		struct qstr *qstr)
 #endif
 {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,8,0)
+	qstr->hash = full_name_hash(dentry, qstr->name, exfat_striptail_len(qstr));
+#else
 	qstr->hash = full_name_hash(qstr->name, exfat_striptail_len(qstr));
+#endif
 	return 0;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
 static int exfat_d_hashi(const struct dentry *dentry, struct qstr *qstr)
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+static int exfat_d_hashi(struct dentry *dentry, struct qstr *qstr)
 #else
 static int exfat_d_hashi(const struct dentry *dentry, const struct inode *inode,
 		struct qstr *qstr)
 #endif
 {
-	struct nls_table *t = EXFAT_SB(dentry->d_sb)->nls_io;
+	struct super_block *sb = dentry->d_sb;
 	const unsigned char *name;
 	unsigned int len;
 	unsigned long hash;
@@ -362,38 +378,72 @@ static int exfat_d_hashi(const struct dentry *dentry, const struct inode *inode,
 	name = qstr->name;
 	len = exfat_striptail_len(qstr);
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,8,0)
+	hash = init_name_hash(dentry);
+#else
 	hash = init_name_hash();
+#endif
 	while (len--)
-		hash = partial_name_hash(nls_tolower(t, *name++), hash);
+		hash = partial_name_hash(nls_upper(sb, *name++), hash);
 	qstr->hash = end_name_hash(hash);
 
 	return 0;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,8,0)
+static int exfat_cmpi(const struct dentry *dentry,
+		unsigned int len, const char *str, const struct qstr *name)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
 static int exfat_cmpi(const struct dentry *parent, const struct dentry *dentry,
 		unsigned int len, const char *str, const struct qstr *name)
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+static int exfat_cmpi(struct dentry *parent, struct qstr *a, struct qstr *b)
 #else
 static int exfat_cmpi(const struct dentry *parent, const struct inode *pinode,
 		const struct dentry *dentry, const struct inode *inode,
 		unsigned int len, const char *str, const struct qstr *name)
 #endif
 {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,8,0)
+	struct nls_table *t = EXFAT_SB(dentry->d_sb)->nls_io;
+#else
 	struct nls_table *t = EXFAT_SB(parent->d_sb)->nls_io;
+#endif
 	unsigned int alen, blen;
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+	alen = exfat_striptail_len(a);
+	blen = exfat_striptail_len(b);
+#else
 	alen = exfat_striptail_len(name);
 	blen = __exfat_striptail_len(len, str);
+#endif
 	if (alen == blen) {
-		if (nls_strnicmp(t, name->name, str, alen) == 0)
+		if (t == NULL) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+			if (strncasecmp(a->name, b->name, alen) == 0)
+#else
+			if (strncasecmp(name->name, str, alen) == 0)
+#endif
+				return 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+		} else if (nls_strnicmp(t, a->name, b->name, alen) == 0)
+#else
+		} else if (nls_strnicmp(t, name->name, str, alen) == 0)
+#endif
 			return 0;
 	}
 	return 1;
 }
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,8,0)
+static int exfat_cmp(const struct dentry *dentry,
+		unsigned int len, const char *str, const struct qstr *name)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
 static int exfat_cmp(const struct dentry *parent, const struct dentry *dentry,
 		unsigned int len, const char *str, const struct qstr *name)
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+static int exfat_cmp(struct dentry *parent, struct qstr *a,
+			struct qstr *b)
 #else
 static int exfat_cmp(const struct dentry *parent, const struct inode *pinode,
 		const struct dentry *dentry, const struct inode *inode,
@@ -402,10 +452,19 @@ static int exfat_cmp(const struct dentry *parent, const struct inode *pinode,
 {
 	unsigned int alen, blen;
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+	alen = exfat_striptail_len(a);
+	blen = exfat_striptail_len(b);
+#else
 	alen = exfat_striptail_len(name);
 	blen = __exfat_striptail_len(len, str);
+#endif
 	if (alen == blen) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+		if (strncmp(a->name, b->name, alen) == 0)
+#else
 		if (strncmp(name->name, str, alen) == 0)
+#endif
 			return 0;
 	}
 	return 1;
@@ -570,7 +629,11 @@ static long exfat_generic_ioctl(struct file *filp,
 #endif
 {
 #if !(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
-	struct inode *inode = filp->f_dentry->d_inode;
+    #if !(LINUX_VERSION_CODE < KERNEL_VERSION(3,18,3))
+		  struct inode *inode = filp->f_path.dentry->d_inode;
+    #else
+		  struct inode *inode = filp->f_dentry->d_inode;
+	#endif
 #endif
 #ifdef CONFIG_EXFAT_KERNEL_DEBUG
 	unsigned int flags;
@@ -610,13 +673,22 @@ static long exfat_generic_ioctl(struct file *filp,
 }
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
+static int exfat_file_fsync(struct file *filp, struct dentry *dentry,
+				int datasync)
+#else
 static int exfat_file_fsync(struct file *filp, int datasync)
+#endif
 {
 	struct inode *inode = filp->f_mapping->host;
 	struct super_block *sb = inode->i_sb;
 	int res, err;
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
+	res = simple_fsync(filp, dentry, datasync);
+#else
 	res = generic_file_fsync(filp, datasync);
+#endif
 	err = FsSyncVol(sb, 1);
 
 	return res ? res : err;
@@ -643,7 +715,7 @@ const struct file_operations exfat_dir_operations = {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,00)
 static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 						bool excl)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
 static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 						struct nameidata *nd)
 #else
@@ -653,7 +725,6 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, int mode,
 {
 	struct super_block *sb = dir->i_sb;
 	struct inode *inode;
-	struct timespec ts;
 	FILE_ID_T fid;
 	loff_t i_pos;
 	int err;
@@ -662,8 +733,6 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, int mode,
 
 	DPRINTK("exfat_create entered\n");
 
-	ts = CURRENT_TIME_SEC;
-
 	err = FsCreateFile(dir, (u8 *) dentry->d_name.name, FM_REGULAR, &fid);
 	if (err) {
 		if (err == FFS_INVALIDPATH)
@@ -679,7 +748,7 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, int mode,
 		goto out;
 	}
 	dir->i_version++;
-	dir->i_ctime = dir->i_mtime = dir->i_atime = ts;
+	dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir);
 	if (IS_DIRSYNC(dir))
 		(void) exfat_sync_inode(dir);
 	else
@@ -693,7 +762,7 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, int mode,
 		goto out;
 	}
 	inode->i_version++;
-	inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
 	/* timestamp is already written, so mark_inode_dirty() is unnecessary. */
 
 	dentry->d_time = dentry->d_parent->d_inode->i_version;
@@ -761,7 +830,7 @@ static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry,
 	}
 
 	i_mode = inode->i_mode;
-	if (S_ISLNK(i_mode)) {
+	if (S_ISLNK(i_mode) && !EXFAT_I(inode)->target) {
 		EXFAT_I(inode)->target = kmalloc(i_size_read(inode)+1, GFP_KERNEL);
 		if (!EXFAT_I(inode)->target) {
 			err = -ENOMEM;
@@ -811,15 +880,12 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
 {
 	struct inode *inode = dentry->d_inode;
 	struct super_block *sb = dir->i_sb;
-	struct timespec ts;
 	int err;
 
 	__lock_super(sb);
 
 	DPRINTK("exfat_unlink entered\n");
 
-	ts = CURRENT_TIME_SEC;
-
 	EXFAT_I(inode)->fid.size = i_size_read(inode);
 
 	err = FsRemoveFile(dir, &(EXFAT_I(inode)->fid));
@@ -831,14 +897,14 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
 		goto out;
 	}
 	dir->i_version++;
-	dir->i_mtime = dir->i_atime = ts;
+	dir->i_mtime = dir->i_atime = current_time(dir);
 	if (IS_DIRSYNC(dir))
 		(void) exfat_sync_inode(dir);
 	else
 		mark_inode_dirty(dir);
 
 	clear_nlink(inode);
-	inode->i_mtime = inode->i_atime = ts;
+	inode->i_mtime = inode->i_atime = current_time(inode);
 	exfat_detach(inode);
 	remove_inode_hash(inode);
 
@@ -852,7 +918,6 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry, const char *t
 {
 	struct super_block *sb = dir->i_sb;
 	struct inode *inode;
-	struct timespec ts;
 	FILE_ID_T fid;
 	loff_t i_pos;
 	int err;
@@ -863,8 +928,6 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry, const char *t
 
 	DPRINTK("exfat_symlink entered\n");
 
-	ts = CURRENT_TIME_SEC;
-
 	err = FsCreateFile(dir, (u8 *) dentry->d_name.name, FM_SYMLINK, &fid);
 	if (err) {
 		if (err == FFS_INVALIDPATH)
@@ -891,7 +954,7 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry, const char *t
 	}
 
 	dir->i_version++;
-	dir->i_ctime = dir->i_mtime = dir->i_atime = ts;
+	dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir);
 	if (IS_DIRSYNC(dir))
 		(void) exfat_sync_inode(dir);
 	else
@@ -905,7 +968,7 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry, const char *t
 		goto out;
 	}
 	inode->i_version++;
-	inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
 	/* timestamp is already written, so mark_inode_dirty() is unneeded. */
 
 	EXFAT_I(inode)->target = kmalloc(len+1, GFP_KERNEL);
@@ -924,7 +987,7 @@ out:
 	return err;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
 static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 #else
 static int exfat_mkdir(struct inode *dir, struct dentry *dentry, int mode)
@@ -932,7 +995,6 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
 	struct super_block *sb = dir->i_sb;
 	struct inode *inode;
-	struct timespec ts;
 	FILE_ID_T fid;
 	loff_t i_pos;
 	int err;
@@ -941,8 +1003,6 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
 	DPRINTK("exfat_mkdir entered\n");
 
-	ts = CURRENT_TIME_SEC;
-
 	err = FsCreateDir(dir, (u8 *) dentry->d_name.name, &fid);
 	if (err) {
 		if (err == FFS_INVALIDPATH)
@@ -958,7 +1018,7 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 		goto out;
 	}
 	dir->i_version++;
-	dir->i_ctime = dir->i_mtime = dir->i_atime = ts;
+	dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir);
 	if (IS_DIRSYNC(dir))
 		(void) exfat_sync_inode(dir);
 	else
@@ -973,7 +1033,7 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 		goto out;
 	}
 	inode->i_version++;
-	inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
 	/* timestamp is already written, so mark_inode_dirty() is unneeded. */
 
 	dentry->d_time = dentry->d_parent->d_inode->i_version;
@@ -989,15 +1049,12 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	struct inode *inode = dentry->d_inode;
 	struct super_block *sb = dir->i_sb;
-	struct timespec ts;
 	int err;
 
 	__lock_super(sb);
 
 	DPRINTK("exfat_rmdir entered\n");
 
-	ts = CURRENT_TIME_SEC;
-
 	EXFAT_I(inode)->fid.size = i_size_read(inode);
 
 	err = FsRemoveDir(dir, &(EXFAT_I(inode)->fid));
@@ -1015,7 +1072,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
 		goto out;
 	}
 	dir->i_version++;
-	dir->i_mtime = dir->i_atime = ts;
+	dir->i_mtime = dir->i_atime = current_time(dir);
 	if (IS_DIRSYNC(dir))
 		(void) exfat_sync_inode(dir);
 	else
@@ -1023,7 +1080,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
 	drop_nlink(dir);
 
 	clear_nlink(inode);
-	inode->i_mtime = inode->i_atime = ts;
+	inode->i_mtime = inode->i_atime = current_time(inode);
 	exfat_detach(inode);
 	remove_inode_hash(inode);
 
@@ -1033,15 +1090,25 @@ out:
 	return err;
 }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,9,0)
+static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
+						struct inode *new_dir, struct dentry *new_dentry,
+						unsigned int flags)
+#else
 static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
 						struct inode *new_dir, struct dentry *new_dentry)
+#endif
 {
 	struct inode *old_inode, *new_inode;
 	struct super_block *sb = old_dir->i_sb;
-	struct timespec ts;
 	loff_t i_pos;
 	int err;
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,9,0)
+	if (flags)
+		return -EINVAL;
+#endif
+
 	__lock_super(sb);
 
 	DPRINTK("exfat_rename entered\n");
@@ -1049,8 +1116,6 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
 	old_inode = old_dentry->d_inode;
 	new_inode = new_dentry->d_inode;
 
-	ts = CURRENT_TIME_SEC;
-
 	EXFAT_I(old_inode)->fid.size = i_size_read(old_inode);
 
 	err = FsMoveFile(old_dir, &(EXFAT_I(old_inode)->fid), new_dir, new_dentry);
@@ -1070,7 +1135,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
 		goto out;
 	}
 	new_dir->i_version++;
-	new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = ts;
+	new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = current_time(new_dir);
 	if (IS_DIRSYNC(new_dir))
 		(void) exfat_sync_inode(new_dir);
 	else
@@ -1093,7 +1158,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
 	}
 
 	old_dir->i_version++;
-	old_dir->i_ctime = old_dir->i_mtime = ts;
+	old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir);
 	if (IS_DIRSYNC(old_dir))
 		(void) exfat_sync_inode(old_dir);
 	else
@@ -1104,7 +1169,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
 		drop_nlink(new_inode);
 		if (S_ISDIR(new_inode->i_mode))
 			drop_nlink(new_inode);
-		new_inode->i_ctime = ts;
+		new_inode->i_ctime = current_time(new_inode);
 	}
 
 out:
@@ -1123,7 +1188,7 @@ static int exfat_cont_expand(struct inode *inode, loff_t size)
 	if (err != 0)
 		return err;
 
-	inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+	inode->i_ctime = inode->i_mtime = current_time(inode);
 	mark_inode_dirty(inode);
 
 	if (IS_SYNC(inode)) {
@@ -1133,7 +1198,13 @@ static int exfat_cont_expand(struct inode *inode, loff_t size)
 		err2 = write_inode_now(inode, 1);
 		err = (err) ? (err) : (err2);
 		if (!err)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
+			err =  wait_on_page_writeback_range(mapping,
+					start >> PAGE_CACHE_SHIFT,
+					(start + count - 1) >> PAGE_CACHE_SHIFT);
+#else
 			err =  filemap_fdatawait_range(mapping, start, start + count - 1);
+#endif
 	}
 	return err;
 }
@@ -1198,7 +1269,9 @@ static int exfat_setattr(struct dentry *dentry, struct iattr *attr)
 	struct inode *inode = dentry->d_inode;
 	unsigned int ia_valid;
 	int error;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
 	loff_t old_size;
+#endif
 
 	DPRINTK("exfat_setattr entered\n");
 
@@ -1217,7 +1290,11 @@ static int exfat_setattr(struct dentry *dentry, struct iattr *attr)
 		attr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET);
 	}
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,9,0)
+	error = setattr_prepare(dentry, attr);
+#else
 	error = inode_change_ok(inode, attr);
+#endif
 	attr->ia_valid = ia_valid;
 	if (error)
 		return error;
@@ -1272,9 +1349,16 @@ static int exfat_setattr(struct dentry *dentry, struct iattr *attr)
 	return error;
 }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+static int exfat_getattr(const struct path *path, struct kstat *stat,
+			 u32 request_mask, unsigned int flags)
+{
+	struct inode *inode = path->dentry->d_inode;
+#else
 static int exfat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
 	struct inode *inode = dentry->d_inode;
+#endif
 
 	DPRINTK("exfat_getattr entered\n");
 
@@ -1300,17 +1384,43 @@ const struct inode_operations exfat_dir_inode_operations = {
 /*======================================================================*/
 /*  File Operations                                                     */
 /*======================================================================*/
-
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0)
+static const char *exfat_get_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done)
+{
+	struct exfat_inode_info *ei = EXFAT_I(inode);
+	if (ei->target != NULL) {
+		char *cookie = ei->target;
+		if (cookie != NULL) {
+			return (char *)(ei->target);
+		}
+	}
+	return NULL;
+}
+#elif LINUX_VERSION_CODE > KERNEL_VERSION(4,1,0)
+static const char *exfat_follow_link(struct dentry *dentry, void **cookie)
+{
+	struct exfat_inode_info *ei = EXFAT_I(dentry->d_inode);
+	return *cookie = (char *)(ei->target);
+}
+#else
 static void *exfat_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	struct exfat_inode_info *ei = EXFAT_I(dentry->d_inode);
 	nd_set_link(nd, (char *)(ei->target));
 	return NULL;
 }
+#endif
 
 const struct inode_operations exfat_symlink_inode_operations = {
-	.readlink    = generic_readlink,
-	.follow_link = exfat_follow_link,
+	#if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0)
+		.readlink    = generic_readlink,
+	#endif
+	#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0)
+		.follow_link = exfat_follow_link,
+	#endif
+	#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0)
+		.get_link = exfat_get_link,
+	#endif
 };
 
 static int exfat_file_release(struct inode *inode, struct file *filp)
@@ -1324,10 +1434,19 @@ static int exfat_file_release(struct inode *inode, struct file *filp)
 
 const struct file_operations exfat_file_operations = {
 	.llseek      = generic_file_llseek,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)
 	.read        = do_sync_read,
 	.write       = do_sync_write,
 	.aio_read    = generic_file_aio_read,
 	.aio_write   = generic_file_aio_write,
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
+	.read        = new_sync_read,
+	.write       = new_sync_write,
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
+	.read_iter   = generic_file_read_iter,
+	.write_iter  = generic_file_write_iter,
+#endif
 	.mmap        = generic_file_mmap,
 	.release     = exfat_file_release,
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
@@ -1363,7 +1482,7 @@ static void _exfat_truncate(struct inode *inode, loff_t old_size)
 	if (err)
 		goto out;
 
-	inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+	inode->i_ctime = inode->i_mtime = current_time(inode);
 	if (IS_DIRSYNC(inode))
 		(void) exfat_sync_inode(inode);
 	else
@@ -1559,24 +1678,30 @@ static int exfat_write_end(struct file *file, struct address_space *mapping,
 #endif
 
 	if (!(err < 0) && !(fid->attr & ATTR_ARCHIVE)) {
-		inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+		inode->i_mtime = inode->i_ctime = current_time(inode);
 		fid->attr |= ATTR_ARCHIVE;
 		mark_inode_dirty(inode);
 	}
 	return err;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0)
-static ssize_t exfat_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
-				loff_t offset)
-#else
-static ssize_t exfat_direct_IO(int rw, struct kiocb *iocb,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)
 #ifdef CONFIG_AIO_OPTIMIZATION
-				struct iov_iter *iter, loff_t offset)
+static ssize_t exfat_direct_IO(int rw, struct kiocb *iocb,
+						struct iov_iter *iter, loff_t offset)
 #else
-				const struct iovec *iov,
-				loff_t offset, unsigned long nr_segs)
+static ssize_t exfat_direct_IO(int rw, struct kiocb *iocb,
+					   const struct iovec *iov,
+					   loff_t offset, unsigned long nr_segs)
 #endif
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0)
+static ssize_t exfat_direct_IO(int rw, struct kiocb *iocb,
+					   struct iov_iter *iter, loff_t offset)
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+static ssize_t exfat_direct_IO(struct kiocb *iocb,
+					   struct iov_iter *iter, loff_t offset)
+#else /* >= 4.7.x */
+static ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
 #endif
 {
 	struct inode *inode = iocb->ki_filp->f_mapping->host;
@@ -1584,50 +1709,62 @@ static ssize_t exfat_direct_IO(int rw, struct kiocb *iocb,
 	struct address_space *mapping = iocb->ki_filp->f_mapping;
 #endif
 	ssize_t ret;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0)
+	int rw;
+
+	rw = iov_iter_rw(iter);
+#endif
 
 	if (rw == WRITE) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0)
-		if (EXFAT_I(inode)->mmu_private < (offset + iov_iter_count(iter)))
-#else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)
 #ifdef CONFIG_AIO_OPTIMIZATION
 		if (EXFAT_I(inode)->mmu_private <
 					(offset + iov_iter_count(iter)))
 #else
 		if (EXFAT_I(inode)->mmu_private < (offset + iov_length(iov, nr_segs)))
 #endif
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+		if (EXFAT_I(inode)->mmu_private < (offset + iov_iter_count(iter)))
+#else
+		if (EXFAT_I(inode)->mmu_private < iov_iter_count(iter))
 #endif
 			return 0;
 	}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,00)
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0)
+	ret = blockdev_direct_IO(iocb, inode, iter, exfat_get_block);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0)
+	ret = blockdev_direct_IO(iocb, inode, iter,
+					offset, exfat_get_block);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
 	ret = blockdev_direct_IO(rw, iocb, inode, iter,
 					offset, exfat_get_block);
-#else
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0)
 #ifdef CONFIG_AIO_OPTIMIZATION
-	ret = blockdev_direct_IO(rw, iocb, inode, iter, offset,
-					exfat_get_block);
+	ret = blockdev_direct_IO(rw, iocb, inode, iter,
+					offset, exfat_get_block);
 #else
 	ret = blockdev_direct_IO(rw, iocb, inode, iov,
 					offset, nr_segs, exfat_get_block);
 #endif
-#endif
 #else
         ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
 					offset, nr_segs, exfat_get_block, NULL);
 #endif
 
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0)
+	if ((ret < 0) && (rw & WRITE))
+		exfat_write_failed(mapping, iov_iter_count(iter));
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
 	if ((ret < 0) && (rw & WRITE))
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0)
 		exfat_write_failed(mapping, offset+iov_iter_count(iter));
-#else
+#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34)
+	if ((ret < 0) && (rw & WRITE))
 #ifdef CONFIG_AIO_OPTIMIZATION
 		exfat_write_failed(mapping, offset+iov_iter_count(iter));
 #else
 		exfat_write_failed(mapping, offset+iov_length(iov, nr_segs));
 #endif
 #endif
-#endif
 	return ret;
 }
 
@@ -1810,7 +1947,11 @@ out:
 
 static int exfat_sync_inode(struct inode *inode)
 {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)
+	return exfat_write_inode(inode, 0);
+#else
 	return exfat_write_inode(inode, NULL);
+#endif
 }
 
 static struct inode *exfat_alloc_inode(struct super_block *sb)
@@ -1837,7 +1978,11 @@ static void exfat_destroy_inode(struct inode *inode)
 	kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode));
 }
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)
+static int exfat_write_inode(struct inode *inode, int wait)
+#else
 static int exfat_write_inode(struct inode *inode, struct writeback_control *wbc)
+#endif
 {
 	struct super_block *sb = inode->i_sb;
 	struct exfat_sb_info *sbi = EXFAT_SB(sb);
@@ -1982,7 +2127,7 @@ static int exfat_remount(struct super_block *sb, int *flags, char *data)
 	return 0;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
 static int exfat_show_options(struct seq_file *m, struct dentry *root)
 {
 	struct exfat_sb_info *sbi = EXFAT_SB(root->d_sb);
@@ -2046,6 +2191,45 @@ const struct super_operations exfat_sops = {
 };
 
 /*======================================================================*/
+/*  Export Operations                                                   */
+/*======================================================================*/
+
+static struct inode *exfat_nfs_get_inode(struct super_block *sb,
+				       u64 ino, u32 generation)
+{
+	struct inode *inode = NULL;
+	if (ino < EXFAT_ROOT_INO)
+		return inode;
+	inode = ilookup(sb, ino);
+
+	if (inode && generation && (inode->i_generation != generation)) {
+		iput(inode);
+		inode = NULL;
+	}
+
+	return inode;
+}
+
+static struct dentry *exfat_fh_to_dentry(struct super_block *sb, struct fid *fid,
+				int fh_len, int fh_type)
+{
+	return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+				    exfat_nfs_get_inode);
+}
+
+static struct dentry *exfat_fh_to_parent(struct super_block *sb, struct fid *fid,
+				int fh_len, int fh_type)
+{
+	return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+				    exfat_nfs_get_inode);
+}
+
+const struct export_operations exfat_export_ops = {
+	.fh_to_dentry   = exfat_fh_to_dentry,
+	.fh_to_parent   = exfat_fh_to_parent,
+};
+
+/*======================================================================*/
 /*  Super Block Read Operations                                         */
 /*======================================================================*/
 
@@ -2220,12 +2404,9 @@ static int exfat_read_root(struct inode *inode)
 {
 	struct super_block *sb = inode->i_sb;
 	struct exfat_sb_info *sbi = EXFAT_SB(sb);
-	struct timespec ts;
 	FS_INFO_T *p_fs = &(sbi->fs_info);
 	DIR_ENTRY_T info;
 
-	ts = CURRENT_TIME_SEC;
-
 	EXFAT_I(inode)->fid.dir.dir = p_fs->root_dir;
 	EXFAT_I(inode)->fid.dir.flags = 0x01;
 	EXFAT_I(inode)->fid.entry = -1;
@@ -2254,7 +2435,7 @@ static int exfat_read_root(struct inode *inode)
 	EXFAT_I(inode)->mmu_private = i_size_read(inode);
 
 	exfat_save_attr(inode, ATTR_SUBDIR);
-	inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,00)
 	set_nlink(inode, info.NumSubdirs + 2);
 #else
@@ -2264,6 +2445,7 @@ static int exfat_read_root(struct inode *inode)
 	return 0;
 }
 
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,37)
 static void setup_dops(struct super_block *sb)
 {
 	if (EXFAT_SB(sb)->options.casesensitive == 0)
@@ -2271,6 +2453,7 @@ static void setup_dops(struct super_block *sb)
 	else
 		sb->s_d_op = &exfat_dentry_ops;
 }
+#endif
 
 static int exfat_fill_super(struct super_block *sb, void *data, int silent)
 {
@@ -2296,12 +2479,15 @@ static int exfat_fill_super(struct super_block *sb, void *data, int silent)
 	sb->s_flags |= MS_NODIRATIME;
 	sb->s_magic = EXFAT_SUPER_MAGIC;
 	sb->s_op = &exfat_sops;
+	sb->s_export_op = &exfat_export_ops;
 
 	error = parse_options(data, silent, &debug, &sbi->options);
 	if (error)
 		goto out_fail;
 
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,37)
 	setup_dops(sb);
+#endif
 
 	error = -EIO;
 	sb_min_blocksize(sb, 512);
@@ -2409,6 +2595,13 @@ static int __init exfat_init_inodecache(void)
 
 static void __exit exfat_destroy_inodecache(void)
 {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
+	/*
+	 * Make sure all delayed rcu free inodes are flushed before we
+	 * destroy cache.
+	 */
+	rcu_barrier();
+#endif
 	kmem_cache_destroy(exfat_inode_cachep);
 }
 
diff --git a/exfat_upcase.c b/exfat_upcase.c
index 457ee8d..3807f37 100644
--- a/exfat_upcase.c
+++ b/exfat_upcase.c
@@ -36,7 +36,7 @@
 
 #include "exfat_nls.h"
 
-u8 uni_upcase[NUM_UPCASE<<1] = {
+const u8 uni_upcase[NUM_UPCASE<<1] = {
 	0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00,
 	0x08, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x0B, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x0E, 0x00, 0x0F, 0x00,
 	0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00,
@@ -403,5 +403,3 @@ u8 uni_upcase[NUM_UPCASE<<1] = {
 	0xF2, 0xFF, 0xF3, 0xFF, 0xF4, 0xFF, 0xF5, 0xFF, 0xF6, 0xFF, 0xF7, 0xFF, 0xF8, 0xFF, 0xF9, 0xFF,
 	0xFA, 0xFF, 0xFB, 0xFF, 0xFC, 0xFF, 0xFD, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF
 };
-
-/* end of exfat_upcase.c */