cpupowertools 5.6.4
This commit is contained in:
+11
@@ -0,0 +1,11 @@
|
||||
--- linux-3.16/include/linux/printk.h.old 2014-08-04 18:48:30.686043266 +0200
|
||||
+++ linux-3.16/include/linux/printk.h 2014-08-04 18:48:47.706218528 +0200
|
||||
@@ -37,7 +37,7 @@
|
||||
#define CONSOLE_LOGLEVEL_SILENT 0 /* Mum's the word */
|
||||
#define CONSOLE_LOGLEVEL_MIN 1 /* Minimum loglevel we let people use */
|
||||
#define CONSOLE_LOGLEVEL_QUIET 4 /* Shhh ..., when booted with "quiet" */
|
||||
-#define CONSOLE_LOGLEVEL_DEFAULT 7 /* anything MORE serious than KERN_DEBUG */
|
||||
+#define CONSOLE_LOGLEVEL_DEFAULT 4 /* anything MORE serious than KERN_DEBUG */
|
||||
#define CONSOLE_LOGLEVEL_DEBUG 10 /* issue debug messages */
|
||||
#define CONSOLE_LOGLEVEL_MOTORMOUTH 15 /* You can't shut this one up */
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
|
||||
index dd9d6190b08d..181e42bd85d3 100644
|
||||
--- a/arch/x86/kernel/cpu/microcode/core.c
|
||||
+++ b/arch/x86/kernel/cpu/microcode/core.c
|
||||
@@ -85,6 +85,7 @@
|
||||
#include <linux/syscore_ops.h>
|
||||
|
||||
#include <asm/microcode.h>
|
||||
+#include <asm/microcode_intel.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <asm/perf_event.h>
|
||||
@@ -465,6 +466,8 @@ static void mc_bp_resume(void)
|
||||
|
||||
if (uci->valid && uci->mc)
|
||||
microcode_ops->apply_microcode(cpu);
|
||||
+ else if (!uci->mc)
|
||||
+ load_ucode_intel_ap();
|
||||
}
|
||||
|
||||
static struct syscore_ops mc_syscore_ops = {
|
||||
@@ -0,0 +1,54 @@
|
||||
From: Anthony G. Basile <blueness@gentoo.org>
|
||||
|
||||
This patch adds support for a restricted user-controlled namespace on
|
||||
tmpfs filesystem used to house PaX flags. The namespace must be of the
|
||||
form user.pax.* and its value cannot exceed a size of 8 bytes.
|
||||
|
||||
This is needed even on all Gentoo systems so that XATTR_PAX flags
|
||||
are preserved for users who might build packages using portage on
|
||||
a tmpfs system with a non-hardened kernel and then switch to a
|
||||
hardened kernel with XATTR_PAX enabled.
|
||||
|
||||
The namespace is added to any user with Extended Attribute support
|
||||
enabled for tmpfs. Users who do not enable xattrs will not have
|
||||
the XATTR_PAX flags preserved.
|
||||
|
||||
diff --git a/include/uapi/linux/xattr.h b/include/uapi/linux/xattr.h
|
||||
index e4629b9..6958086 100644
|
||||
--- a/include/uapi/linux/xattr.h
|
||||
+++ b/include/uapi/linux/xattr.h
|
||||
@@ -63,5 +63,9 @@
|
||||
#define XATTR_POSIX_ACL_DEFAULT "posix_acl_default"
|
||||
#define XATTR_NAME_POSIX_ACL_DEFAULT XATTR_SYSTEM_PREFIX XATTR_POSIX_ACL_DEFAULT
|
||||
|
||||
+/* User namespace */
|
||||
+#define XATTR_PAX_PREFIX XATTR_USER_PREFIX "pax."
|
||||
+#define XATTR_PAX_FLAGS_SUFFIX "flags"
|
||||
+#define XATTR_NAME_PAX_FLAGS XATTR_PAX_PREFIX XATTR_PAX_FLAGS_SUFFIX
|
||||
|
||||
#endif /* _UAPI_LINUX_XATTR_H */
|
||||
diff --git a/mm/shmem.c b/mm/shmem.c
|
||||
index 1c44af7..f23bb1b 100644
|
||||
--- a/mm/shmem.c
|
||||
+++ b/mm/shmem.c
|
||||
@@ -2201,6 +2201,7 @@ static const struct xattr_handler *shmem_xattr_handlers[] = {
|
||||
static int shmem_xattr_validate(const char *name)
|
||||
{
|
||||
struct { const char *prefix; size_t len; } arr[] = {
|
||||
+ { XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN},
|
||||
{ XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN },
|
||||
{ XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN }
|
||||
};
|
||||
@@ -2256,6 +2257,12 @@ static int shmem_setxattr(struct dentry *dentry, const char *name,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
+ if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
|
||||
+ if (strcmp(name, XATTR_NAME_PAX_FLAGS))
|
||||
+ return -EOPNOTSUPP;
|
||||
+ if (size > 8)
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
return simple_xattr_set(&info->xattrs, name, value, size, flags);
|
||||
}
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
From: Ben Hutchings <ben@decadent.org.uk>
|
||||
Subject: fs: Enable link security restrictions by default
|
||||
Date: Fri, 02 Nov 2012 05:32:06 +0000
|
||||
Bug-Debian: https://bugs.debian.org/609455
|
||||
Forwarded: not-needed
|
||||
|
||||
This reverts commit 561ec64ae67ef25cac8d72bb9c4bfc955edfd415
|
||||
('VFS: don't do protected {sym,hard}links by default').
|
||||
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -651,8 +651,8 @@ static inline void put_link(struct namei
|
||||
path_put(link);
|
||||
}
|
||||
|
||||
-int sysctl_protected_symlinks __read_mostly = 0;
|
||||
-int sysctl_protected_hardlinks __read_mostly = 0;
|
||||
+int sysctl_protected_symlinks __read_mostly = 1;
|
||||
+int sysctl_protected_hardlinks __read_mostly = 1;
|
||||
|
||||
/**
|
||||
* may_follow_link - Check symlink following for unsafe situations
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
|
||||
index cb96296..6c242ed 100644
|
||||
--- a/drivers/acpi/blacklist.c
|
||||
+++ b/drivers/acpi/blacklist.c
|
||||
@@ -269,6 +276,61 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
|
||||
},
|
||||
|
||||
/*
|
||||
+ * The following Lenovo models have a broken workaround in the
|
||||
+ * acpi_video backlight implementation to meet the Windows 8
|
||||
+ * requirement of 101 backlight levels. Reverting to pre-Win8
|
||||
+ * behavior fixes the problem.
|
||||
+ */
|
||||
+ {
|
||||
+ .callback = dmi_disable_osi_win8,
|
||||
+ .ident = "Lenovo ThinkPad L430",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L430"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .callback = dmi_disable_osi_win8,
|
||||
+ .ident = "Lenovo ThinkPad T430s",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430s"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .callback = dmi_disable_osi_win8,
|
||||
+ .ident = "Lenovo ThinkPad T530",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T530"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .callback = dmi_disable_osi_win8,
|
||||
+ .ident = "Lenovo ThinkPad W530",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W530"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .callback = dmi_disable_osi_win8,
|
||||
+ .ident = "Lenovo ThinkPad X1 Carbon",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X1 Carbon"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .callback = dmi_disable_osi_win8,
|
||||
+ .ident = "Lenovo ThinkPad X230",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"),
|
||||
+ },
|
||||
+ },
|
||||
+
|
||||
+ /*
|
||||
* BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
|
||||
* Linux ignores it, except for the machines enumerated below.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
--- a/init/do_mounts.c 2014-08-26 08:03:30.000013100 -0400
|
||||
+++ b/init/do_mounts.c 2014-08-26 08:11:19.720014712 -0400
|
||||
@@ -484,7 +484,10 @@ void __init change_floppy(char *fmt, ...
|
||||
va_start(args, fmt);
|
||||
vsprintf(buf, fmt, args);
|
||||
va_end(args);
|
||||
- fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0);
|
||||
+ if (saved_root_name[0])
|
||||
+ fd = sys_open(saved_root_name, O_RDWR | O_NDELAY, 0);
|
||||
+ else
|
||||
+ fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0);
|
||||
if (fd >= 0) {
|
||||
sys_ioctl(fd, FDEJECT, 0);
|
||||
sys_close(fd);
|
||||
@@ -527,8 +530,13 @@ void __init mount_root(void)
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_BLOCK
|
||||
- create_dev("/dev/root", ROOT_DEV);
|
||||
- mount_block_root("/dev/root", root_mountflags);
|
||||
+ if (saved_root_name[0]) {
|
||||
+ create_dev(saved_root_name, ROOT_DEV);
|
||||
+ mount_block_root(saved_root_name, root_mountflags);
|
||||
+ } else {
|
||||
+ create_dev("/dev/root", ROOT_DEV);
|
||||
+ mount_block_root("/dev/root", root_mountflags);
|
||||
+ }
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
diff --git a/kernel/kmod.c b/kernel/kmod.c
|
||||
index fb32636..d968882 100644
|
||||
--- a/kernel/kmod.c
|
||||
+++ b/kernel/kmod.c
|
||||
@@ -575,7 +575,8 @@
|
||||
call_usermodehelper_freeinfo(sub_info);
|
||||
return -EINVAL;
|
||||
}
|
||||
- helper_lock();
|
||||
+ if (!(current->flags & PF_FREEZER_SKIP))
|
||||
+ helper_lock();
|
||||
if (!khelper_wq || usermodehelper_disabled) {
|
||||
retval = -EBUSY;
|
||||
goto out;
|
||||
@@ -611,7 +612,8 @@ wait_done:
|
||||
out:
|
||||
call_usermodehelper_freeinfo(sub_info);
|
||||
unlock:
|
||||
- helper_unlock();
|
||||
+ if (!(current->flags & PF_FREEZER_SKIP))
|
||||
+ helper_unlock();
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL(call_usermodehelper_exec);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,143 @@
|
||||
--- a/Kconfig
|
||||
+++ b/Kconfig
|
||||
@@ -8,4 +8,6 @@ config SRCARCH
|
||||
string
|
||||
option env="SRCARCH"
|
||||
|
||||
+source "distro/Kconfig"
|
||||
+
|
||||
source "arch/$SRCARCH/Kconfig"
|
||||
--- /dev/null
|
||||
+++ b/distro/Kconfig
|
||||
@@ -0,0 +1,131 @@
|
||||
+menu "Gentoo Linux"
|
||||
+
|
||||
+config GENTOO_LINUX
|
||||
+ bool "Gentoo Linux support"
|
||||
+
|
||||
+ default y
|
||||
+
|
||||
+ help
|
||||
+ In order to boot Gentoo Linux a minimal set of config settings needs to
|
||||
+ be enabled in the kernel; to avoid the users from having to enable them
|
||||
+ manually as part of a Gentoo Linux installation or a new clean config,
|
||||
+ we enable these config settings by default for convenience.
|
||||
+
|
||||
+ See the settings that become available for more details and fine-tuning.
|
||||
+
|
||||
+config GENTOO_LINUX_UDEV
|
||||
+ bool "Linux dynamic and persistent device naming (userspace devfs) support"
|
||||
+
|
||||
+ depends on GENTOO_LINUX
|
||||
+ default y if GENTOO_LINUX
|
||||
+
|
||||
+ select DEVTMPFS
|
||||
+ select TMPFS
|
||||
+
|
||||
+ select MMU
|
||||
+ select SHMEM
|
||||
+
|
||||
+ help
|
||||
+ In order to boot Gentoo Linux a minimal set of config settings needs to
|
||||
+ be enabled in the kernel; to avoid the users from having to enable them
|
||||
+ manually as part of a Gentoo Linux installation or a new clean config,
|
||||
+ we enable these config settings by default for convenience.
|
||||
+
|
||||
+ Currently this only selects TMPFS, DEVTMPFS and their dependencies.
|
||||
+ TMPFS is enabled to maintain a tmpfs file system at /dev/shm, /run and
|
||||
+ /sys/fs/cgroup; DEVTMPFS to maintain a devtmpfs file system at /dev.
|
||||
+
|
||||
+ Some of these are critical files that need to be available early in the
|
||||
+ boot process; if not available, it causes sysfs and udev to malfunction.
|
||||
+
|
||||
+ To ensure Gentoo Linux boots, it is best to leave this setting enabled;
|
||||
+ if you run a custom setup, you could consider whether to disable this.
|
||||
+
|
||||
+config GENTOO_LINUX_PORTAGE
|
||||
+ bool "Select options required by Portage features"
|
||||
+
|
||||
+ depends on GENTOO_LINUX
|
||||
+ default y if GENTOO_LINUX
|
||||
+
|
||||
+ select CGROUPS
|
||||
+ select NAMESPACES
|
||||
+ select IPC_NS
|
||||
+ select NET_NS
|
||||
+
|
||||
+ help
|
||||
+ This enables options required by various Portage FEATURES.
|
||||
+ Currently this selects:
|
||||
+
|
||||
+ CGROUPS (required for FEATURES=cgroup)
|
||||
+ IPC_NS (required for FEATURES=ipc-sandbox)
|
||||
+ NET_NS (required for FEATURES=network-sandbox)
|
||||
+
|
||||
+ It is highly recommended that you leave this enabled as these FEATURES
|
||||
+ are, or will soon be, enabled by default.
|
||||
+
|
||||
+menu "Support for init systems, system and service managers"
|
||||
+ visible if GENTOO_LINUX
|
||||
+
|
||||
+config GENTOO_LINUX_INIT_SCRIPT
|
||||
+ bool "OpenRC, runit and other script based systems and managers"
|
||||
+
|
||||
+ default y if GENTOO_LINUX
|
||||
+
|
||||
+ depends on GENTOO_LINUX
|
||||
+
|
||||
+ select BINFMT_SCRIPT
|
||||
+
|
||||
+ help
|
||||
+ The init system is the first thing that loads after the kernel booted.
|
||||
+
|
||||
+ These config settings allow you to select which init systems to support;
|
||||
+ instead of having to select all the individual settings all over the
|
||||
+ place, these settings allows you to select all the settings at once.
|
||||
+
|
||||
+ This particular setting enables all the known requirements for OpenRC,
|
||||
+ runit and similar script based systems and managers.
|
||||
+
|
||||
+ If you are unsure about this, it is best to leave this setting enabled.
|
||||
+
|
||||
+config GENTOO_LINUX_INIT_SYSTEMD
|
||||
+ bool "systemd"
|
||||
+
|
||||
+ default n
|
||||
+
|
||||
+ depends on GENTOO_LINUX && GENTOO_LINUX_UDEV
|
||||
+
|
||||
+ select AUTOFS4_FS
|
||||
+ select BLK_DEV_BSG
|
||||
+ select CGROUPS
|
||||
+ select DEVPTS_MULTIPLE_INSTANCES
|
||||
+ select EPOLL
|
||||
+ select FANOTIFY
|
||||
+ select FHANDLE
|
||||
+ select INOTIFY_USER
|
||||
+ select NET
|
||||
+ select NET_NS
|
||||
+ select PROC_FS
|
||||
+ select SIGNALFD
|
||||
+ select SYSFS
|
||||
+ select TIMERFD
|
||||
+
|
||||
+ select ANON_INODES
|
||||
+ select BLOCK
|
||||
+ select EVENTFD
|
||||
+ select FSNOTIFY
|
||||
+ select INET
|
||||
+ select NLATTR
|
||||
+
|
||||
+ help
|
||||
+ The init system is the first thing that loads after the kernel booted.
|
||||
+
|
||||
+ These config settings allow you to select which init systems to support;
|
||||
+ instead of having to select all the individual settings all over the
|
||||
+ place, these settings allows you to select all the settings at once.
|
||||
+
|
||||
+ This particular setting enables all the known requirements for systemd;
|
||||
+ it also enables suggested optional settings, as the package suggests to.
|
||||
+
|
||||
+endmenu
|
||||
+
|
||||
+endmenu
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
From a828d56aebc0735676be23734cccf31e279c0d1b Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@unimore.it>
|
||||
Date: Mon, 8 Dec 2014 16:04:25 +0100
|
||||
Subject: [PATCH 1/3] block: cgroups, kconfig, build bits for BFQ-v7r7-3.19
|
||||
|
||||
Update Kconfig.iosched and do the related Makefile changes to include
|
||||
kernel configuration options for BFQ. Also add the bfqio controller
|
||||
to the cgroups subsystem.
|
||||
|
||||
Signed-off-by: Paolo Valente <paolo.valente@unimore.it>
|
||||
Signed-off-by: Arianna Avanzini <avanzini.arianna@gmail.com>
|
||||
---
|
||||
block/Kconfig.iosched | 32 ++++++++++++++++++++++++++++++++
|
||||
block/Makefile | 1 +
|
||||
include/linux/cgroup_subsys.h | 4 ++++
|
||||
3 files changed, 37 insertions(+)
|
||||
|
||||
diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched
|
||||
index 421bef9..0ee5f0f 100644
|
||||
--- a/block/Kconfig.iosched
|
||||
+++ b/block/Kconfig.iosched
|
||||
@@ -39,6 +39,27 @@ config CFQ_GROUP_IOSCHED
|
||||
---help---
|
||||
Enable group IO scheduling in CFQ.
|
||||
|
||||
+config IOSCHED_BFQ
|
||||
+ tristate "BFQ I/O scheduler"
|
||||
+ default n
|
||||
+ ---help---
|
||||
+ The BFQ I/O scheduler tries to distribute bandwidth among
|
||||
+ all processes according to their weights.
|
||||
+ It aims at distributing the bandwidth as desired, independently of
|
||||
+ the disk parameters and with any workload. It also tries to
|
||||
+ guarantee low latency to interactive and soft real-time
|
||||
+ applications. If compiled built-in (saying Y here), BFQ can
|
||||
+ be configured to support hierarchical scheduling.
|
||||
+
|
||||
+config CGROUP_BFQIO
|
||||
+ bool "BFQ hierarchical scheduling support"
|
||||
+ depends on CGROUPS && IOSCHED_BFQ=y
|
||||
+ default n
|
||||
+ ---help---
|
||||
+ Enable hierarchical scheduling in BFQ, using the cgroups
|
||||
+ filesystem interface. The name of the subsystem will be
|
||||
+ bfqio.
|
||||
+
|
||||
choice
|
||||
prompt "Default I/O scheduler"
|
||||
default DEFAULT_CFQ
|
||||
@@ -52,6 +73,16 @@ choice
|
||||
config DEFAULT_CFQ
|
||||
bool "CFQ" if IOSCHED_CFQ=y
|
||||
|
||||
+ config DEFAULT_BFQ
|
||||
+ bool "BFQ" if IOSCHED_BFQ=y
|
||||
+ help
|
||||
+ Selects BFQ as the default I/O scheduler which will be
|
||||
+ used by default for all block devices.
|
||||
+ The BFQ I/O scheduler aims at distributing the bandwidth
|
||||
+ as desired, independently of the disk parameters and with
|
||||
+ any workload. It also tries to guarantee low latency to
|
||||
+ interactive and soft real-time applications.
|
||||
+
|
||||
config DEFAULT_NOOP
|
||||
bool "No-op"
|
||||
|
||||
@@ -61,6 +92,7 @@ config DEFAULT_IOSCHED
|
||||
string
|
||||
default "deadline" if DEFAULT_DEADLINE
|
||||
default "cfq" if DEFAULT_CFQ
|
||||
+ default "bfq" if DEFAULT_BFQ
|
||||
default "noop" if DEFAULT_NOOP
|
||||
|
||||
endmenu
|
||||
diff --git a/block/Makefile b/block/Makefile
|
||||
index 00ecc97..1ed86d5 100644
|
||||
--- a/block/Makefile
|
||||
+++ b/block/Makefile
|
||||
@@ -18,6 +18,7 @@ obj-$(CONFIG_BLK_DEV_THROTTLING) += blk-throttle.o
|
||||
obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o
|
||||
obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o
|
||||
obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o
|
||||
+obj-$(CONFIG_IOSCHED_BFQ) += bfq-iosched.o
|
||||
|
||||
obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o
|
||||
obj-$(CONFIG_BLK_CMDLINE_PARSER) += cmdline-parser.o
|
||||
diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h
|
||||
index 98c4f9b..13b010d 100644
|
||||
--- a/include/linux/cgroup_subsys.h
|
||||
+++ b/include/linux/cgroup_subsys.h
|
||||
@@ -35,6 +35,10 @@ SUBSYS(net_cls)
|
||||
SUBSYS(blkio)
|
||||
#endif
|
||||
|
||||
+#if IS_ENABLED(CONFIG_CGROUP_BFQIO)
|
||||
+SUBSYS(bfqio)
|
||||
+#endif
|
||||
+
|
||||
#if IS_ENABLED(CONFIG_CGROUP_PERF)
|
||||
SUBSYS(perf_event)
|
||||
#endif
|
||||
--
|
||||
2.3.0
|
||||
|
||||
+6966
File diff suppressed because it is too large
Load Diff
+6966
File diff suppressed because it is too large
Load Diff
+1222
File diff suppressed because it is too large
Load Diff
+387
@@ -0,0 +1,387 @@
|
||||
WARNING - this version of the patch works with version 4.9+ of gcc and with
|
||||
kernel version 3.15.x+ and should NOT be applied when compiling on older
|
||||
versions due to name changes of the flags with the 4.9 release of gcc.
|
||||
Use the older version of this patch hosted on the same github for older
|
||||
versions of gcc. For example:
|
||||
|
||||
corei7 --> nehalem
|
||||
corei7-avx --> sandybridge
|
||||
core-avx-i --> ivybridge
|
||||
core-avx2 --> haswell
|
||||
|
||||
For more, see: https://gcc.gnu.org/gcc-4.9/changes.html
|
||||
|
||||
It also changes 'atom' to 'bonnell' in accordance with the gcc v4.9 changes.
|
||||
Note that upstream is using the deprecated 'match=atom' flags when I believe it
|
||||
should use the newer 'march=bonnell' flag for atom processors.
|
||||
|
||||
I have made that change to this patch set as well. See the following kernel
|
||||
bug report to see if I'm right: https://bugzilla.kernel.org/show_bug.cgi?id=77461
|
||||
|
||||
This patch will expand the number of microarchitectures to include new
|
||||
processors including: AMD K10-family, AMD Family 10h (Barcelona), AMD Family
|
||||
14h (Bobcat), AMD Family 15h (Bulldozer), AMD Family 15h (Piledriver), AMD
|
||||
Family 16h (Jaguar), Intel 1st Gen Core i3/i5/i7 (Nehalem), Intel 1.5 Gen Core
|
||||
i3/i5/i7 (Westmere), Intel 2nd Gen Core i3/i5/i7 (Sandybridge), Intel 3rd Gen
|
||||
Core i3/i5/i7 (Ivybridge), Intel 4th Gen Core i3/i5/i7 (Haswell), and Intel 5th
|
||||
Gen Core i3/i5/i7 (Broadwell). It also offers the compiler the 'native' flag.
|
||||
|
||||
Small but real speed increases are measurable using a make endpoint comparing
|
||||
a generic kernel to one built with one of the respective microarchs.
|
||||
|
||||
See the following experimental evidence supporting this statement:
|
||||
https://github.com/graysky2/kernel_gcc_patch
|
||||
|
||||
REQUIREMENTS
|
||||
linux version >=3.15
|
||||
gcc version >=4.9
|
||||
|
||||
--- a/arch/x86/include/asm/module.h 2014-08-03 18:25:02.000000000 -0400
|
||||
+++ b/arch/x86/include/asm/module.h 2014-09-13 09:37:16.721385247 -0400
|
||||
@@ -15,6 +15,20 @@
|
||||
#define MODULE_PROC_FAMILY "586MMX "
|
||||
#elif defined CONFIG_MCORE2
|
||||
#define MODULE_PROC_FAMILY "CORE2 "
|
||||
+#elif defined CONFIG_MNATIVE
|
||||
+#define MODULE_PROC_FAMILY "NATIVE "
|
||||
+#elif defined CONFIG_MNEHALEM
|
||||
+#define MODULE_PROC_FAMILY "NEHALEM "
|
||||
+#elif defined CONFIG_MWESTMERE
|
||||
+#define MODULE_PROC_FAMILY "WESTMERE "
|
||||
+#elif defined CONFIG_MSANDYBRIDGE
|
||||
+#define MODULE_PROC_FAMILY "SANDYBRIDGE "
|
||||
+#elif defined CONFIG_MIVYBRIDGE
|
||||
+#define MODULE_PROC_FAMILY "IVYBRIDGE "
|
||||
+#elif defined CONFIG_MHASWELL
|
||||
+#define MODULE_PROC_FAMILY "HASWELL "
|
||||
+#elif defined CONFIG_MBROADWELL
|
||||
+#define MODULE_PROC_FAMILY "BROADWELL "
|
||||
#elif defined CONFIG_MATOM
|
||||
#define MODULE_PROC_FAMILY "ATOM "
|
||||
#elif defined CONFIG_M686
|
||||
@@ -33,6 +47,20 @@
|
||||
#define MODULE_PROC_FAMILY "K7 "
|
||||
#elif defined CONFIG_MK8
|
||||
#define MODULE_PROC_FAMILY "K8 "
|
||||
+#elif defined CONFIG_MK8SSE3
|
||||
+#define MODULE_PROC_FAMILY "K8SSE3 "
|
||||
+#elif defined CONFIG_MK10
|
||||
+#define MODULE_PROC_FAMILY "K10 "
|
||||
+#elif defined CONFIG_MBARCELONA
|
||||
+#define MODULE_PROC_FAMILY "BARCELONA "
|
||||
+#elif defined CONFIG_MBOBCAT
|
||||
+#define MODULE_PROC_FAMILY "BOBCAT "
|
||||
+#elif defined CONFIG_MBULLDOZER
|
||||
+#define MODULE_PROC_FAMILY "BULLDOZER "
|
||||
+#elif defined CONFIG_MPILEDRIVER
|
||||
+#define MODULE_PROC_FAMILY "PILEDRIVER "
|
||||
+#elif defined CONFIG_MJAGUAR
|
||||
+#define MODULE_PROC_FAMILY "JAGUAR "
|
||||
#elif defined CONFIG_MELAN
|
||||
#define MODULE_PROC_FAMILY "ELAN "
|
||||
#elif defined CONFIG_MCRUSOE
|
||||
--- a/arch/x86/Kconfig.cpu 2014-08-03 18:25:02.000000000 -0400
|
||||
+++ b/arch/x86/Kconfig.cpu 2014-09-13 09:37:16.721385247 -0400
|
||||
@@ -137,9 +137,8 @@ config MPENTIUM4
|
||||
-Paxville
|
||||
-Dempsey
|
||||
|
||||
-
|
||||
config MK6
|
||||
- bool "K6/K6-II/K6-III"
|
||||
+ bool "AMD K6/K6-II/K6-III"
|
||||
depends on X86_32
|
||||
---help---
|
||||
Select this for an AMD K6-family processor. Enables use of
|
||||
@@ -147,7 +146,7 @@ config MK6
|
||||
flags to GCC.
|
||||
|
||||
config MK7
|
||||
- bool "Athlon/Duron/K7"
|
||||
+ bool "AMD Athlon/Duron/K7"
|
||||
depends on X86_32
|
||||
---help---
|
||||
Select this for an AMD Athlon K7-family processor. Enables use of
|
||||
@@ -155,12 +154,62 @@ config MK7
|
||||
flags to GCC.
|
||||
|
||||
config MK8
|
||||
- bool "Opteron/Athlon64/Hammer/K8"
|
||||
+ bool "AMD Opteron/Athlon64/Hammer/K8"
|
||||
---help---
|
||||
Select this for an AMD Opteron or Athlon64 Hammer-family processor.
|
||||
Enables use of some extended instructions, and passes appropriate
|
||||
optimization flags to GCC.
|
||||
|
||||
+config MK8SSE3
|
||||
+ bool "AMD Opteron/Athlon64/Hammer/K8 with SSE3"
|
||||
+ ---help---
|
||||
+ Select this for improved AMD Opteron or Athlon64 Hammer-family processors.
|
||||
+ Enables use of some extended instructions, and passes appropriate
|
||||
+ optimization flags to GCC.
|
||||
+
|
||||
+config MK10
|
||||
+ bool "AMD 61xx/7x50/PhenomX3/X4/II/K10"
|
||||
+ ---help---
|
||||
+ Select this for an AMD 61xx Eight-Core Magny-Cours, Athlon X2 7x50,
|
||||
+ Phenom X3/X4/II, Athlon II X2/X3/X4, or Turion II-family processor.
|
||||
+ Enables use of some extended instructions, and passes appropriate
|
||||
+ optimization flags to GCC.
|
||||
+
|
||||
+config MBARCELONA
|
||||
+ bool "AMD Barcelona"
|
||||
+ ---help---
|
||||
+ Select this for AMD Barcelona and newer processors.
|
||||
+
|
||||
+ Enables -march=barcelona
|
||||
+
|
||||
+config MBOBCAT
|
||||
+ bool "AMD Bobcat"
|
||||
+ ---help---
|
||||
+ Select this for AMD Bobcat processors.
|
||||
+
|
||||
+ Enables -march=btver1
|
||||
+
|
||||
+config MBULLDOZER
|
||||
+ bool "AMD Bulldozer"
|
||||
+ ---help---
|
||||
+ Select this for AMD Bulldozer processors.
|
||||
+
|
||||
+ Enables -march=bdver1
|
||||
+
|
||||
+config MPILEDRIVER
|
||||
+ bool "AMD Piledriver"
|
||||
+ ---help---
|
||||
+ Select this for AMD Piledriver processors.
|
||||
+
|
||||
+ Enables -march=bdver2
|
||||
+
|
||||
+config MJAGUAR
|
||||
+ bool "AMD Jaguar"
|
||||
+ ---help---
|
||||
+ Select this for AMD Jaguar processors.
|
||||
+
|
||||
+ Enables -march=btver2
|
||||
+
|
||||
config MCRUSOE
|
||||
bool "Crusoe"
|
||||
depends on X86_32
|
||||
@@ -251,8 +300,17 @@ config MPSC
|
||||
using the cpu family field
|
||||
in /proc/cpuinfo. Family 15 is an older Xeon, Family 6 a newer one.
|
||||
|
||||
+config MATOM
|
||||
+ bool "Intel Atom"
|
||||
+ ---help---
|
||||
+
|
||||
+ Select this for the Intel Atom platform. Intel Atom CPUs have an
|
||||
+ in-order pipelining architecture and thus can benefit from
|
||||
+ accordingly optimized code. Use a recent GCC with specific Atom
|
||||
+ support in order to fully benefit from selecting this option.
|
||||
+
|
||||
config MCORE2
|
||||
- bool "Core 2/newer Xeon"
|
||||
+ bool "Intel Core 2"
|
||||
---help---
|
||||
|
||||
Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and
|
||||
@@ -260,14 +318,55 @@ config MCORE2
|
||||
family in /proc/cpuinfo. Newer ones have 6 and older ones 15
|
||||
(not a typo)
|
||||
|
||||
-config MATOM
|
||||
- bool "Intel Atom"
|
||||
+ Enables -march=core2
|
||||
+
|
||||
+config MNEHALEM
|
||||
+ bool "Intel Nehalem"
|
||||
---help---
|
||||
|
||||
- Select this for the Intel Atom platform. Intel Atom CPUs have an
|
||||
- in-order pipelining architecture and thus can benefit from
|
||||
- accordingly optimized code. Use a recent GCC with specific Atom
|
||||
- support in order to fully benefit from selecting this option.
|
||||
+ Select this for 1st Gen Core processors in the Nehalem family.
|
||||
+
|
||||
+ Enables -march=nehalem
|
||||
+
|
||||
+config MWESTMERE
|
||||
+ bool "Intel Westmere"
|
||||
+ ---help---
|
||||
+
|
||||
+ Select this for the Intel Westmere formerly Nehalem-C family.
|
||||
+
|
||||
+ Enables -march=westmere
|
||||
+
|
||||
+config MSANDYBRIDGE
|
||||
+ bool "Intel Sandy Bridge"
|
||||
+ ---help---
|
||||
+
|
||||
+ Select this for 2nd Gen Core processors in the Sandy Bridge family.
|
||||
+
|
||||
+ Enables -march=sandybridge
|
||||
+
|
||||
+config MIVYBRIDGE
|
||||
+ bool "Intel Ivy Bridge"
|
||||
+ ---help---
|
||||
+
|
||||
+ Select this for 3rd Gen Core processors in the Ivy Bridge family.
|
||||
+
|
||||
+ Enables -march=ivybridge
|
||||
+
|
||||
+config MHASWELL
|
||||
+ bool "Intel Haswell"
|
||||
+ ---help---
|
||||
+
|
||||
+ Select this for 4th Gen Core processors in the Haswell family.
|
||||
+
|
||||
+ Enables -march=haswell
|
||||
+
|
||||
+config MBROADWELL
|
||||
+ bool "Intel Broadwell"
|
||||
+ ---help---
|
||||
+
|
||||
+ Select this for 5th Gen Core processors in the Broadwell family.
|
||||
+
|
||||
+ Enables -march=broadwell
|
||||
|
||||
config GENERIC_CPU
|
||||
bool "Generic-x86-64"
|
||||
@@ -276,6 +375,19 @@ config GENERIC_CPU
|
||||
Generic x86-64 CPU.
|
||||
Run equally well on all x86-64 CPUs.
|
||||
|
||||
+config MNATIVE
|
||||
+ bool "Native optimizations autodetected by GCC"
|
||||
+ ---help---
|
||||
+
|
||||
+ GCC 4.2 and above support -march=native, which automatically detects
|
||||
+ the optimum settings to use based on your processor. -march=native
|
||||
+ also detects and applies additional settings beyond -march specific
|
||||
+ to your CPU, (eg. -msse4). Unless you have a specific reason not to
|
||||
+ (e.g. distcc cross-compiling), you should probably be using
|
||||
+ -march=native rather than anything listed below.
|
||||
+
|
||||
+ Enables -march=native
|
||||
+
|
||||
endchoice
|
||||
|
||||
config X86_GENERIC
|
||||
@@ -300,7 +412,7 @@ config X86_INTERNODE_CACHE_SHIFT
|
||||
config X86_L1_CACHE_SHIFT
|
||||
int
|
||||
default "7" if MPENTIUM4 || MPSC
|
||||
- default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MATOM || MVIAC7 || X86_GENERIC || GENERIC_CPU
|
||||
+ default "6" if MK7 || MK8 || MK8SSE3 || MK10 || MBARCELONA || MBOBCAT || MBULLDOZER || MPILEDRIVER || MJAGUAR || MPENTIUMM || MCORE2 || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || BROADWELL || MNATIVE || MATOM || MVIAC7 || X86_GENERIC || GENERIC_CPU
|
||||
default "4" if MELAN || M486 || MGEODEGX1
|
||||
default "5" if MWINCHIP3D || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX
|
||||
|
||||
@@ -331,11 +443,11 @@ config X86_ALIGNMENT_16
|
||||
|
||||
config X86_INTEL_USERCOPY
|
||||
def_bool y
|
||||
- depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON || MCORE2
|
||||
+ depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK8SSE3 || MK7 || MEFFICEON || MCORE2 || MK10 || MBARCELONA || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MNATIVE
|
||||
|
||||
config X86_USE_PPRO_CHECKSUM
|
||||
def_bool y
|
||||
- depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MVIAC7 || MEFFICEON || MGEODE_LX || MCORE2 || MATOM
|
||||
+ depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MK10 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MK8SSE3 || MVIAC3_2 || MVIAC7 || MEFFICEON || MGEODE_LX || MCORE2 || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MATOM || MNATIVE
|
||||
|
||||
config X86_USE_3DNOW
|
||||
def_bool y
|
||||
@@ -359,17 +471,17 @@ config X86_P6_NOP
|
||||
|
||||
config X86_TSC
|
||||
def_bool y
|
||||
- depends on (MWINCHIP3D || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2 || MATOM) || X86_64
|
||||
+ depends on (MWINCHIP3D || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MK8SSE3 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2 || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MNATIVE || MATOM) || X86_64
|
||||
|
||||
config X86_CMPXCHG64
|
||||
def_bool y
|
||||
- depends on X86_PAE || X86_64 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MATOM
|
||||
+ depends on X86_PAE || X86_64 || MCORE2 || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MATOM || MNATIVE
|
||||
|
||||
# this should be set for all -march=.. options where the compiler
|
||||
# generates cmov.
|
||||
config X86_CMOV
|
||||
def_bool y
|
||||
- depends on (MK8 || MK7 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64 || MATOM || MGEODE_LX)
|
||||
+ depends on (MK8 || MK8SSE3 || MK10 || MBARCELONA || MBOBCAT || MBULLDOZER || MPILEDRIVER || MJAGUAR || MK7 || MCORE2 || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64 || MNATIVE || MATOM || MGEODE_LX)
|
||||
|
||||
config X86_MINIMUM_CPU_FAMILY
|
||||
int
|
||||
--- a/arch/x86/Makefile 2014-08-03 18:25:02.000000000 -0400
|
||||
+++ b/arch/x86/Makefile 2014-09-13 09:37:16.721385247 -0400
|
||||
@@ -92,13 +92,33 @@ else
|
||||
KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=3)
|
||||
|
||||
# FIXME - should be integrated in Makefile.cpu (Makefile_32.cpu)
|
||||
+ cflags-$(CONFIG_MNATIVE) += $(call cc-option,-march=native)
|
||||
cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
|
||||
+ cflags-$(CONFIG_MK8SSE3) += $(call cc-option,-march=k8-sse3,-mtune=k8)
|
||||
+ cflags-$(CONFIG_MK10) += $(call cc-option,-march=amdfam10)
|
||||
+ cflags-$(CONFIG_MBARCELONA) += $(call cc-option,-march=barcelona)
|
||||
+ cflags-$(CONFIG_MBOBCAT) += $(call cc-option,-march=btver1)
|
||||
+ cflags-$(CONFIG_MBULLDOZER) += $(call cc-option,-march=bdver1)
|
||||
+ cflags-$(CONFIG_MPILEDRIVER) += $(call cc-option,-march=bdver2)
|
||||
+ cflags-$(CONFIG_MJAGUAR) += $(call cc-option,-march=btver2)
|
||||
cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
|
||||
|
||||
cflags-$(CONFIG_MCORE2) += \
|
||||
- $(call cc-option,-march=core2,$(call cc-option,-mtune=generic))
|
||||
- cflags-$(CONFIG_MATOM) += $(call cc-option,-march=atom) \
|
||||
- $(call cc-option,-mtune=atom,$(call cc-option,-mtune=generic))
|
||||
+ $(call cc-option,-march=core2,$(call cc-option,-mtune=core2))
|
||||
+ cflags-$(CONFIG_MNEHALEM) += \
|
||||
+ $(call cc-option,-march=nehalem,$(call cc-option,-mtune=nehalem))
|
||||
+ cflags-$(CONFIG_MWESTMERE) += \
|
||||
+ $(call cc-option,-march=westmere,$(call cc-option,-mtune=westmere))
|
||||
+ cflags-$(CONFIG_MSANDYBRIDGE) += \
|
||||
+ $(call cc-option,-march=sandybridge,$(call cc-option,-mtune=sandybridge))
|
||||
+ cflags-$(CONFIG_MIVYBRIDGE) += \
|
||||
+ $(call cc-option,-march=ivybridge,$(call cc-option,-mtune=ivybridge))
|
||||
+ cflags-$(CONFIG_MHASWELL) += \
|
||||
+ $(call cc-option,-march=haswell,$(call cc-option,-mtune=haswell))
|
||||
+ cflags-$(CONFIG_MBROADWELL) += \
|
||||
+ $(call cc-option,-march=broadwell,$(call cc-option,-mtune=broadwell))
|
||||
+ cflags-$(CONFIG_MATOM) += $(call cc-option,-march=bonnell) \
|
||||
+ $(call cc-option,-mtune=bonnell,$(call cc-option,-mtune=generic))
|
||||
cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic)
|
||||
KBUILD_CFLAGS += $(cflags-y)
|
||||
|
||||
--- a/arch/x86/Makefile_32.cpu 2014-08-03 18:25:02.000000000 -0400
|
||||
+++ b/arch/x86/Makefile_32.cpu 2014-09-13 09:37:16.721385247 -0400
|
||||
@@ -23,7 +23,15 @@ cflags-$(CONFIG_MK6) += -march=k6
|
||||
# Please note, that patches that add -march=athlon-xp and friends are pointless.
|
||||
# They make zero difference whatsosever to performance at this time.
|
||||
cflags-$(CONFIG_MK7) += -march=athlon
|
||||
+cflags-$(CONFIG_MNATIVE) += $(call cc-option,-march=native)
|
||||
cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8,-march=athlon)
|
||||
+cflags-$(CONFIG_MK8SSE3) += $(call cc-option,-march=k8-sse3,-march=athlon)
|
||||
+cflags-$(CONFIG_MK10) += $(call cc-option,-march=amdfam10,-march=athlon)
|
||||
+cflags-$(CONFIG_MBARCELONA) += $(call cc-option,-march=barcelona,-march=athlon)
|
||||
+cflags-$(CONFIG_MBOBCAT) += $(call cc-option,-march=btver1,-march=athlon)
|
||||
+cflags-$(CONFIG_MBULLDOZER) += $(call cc-option,-march=bdver1,-march=athlon)
|
||||
+cflags-$(CONFIG_MPILEDRIVER) += $(call cc-option,-march=bdver2,-march=athlon)
|
||||
+cflags-$(CONFIG_MJAGUAR) += $(call cc-option,-march=btver2,-march=athlon)
|
||||
cflags-$(CONFIG_MCRUSOE) += -march=i686 $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
|
||||
cflags-$(CONFIG_MEFFICEON) += -march=i686 $(call tune,pentium3) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
|
||||
cflags-$(CONFIG_MWINCHIPC6) += $(call cc-option,-march=winchip-c6,-march=i586)
|
||||
@@ -32,8 +40,14 @@ cflags-$(CONFIG_MCYRIXIII) += $(call cc-
|
||||
cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686)
|
||||
cflags-$(CONFIG_MVIAC7) += -march=i686
|
||||
cflags-$(CONFIG_MCORE2) += -march=i686 $(call tune,core2)
|
||||
-cflags-$(CONFIG_MATOM) += $(call cc-option,-march=atom,$(call cc-option,-march=core2,-march=i686)) \
|
||||
- $(call cc-option,-mtune=atom,$(call cc-option,-mtune=generic))
|
||||
+cflags-$(CONFIG_MNEHALEM) += -march=i686 $(call tune,nehalem)
|
||||
+cflags-$(CONFIG_MWESTMERE) += -march=i686 $(call tune,westmere)
|
||||
+cflags-$(CONFIG_MSANDYBRIDGE) += -march=i686 $(call tune,sandybridge)
|
||||
+cflags-$(CONFIG_MIVYBRIDGE) += -march=i686 $(call tune,ivybridge)
|
||||
+cflags-$(CONFIG_MHASWELL) += -march=i686 $(call tune,haswell)
|
||||
+cflags-$(CONFIG_MBROADWELL) += -march=i686 $(call tune,broadwell)
|
||||
+cflags-$(CONFIG_MATOM) += $(call cc-option,-march=bonnell,$(call cc-option,-march=core2,-march=i686)) \
|
||||
+ $(call cc-option,-mtune=bonnell,$(call cc-option,-mtune=generic))
|
||||
|
||||
# AMD Elan support
|
||||
cflags-$(CONFIG_MELAN) += -march=i486
|
||||
Binary file not shown.
@@ -0,0 +1,37 @@
|
||||
From 84ecc2f6eb1cb12e6d44818f94fa49b50f06e6ac Mon Sep 17 00:00:00 2001
|
||||
From: Gen Zhang <blackgod016574@gmail.com>
|
||||
Date: Thu, 23 May 2019 08:34:52 +0800
|
||||
Subject: consolemap: Fix a memory leaking bug in drivers/tty/vt/consolemap.c
|
||||
|
||||
In function con_insert_unipair(), when allocation for p2 and p1[n]
|
||||
fails, ENOMEM is returned, but previously allocated p1 is not freed,
|
||||
remains as leaking memory. Thus we should free p1 as well when this
|
||||
allocation fails.
|
||||
|
||||
Signed-off-by: Gen Zhang <blackgod016574@gmail.com>
|
||||
Reviewed-by: Kees Cook <keescook@chromium.org>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/tty/vt/consolemap.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c
|
||||
index b28aa0d289f8..79fcc96cc7c0 100644
|
||||
--- a/drivers/tty/vt/consolemap.c
|
||||
+++ b/drivers/tty/vt/consolemap.c
|
||||
@@ -489,7 +489,11 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
|
||||
p2 = p1[n = (unicode >> 6) & 0x1f];
|
||||
if (!p2) {
|
||||
p2 = p1[n] = kmalloc_array(64, sizeof(u16), GFP_KERNEL);
|
||||
- if (!p2) return -ENOMEM;
|
||||
+ if (!p2) {
|
||||
+ kfree(p1);
|
||||
+ p->uni_pgdir[n] = NULL;
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
|
||||
}
|
||||
|
||||
--
|
||||
cgit 1.2-0.3.lf.el7
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
From 88ab55f16aae90e2e974eb67cc2380edb92b0661 Mon Sep 17 00:00:00 2001
|
||||
From: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Date: Mon, 2 Mar 2020 15:21:43 +0900
|
||||
Subject: [PATCH 12/14] MAINTAINERS: add exfat filesystem
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Add myself and Sungjong Seo as exfat maintainer.
|
||||
|
||||
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
|
||||
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
|
||||
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
||||
---
|
||||
MAINTAINERS | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/MAINTAINERS b/MAINTAINERS
|
||||
index 38fe2f3f7b6f..27d912bc5ae2 100644
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -6240,6 +6240,13 @@ F: include/trace/events/mdio.h
|
||||
F: include/uapi/linux/mdio.h
|
||||
F: include/uapi/linux/mii.h
|
||||
|
||||
+EXFAT FILE SYSTEM
|
||||
+M: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
+M: Sungjong Seo <sj1557.seo@samsung.com>
|
||||
+L: linux-fsdevel@vger.kernel.org
|
||||
+S: Maintained
|
||||
+F: fs/exfat/
|
||||
+
|
||||
EXT2 FILE SYSTEM
|
||||
M: Jan Kara <jack@suse.com>
|
||||
L: linux-ext4@vger.kernel.org
|
||||
--
|
||||
2.25.1
|
||||
@@ -0,0 +1,39 @@
|
||||
diff -Nurp linux-5.6.3-aufs/fs/aufs/procfs.c linux-5.6.3-aufs-fix/fs/aufs/procfs.c
|
||||
--- linux-5.6.3-aufs/fs/aufs/procfs.c 2020-04-10 12:40:52.192049502 +0300
|
||||
+++ linux-5.6.3-aufs-fix/fs/aufs/procfs.c 2020-04-10 17:46:50.019444421 +0300
|
||||
@@ -116,10 +116,9 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static const struct file_operations au_procfs_plm_fop = {
|
||||
- .write = au_procfs_plm_write,
|
||||
- .release = au_procfs_plm_release,
|
||||
- .owner = THIS_MODULE
|
||||
+static const struct proc_ops au_procfs_plm_op = {
|
||||
+ .proc_write = au_procfs_plm_write,
|
||||
+ .proc_release = au_procfs_plm_release
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
@@ -143,7 +142,7 @@ int __init au_procfs_init(void)
|
||||
goto out;
|
||||
|
||||
entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | 0200,
|
||||
- au_procfs_dir, &au_procfs_plm_fop);
|
||||
+ au_procfs_dir, &au_procfs_plm_op);
|
||||
if (unlikely(!entry))
|
||||
goto out_dir;
|
||||
|
||||
diff -Nurp linux-5.6.3-aufs/fs/aufs/xino.c linux-5.6.3-aufs-fix/fs/aufs/xino.c
|
||||
--- linux-5.6.3-aufs/fs/aufs/xino.c 2020-04-10 12:40:52.193049549 +0300
|
||||
+++ linux-5.6.3-aufs-fix/fs/aufs/xino.c 2020-04-10 17:46:25.165284147 +0300
|
||||
@@ -1344,7 +1344,8 @@ static void au_xino_release(struct kref
|
||||
hlist_bl_lock(hbl);
|
||||
hlist_bl_for_each_entry_safe(p, pos, n, hbl, node) {
|
||||
hlist_bl_del(&p->node);
|
||||
- au_kfree_rcu(p);
|
||||
+ /* kmemleak reported au_kfree_rcu() doesn't free it */
|
||||
+ kfree(p);
|
||||
}
|
||||
hlist_bl_unlock(hbl);
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
|
||||
fs/aufs/Kconfig | 2 +-
|
||||
fs/dcache.c | 2 ++
|
||||
fs/exec.c | 1 +
|
||||
fs/fcntl.c | 1 +
|
||||
fs/file_table.c | 2 ++
|
||||
fs/inode.c | 1 +
|
||||
fs/namespace.c | 3 +++
|
||||
fs/notify/group.c | 1 +
|
||||
fs/open.c | 1 +
|
||||
fs/read_write.c | 4 ++++
|
||||
fs/splice.c | 2 ++
|
||||
fs/sync.c | 1 +
|
||||
fs/xattr.c | 1 +
|
||||
kernel/locking/lockdep.c | 1 +
|
||||
kernel/task_work.c | 1 +
|
||||
security/security.c | 8 ++++++++
|
||||
16 files changed, 31 insertions(+), 1 deletion(-)
|
||||
|
||||
diff -Nurp linux-5.6.3-aufs/fs/aufs/Kconfig linux-5.6.3-aufs-mod/fs/aufs/Kconfig
|
||||
--- linux-5.6.3-aufs/fs/aufs/Kconfig 2020-04-10 12:40:52.187049268 +0300
|
||||
+++ linux-5.6.3-aufs-mod/fs/aufs/Kconfig 2020-04-10 13:15:44.979742386 +0300
|
||||
@@ -1,6 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
config AUFS_FS
|
||||
- bool "Aufs (Advanced multi layered unification filesystem) support"
|
||||
+ tristate "Aufs (Advanced multi layered unification filesystem) support"
|
||||
help
|
||||
Aufs is a stackable unification filesystem such as Unionfs,
|
||||
which unifies several directories and provides a merged single
|
||||
diff -Nurp linux-5.6.3-aufs/fs/dcache.c linux-5.6.3-aufs-mod/fs/dcache.c
|
||||
--- linux-5.6.3-aufs/fs/dcache.c 2020-04-10 12:40:52.194049596 +0300
|
||||
+++ linux-5.6.3-aufs-mod/fs/dcache.c 2020-04-10 13:15:44.979742386 +0300
|
||||
@@ -1371,6 +1371,7 @@ rename_retry:
|
||||
seq = 1;
|
||||
goto again;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(d_walk);
|
||||
|
||||
struct check_mount {
|
||||
struct vfsmount *mnt;
|
||||
@@ -2916,6 +2917,7 @@ void d_exchange(struct dentry *dentry1,
|
||||
|
||||
write_sequnlock(&rename_lock);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(d_exchange);
|
||||
|
||||
/**
|
||||
* d_ancestor - search for an ancestor
|
||||
diff -Nurp linux-5.6.3-aufs/fs/exec.c linux-5.6.3-aufs-mod/fs/exec.c
|
||||
--- linux-5.6.3-aufs/fs/exec.c 2020-03-30 01:25:41.000000000 +0300
|
||||
+++ linux-5.6.3-aufs-mod/fs/exec.c 2020-04-10 13:15:44.979742386 +0300
|
||||
@@ -109,6 +109,7 @@ bool path_noexec(const struct path *path
|
||||
return (path->mnt->mnt_flags & MNT_NOEXEC) ||
|
||||
(path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(path_noexec);
|
||||
|
||||
#ifdef CONFIG_USELIB
|
||||
/*
|
||||
diff -Nurp linux-5.6.3-aufs/fs/fcntl.c linux-5.6.3-aufs-mod/fs/fcntl.c
|
||||
--- linux-5.6.3-aufs/fs/fcntl.c 2020-04-10 12:40:52.194049596 +0300
|
||||
+++ linux-5.6.3-aufs-mod/fs/fcntl.c 2020-04-10 13:15:44.979742386 +0300
|
||||
@@ -85,6 +85,7 @@ int setfl(int fd, struct file *filp, uns
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(setfl);
|
||||
|
||||
static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
|
||||
int force)
|
||||
diff -Nurp linux-5.6.3-aufs/fs/file_table.c linux-5.6.3-aufs-mod/fs/file_table.c
|
||||
--- linux-5.6.3-aufs/fs/file_table.c 2020-03-30 01:25:41.000000000 +0300
|
||||
+++ linux-5.6.3-aufs-mod/fs/file_table.c 2020-04-10 13:15:44.979742386 +0300
|
||||
@@ -162,6 +162,7 @@ over:
|
||||
}
|
||||
return ERR_PTR(-ENFILE);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(alloc_empty_file);
|
||||
|
||||
/*
|
||||
* Variant of alloc_empty_file() that doesn't check and modify nr_files.
|
||||
@@ -375,6 +376,7 @@ void __fput_sync(struct file *file)
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(fput);
|
||||
+EXPORT_SYMBOL_GPL(__fput_sync);
|
||||
|
||||
void __init files_init(void)
|
||||
{
|
||||
diff -Nurp linux-5.6.3-aufs/fs/inode.c linux-5.6.3-aufs-mod/fs/inode.c
|
||||
--- linux-5.6.3-aufs/fs/inode.c 2020-04-10 12:40:52.194049596 +0300
|
||||
+++ linux-5.6.3-aufs-mod/fs/inode.c 2020-04-10 13:15:44.980742432 +0300
|
||||
@@ -1694,6 +1694,7 @@ int update_time(struct inode *inode, str
|
||||
return inode->i_op->update_time(inode, time, flags);
|
||||
return generic_update_time(inode, time, flags);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(update_time);
|
||||
|
||||
/**
|
||||
* touch_atime - update the access time
|
||||
diff -Nurp linux-5.6.3-aufs/fs/namespace.c linux-5.6.3-aufs-mod/fs/namespace.c
|
||||
--- linux-5.6.3-aufs/fs/namespace.c 2020-04-10 12:40:52.194049596 +0300
|
||||
+++ linux-5.6.3-aufs-mod/fs/namespace.c 2020-04-10 13:15:44.980742432 +0300
|
||||
@@ -431,6 +431,7 @@ void __mnt_drop_write(struct vfsmount *m
|
||||
mnt_dec_writers(real_mount(mnt));
|
||||
preempt_enable();
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(__mnt_drop_write);
|
||||
|
||||
/**
|
||||
* mnt_drop_write - give up write access to a mount
|
||||
@@ -781,6 +782,7 @@ int is_current_mnt_ns(struct vfsmount *m
|
||||
{
|
||||
return check_mnt(real_mount(mnt));
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(is_current_mnt_ns);
|
||||
|
||||
/*
|
||||
* vfsmount lock must be held for write
|
||||
@@ -1903,6 +1905,7 @@ int iterate_mounts(int (*f)(struct vfsmo
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(iterate_mounts);
|
||||
|
||||
static void lock_mnt_tree(struct mount *mnt)
|
||||
{
|
||||
diff -Nurp linux-5.6.3-aufs/fs/notify/group.c linux-5.6.3-aufs-mod/fs/notify/group.c
|
||||
--- linux-5.6.3-aufs/fs/notify/group.c 2020-03-30 01:25:41.000000000 +0300
|
||||
+++ linux-5.6.3-aufs-mod/fs/notify/group.c 2020-04-10 13:15:44.980742432 +0300
|
||||
@@ -99,6 +99,7 @@ void fsnotify_get_group(struct fsnotify_
|
||||
{
|
||||
refcount_inc(&group->refcnt);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(fsnotify_get_group);
|
||||
|
||||
/*
|
||||
* Drop a reference to a group. Free it if it's through.
|
||||
diff -Nurp linux-5.6.3-aufs/fs/open.c linux-5.6.3-aufs-mod/fs/open.c
|
||||
--- linux-5.6.3-aufs/fs/open.c 2020-03-30 01:25:41.000000000 +0300
|
||||
+++ linux-5.6.3-aufs-mod/fs/open.c 2020-04-10 13:15:44.980742432 +0300
|
||||
@@ -65,6 +65,7 @@ int do_truncate(struct dentry *dentry, l
|
||||
inode_unlock(dentry->d_inode);
|
||||
return ret;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(do_truncate);
|
||||
|
||||
long vfs_truncate(const struct path *path, loff_t length)
|
||||
{
|
||||
diff -Nurp linux-5.6.3-aufs/fs/read_write.c linux-5.6.3-aufs-mod/fs/read_write.c
|
||||
--- linux-5.6.3-aufs/fs/read_write.c 2020-04-10 12:40:52.194049596 +0300
|
||||
+++ linux-5.6.3-aufs-mod/fs/read_write.c 2020-04-10 13:15:44.981742479 +0300
|
||||
@@ -468,6 +468,7 @@ ssize_t vfs_read(struct file *file, char
|
||||
|
||||
return ret;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(vfs_read);
|
||||
|
||||
static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
|
||||
{
|
||||
@@ -508,6 +509,7 @@ vfs_readf_t vfs_readf(struct file *file)
|
||||
return new_sync_read;
|
||||
return ERR_PTR(-ENOSYS); /* doesn't have ->read(|_iter)() op */
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(vfs_readf);
|
||||
|
||||
vfs_writef_t vfs_writef(struct file *file)
|
||||
{
|
||||
@@ -519,6 +521,7 @@ vfs_writef_t vfs_writef(struct file *fil
|
||||
return new_sync_write;
|
||||
return ERR_PTR(-ENOSYS); /* doesn't have ->write(|_iter)() op */
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(vfs_writef);
|
||||
|
||||
ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
|
||||
{
|
||||
@@ -588,6 +591,7 @@ ssize_t vfs_write(struct file *file, con
|
||||
|
||||
return ret;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(vfs_write);
|
||||
|
||||
/* file_ppos returns &file->f_pos or NULL if file is stream */
|
||||
static inline loff_t *file_ppos(struct file *file)
|
||||
diff -Nurp linux-5.6.3-aufs/fs/splice.c linux-5.6.3-aufs-mod/fs/splice.c
|
||||
--- linux-5.6.3-aufs/fs/splice.c 2020-04-10 12:40:52.194049596 +0300
|
||||
+++ linux-5.6.3-aufs-mod/fs/splice.c 2020-04-10 13:15:44.981742479 +0300
|
||||
@@ -862,6 +862,7 @@ long do_splice_from(struct pipe_inode_in
|
||||
|
||||
return splice_write(pipe, out, ppos, len, flags);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(do_splice_from);
|
||||
|
||||
/*
|
||||
* Attempt to initiate a splice from a file to a pipe.
|
||||
@@ -891,6 +892,7 @@ long do_splice_to(struct file *in, loff_
|
||||
|
||||
return splice_read(in, ppos, pipe, len, flags);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(do_splice_to);
|
||||
|
||||
/**
|
||||
* splice_direct_to_actor - splices data directly between two non-pipes
|
||||
diff -Nurp linux-5.6.3-aufs/fs/sync.c linux-5.6.3-aufs-mod/fs/sync.c
|
||||
--- linux-5.6.3-aufs/fs/sync.c 2020-04-10 12:40:52.194049596 +0300
|
||||
+++ linux-5.6.3-aufs-mod/fs/sync.c 2020-04-10 13:15:44.981742479 +0300
|
||||
@@ -39,6 +39,7 @@ int __sync_filesystem(struct super_block
|
||||
sb->s_op->sync_fs(sb, wait);
|
||||
return __sync_blockdev(sb->s_bdev, wait);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(__sync_filesystem);
|
||||
|
||||
/*
|
||||
* Write out and wait upon all dirty data associated with this
|
||||
diff -Nurp linux-5.6.3-aufs/fs/xattr.c linux-5.6.3-aufs-mod/fs/xattr.c
|
||||
--- linux-5.6.3-aufs/fs/xattr.c 2020-03-30 01:25:41.000000000 +0300
|
||||
+++ linux-5.6.3-aufs-mod/fs/xattr.c 2020-04-10 13:15:44.981742479 +0300
|
||||
@@ -296,6 +296,7 @@ vfs_getxattr_alloc(struct dentry *dentry
|
||||
*xattr_value = value;
|
||||
return error;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(vfs_getxattr_alloc);
|
||||
|
||||
ssize_t
|
||||
__vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
|
||||
diff -Nurp linux-5.6.3-aufs/kernel/locking/lockdep.c linux-5.6.3-aufs-mod/kernel/locking/lockdep.c
|
||||
--- linux-5.6.3-aufs/kernel/locking/lockdep.c 2020-04-10 12:40:52.195049643 +0300
|
||||
+++ linux-5.6.3-aufs-mod/kernel/locking/lockdep.c 2020-04-10 13:15:44.982742525 +0300
|
||||
@@ -174,6 +174,7 @@ inline struct lock_class *lockdep_hlock_
|
||||
*/
|
||||
return lock_classes + class_idx;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(lockdep_hlock_class);
|
||||
#define hlock_class(hlock) lockdep_hlock_class(hlock)
|
||||
|
||||
#ifdef CONFIG_LOCK_STAT
|
||||
diff -Nurp linux-5.6.3-aufs/kernel/task_work.c linux-5.6.3-aufs-mod/kernel/task_work.c
|
||||
--- linux-5.6.3-aufs/kernel/task_work.c 2020-03-30 01:25:41.000000000 +0300
|
||||
+++ linux-5.6.3-aufs-mod/kernel/task_work.c 2020-04-10 13:15:44.982742525 +0300
|
||||
@@ -116,3 +116,4 @@ void task_work_run(void)
|
||||
} while (work);
|
||||
}
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(task_work_run);
|
||||
diff -Nurp linux-5.6.3-aufs/security/security.c linux-5.6.3-aufs-mod/security/security.c
|
||||
--- linux-5.6.3-aufs/security/security.c 2020-03-30 01:25:41.000000000 +0300
|
||||
+++ linux-5.6.3-aufs-mod/security/security.c 2020-04-10 13:15:44.982742525 +0300
|
||||
@@ -1068,6 +1068,7 @@ int security_path_rmdir(const struct pat
|
||||
return 0;
|
||||
return call_int_hook(path_rmdir, 0, dir, dentry);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(security_path_rmdir);
|
||||
|
||||
int security_path_unlink(const struct path *dir, struct dentry *dentry)
|
||||
{
|
||||
@@ -1084,6 +1085,7 @@ int security_path_symlink(const struct p
|
||||
return 0;
|
||||
return call_int_hook(path_symlink, 0, dir, dentry, old_name);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(security_path_symlink);
|
||||
|
||||
int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
|
||||
struct dentry *new_dentry)
|
||||
@@ -1092,6 +1094,7 @@ int security_path_link(struct dentry *ol
|
||||
return 0;
|
||||
return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(security_path_link);
|
||||
|
||||
int security_path_rename(const struct path *old_dir, struct dentry *old_dentry,
|
||||
const struct path *new_dir, struct dentry *new_dentry,
|
||||
@@ -1119,6 +1122,7 @@ int security_path_truncate(const struct
|
||||
return 0;
|
||||
return call_int_hook(path_truncate, 0, path);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(security_path_truncate);
|
||||
|
||||
int security_path_chmod(const struct path *path, umode_t mode)
|
||||
{
|
||||
@@ -1126,6 +1130,7 @@ int security_path_chmod(const struct pat
|
||||
return 0;
|
||||
return call_int_hook(path_chmod, 0, path, mode);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(security_path_chmod);
|
||||
|
||||
int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
|
||||
{
|
||||
@@ -1133,6 +1138,7 @@ int security_path_chown(const struct pat
|
||||
return 0;
|
||||
return call_int_hook(path_chown, 0, path, uid, gid);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(security_path_chown);
|
||||
|
||||
int security_path_chroot(const struct path *path)
|
||||
{
|
||||
@@ -1233,6 +1239,7 @@ int security_inode_permission(struct ino
|
||||
return 0;
|
||||
return call_int_hook(inode_permission, 0, inode, mask);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(security_inode_permission);
|
||||
|
||||
int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
{
|
||||
@@ -1410,6 +1417,7 @@ int security_file_permission(struct file
|
||||
|
||||
return fsnotify_perm(file, mask);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(security_file_permission);
|
||||
|
||||
int security_file_alloc(struct file *file)
|
||||
{
|
||||
File diff suppressed because it is too large
Load Diff
+96
@@ -0,0 +1,96 @@
|
||||
From b9d1e2e6265f5dc25e9f5dbfbde3e53d8a4958ac Mon Sep 17 00:00:00 2001
|
||||
From: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Date: Mon, 2 Mar 2020 15:21:42 +0900
|
||||
Subject: [PATCH 11/14] exfat: add Kconfig and Makefile
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This adds the Kconfig and Makefile for exfat.
|
||||
|
||||
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
|
||||
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
|
||||
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
||||
---
|
||||
fs/Kconfig | 3 ++-
|
||||
fs/Makefile | 1 +
|
||||
fs/exfat/Kconfig | 21 +++++++++++++++++++++
|
||||
fs/exfat/Makefile | 8 ++++++++
|
||||
4 files changed, 32 insertions(+), 1 deletion(-)
|
||||
create mode 100644 fs/exfat/Kconfig
|
||||
create mode 100644 fs/exfat/Makefile
|
||||
|
||||
diff --git a/fs/Kconfig b/fs/Kconfig
|
||||
index 708ba336e689..f08fbbfafd9a 100644
|
||||
--- a/fs/Kconfig
|
||||
+++ b/fs/Kconfig
|
||||
@@ -140,9 +140,10 @@ endmenu
|
||||
endif # BLOCK
|
||||
|
||||
if BLOCK
|
||||
-menu "DOS/FAT/NT Filesystems"
|
||||
+menu "DOS/FAT/EXFAT/NT Filesystems"
|
||||
|
||||
source "fs/fat/Kconfig"
|
||||
+source "fs/exfat/Kconfig"
|
||||
source "fs/ntfs/Kconfig"
|
||||
|
||||
endmenu
|
||||
diff --git a/fs/Makefile b/fs/Makefile
|
||||
index 505e51166973..2ce5112b02c8 100644
|
||||
--- a/fs/Makefile
|
||||
+++ b/fs/Makefile
|
||||
@@ -83,6 +83,7 @@ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
|
||||
obj-$(CONFIG_CODA_FS) += coda/
|
||||
obj-$(CONFIG_MINIX_FS) += minix/
|
||||
obj-$(CONFIG_FAT_FS) += fat/
|
||||
+obj-$(CONFIG_EXFAT_FS) += exfat/
|
||||
obj-$(CONFIG_BFS_FS) += bfs/
|
||||
obj-$(CONFIG_ISO9660_FS) += isofs/
|
||||
obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+
|
||||
diff --git a/fs/exfat/Kconfig b/fs/exfat/Kconfig
|
||||
new file mode 100644
|
||||
index 000000000000..2d3636dc5b8c
|
||||
--- /dev/null
|
||||
+++ b/fs/exfat/Kconfig
|
||||
@@ -0,0 +1,21 @@
|
||||
+# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+
|
||||
+config EXFAT_FS
|
||||
+ tristate "exFAT filesystem support"
|
||||
+ select NLS
|
||||
+ help
|
||||
+ This allows you to mount devices formatted with the exFAT file system.
|
||||
+ exFAT is typically used on SD-Cards or USB sticks.
|
||||
+
|
||||
+ To compile this as a module, choose M here: the module will be called
|
||||
+ exfat.
|
||||
+
|
||||
+config EXFAT_DEFAULT_IOCHARSET
|
||||
+ string "Default iocharset for exFAT"
|
||||
+ default "utf8"
|
||||
+ depends on EXFAT_FS
|
||||
+ help
|
||||
+ Set this to the default input/output character set to use for
|
||||
+ converting between the encoding is used for user visible filename and
|
||||
+ UTF-16 character that exfat filesystem use, and can be overridden with
|
||||
+ the "iocharset" mount option for exFAT filesystems.
|
||||
diff --git a/fs/exfat/Makefile b/fs/exfat/Makefile
|
||||
new file mode 100644
|
||||
index 000000000000..ed51926a4971
|
||||
--- /dev/null
|
||||
+++ b/fs/exfat/Makefile
|
||||
@@ -0,0 +1,8 @@
|
||||
+# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+#
|
||||
+# Makefile for the linux exFAT filesystem support.
|
||||
+#
|
||||
+obj-$(CONFIG_EXFAT_FS) += exfat.o
|
||||
+
|
||||
+exfat-y := inode.o namei.o dir.o super.o fatent.o cache.o nls.o misc.o \
|
||||
+ file.o balloc.o
|
||||
--
|
||||
2.25.1
|
||||
|
||||
@@ -0,0 +1,309 @@
|
||||
From 1e49a94cf707204b66a3fb242f2814712c941f52 Mon Sep 17 00:00:00 2001
|
||||
From: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Date: Mon, 2 Mar 2020 15:21:38 +0900
|
||||
Subject: [PATCH 07/14] exfat: add bitmap operations
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This adds the implementation of bitmap operations for exfat.
|
||||
|
||||
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
|
||||
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
|
||||
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
||||
---
|
||||
fs/exfat/balloc.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 280 insertions(+)
|
||||
create mode 100644 fs/exfat/balloc.c
|
||||
|
||||
diff --git a/fs/exfat/balloc.c b/fs/exfat/balloc.c
|
||||
new file mode 100644
|
||||
index 000000000000..6a04cc02565a
|
||||
--- /dev/null
|
||||
+++ b/fs/exfat/balloc.c
|
||||
@@ -0,0 +1,280 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+/*
|
||||
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/blkdev.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/buffer_head.h>
|
||||
+
|
||||
+#include "exfat_raw.h"
|
||||
+#include "exfat_fs.h"
|
||||
+
|
||||
+static const unsigned char free_bit[] = {
|
||||
+ 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,/* 0 ~ 19*/
|
||||
+ 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3,/* 20 ~ 39*/
|
||||
+ 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/* 40 ~ 59*/
|
||||
+ 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,/* 60 ~ 79*/
|
||||
+ 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2,/* 80 ~ 99*/
|
||||
+ 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3,/*100 ~ 119*/
|
||||
+ 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/*120 ~ 139*/
|
||||
+ 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,/*140 ~ 159*/
|
||||
+ 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,/*160 ~ 179*/
|
||||
+ 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3,/*180 ~ 199*/
|
||||
+ 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/*200 ~ 219*/
|
||||
+ 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,/*220 ~ 239*/
|
||||
+ 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /*240 ~ 254*/
|
||||
+};
|
||||
+
|
||||
+static const unsigned char used_bit[] = {
|
||||
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3,/* 0 ~ 19*/
|
||||
+ 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4,/* 20 ~ 39*/
|
||||
+ 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,/* 40 ~ 59*/
|
||||
+ 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,/* 60 ~ 79*/
|
||||
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4,/* 80 ~ 99*/
|
||||
+ 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,/*100 ~ 119*/
|
||||
+ 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4,/*120 ~ 139*/
|
||||
+ 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,/*140 ~ 159*/
|
||||
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5,/*160 ~ 179*/
|
||||
+ 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,/*180 ~ 199*/
|
||||
+ 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6,/*200 ~ 219*/
|
||||
+ 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,/*220 ~ 239*/
|
||||
+ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 /*240 ~ 255*/
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * Allocation Bitmap Management Functions
|
||||
+ */
|
||||
+static int exfat_allocate_bitmap(struct super_block *sb,
|
||||
+ struct exfat_dentry *ep)
|
||||
+{
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ long long map_size;
|
||||
+ unsigned int i, need_map_size;
|
||||
+ sector_t sector;
|
||||
+
|
||||
+ sbi->map_clu = le32_to_cpu(ep->dentry.bitmap.start_clu);
|
||||
+ map_size = le64_to_cpu(ep->dentry.bitmap.size);
|
||||
+ need_map_size = ((EXFAT_DATA_CLUSTER_COUNT(sbi) - 1) / BITS_PER_BYTE)
|
||||
+ + 1;
|
||||
+ if (need_map_size != map_size) {
|
||||
+ exfat_msg(sb, KERN_ERR,
|
||||
+ "bogus allocation bitmap size(need : %u, cur : %lld)",
|
||||
+ need_map_size, map_size);
|
||||
+ /*
|
||||
+ * Only allowed when bogus allocation
|
||||
+ * bitmap size is large
|
||||
+ */
|
||||
+ if (need_map_size > map_size)
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+ sbi->map_sectors = ((need_map_size - 1) >>
|
||||
+ (sb->s_blocksize_bits)) + 1;
|
||||
+ sbi->vol_amap = kmalloc_array(sbi->map_sectors,
|
||||
+ sizeof(struct buffer_head *), GFP_KERNEL);
|
||||
+ if (!sbi->vol_amap)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ sector = exfat_cluster_to_sector(sbi, sbi->map_clu);
|
||||
+ for (i = 0; i < sbi->map_sectors; i++) {
|
||||
+ sbi->vol_amap[i] = sb_bread(sb, sector + i);
|
||||
+ if (!sbi->vol_amap[i]) {
|
||||
+ /* release all buffers and free vol_amap */
|
||||
+ int j = 0;
|
||||
+
|
||||
+ while (j < i)
|
||||
+ brelse(sbi->vol_amap[j++]);
|
||||
+
|
||||
+ kfree(sbi->vol_amap);
|
||||
+ sbi->vol_amap = NULL;
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ sbi->pbr_bh = NULL;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int exfat_load_bitmap(struct super_block *sb)
|
||||
+{
|
||||
+ unsigned int i, type;
|
||||
+ struct exfat_chain clu;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+
|
||||
+ exfat_chain_set(&clu, sbi->root_dir, 0, ALLOC_FAT_CHAIN);
|
||||
+ while (clu.dir != EXFAT_EOF_CLUSTER) {
|
||||
+ for (i = 0; i < sbi->dentries_per_clu; i++) {
|
||||
+ struct exfat_dentry *ep;
|
||||
+ struct buffer_head *bh;
|
||||
+
|
||||
+ ep = exfat_get_dentry(sb, &clu, i, &bh, NULL);
|
||||
+ if (!ep)
|
||||
+ return -EIO;
|
||||
+
|
||||
+ type = exfat_get_entry_type(ep);
|
||||
+ if (type == TYPE_UNUSED)
|
||||
+ break;
|
||||
+ if (type != TYPE_BITMAP)
|
||||
+ continue;
|
||||
+ if (ep->dentry.bitmap.flags == 0x0) {
|
||||
+ int err;
|
||||
+
|
||||
+ err = exfat_allocate_bitmap(sb, ep);
|
||||
+ brelse(bh);
|
||||
+ return err;
|
||||
+ }
|
||||
+ brelse(bh);
|
||||
+ }
|
||||
+
|
||||
+ if (exfat_get_next_cluster(sb, &clu.dir))
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+void exfat_free_bitmap(struct exfat_sb_info *sbi)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ brelse(sbi->pbr_bh);
|
||||
+
|
||||
+ for (i = 0; i < sbi->map_sectors; i++)
|
||||
+ __brelse(sbi->vol_amap[i]);
|
||||
+
|
||||
+ kfree(sbi->vol_amap);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * If the value of "clu" is 0, it means cluster 2 which is the first cluster of
|
||||
+ * the cluster heap.
|
||||
+ */
|
||||
+int exfat_set_bitmap(struct inode *inode, unsigned int clu)
|
||||
+{
|
||||
+ int i, b;
|
||||
+ unsigned int ent_idx;
|
||||
+ struct super_block *sb = inode->i_sb;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+
|
||||
+ WARN_ON(clu < EXFAT_FIRST_CLUSTER);
|
||||
+ ent_idx = CLUSTER_TO_BITMAP_ENT(clu);
|
||||
+ i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx);
|
||||
+ b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx);
|
||||
+
|
||||
+ set_bit_le(b, sbi->vol_amap[i]->b_data);
|
||||
+ exfat_update_bh(sb, sbi->vol_amap[i], IS_DIRSYNC(inode));
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * If the value of "clu" is 0, it means cluster 2 which is the first cluster of
|
||||
+ * the cluster heap.
|
||||
+ */
|
||||
+void exfat_clear_bitmap(struct inode *inode, unsigned int clu)
|
||||
+{
|
||||
+ int i, b;
|
||||
+ unsigned int ent_idx;
|
||||
+ struct super_block *sb = inode->i_sb;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ struct exfat_mount_options *opts = &sbi->options;
|
||||
+
|
||||
+ WARN_ON(clu < EXFAT_FIRST_CLUSTER);
|
||||
+ ent_idx = CLUSTER_TO_BITMAP_ENT(clu);
|
||||
+ i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx);
|
||||
+ b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx);
|
||||
+
|
||||
+ clear_bit_le(b, sbi->vol_amap[i]->b_data);
|
||||
+ exfat_update_bh(sb, sbi->vol_amap[i], IS_DIRSYNC(inode));
|
||||
+
|
||||
+ if (opts->discard) {
|
||||
+ int ret_discard;
|
||||
+
|
||||
+ ret_discard = sb_issue_discard(sb,
|
||||
+ exfat_cluster_to_sector(sbi, clu +
|
||||
+ EXFAT_RESERVED_CLUSTERS),
|
||||
+ (1 << sbi->sect_per_clus_bits), GFP_NOFS, 0);
|
||||
+
|
||||
+ if (ret_discard == -EOPNOTSUPP) {
|
||||
+ exfat_msg(sb, KERN_ERR,
|
||||
+ "discard not supported by device, disabling");
|
||||
+ opts->discard = 0;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * If the value of "clu" is 0, it means cluster 2 which is the first cluster of
|
||||
+ * the cluster heap.
|
||||
+ */
|
||||
+unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu)
|
||||
+{
|
||||
+ unsigned int i, map_i, map_b, ent_idx;
|
||||
+ unsigned int clu_base, clu_free;
|
||||
+ unsigned char k, clu_mask;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+
|
||||
+ WARN_ON(clu < EXFAT_FIRST_CLUSTER);
|
||||
+ ent_idx = CLUSTER_TO_BITMAP_ENT(clu);
|
||||
+ clu_base = BITMAP_ENT_TO_CLUSTER(ent_idx & ~(BITS_PER_BYTE_MASK));
|
||||
+ clu_mask = IGNORED_BITS_REMAINED(clu, clu_base);
|
||||
+
|
||||
+ map_i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx);
|
||||
+ map_b = BITMAP_OFFSET_BYTE_IN_SECTOR(sb, ent_idx);
|
||||
+
|
||||
+ for (i = EXFAT_FIRST_CLUSTER; i < sbi->num_clusters;
|
||||
+ i += BITS_PER_BYTE) {
|
||||
+ k = *(sbi->vol_amap[map_i]->b_data + map_b);
|
||||
+ if (clu_mask > 0) {
|
||||
+ k |= clu_mask;
|
||||
+ clu_mask = 0;
|
||||
+ }
|
||||
+ if (k < 0xFF) {
|
||||
+ clu_free = clu_base + free_bit[k];
|
||||
+ if (clu_free < sbi->num_clusters)
|
||||
+ return clu_free;
|
||||
+ }
|
||||
+ clu_base += BITS_PER_BYTE;
|
||||
+
|
||||
+ if (++map_b >= sb->s_blocksize ||
|
||||
+ clu_base >= sbi->num_clusters) {
|
||||
+ if (++map_i >= sbi->map_sectors) {
|
||||
+ clu_base = EXFAT_FIRST_CLUSTER;
|
||||
+ map_i = 0;
|
||||
+ }
|
||||
+ map_b = 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return EXFAT_EOF_CLUSTER;
|
||||
+}
|
||||
+
|
||||
+int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count)
|
||||
+{
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ unsigned int count = 0;
|
||||
+ unsigned int i, map_i = 0, map_b = 0;
|
||||
+ unsigned int total_clus = EXFAT_DATA_CLUSTER_COUNT(sbi);
|
||||
+ unsigned int last_mask = total_clus & BITS_PER_BYTE_MASK;
|
||||
+ unsigned char clu_bits;
|
||||
+ const unsigned char last_bit_mask[] = {0, 0b00000001, 0b00000011,
|
||||
+ 0b00000111, 0b00001111, 0b00011111, 0b00111111, 0b01111111};
|
||||
+
|
||||
+ total_clus &= ~last_mask;
|
||||
+ for (i = 0; i < total_clus; i += BITS_PER_BYTE) {
|
||||
+ clu_bits = *(sbi->vol_amap[map_i]->b_data + map_b);
|
||||
+ count += used_bit[clu_bits];
|
||||
+ if (++map_b >= (unsigned int)sb->s_blocksize) {
|
||||
+ map_i++;
|
||||
+ map_b = 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (last_mask) {
|
||||
+ clu_bits = *(sbi->vol_amap[map_i]->b_data + map_b);
|
||||
+ clu_bits &= last_bit_mask[last_mask];
|
||||
+ count += used_bit[clu_bits];
|
||||
+ }
|
||||
+
|
||||
+ *ret_count = count;
|
||||
+ return 0;
|
||||
+}
|
||||
--
|
||||
2.25.1
|
||||
|
||||
+1267
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,354 @@
|
||||
From c35b6810c4952ae5776607e2c1d6a587425d5834 Mon Sep 17 00:00:00 2001
|
||||
From: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Date: Mon, 2 Mar 2020 15:21:39 +0900
|
||||
Subject: [PATCH 08/14] exfat: add exfat cache
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This adds the implementation of exfat cache.
|
||||
|
||||
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
|
||||
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
|
||||
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
||||
---
|
||||
fs/exfat/cache.c | 325 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 325 insertions(+)
|
||||
create mode 100644 fs/exfat/cache.c
|
||||
|
||||
diff --git a/fs/exfat/cache.c b/fs/exfat/cache.c
|
||||
new file mode 100644
|
||||
index 000000000000..03d0824fc368
|
||||
--- /dev/null
|
||||
+++ b/fs/exfat/cache.c
|
||||
@@ -0,0 +1,325 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+/*
|
||||
+ * linux/fs/fat/cache.c
|
||||
+ *
|
||||
+ * Written 1992,1993 by Werner Almesberger
|
||||
+ *
|
||||
+ * Mar 1999. AV. Changed cache, so that it uses the starting cluster instead
|
||||
+ * of inode number.
|
||||
+ * May 1999. AV. Fixed the bogosity with FAT32 (read "FAT28"). Fscking lusers.
|
||||
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/slab.h>
|
||||
+#include <asm/unaligned.h>
|
||||
+#include <linux/buffer_head.h>
|
||||
+
|
||||
+#include "exfat_raw.h"
|
||||
+#include "exfat_fs.h"
|
||||
+
|
||||
+#define EXFAT_CACHE_VALID 0
|
||||
+#define EXFAT_MAX_CACHE 16
|
||||
+
|
||||
+struct exfat_cache {
|
||||
+ struct list_head cache_list;
|
||||
+ unsigned int nr_contig; /* number of contiguous clusters */
|
||||
+ unsigned int fcluster; /* cluster number in the file. */
|
||||
+ unsigned int dcluster; /* cluster number on disk. */
|
||||
+};
|
||||
+
|
||||
+struct exfat_cache_id {
|
||||
+ unsigned int id;
|
||||
+ unsigned int nr_contig;
|
||||
+ unsigned int fcluster;
|
||||
+ unsigned int dcluster;
|
||||
+};
|
||||
+
|
||||
+static struct kmem_cache *exfat_cachep;
|
||||
+
|
||||
+static void exfat_cache_init_once(void *c)
|
||||
+{
|
||||
+ struct exfat_cache *cache = (struct exfat_cache *)c;
|
||||
+
|
||||
+ INIT_LIST_HEAD(&cache->cache_list);
|
||||
+}
|
||||
+
|
||||
+int exfat_cache_init(void)
|
||||
+{
|
||||
+ exfat_cachep = kmem_cache_create("exfat_cache",
|
||||
+ sizeof(struct exfat_cache),
|
||||
+ 0, SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
|
||||
+ exfat_cache_init_once);
|
||||
+ if (!exfat_cachep)
|
||||
+ return -ENOMEM;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void exfat_cache_shutdown(void)
|
||||
+{
|
||||
+ if (!exfat_cachep)
|
||||
+ return;
|
||||
+ kmem_cache_destroy(exfat_cachep);
|
||||
+}
|
||||
+
|
||||
+void exfat_cache_init_inode(struct inode *inode)
|
||||
+{
|
||||
+ struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
+
|
||||
+ spin_lock_init(&ei->cache_lru_lock);
|
||||
+ ei->nr_caches = 0;
|
||||
+ ei->cache_valid_id = EXFAT_CACHE_VALID + 1;
|
||||
+ INIT_LIST_HEAD(&ei->cache_lru);
|
||||
+}
|
||||
+
|
||||
+static inline struct exfat_cache *exfat_cache_alloc(void)
|
||||
+{
|
||||
+ return kmem_cache_alloc(exfat_cachep, GFP_NOFS);
|
||||
+}
|
||||
+
|
||||
+static inline void exfat_cache_free(struct exfat_cache *cache)
|
||||
+{
|
||||
+ WARN_ON(!list_empty(&cache->cache_list));
|
||||
+ kmem_cache_free(exfat_cachep, cache);
|
||||
+}
|
||||
+
|
||||
+static inline void exfat_cache_update_lru(struct inode *inode,
|
||||
+ struct exfat_cache *cache)
|
||||
+{
|
||||
+ struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
+
|
||||
+ if (ei->cache_lru.next != &cache->cache_list)
|
||||
+ list_move(&cache->cache_list, &ei->cache_lru);
|
||||
+}
|
||||
+
|
||||
+static unsigned int exfat_cache_lookup(struct inode *inode,
|
||||
+ unsigned int fclus, struct exfat_cache_id *cid,
|
||||
+ unsigned int *cached_fclus, unsigned int *cached_dclus)
|
||||
+{
|
||||
+ struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
+ static struct exfat_cache nohit = { .fcluster = 0, };
|
||||
+ struct exfat_cache *hit = &nohit, *p;
|
||||
+ unsigned int offset = EXFAT_EOF_CLUSTER;
|
||||
+
|
||||
+ spin_lock(&ei->cache_lru_lock);
|
||||
+ list_for_each_entry(p, &ei->cache_lru, cache_list) {
|
||||
+ /* Find the cache of "fclus" or nearest cache. */
|
||||
+ if (p->fcluster <= fclus && hit->fcluster < p->fcluster) {
|
||||
+ hit = p;
|
||||
+ if (hit->fcluster + hit->nr_contig < fclus) {
|
||||
+ offset = hit->nr_contig;
|
||||
+ } else {
|
||||
+ offset = fclus - hit->fcluster;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ if (hit != &nohit) {
|
||||
+ exfat_cache_update_lru(inode, hit);
|
||||
+
|
||||
+ cid->id = ei->cache_valid_id;
|
||||
+ cid->nr_contig = hit->nr_contig;
|
||||
+ cid->fcluster = hit->fcluster;
|
||||
+ cid->dcluster = hit->dcluster;
|
||||
+ *cached_fclus = cid->fcluster + offset;
|
||||
+ *cached_dclus = cid->dcluster + offset;
|
||||
+ }
|
||||
+ spin_unlock(&ei->cache_lru_lock);
|
||||
+
|
||||
+ return offset;
|
||||
+}
|
||||
+
|
||||
+static struct exfat_cache *exfat_cache_merge(struct inode *inode,
|
||||
+ struct exfat_cache_id *new)
|
||||
+{
|
||||
+ struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
+ struct exfat_cache *p;
|
||||
+
|
||||
+ list_for_each_entry(p, &ei->cache_lru, cache_list) {
|
||||
+ /* Find the same part as "new" in cluster-chain. */
|
||||
+ if (p->fcluster == new->fcluster) {
|
||||
+ if (new->nr_contig > p->nr_contig)
|
||||
+ p->nr_contig = new->nr_contig;
|
||||
+ return p;
|
||||
+ }
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static void exfat_cache_add(struct inode *inode,
|
||||
+ struct exfat_cache_id *new)
|
||||
+{
|
||||
+ struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
+ struct exfat_cache *cache, *tmp;
|
||||
+
|
||||
+ if (new->fcluster == EXFAT_EOF_CLUSTER) /* dummy cache */
|
||||
+ return;
|
||||
+
|
||||
+ spin_lock(&ei->cache_lru_lock);
|
||||
+ if (new->id != EXFAT_CACHE_VALID &&
|
||||
+ new->id != ei->cache_valid_id)
|
||||
+ goto unlock; /* this cache was invalidated */
|
||||
+
|
||||
+ cache = exfat_cache_merge(inode, new);
|
||||
+ if (cache == NULL) {
|
||||
+ if (ei->nr_caches < EXFAT_MAX_CACHE) {
|
||||
+ ei->nr_caches++;
|
||||
+ spin_unlock(&ei->cache_lru_lock);
|
||||
+
|
||||
+ tmp = exfat_cache_alloc();
|
||||
+ if (!tmp) {
|
||||
+ spin_lock(&ei->cache_lru_lock);
|
||||
+ ei->nr_caches--;
|
||||
+ spin_unlock(&ei->cache_lru_lock);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ spin_lock(&ei->cache_lru_lock);
|
||||
+ cache = exfat_cache_merge(inode, new);
|
||||
+ if (cache != NULL) {
|
||||
+ ei->nr_caches--;
|
||||
+ exfat_cache_free(tmp);
|
||||
+ goto out_update_lru;
|
||||
+ }
|
||||
+ cache = tmp;
|
||||
+ } else {
|
||||
+ struct list_head *p = ei->cache_lru.prev;
|
||||
+
|
||||
+ cache = list_entry(p,
|
||||
+ struct exfat_cache, cache_list);
|
||||
+ }
|
||||
+ cache->fcluster = new->fcluster;
|
||||
+ cache->dcluster = new->dcluster;
|
||||
+ cache->nr_contig = new->nr_contig;
|
||||
+ }
|
||||
+out_update_lru:
|
||||
+ exfat_cache_update_lru(inode, cache);
|
||||
+unlock:
|
||||
+ spin_unlock(&ei->cache_lru_lock);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Cache invalidation occurs rarely, thus the LRU chain is not updated. It
|
||||
+ * fixes itself after a while.
|
||||
+ */
|
||||
+static void __exfat_cache_inval_inode(struct inode *inode)
|
||||
+{
|
||||
+ struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
+ struct exfat_cache *cache;
|
||||
+
|
||||
+ while (!list_empty(&ei->cache_lru)) {
|
||||
+ cache = list_entry(ei->cache_lru.next,
|
||||
+ struct exfat_cache, cache_list);
|
||||
+ list_del_init(&cache->cache_list);
|
||||
+ ei->nr_caches--;
|
||||
+ exfat_cache_free(cache);
|
||||
+ }
|
||||
+ /* Update. The copy of caches before this id is discarded. */
|
||||
+ ei->cache_valid_id++;
|
||||
+ if (ei->cache_valid_id == EXFAT_CACHE_VALID)
|
||||
+ ei->cache_valid_id++;
|
||||
+}
|
||||
+
|
||||
+void exfat_cache_inval_inode(struct inode *inode)
|
||||
+{
|
||||
+ struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
+
|
||||
+ spin_lock(&ei->cache_lru_lock);
|
||||
+ __exfat_cache_inval_inode(inode);
|
||||
+ spin_unlock(&ei->cache_lru_lock);
|
||||
+}
|
||||
+
|
||||
+static inline int cache_contiguous(struct exfat_cache_id *cid,
|
||||
+ unsigned int dclus)
|
||||
+{
|
||||
+ cid->nr_contig++;
|
||||
+ return cid->dcluster + cid->nr_contig == dclus;
|
||||
+}
|
||||
+
|
||||
+static inline void cache_init(struct exfat_cache_id *cid,
|
||||
+ unsigned int fclus, unsigned int dclus)
|
||||
+{
|
||||
+ cid->id = EXFAT_CACHE_VALID;
|
||||
+ cid->fcluster = fclus;
|
||||
+ cid->dcluster = dclus;
|
||||
+ cid->nr_contig = 0;
|
||||
+}
|
||||
+
|
||||
+int exfat_get_cluster(struct inode *inode, unsigned int cluster,
|
||||
+ unsigned int *fclus, unsigned int *dclus,
|
||||
+ unsigned int *last_dclus, int allow_eof)
|
||||
+{
|
||||
+ struct super_block *sb = inode->i_sb;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ unsigned int limit = sbi->num_clusters;
|
||||
+ struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
+ struct exfat_cache_id cid;
|
||||
+ unsigned int content;
|
||||
+
|
||||
+ if (ei->start_clu == EXFAT_FREE_CLUSTER) {
|
||||
+ exfat_fs_error(sb,
|
||||
+ "invalid access to exfat cache (entry 0x%08x)",
|
||||
+ ei->start_clu);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ *fclus = 0;
|
||||
+ *dclus = ei->start_clu;
|
||||
+ *last_dclus = *dclus;
|
||||
+
|
||||
+ /*
|
||||
+ * Don`t use exfat_cache if zero offset or non-cluster allocation
|
||||
+ */
|
||||
+ if (cluster == 0 || *dclus == EXFAT_EOF_CLUSTER)
|
||||
+ return 0;
|
||||
+
|
||||
+ cache_init(&cid, EXFAT_EOF_CLUSTER, EXFAT_EOF_CLUSTER);
|
||||
+
|
||||
+ if (exfat_cache_lookup(inode, cluster, &cid, fclus, dclus) ==
|
||||
+ EXFAT_EOF_CLUSTER) {
|
||||
+ /*
|
||||
+ * dummy, always not contiguous
|
||||
+ * This is reinitialized by cache_init(), later.
|
||||
+ */
|
||||
+ WARN_ON(cid.id != EXFAT_CACHE_VALID ||
|
||||
+ cid.fcluster != EXFAT_EOF_CLUSTER ||
|
||||
+ cid.dcluster != EXFAT_EOF_CLUSTER ||
|
||||
+ cid.nr_contig != 0);
|
||||
+ }
|
||||
+
|
||||
+ if (*fclus == cluster)
|
||||
+ return 0;
|
||||
+
|
||||
+ while (*fclus < cluster) {
|
||||
+ /* prevent the infinite loop of cluster chain */
|
||||
+ if (*fclus > limit) {
|
||||
+ exfat_fs_error(sb,
|
||||
+ "detected the cluster chain loop (i_pos %u)",
|
||||
+ (*fclus));
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ if (exfat_ent_get(sb, *dclus, &content))
|
||||
+ return -EIO;
|
||||
+
|
||||
+ *last_dclus = *dclus;
|
||||
+ *dclus = content;
|
||||
+ (*fclus)++;
|
||||
+
|
||||
+ if (content == EXFAT_EOF_CLUSTER) {
|
||||
+ if (!allow_eof) {
|
||||
+ exfat_fs_error(sb,
|
||||
+ "invalid cluster chain (i_pos %u, last_clus 0x%08x is EOF)",
|
||||
+ *fclus, (*last_dclus));
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (!cache_contiguous(&cid, *dclus))
|
||||
+ cache_init(&cid, *fclus, *dclus);
|
||||
+ }
|
||||
+
|
||||
+ exfat_cache_add(inode, &cid);
|
||||
+ return 0;
|
||||
+}
|
||||
--
|
||||
2.25.1
|
||||
|
||||
+492
@@ -0,0 +1,492 @@
|
||||
From 31023864e67a5f390cefbe92f72343027dc3aa33 Mon Sep 17 00:00:00 2001
|
||||
From: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Date: Mon, 2 Mar 2020 15:21:37 +0900
|
||||
Subject: [PATCH 06/14] exfat: add fat entry operations
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This adds the implementation of fat entry operations for exfat.
|
||||
|
||||
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
|
||||
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
|
||||
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
||||
---
|
||||
fs/exfat/fatent.c | 463 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 463 insertions(+)
|
||||
create mode 100644 fs/exfat/fatent.c
|
||||
|
||||
diff --git a/fs/exfat/fatent.c b/fs/exfat/fatent.c
|
||||
new file mode 100644
|
||||
index 000000000000..a855b1769a96
|
||||
--- /dev/null
|
||||
+++ b/fs/exfat/fatent.c
|
||||
@@ -0,0 +1,463 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+/*
|
||||
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/slab.h>
|
||||
+#include <asm/unaligned.h>
|
||||
+#include <linux/buffer_head.h>
|
||||
+
|
||||
+#include "exfat_raw.h"
|
||||
+#include "exfat_fs.h"
|
||||
+
|
||||
+static int exfat_mirror_bh(struct super_block *sb, sector_t sec,
|
||||
+ struct buffer_head *bh)
|
||||
+{
|
||||
+ struct buffer_head *c_bh;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ sector_t sec2;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ if (sbi->FAT2_start_sector != sbi->FAT1_start_sector) {
|
||||
+ sec2 = sec - sbi->FAT1_start_sector + sbi->FAT2_start_sector;
|
||||
+ c_bh = sb_getblk(sb, sec2);
|
||||
+ if (!c_bh)
|
||||
+ return -ENOMEM;
|
||||
+ memcpy(c_bh->b_data, bh->b_data, sb->s_blocksize);
|
||||
+ set_buffer_uptodate(c_bh);
|
||||
+ mark_buffer_dirty(c_bh);
|
||||
+ if (sb->s_flags & SB_SYNCHRONOUS)
|
||||
+ err = sync_dirty_buffer(c_bh);
|
||||
+ brelse(c_bh);
|
||||
+ }
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int __exfat_ent_get(struct super_block *sb, unsigned int loc,
|
||||
+ unsigned int *content)
|
||||
+{
|
||||
+ unsigned int off;
|
||||
+ sector_t sec;
|
||||
+ struct buffer_head *bh;
|
||||
+
|
||||
+ sec = FAT_ENT_OFFSET_SECTOR(sb, loc);
|
||||
+ off = FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc);
|
||||
+
|
||||
+ bh = sb_bread(sb, sec);
|
||||
+ if (!bh)
|
||||
+ return -EIO;
|
||||
+
|
||||
+ *content = le32_to_cpu(*(__le32 *)(&bh->b_data[off]));
|
||||
+
|
||||
+ /* remap reserved clusters to simplify code */
|
||||
+ if (*content > EXFAT_BAD_CLUSTER)
|
||||
+ *content = EXFAT_EOF_CLUSTER;
|
||||
+
|
||||
+ brelse(bh);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int exfat_ent_set(struct super_block *sb, unsigned int loc,
|
||||
+ unsigned int content)
|
||||
+{
|
||||
+ unsigned int off;
|
||||
+ sector_t sec;
|
||||
+ __le32 *fat_entry;
|
||||
+ struct buffer_head *bh;
|
||||
+
|
||||
+ sec = FAT_ENT_OFFSET_SECTOR(sb, loc);
|
||||
+ off = FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc);
|
||||
+
|
||||
+ bh = sb_bread(sb, sec);
|
||||
+ if (!bh)
|
||||
+ return -EIO;
|
||||
+
|
||||
+ fat_entry = (__le32 *)&(bh->b_data[off]);
|
||||
+ *fat_entry = cpu_to_le32(content);
|
||||
+ exfat_update_bh(sb, bh, sb->s_flags & SB_SYNCHRONOUS);
|
||||
+ exfat_mirror_bh(sb, sec, bh);
|
||||
+ brelse(bh);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline bool is_valid_cluster(struct exfat_sb_info *sbi,
|
||||
+ unsigned int clus)
|
||||
+{
|
||||
+ if (clus < EXFAT_FIRST_CLUSTER || sbi->num_clusters <= clus)
|
||||
+ return false;
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+int exfat_ent_get(struct super_block *sb, unsigned int loc,
|
||||
+ unsigned int *content)
|
||||
+{
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ int err;
|
||||
+
|
||||
+ if (!is_valid_cluster(sbi, loc)) {
|
||||
+ exfat_fs_error(sb, "invalid access to FAT (entry 0x%08x)",
|
||||
+ loc);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ err = __exfat_ent_get(sb, loc, content);
|
||||
+ if (err) {
|
||||
+ exfat_fs_error(sb,
|
||||
+ "failed to access to FAT (entry 0x%08x, err:%d)",
|
||||
+ loc, err);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ if (*content == EXFAT_FREE_CLUSTER) {
|
||||
+ exfat_fs_error(sb,
|
||||
+ "invalid access to FAT free cluster (entry 0x%08x)",
|
||||
+ loc);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ if (*content == EXFAT_BAD_CLUSTER) {
|
||||
+ exfat_fs_error(sb,
|
||||
+ "invalid access to FAT bad cluster (entry 0x%08x)",
|
||||
+ loc);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ if (*content != EXFAT_EOF_CLUSTER && !is_valid_cluster(sbi, *content)) {
|
||||
+ exfat_fs_error(sb,
|
||||
+ "invalid access to FAT (entry 0x%08x) bogus content (0x%08x)",
|
||||
+ loc, *content);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int exfat_chain_cont_cluster(struct super_block *sb, unsigned int chain,
|
||||
+ unsigned int len)
|
||||
+{
|
||||
+ if (!len)
|
||||
+ return 0;
|
||||
+
|
||||
+ while (len > 1) {
|
||||
+ if (exfat_ent_set(sb, chain, chain + 1))
|
||||
+ return -EIO;
|
||||
+ chain++;
|
||||
+ len--;
|
||||
+ }
|
||||
+
|
||||
+ if (exfat_ent_set(sb, chain, EXFAT_EOF_CLUSTER))
|
||||
+ return -EIO;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
|
||||
+{
|
||||
+ unsigned int num_clusters = 0;
|
||||
+ unsigned int clu;
|
||||
+ struct super_block *sb = inode->i_sb;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+
|
||||
+ /* invalid cluster number */
|
||||
+ if (p_chain->dir == EXFAT_FREE_CLUSTER ||
|
||||
+ p_chain->dir == EXFAT_EOF_CLUSTER ||
|
||||
+ p_chain->dir < EXFAT_FIRST_CLUSTER)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* no cluster to truncate */
|
||||
+ if (p_chain->size == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* check cluster validation */
|
||||
+ if (p_chain->dir < 2 && p_chain->dir >= sbi->num_clusters) {
|
||||
+ exfat_msg(sb, KERN_ERR, "invalid start cluster (%u)",
|
||||
+ p_chain->dir);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ set_bit(EXFAT_SB_DIRTY, &sbi->s_state);
|
||||
+ clu = p_chain->dir;
|
||||
+
|
||||
+ if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
|
||||
+ do {
|
||||
+ exfat_clear_bitmap(inode, clu);
|
||||
+ clu++;
|
||||
+
|
||||
+ num_clusters++;
|
||||
+ } while (num_clusters < p_chain->size);
|
||||
+ } else {
|
||||
+ do {
|
||||
+ exfat_clear_bitmap(inode, clu);
|
||||
+
|
||||
+ if (exfat_get_next_cluster(sb, &clu))
|
||||
+ goto dec_used_clus;
|
||||
+
|
||||
+ num_clusters++;
|
||||
+ } while (clu != EXFAT_EOF_CLUSTER);
|
||||
+ }
|
||||
+
|
||||
+dec_used_clus:
|
||||
+ sbi->used_clusters -= num_clusters;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int exfat_find_last_cluster(struct super_block *sb, struct exfat_chain *p_chain,
|
||||
+ unsigned int *ret_clu)
|
||||
+{
|
||||
+ unsigned int clu, next;
|
||||
+ unsigned int count = 0;
|
||||
+
|
||||
+ next = p_chain->dir;
|
||||
+ if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
|
||||
+ *ret_clu = next + p_chain->size - 1;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ do {
|
||||
+ count++;
|
||||
+ clu = next;
|
||||
+ if (exfat_ent_get(sb, clu, &next))
|
||||
+ return -EIO;
|
||||
+ } while (next != EXFAT_EOF_CLUSTER);
|
||||
+
|
||||
+ if (p_chain->size != count) {
|
||||
+ exfat_fs_error(sb,
|
||||
+ "bogus directory size (clus : ondisk(%d) != counted(%d))",
|
||||
+ p_chain->size, count);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ *ret_clu = clu;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int exfat_sync_bhs(struct buffer_head **bhs, int nr_bhs)
|
||||
+{
|
||||
+ int i, err = 0;
|
||||
+
|
||||
+ for (i = 0; i < nr_bhs; i++)
|
||||
+ write_dirty_buffer(bhs[i], 0);
|
||||
+
|
||||
+ for (i = 0; i < nr_bhs; i++) {
|
||||
+ wait_on_buffer(bhs[i]);
|
||||
+ if (!err && !buffer_uptodate(bhs[i]))
|
||||
+ err = -EIO;
|
||||
+ }
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+int exfat_zeroed_cluster(struct inode *dir, unsigned int clu)
|
||||
+{
|
||||
+ struct super_block *sb = dir->i_sb;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ struct buffer_head *bhs[MAX_BUF_PER_PAGE];
|
||||
+ int nr_bhs = MAX_BUF_PER_PAGE;
|
||||
+ sector_t blknr, last_blknr;
|
||||
+ int err, i, n;
|
||||
+
|
||||
+ blknr = exfat_cluster_to_sector(sbi, clu);
|
||||
+ last_blknr = blknr + sbi->sect_per_clus;
|
||||
+
|
||||
+ if (last_blknr > sbi->num_sectors && sbi->num_sectors > 0) {
|
||||
+ exfat_fs_error_ratelimit(sb,
|
||||
+ "%s: out of range(sect:%llu len:%u)",
|
||||
+ __func__, (unsigned long long)blknr,
|
||||
+ sbi->sect_per_clus);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ /* Zeroing the unused blocks on this cluster */
|
||||
+ n = 0;
|
||||
+ while (blknr < last_blknr) {
|
||||
+ bhs[n] = sb_getblk(sb, blknr);
|
||||
+ if (!bhs[n]) {
|
||||
+ err = -ENOMEM;
|
||||
+ goto release_bhs;
|
||||
+ }
|
||||
+ memset(bhs[n]->b_data, 0, sb->s_blocksize);
|
||||
+ exfat_update_bh(sb, bhs[n], 0);
|
||||
+
|
||||
+ n++;
|
||||
+ blknr++;
|
||||
+
|
||||
+ if (n == nr_bhs) {
|
||||
+ if (IS_DIRSYNC(dir)) {
|
||||
+ err = exfat_sync_bhs(bhs, n);
|
||||
+ if (err)
|
||||
+ goto release_bhs;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < n; i++)
|
||||
+ brelse(bhs[i]);
|
||||
+ n = 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (IS_DIRSYNC(dir)) {
|
||||
+ err = exfat_sync_bhs(bhs, n);
|
||||
+ if (err)
|
||||
+ goto release_bhs;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < n; i++)
|
||||
+ brelse(bhs[i]);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+release_bhs:
|
||||
+ exfat_msg(sb, KERN_ERR, "failed zeroed sect %llu\n",
|
||||
+ (unsigned long long)blknr);
|
||||
+ for (i = 0; i < n; i++)
|
||||
+ bforget(bhs[i]);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
|
||||
+ struct exfat_chain *p_chain)
|
||||
+{
|
||||
+ int ret = -ENOSPC;
|
||||
+ unsigned int num_clusters = 0, total_cnt;
|
||||
+ unsigned int hint_clu, new_clu, last_clu = EXFAT_EOF_CLUSTER;
|
||||
+ struct super_block *sb = inode->i_sb;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+
|
||||
+ total_cnt = EXFAT_DATA_CLUSTER_COUNT(sbi);
|
||||
+
|
||||
+ if (unlikely(total_cnt < sbi->used_clusters)) {
|
||||
+ exfat_fs_error_ratelimit(sb,
|
||||
+ "%s: invalid used clusters(t:%u,u:%u)\n",
|
||||
+ __func__, total_cnt, sbi->used_clusters);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ if (num_alloc > total_cnt - sbi->used_clusters)
|
||||
+ return -ENOSPC;
|
||||
+
|
||||
+ hint_clu = p_chain->dir;
|
||||
+ /* find new cluster */
|
||||
+ if (hint_clu == EXFAT_EOF_CLUSTER) {
|
||||
+ if (sbi->clu_srch_ptr < EXFAT_FIRST_CLUSTER) {
|
||||
+ exfat_msg(sb, KERN_ERR,
|
||||
+ "sbi->clu_srch_ptr is invalid (%u)\n",
|
||||
+ sbi->clu_srch_ptr);
|
||||
+ sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER;
|
||||
+ }
|
||||
+
|
||||
+ hint_clu = exfat_find_free_bitmap(sb, sbi->clu_srch_ptr);
|
||||
+ if (hint_clu == EXFAT_EOF_CLUSTER)
|
||||
+ return -ENOSPC;
|
||||
+ }
|
||||
+
|
||||
+ /* check cluster validation */
|
||||
+ if (hint_clu < EXFAT_FIRST_CLUSTER && hint_clu >= sbi->num_clusters) {
|
||||
+ exfat_msg(sb, KERN_ERR, "hint_cluster is invalid (%u)\n",
|
||||
+ hint_clu);
|
||||
+ hint_clu = EXFAT_FIRST_CLUSTER;
|
||||
+ if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
|
||||
+ if (exfat_chain_cont_cluster(sb, p_chain->dir,
|
||||
+ num_clusters))
|
||||
+ return -EIO;
|
||||
+ p_chain->flags = ALLOC_FAT_CHAIN;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ set_bit(EXFAT_SB_DIRTY, &sbi->s_state);
|
||||
+
|
||||
+ p_chain->dir = EXFAT_EOF_CLUSTER;
|
||||
+
|
||||
+ while ((new_clu = exfat_find_free_bitmap(sb, hint_clu)) !=
|
||||
+ EXFAT_EOF_CLUSTER) {
|
||||
+ if (new_clu != hint_clu &&
|
||||
+ p_chain->flags == ALLOC_NO_FAT_CHAIN) {
|
||||
+ if (exfat_chain_cont_cluster(sb, p_chain->dir,
|
||||
+ num_clusters)) {
|
||||
+ ret = -EIO;
|
||||
+ goto free_cluster;
|
||||
+ }
|
||||
+ p_chain->flags = ALLOC_FAT_CHAIN;
|
||||
+ }
|
||||
+
|
||||
+ /* update allocation bitmap */
|
||||
+ if (exfat_set_bitmap(inode, new_clu)) {
|
||||
+ ret = -EIO;
|
||||
+ goto free_cluster;
|
||||
+ }
|
||||
+
|
||||
+ num_clusters++;
|
||||
+
|
||||
+ /* update FAT table */
|
||||
+ if (p_chain->flags == ALLOC_FAT_CHAIN) {
|
||||
+ if (exfat_ent_set(sb, new_clu, EXFAT_EOF_CLUSTER)) {
|
||||
+ ret = -EIO;
|
||||
+ goto free_cluster;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (p_chain->dir == EXFAT_EOF_CLUSTER) {
|
||||
+ p_chain->dir = new_clu;
|
||||
+ } else if (p_chain->flags == ALLOC_FAT_CHAIN) {
|
||||
+ if (exfat_ent_set(sb, last_clu, new_clu)) {
|
||||
+ ret = -EIO;
|
||||
+ goto free_cluster;
|
||||
+ }
|
||||
+ }
|
||||
+ last_clu = new_clu;
|
||||
+
|
||||
+ if (--num_alloc == 0) {
|
||||
+ sbi->clu_srch_ptr = hint_clu;
|
||||
+ sbi->used_clusters += num_clusters;
|
||||
+
|
||||
+ p_chain->size += num_clusters;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ hint_clu = new_clu + 1;
|
||||
+ if (hint_clu >= sbi->num_clusters) {
|
||||
+ hint_clu = EXFAT_FIRST_CLUSTER;
|
||||
+
|
||||
+ if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
|
||||
+ if (exfat_chain_cont_cluster(sb, p_chain->dir,
|
||||
+ num_clusters)) {
|
||||
+ ret = -EIO;
|
||||
+ goto free_cluster;
|
||||
+ }
|
||||
+ p_chain->flags = ALLOC_FAT_CHAIN;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+free_cluster:
|
||||
+ if (num_clusters)
|
||||
+ exfat_free_cluster(inode, p_chain);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int exfat_count_num_clusters(struct super_block *sb,
|
||||
+ struct exfat_chain *p_chain, unsigned int *ret_count)
|
||||
+{
|
||||
+ unsigned int i, count;
|
||||
+ unsigned int clu;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+
|
||||
+ if (!p_chain->dir || p_chain->dir == EXFAT_EOF_CLUSTER) {
|
||||
+ *ret_count = 0;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
|
||||
+ *ret_count = p_chain->size;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ clu = p_chain->dir;
|
||||
+ count = 0;
|
||||
+ for (i = EXFAT_FIRST_CLUSTER; i < sbi->num_clusters; i++) {
|
||||
+ count++;
|
||||
+ if (exfat_ent_get(sb, clu, &clu))
|
||||
+ return -EIO;
|
||||
+ if (clu == EXFAT_EOF_CLUSTER)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ *ret_count = count;
|
||||
+ return 0;
|
||||
+}
|
||||
--
|
||||
2.25.1
|
||||
|
||||
@@ -0,0 +1,390 @@
|
||||
From 98d917047e8b7f4bb2ff61d81b0ccd94a00444f9 Mon Sep 17 00:00:00 2001
|
||||
From: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Date: Mon, 2 Mar 2020 15:21:36 +0900
|
||||
Subject: [PATCH 05/14] exfat: add file operations
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This adds the implementation of file operations for exfat.
|
||||
|
||||
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
|
||||
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
|
||||
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
|
||||
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
||||
---
|
||||
fs/exfat/file.c | 360 ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 360 insertions(+)
|
||||
create mode 100644 fs/exfat/file.c
|
||||
|
||||
diff --git a/fs/exfat/file.c b/fs/exfat/file.c
|
||||
new file mode 100644
|
||||
index 000000000000..483f683757aa
|
||||
--- /dev/null
|
||||
+++ b/fs/exfat/file.c
|
||||
@@ -0,0 +1,360 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+/*
|
||||
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/cred.h>
|
||||
+#include <linux/buffer_head.h>
|
||||
+
|
||||
+#include "exfat_raw.h"
|
||||
+#include "exfat_fs.h"
|
||||
+
|
||||
+static int exfat_cont_expand(struct inode *inode, loff_t size)
|
||||
+{
|
||||
+ struct address_space *mapping = inode->i_mapping;
|
||||
+ loff_t start = i_size_read(inode), count = size - i_size_read(inode);
|
||||
+ int err, err2;
|
||||
+
|
||||
+ err = generic_cont_expand_simple(inode, size);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ inode->i_ctime = inode->i_mtime = current_time(inode);
|
||||
+ mark_inode_dirty(inode);
|
||||
+
|
||||
+ if (!IS_SYNC(inode))
|
||||
+ return 0;
|
||||
+
|
||||
+ err = filemap_fdatawrite_range(mapping, start, start + count - 1);
|
||||
+ err2 = sync_mapping_buffers(mapping);
|
||||
+ if (!err)
|
||||
+ err = err2;
|
||||
+ err2 = write_inode_now(inode, 1);
|
||||
+ if (!err)
|
||||
+ err = err2;
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ return filemap_fdatawait_range(mapping, start, start + count - 1);
|
||||
+}
|
||||
+
|
||||
+static bool exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode)
|
||||
+{
|
||||
+ mode_t allow_utime = sbi->options.allow_utime;
|
||||
+
|
||||
+ if (!uid_eq(current_fsuid(), inode->i_uid)) {
|
||||
+ if (in_group_p(inode->i_gid))
|
||||
+ allow_utime >>= 3;
|
||||
+ if (allow_utime & MAY_WRITE)
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ /* use a default check */
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static int exfat_sanitize_mode(const struct exfat_sb_info *sbi,
|
||||
+ struct inode *inode, umode_t *mode_ptr)
|
||||
+{
|
||||
+ mode_t i_mode, mask, perm;
|
||||
+
|
||||
+ i_mode = inode->i_mode;
|
||||
+
|
||||
+ mask = (S_ISREG(i_mode) || S_ISLNK(i_mode)) ?
|
||||
+ sbi->options.fs_fmask : sbi->options.fs_dmask;
|
||||
+ perm = *mode_ptr & ~(S_IFMT | mask);
|
||||
+
|
||||
+ /* Of the r and x bits, all (subject to umask) must be present.*/
|
||||
+ if ((perm & 0555) != (i_mode & 0555))
|
||||
+ return -EPERM;
|
||||
+
|
||||
+ if (exfat_mode_can_hold_ro(inode)) {
|
||||
+ /*
|
||||
+ * Of the w bits, either all (subject to umask) or none must
|
||||
+ * be present.
|
||||
+ */
|
||||
+ if ((perm & 0222) && ((perm & 0222) != (0222 & ~mask)))
|
||||
+ return -EPERM;
|
||||
+ } else {
|
||||
+ /*
|
||||
+ * If exfat_mode_can_hold_ro(inode) is false, can't change
|
||||
+ * w bits.
|
||||
+ */
|
||||
+ if ((perm & 0222) != (0222 & ~mask))
|
||||
+ return -EPERM;
|
||||
+ }
|
||||
+
|
||||
+ *mode_ptr &= S_IFMT | perm;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* resize the file length */
|
||||
+int __exfat_truncate(struct inode *inode, loff_t new_size)
|
||||
+{
|
||||
+ unsigned int num_clusters_new, num_clusters_phys;
|
||||
+ unsigned int last_clu = EXFAT_FREE_CLUSTER;
|
||||
+ struct exfat_chain clu;
|
||||
+ struct exfat_dentry *ep, *ep2;
|
||||
+ struct super_block *sb = inode->i_sb;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
+ struct exfat_entry_set_cache *es = NULL;
|
||||
+ int evict = (ei->dir.dir == DIR_DELETED) ? 1 : 0;
|
||||
+
|
||||
+ /* check if the given file ID is opened */
|
||||
+ if (ei->type != TYPE_FILE && ei->type != TYPE_DIR)
|
||||
+ return -EPERM;
|
||||
+
|
||||
+ exfat_set_vol_flags(sb, VOL_DIRTY);
|
||||
+
|
||||
+ num_clusters_new = EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi);
|
||||
+ num_clusters_phys =
|
||||
+ EXFAT_B_TO_CLU_ROUND_UP(EXFAT_I(inode)->i_size_ondisk, sbi);
|
||||
+
|
||||
+ exfat_chain_set(&clu, ei->start_clu, num_clusters_phys, ei->flags);
|
||||
+
|
||||
+ if (new_size > 0) {
|
||||
+ /*
|
||||
+ * Truncate FAT chain num_clusters after the first cluster
|
||||
+ * num_clusters = min(new, phys);
|
||||
+ */
|
||||
+ unsigned int num_clusters =
|
||||
+ min(num_clusters_new, num_clusters_phys);
|
||||
+
|
||||
+ /*
|
||||
+ * Follow FAT chain
|
||||
+ * (defensive coding - works fine even with corrupted FAT table
|
||||
+ */
|
||||
+ if (clu.flags == ALLOC_NO_FAT_CHAIN) {
|
||||
+ clu.dir += num_clusters;
|
||||
+ clu.size -= num_clusters;
|
||||
+ } else {
|
||||
+ while (num_clusters > 0) {
|
||||
+ last_clu = clu.dir;
|
||||
+ if (exfat_get_next_cluster(sb, &(clu.dir)))
|
||||
+ return -EIO;
|
||||
+
|
||||
+ num_clusters--;
|
||||
+ clu.size--;
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
+ ei->flags = ALLOC_NO_FAT_CHAIN;
|
||||
+ ei->start_clu = EXFAT_EOF_CLUSTER;
|
||||
+ }
|
||||
+
|
||||
+ i_size_write(inode, new_size);
|
||||
+
|
||||
+ if (ei->type == TYPE_FILE)
|
||||
+ ei->attr |= ATTR_ARCHIVE;
|
||||
+
|
||||
+ /* update the directory entry */
|
||||
+ if (!evict) {
|
||||
+ struct timespec64 ts;
|
||||
+
|
||||
+ es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry,
|
||||
+ ES_ALL_ENTRIES, &ep);
|
||||
+ if (!es)
|
||||
+ return -EIO;
|
||||
+ ep2 = ep + 1;
|
||||
+
|
||||
+ ts = current_time(inode);
|
||||
+ exfat_set_entry_time(sbi, &ts,
|
||||
+ &ep->dentry.file.modify_tz,
|
||||
+ &ep->dentry.file.modify_time,
|
||||
+ &ep->dentry.file.modify_date,
|
||||
+ &ep->dentry.file.modify_time_ms);
|
||||
+ ep->dentry.file.attr = cpu_to_le16(ei->attr);
|
||||
+
|
||||
+ /* File size should be zero if there is no cluster allocated */
|
||||
+ if (ei->start_clu == EXFAT_EOF_CLUSTER) {
|
||||
+ ep->dentry.stream.valid_size = 0;
|
||||
+ ep->dentry.stream.size = 0;
|
||||
+ } else {
|
||||
+ ep->dentry.stream.valid_size = cpu_to_le64(new_size);
|
||||
+ ep->dentry.stream.size = ep->dentry.stream.valid_size;
|
||||
+ }
|
||||
+
|
||||
+ if (new_size == 0) {
|
||||
+ /* Any directory can not be truncated to zero */
|
||||
+ WARN_ON(ei->type != TYPE_FILE);
|
||||
+
|
||||
+ ep2->dentry.stream.flags = ALLOC_FAT_CHAIN;
|
||||
+ ep2->dentry.stream.start_clu = EXFAT_FREE_CLUSTER;
|
||||
+ }
|
||||
+
|
||||
+ if (exfat_update_dir_chksum_with_entry_set(sb, es,
|
||||
+ inode_needs_sync(inode)))
|
||||
+ return -EIO;
|
||||
+ kfree(es);
|
||||
+ }
|
||||
+
|
||||
+ /* cut off from the FAT chain */
|
||||
+ if (ei->flags == ALLOC_FAT_CHAIN && last_clu != EXFAT_FREE_CLUSTER &&
|
||||
+ last_clu != EXFAT_EOF_CLUSTER) {
|
||||
+ if (exfat_ent_set(sb, last_clu, EXFAT_EOF_CLUSTER))
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ /* invalidate cache and free the clusters */
|
||||
+ /* clear exfat cache */
|
||||
+ exfat_cache_inval_inode(inode);
|
||||
+
|
||||
+ /* hint information */
|
||||
+ ei->hint_bmap.off = EXFAT_EOF_CLUSTER;
|
||||
+ ei->hint_bmap.clu = EXFAT_EOF_CLUSTER;
|
||||
+ if (ei->rwoffset > new_size)
|
||||
+ ei->rwoffset = new_size;
|
||||
+
|
||||
+ /* hint_stat will be used if this is directory. */
|
||||
+ ei->hint_stat.eidx = 0;
|
||||
+ ei->hint_stat.clu = ei->start_clu;
|
||||
+ ei->hint_femp.eidx = EXFAT_HINT_NONE;
|
||||
+
|
||||
+ /* free the clusters */
|
||||
+ if (exfat_free_cluster(inode, &clu))
|
||||
+ return -EIO;
|
||||
+
|
||||
+ exfat_set_vol_flags(sb, VOL_CLEAN);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void exfat_truncate(struct inode *inode, loff_t size)
|
||||
+{
|
||||
+ struct super_block *sb = inode->i_sb;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ unsigned int blocksize = 1 << inode->i_blkbits;
|
||||
+ loff_t aligned_size;
|
||||
+ int err;
|
||||
+
|
||||
+ mutex_lock(&sbi->s_lock);
|
||||
+ if (EXFAT_I(inode)->start_clu == 0) {
|
||||
+ /*
|
||||
+ * Empty start_clu != ~0 (not allocated)
|
||||
+ */
|
||||
+ exfat_fs_error(sb, "tried to truncate zeroed cluster.");
|
||||
+ goto write_size;
|
||||
+ }
|
||||
+
|
||||
+ err = __exfat_truncate(inode, i_size_read(inode));
|
||||
+ if (err)
|
||||
+ goto write_size;
|
||||
+
|
||||
+ inode->i_ctime = inode->i_mtime = current_time(inode);
|
||||
+ if (IS_DIRSYNC(inode))
|
||||
+ exfat_sync_inode(inode);
|
||||
+ else
|
||||
+ mark_inode_dirty(inode);
|
||||
+
|
||||
+ inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1)) &
|
||||
+ ~(sbi->cluster_size - 1)) >> inode->i_blkbits;
|
||||
+write_size:
|
||||
+ aligned_size = i_size_read(inode);
|
||||
+ if (aligned_size & (blocksize - 1)) {
|
||||
+ aligned_size |= (blocksize - 1);
|
||||
+ aligned_size++;
|
||||
+ }
|
||||
+
|
||||
+ if (EXFAT_I(inode)->i_size_ondisk > i_size_read(inode))
|
||||
+ EXFAT_I(inode)->i_size_ondisk = aligned_size;
|
||||
+
|
||||
+ if (EXFAT_I(inode)->i_size_aligned > i_size_read(inode))
|
||||
+ EXFAT_I(inode)->i_size_aligned = aligned_size;
|
||||
+ mutex_unlock(&sbi->s_lock);
|
||||
+}
|
||||
+
|
||||
+int exfat_getattr(const struct path *path, struct kstat *stat,
|
||||
+ unsigned int request_mask, unsigned int query_flags)
|
||||
+{
|
||||
+ struct inode *inode = d_backing_inode(path->dentry);
|
||||
+ struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
+
|
||||
+ generic_fillattr(inode, stat);
|
||||
+ stat->result_mask |= STATX_BTIME;
|
||||
+ stat->btime.tv_sec = ei->i_crtime.tv_sec;
|
||||
+ stat->btime.tv_nsec = ei->i_crtime.tv_nsec;
|
||||
+ stat->blksize = EXFAT_SB(inode->i_sb)->cluster_size;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int exfat_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
+{
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(dentry->d_sb);
|
||||
+ struct inode *inode = dentry->d_inode;
|
||||
+ unsigned int ia_valid;
|
||||
+ int error;
|
||||
+
|
||||
+ if ((attr->ia_valid & ATTR_SIZE) &&
|
||||
+ attr->ia_size > i_size_read(inode)) {
|
||||
+ error = exfat_cont_expand(inode, attr->ia_size);
|
||||
+ if (error || attr->ia_valid == ATTR_SIZE)
|
||||
+ return error;
|
||||
+ attr->ia_valid &= ~ATTR_SIZE;
|
||||
+ }
|
||||
+
|
||||
+ /* Check for setting the inode time. */
|
||||
+ ia_valid = attr->ia_valid;
|
||||
+ if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) &&
|
||||
+ exfat_allow_set_time(sbi, inode)) {
|
||||
+ attr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET |
|
||||
+ ATTR_TIMES_SET);
|
||||
+ }
|
||||
+
|
||||
+ error = setattr_prepare(dentry, attr);
|
||||
+ attr->ia_valid = ia_valid;
|
||||
+ if (error)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (((attr->ia_valid & ATTR_UID) &&
|
||||
+ !uid_eq(attr->ia_uid, sbi->options.fs_uid)) ||
|
||||
+ ((attr->ia_valid & ATTR_GID) &&
|
||||
+ !gid_eq(attr->ia_gid, sbi->options.fs_gid)) ||
|
||||
+ ((attr->ia_valid & ATTR_MODE) &&
|
||||
+ (attr->ia_mode & ~(S_IFREG | S_IFLNK | S_IFDIR | 0777)))) {
|
||||
+ error = -EPERM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * We don't return -EPERM here. Yes, strange, but this is too
|
||||
+ * old behavior.
|
||||
+ */
|
||||
+ if (attr->ia_valid & ATTR_MODE) {
|
||||
+ if (exfat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0)
|
||||
+ attr->ia_valid &= ~ATTR_MODE;
|
||||
+ }
|
||||
+
|
||||
+ if (attr->ia_valid & ATTR_SIZE) {
|
||||
+ error = exfat_block_truncate_page(inode, attr->ia_size);
|
||||
+ if (error)
|
||||
+ goto out;
|
||||
+
|
||||
+ down_write(&EXFAT_I(inode)->truncate_lock);
|
||||
+ truncate_setsize(inode, attr->ia_size);
|
||||
+ exfat_truncate(inode, attr->ia_size);
|
||||
+ up_write(&EXFAT_I(inode)->truncate_lock);
|
||||
+ }
|
||||
+
|
||||
+ setattr_copy(inode, attr);
|
||||
+ mark_inode_dirty(inode);
|
||||
+
|
||||
+out:
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+const struct file_operations exfat_file_operations = {
|
||||
+ .llseek = generic_file_llseek,
|
||||
+ .read_iter = generic_file_read_iter,
|
||||
+ .write_iter = generic_file_write_iter,
|
||||
+ .mmap = generic_file_mmap,
|
||||
+ .fsync = generic_file_fsync,
|
||||
+ .splice_read = generic_file_splice_read,
|
||||
+};
|
||||
+
|
||||
+const struct inode_operations exfat_file_inode_operations = {
|
||||
+ .setattr = exfat_setattr,
|
||||
+ .getattr = exfat_getattr,
|
||||
+};
|
||||
--
|
||||
2.25.1
|
||||
|
||||
+740
@@ -0,0 +1,740 @@
|
||||
From 1acf1a564b6034b5af1e7fb23cb98cb3bb4f6003 Mon Sep 17 00:00:00 2001
|
||||
From: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Date: Mon, 2 Mar 2020 15:21:32 +0900
|
||||
Subject: [PATCH 01/14] exfat: add in-memory and on-disk structures and headers
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This adds in-memory and on-disk structures and headers.
|
||||
|
||||
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
|
||||
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
|
||||
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
||||
---
|
||||
fs/exfat/exfat_fs.h | 519 +++++++++++++++++++++++++++++++++++++++++++
|
||||
fs/exfat/exfat_raw.h | 184 +++++++++++++++
|
||||
2 files changed, 703 insertions(+)
|
||||
create mode 100644 fs/exfat/exfat_fs.h
|
||||
create mode 100644 fs/exfat/exfat_raw.h
|
||||
|
||||
diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h
|
||||
new file mode 100644
|
||||
index 000000000000..67d4e46fb810
|
||||
--- /dev/null
|
||||
+++ b/fs/exfat/exfat_fs.h
|
||||
@@ -0,0 +1,519 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
+/*
|
||||
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
|
||||
+ */
|
||||
+
|
||||
+#ifndef _EXFAT_FS_H
|
||||
+#define _EXFAT_FS_H
|
||||
+
|
||||
+#include <linux/fs.h>
|
||||
+#include <linux/ratelimit.h>
|
||||
+#include <linux/nls.h>
|
||||
+
|
||||
+#define EXFAT_SUPER_MAGIC 0x2011BAB0UL
|
||||
+#define EXFAT_ROOT_INO 1
|
||||
+
|
||||
+#define EXFAT_SB_DIRTY 0
|
||||
+
|
||||
+#define EXFAT_CLUSTERS_UNTRACKED (~0u)
|
||||
+
|
||||
+/*
|
||||
+ * exfat error flags
|
||||
+ */
|
||||
+enum exfat_error_mode {
|
||||
+ EXFAT_ERRORS_CONT, /* ignore error and continue */
|
||||
+ EXFAT_ERRORS_PANIC, /* panic on error */
|
||||
+ EXFAT_ERRORS_RO, /* remount r/o on error */
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * exfat nls lossy flag
|
||||
+ */
|
||||
+enum {
|
||||
+ NLS_NAME_NO_LOSSY, /* no lossy */
|
||||
+ NLS_NAME_LOSSY, /* just detected incorrect filename(s) */
|
||||
+ NLS_NAME_OVERLEN, /* the length is over than its limit */
|
||||
+};
|
||||
+
|
||||
+#define EXFAT_HASH_BITS 8
|
||||
+#define EXFAT_HASH_SIZE (1UL << EXFAT_HASH_BITS)
|
||||
+
|
||||
+/*
|
||||
+ * Type Definitions
|
||||
+ */
|
||||
+#define ES_2_ENTRIES 2
|
||||
+#define ES_ALL_ENTRIES 0
|
||||
+
|
||||
+#define DIR_DELETED 0xFFFF0321
|
||||
+
|
||||
+/* type values */
|
||||
+#define TYPE_UNUSED 0x0000
|
||||
+#define TYPE_DELETED 0x0001
|
||||
+#define TYPE_INVALID 0x0002
|
||||
+#define TYPE_CRITICAL_PRI 0x0100
|
||||
+#define TYPE_BITMAP 0x0101
|
||||
+#define TYPE_UPCASE 0x0102
|
||||
+#define TYPE_VOLUME 0x0103
|
||||
+#define TYPE_DIR 0x0104
|
||||
+#define TYPE_FILE 0x011F
|
||||
+#define TYPE_CRITICAL_SEC 0x0200
|
||||
+#define TYPE_STREAM 0x0201
|
||||
+#define TYPE_EXTEND 0x0202
|
||||
+#define TYPE_ACL 0x0203
|
||||
+#define TYPE_BENIGN_PRI 0x0400
|
||||
+#define TYPE_GUID 0x0401
|
||||
+#define TYPE_PADDING 0x0402
|
||||
+#define TYPE_ACLTAB 0x0403
|
||||
+#define TYPE_BENIGN_SEC 0x0800
|
||||
+#define TYPE_ALL 0x0FFF
|
||||
+
|
||||
+#define MAX_CHARSET_SIZE 6 /* max size of multi-byte character */
|
||||
+#define MAX_NAME_LENGTH 255 /* max len of file name excluding NULL */
|
||||
+#define MAX_VFSNAME_BUF_SIZE ((MAX_NAME_LENGTH + 1) * MAX_CHARSET_SIZE)
|
||||
+
|
||||
+#define FAT_CACHE_SIZE 128
|
||||
+#define FAT_CACHE_HASH_SIZE 64
|
||||
+#define BUF_CACHE_SIZE 256
|
||||
+#define BUF_CACHE_HASH_SIZE 64
|
||||
+
|
||||
+#define EXFAT_HINT_NONE -1
|
||||
+#define EXFAT_MIN_SUBDIR 2
|
||||
+
|
||||
+/*
|
||||
+ * helpers for cluster size to byte conversion.
|
||||
+ */
|
||||
+#define EXFAT_CLU_TO_B(b, sbi) ((b) << (sbi)->cluster_size_bits)
|
||||
+#define EXFAT_B_TO_CLU(b, sbi) ((b) >> (sbi)->cluster_size_bits)
|
||||
+#define EXFAT_B_TO_CLU_ROUND_UP(b, sbi) \
|
||||
+ (((b - 1) >> (sbi)->cluster_size_bits) + 1)
|
||||
+#define EXFAT_CLU_OFFSET(off, sbi) ((off) & ((sbi)->cluster_size - 1))
|
||||
+
|
||||
+/*
|
||||
+ * helpers for block size to byte conversion.
|
||||
+ */
|
||||
+#define EXFAT_BLK_TO_B(b, sb) ((b) << (sb)->s_blocksize_bits)
|
||||
+#define EXFAT_B_TO_BLK(b, sb) ((b) >> (sb)->s_blocksize_bits)
|
||||
+#define EXFAT_B_TO_BLK_ROUND_UP(b, sb) \
|
||||
+ (((b - 1) >> (sb)->s_blocksize_bits) + 1)
|
||||
+#define EXFAT_BLK_OFFSET(off, sb) ((off) & ((sb)->s_blocksize - 1))
|
||||
+
|
||||
+/*
|
||||
+ * helpers for block size to dentry size conversion.
|
||||
+ */
|
||||
+#define EXFAT_B_TO_DEN_IDX(b, sbi) \
|
||||
+ ((b) << ((sbi)->cluster_size_bits - DENTRY_SIZE_BITS))
|
||||
+#define EXFAT_B_TO_DEN(b) ((b) >> DENTRY_SIZE_BITS)
|
||||
+#define EXFAT_DEN_TO_B(b) ((b) << DENTRY_SIZE_BITS)
|
||||
+
|
||||
+/*
|
||||
+ * helpers for fat entry.
|
||||
+ */
|
||||
+#define FAT_ENT_SIZE (4)
|
||||
+#define FAT_ENT_SIZE_BITS (2)
|
||||
+#define FAT_ENT_OFFSET_SECTOR(sb, loc) (EXFAT_SB(sb)->FAT1_start_sector + \
|
||||
+ (((u64)loc << FAT_ENT_SIZE_BITS) >> sb->s_blocksize_bits))
|
||||
+#define FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc) \
|
||||
+ ((loc << FAT_ENT_SIZE_BITS) & (sb->s_blocksize - 1))
|
||||
+
|
||||
+/*
|
||||
+ * helpers for bitmap.
|
||||
+ */
|
||||
+#define CLUSTER_TO_BITMAP_ENT(clu) ((clu) - EXFAT_RESERVED_CLUSTERS)
|
||||
+#define BITMAP_ENT_TO_CLUSTER(ent) ((ent) + EXFAT_RESERVED_CLUSTERS)
|
||||
+#define BITS_PER_SECTOR(sb) ((sb)->s_blocksize * BITS_PER_BYTE)
|
||||
+#define BITS_PER_SECTOR_MASK(sb) (BITS_PER_SECTOR(sb) - 1)
|
||||
+#define BITMAP_OFFSET_SECTOR_INDEX(sb, ent) \
|
||||
+ ((ent / BITS_PER_BYTE) >> (sb)->s_blocksize_bits)
|
||||
+#define BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent) (ent & BITS_PER_SECTOR_MASK(sb))
|
||||
+#define BITMAP_OFFSET_BYTE_IN_SECTOR(sb, ent) \
|
||||
+ ((ent / BITS_PER_BYTE) & ((sb)->s_blocksize - 1))
|
||||
+#define BITS_PER_BYTE_MASK 0x7
|
||||
+#define IGNORED_BITS_REMAINED(clu, clu_base) ((1 << ((clu) - (clu_base))) - 1)
|
||||
+
|
||||
+struct exfat_dentry_namebuf {
|
||||
+ char *lfn;
|
||||
+ int lfnbuf_len; /* usally MAX_UNINAME_BUF_SIZE */
|
||||
+};
|
||||
+
|
||||
+/* unicode name structure */
|
||||
+struct exfat_uni_name {
|
||||
+ /* +3 for null and for converting */
|
||||
+ unsigned short name[MAX_NAME_LENGTH + 3];
|
||||
+ unsigned short name_hash;
|
||||
+ unsigned char name_len;
|
||||
+};
|
||||
+
|
||||
+/* directory structure */
|
||||
+struct exfat_chain {
|
||||
+ unsigned int dir;
|
||||
+ unsigned int size;
|
||||
+ unsigned char flags;
|
||||
+};
|
||||
+
|
||||
+/* first empty entry hint information */
|
||||
+struct exfat_hint_femp {
|
||||
+ /* entry index of a directory */
|
||||
+ int eidx;
|
||||
+ /* count of continuous empty entry */
|
||||
+ int count;
|
||||
+ /* the cluster that first empty slot exists in */
|
||||
+ struct exfat_chain cur;
|
||||
+};
|
||||
+
|
||||
+/* hint structure */
|
||||
+struct exfat_hint {
|
||||
+ unsigned int clu;
|
||||
+ union {
|
||||
+ unsigned int off; /* cluster offset */
|
||||
+ int eidx; /* entry index */
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+struct exfat_entry_set_cache {
|
||||
+ /* sector number that contains file_entry */
|
||||
+ sector_t sector;
|
||||
+ /* byte offset in the sector */
|
||||
+ unsigned int offset;
|
||||
+ /* flag in stream entry. 01 for cluster chain, 03 for contig. */
|
||||
+ int alloc_flag;
|
||||
+ unsigned int num_entries;
|
||||
+ struct exfat_dentry entries[];
|
||||
+};
|
||||
+
|
||||
+struct exfat_dir_entry {
|
||||
+ struct exfat_chain dir;
|
||||
+ int entry;
|
||||
+ unsigned int type;
|
||||
+ unsigned int start_clu;
|
||||
+ unsigned char flags;
|
||||
+ unsigned short attr;
|
||||
+ loff_t size;
|
||||
+ unsigned int num_subdirs;
|
||||
+ struct timespec64 atime;
|
||||
+ struct timespec64 mtime;
|
||||
+ struct timespec64 crtime;
|
||||
+ struct exfat_dentry_namebuf namebuf;
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * exfat mount in-memory data
|
||||
+ */
|
||||
+struct exfat_mount_options {
|
||||
+ kuid_t fs_uid;
|
||||
+ kgid_t fs_gid;
|
||||
+ unsigned short fs_fmask;
|
||||
+ unsigned short fs_dmask;
|
||||
+ /* permission for setting the [am]time */
|
||||
+ unsigned short allow_utime;
|
||||
+ /* charset for filename input/display */
|
||||
+ char *iocharset;
|
||||
+ /* on error: continue, panic, remount-ro */
|
||||
+ enum exfat_error_mode errors;
|
||||
+ unsigned utf8:1, /* Use of UTF-8 character set */
|
||||
+ discard:1; /* Issue discard requests on deletions */
|
||||
+ int time_offset; /* Offset of timestamps from UTC (in minutes) */
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * EXFAT file system superblock in-memory data
|
||||
+ */
|
||||
+struct exfat_sb_info {
|
||||
+ unsigned long long num_sectors; /* num of sectors in volume */
|
||||
+ unsigned int num_clusters; /* num of clusters in volume */
|
||||
+ unsigned int cluster_size; /* cluster size in bytes */
|
||||
+ unsigned int cluster_size_bits;
|
||||
+ unsigned int sect_per_clus; /* cluster size in sectors */
|
||||
+ unsigned int sect_per_clus_bits;
|
||||
+ unsigned long long FAT1_start_sector; /* FAT1 start sector */
|
||||
+ unsigned long long FAT2_start_sector; /* FAT2 start sector */
|
||||
+ unsigned long long data_start_sector; /* data area start sector */
|
||||
+ unsigned int num_FAT_sectors; /* num of FAT sectors */
|
||||
+ unsigned int root_dir; /* root dir cluster */
|
||||
+ unsigned int dentries_per_clu; /* num of dentries per cluster */
|
||||
+ unsigned int vol_flag; /* volume dirty flag */
|
||||
+ struct buffer_head *pbr_bh; /* buffer_head of PBR sector */
|
||||
+
|
||||
+ unsigned int map_clu; /* allocation bitmap start cluster */
|
||||
+ unsigned int map_sectors; /* num of allocation bitmap sectors */
|
||||
+ struct buffer_head **vol_amap; /* allocation bitmap */
|
||||
+
|
||||
+ unsigned short *vol_utbl; /* upcase table */
|
||||
+
|
||||
+ unsigned int clu_srch_ptr; /* cluster search pointer */
|
||||
+ unsigned int used_clusters; /* number of used clusters */
|
||||
+
|
||||
+ unsigned long s_state;
|
||||
+ struct mutex s_lock; /* superblock lock */
|
||||
+ struct exfat_mount_options options;
|
||||
+ struct nls_table *nls_io; /* Charset used for input and display */
|
||||
+ struct ratelimit_state ratelimit;
|
||||
+
|
||||
+ spinlock_t inode_hash_lock;
|
||||
+ struct hlist_head inode_hashtable[EXFAT_HASH_SIZE];
|
||||
+
|
||||
+ struct rcu_head rcu;
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * EXFAT file system inode in-memory data
|
||||
+ */
|
||||
+struct exfat_inode_info {
|
||||
+ struct exfat_chain dir;
|
||||
+ int entry;
|
||||
+ unsigned int type;
|
||||
+ unsigned short attr;
|
||||
+ unsigned int start_clu;
|
||||
+ unsigned char flags;
|
||||
+ /*
|
||||
+ * the copy of low 32bit of i_version to check
|
||||
+ * the validation of hint_stat.
|
||||
+ */
|
||||
+ unsigned int version;
|
||||
+ /* file offset or dentry index for readdir */
|
||||
+ loff_t rwoffset;
|
||||
+
|
||||
+ /* hint for cluster last accessed */
|
||||
+ struct exfat_hint hint_bmap;
|
||||
+ /* hint for entry index we try to lookup next time */
|
||||
+ struct exfat_hint hint_stat;
|
||||
+ /* hint for first empty entry */
|
||||
+ struct exfat_hint_femp hint_femp;
|
||||
+
|
||||
+ spinlock_t cache_lru_lock;
|
||||
+ struct list_head cache_lru;
|
||||
+ int nr_caches;
|
||||
+ /* for avoiding the race between alloc and free */
|
||||
+ unsigned int cache_valid_id;
|
||||
+
|
||||
+ /*
|
||||
+ * NOTE: i_size_ondisk is 64bits, so must hold ->inode_lock to access.
|
||||
+ * physically allocated size.
|
||||
+ */
|
||||
+ loff_t i_size_ondisk;
|
||||
+ /* block-aligned i_size (used in cont_write_begin) */
|
||||
+ loff_t i_size_aligned;
|
||||
+ /* on-disk position of directory entry or 0 */
|
||||
+ loff_t i_pos;
|
||||
+ /* hash by i_location */
|
||||
+ struct hlist_node i_hash_fat;
|
||||
+ /* protect bmap against truncate */
|
||||
+ struct rw_semaphore truncate_lock;
|
||||
+ struct inode vfs_inode;
|
||||
+ /* File creation time */
|
||||
+ struct timespec64 i_crtime;
|
||||
+};
|
||||
+
|
||||
+static inline struct exfat_sb_info *EXFAT_SB(struct super_block *sb)
|
||||
+{
|
||||
+ return sb->s_fs_info;
|
||||
+}
|
||||
+
|
||||
+static inline struct exfat_inode_info *EXFAT_I(struct inode *inode)
|
||||
+{
|
||||
+ return container_of(inode, struct exfat_inode_info, vfs_inode);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * If ->i_mode can't hold 0222 (i.e. ATTR_RO), we use ->i_attrs to
|
||||
+ * save ATTR_RO instead of ->i_mode.
|
||||
+ *
|
||||
+ * If it's directory and !sbi->options.rodir, ATTR_RO isn't read-only
|
||||
+ * bit, it's just used as flag for app.
|
||||
+ */
|
||||
+static inline int exfat_mode_can_hold_ro(struct inode *inode)
|
||||
+{
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
|
||||
+
|
||||
+ if (S_ISDIR(inode->i_mode))
|
||||
+ return 0;
|
||||
+
|
||||
+ if ((~sbi->options.fs_fmask) & 0222)
|
||||
+ return 1;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Convert attribute bits and a mask to the UNIX mode. */
|
||||
+static inline mode_t exfat_make_mode(struct exfat_sb_info *sbi,
|
||||
+ unsigned short attr, mode_t mode)
|
||||
+{
|
||||
+ if ((attr & ATTR_READONLY) && !(attr & ATTR_SUBDIR))
|
||||
+ mode &= ~0222;
|
||||
+
|
||||
+ if (attr & ATTR_SUBDIR)
|
||||
+ return (mode & ~sbi->options.fs_dmask) | S_IFDIR;
|
||||
+
|
||||
+ return (mode & ~sbi->options.fs_fmask) | S_IFREG;
|
||||
+}
|
||||
+
|
||||
+/* Return the FAT attribute byte for this inode */
|
||||
+static inline unsigned short exfat_make_attr(struct inode *inode)
|
||||
+{
|
||||
+ unsigned short attr = EXFAT_I(inode)->attr;
|
||||
+
|
||||
+ if (S_ISDIR(inode->i_mode))
|
||||
+ attr |= ATTR_SUBDIR;
|
||||
+ if (exfat_mode_can_hold_ro(inode) && !(inode->i_mode & 0222))
|
||||
+ attr |= ATTR_READONLY;
|
||||
+ return attr;
|
||||
+}
|
||||
+
|
||||
+static inline void exfat_save_attr(struct inode *inode, unsigned short attr)
|
||||
+{
|
||||
+ if (exfat_mode_can_hold_ro(inode))
|
||||
+ EXFAT_I(inode)->attr = attr & (ATTR_RWMASK | ATTR_READONLY);
|
||||
+ else
|
||||
+ EXFAT_I(inode)->attr = attr & ATTR_RWMASK;
|
||||
+}
|
||||
+
|
||||
+static inline bool exfat_is_last_sector_in_cluster(struct exfat_sb_info *sbi,
|
||||
+ sector_t sec)
|
||||
+{
|
||||
+ return ((sec - sbi->data_start_sector + 1) &
|
||||
+ ((1 << sbi->sect_per_clus_bits) - 1)) == 0;
|
||||
+}
|
||||
+
|
||||
+static inline sector_t exfat_cluster_to_sector(struct exfat_sb_info *sbi,
|
||||
+ unsigned int clus)
|
||||
+{
|
||||
+ return ((clus - EXFAT_RESERVED_CLUSTERS) << sbi->sect_per_clus_bits) +
|
||||
+ sbi->data_start_sector;
|
||||
+}
|
||||
+
|
||||
+static inline int exfat_sector_to_cluster(struct exfat_sb_info *sbi,
|
||||
+ sector_t sec)
|
||||
+{
|
||||
+ return ((sec - sbi->data_start_sector) >> sbi->sect_per_clus_bits) +
|
||||
+ EXFAT_RESERVED_CLUSTERS;
|
||||
+}
|
||||
+
|
||||
+/* super.c */
|
||||
+int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag);
|
||||
+
|
||||
+/* fatent.c */
|
||||
+#define exfat_get_next_cluster(sb, pclu) exfat_ent_get(sb, *(pclu), pclu)
|
||||
+
|
||||
+int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
|
||||
+ struct exfat_chain *p_chain);
|
||||
+int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain);
|
||||
+int exfat_ent_get(struct super_block *sb, unsigned int loc,
|
||||
+ unsigned int *content);
|
||||
+int exfat_ent_set(struct super_block *sb, unsigned int loc,
|
||||
+ unsigned int content);
|
||||
+int exfat_count_ext_entries(struct super_block *sb, struct exfat_chain *p_dir,
|
||||
+ int entry, struct exfat_dentry *p_entry);
|
||||
+int exfat_chain_cont_cluster(struct super_block *sb, unsigned int chain,
|
||||
+ unsigned int len);
|
||||
+int exfat_zeroed_cluster(struct inode *dir, unsigned int clu);
|
||||
+int exfat_find_last_cluster(struct super_block *sb, struct exfat_chain *p_chain,
|
||||
+ unsigned int *ret_clu);
|
||||
+int exfat_count_num_clusters(struct super_block *sb,
|
||||
+ struct exfat_chain *p_chain, unsigned int *ret_count);
|
||||
+
|
||||
+/* balloc.c */
|
||||
+int exfat_load_bitmap(struct super_block *sb);
|
||||
+void exfat_free_bitmap(struct exfat_sb_info *sbi);
|
||||
+int exfat_set_bitmap(struct inode *inode, unsigned int clu);
|
||||
+void exfat_clear_bitmap(struct inode *inode, unsigned int clu);
|
||||
+unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu);
|
||||
+int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count);
|
||||
+
|
||||
+/* file.c */
|
||||
+extern const struct file_operations exfat_file_operations;
|
||||
+int __exfat_truncate(struct inode *inode, loff_t new_size);
|
||||
+void exfat_truncate(struct inode *inode, loff_t size);
|
||||
+int exfat_setattr(struct dentry *dentry, struct iattr *attr);
|
||||
+int exfat_getattr(const struct path *path, struct kstat *stat,
|
||||
+ unsigned int request_mask, unsigned int query_flags);
|
||||
+
|
||||
+/* namei.c */
|
||||
+extern const struct dentry_operations exfat_dentry_ops;
|
||||
+extern const struct dentry_operations exfat_utf8_dentry_ops;
|
||||
+
|
||||
+/* cache.c */
|
||||
+int exfat_cache_init(void);
|
||||
+void exfat_cache_shutdown(void);
|
||||
+void exfat_cache_init_inode(struct inode *inode);
|
||||
+void exfat_cache_inval_inode(struct inode *inode);
|
||||
+int exfat_get_cluster(struct inode *inode, unsigned int cluster,
|
||||
+ unsigned int *fclus, unsigned int *dclus,
|
||||
+ unsigned int *last_dclus, int allow_eof);
|
||||
+
|
||||
+/* dir.c */
|
||||
+extern const struct inode_operations exfat_dir_inode_operations;
|
||||
+extern const struct file_operations exfat_dir_operations;
|
||||
+unsigned int exfat_get_entry_type(struct exfat_dentry *p_entry);
|
||||
+int exfat_init_dir_entry(struct inode *inode, struct exfat_chain *p_dir,
|
||||
+ int entry, unsigned int type, unsigned int start_clu,
|
||||
+ unsigned long long size);
|
||||
+int exfat_init_ext_entry(struct inode *inode, struct exfat_chain *p_dir,
|
||||
+ int entry, int num_entries, struct exfat_uni_name *p_uniname);
|
||||
+int exfat_remove_entries(struct inode *inode, struct exfat_chain *p_dir,
|
||||
+ int entry, int order, int num_entries);
|
||||
+int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir,
|
||||
+ int entry);
|
||||
+int exfat_update_dir_chksum_with_entry_set(struct super_block *sb,
|
||||
+ struct exfat_entry_set_cache *es, int sync);
|
||||
+int exfat_calc_num_entries(struct exfat_uni_name *p_uniname);
|
||||
+int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
|
||||
+ struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname,
|
||||
+ int num_entries, unsigned int type);
|
||||
+int exfat_alloc_new_dir(struct inode *inode, struct exfat_chain *clu);
|
||||
+int exfat_find_location(struct super_block *sb, struct exfat_chain *p_dir,
|
||||
+ int entry, sector_t *sector, int *offset);
|
||||
+struct exfat_dentry *exfat_get_dentry(struct super_block *sb,
|
||||
+ struct exfat_chain *p_dir, int entry, struct buffer_head **bh,
|
||||
+ sector_t *sector);
|
||||
+struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
|
||||
+ struct exfat_chain *p_dir, int entry, unsigned int type,
|
||||
+ struct exfat_dentry **file_ep);
|
||||
+int exfat_count_dir_entries(struct super_block *sb, struct exfat_chain *p_dir);
|
||||
+
|
||||
+/* inode.c */
|
||||
+extern const struct inode_operations exfat_file_inode_operations;
|
||||
+void exfat_sync_inode(struct inode *inode);
|
||||
+struct inode *exfat_build_inode(struct super_block *sb,
|
||||
+ struct exfat_dir_entry *info, loff_t i_pos);
|
||||
+void exfat_hash_inode(struct inode *inode, loff_t i_pos);
|
||||
+void exfat_unhash_inode(struct inode *inode);
|
||||
+struct inode *exfat_iget(struct super_block *sb, loff_t i_pos);
|
||||
+int exfat_write_inode(struct inode *inode, struct writeback_control *wbc);
|
||||
+void exfat_evict_inode(struct inode *inode);
|
||||
+int exfat_block_truncate_page(struct inode *inode, loff_t from);
|
||||
+
|
||||
+/* exfat/nls.c */
|
||||
+unsigned short exfat_toupper(struct super_block *sb, unsigned short a);
|
||||
+int exfat_uniname_ncmp(struct super_block *sb, unsigned short *a,
|
||||
+ unsigned short *b, unsigned int len);
|
||||
+int exfat_utf16_to_nls(struct super_block *sb,
|
||||
+ struct exfat_uni_name *uniname, unsigned char *p_cstring,
|
||||
+ int len);
|
||||
+int exfat_nls_to_utf16(struct super_block *sb,
|
||||
+ const unsigned char *p_cstring, const int len,
|
||||
+ struct exfat_uni_name *uniname, int *p_lossy);
|
||||
+int exfat_create_upcase_table(struct super_block *sb);
|
||||
+void exfat_free_upcase_table(struct exfat_sb_info *sbi);
|
||||
+unsigned short exfat_high_surrogate(unicode_t u);
|
||||
+unsigned short exfat_low_surrogate(unicode_t u);
|
||||
+
|
||||
+/* exfat/misc.c */
|
||||
+void __exfat_fs_error(struct super_block *sb, int report, const char *fmt, ...)
|
||||
+ __printf(3, 4) __cold;
|
||||
+#define exfat_fs_error(sb, fmt, args...) \
|
||||
+ __exfat_fs_error(sb, 1, fmt, ## args)
|
||||
+#define exfat_fs_error_ratelimit(sb, fmt, args...) \
|
||||
+ __exfat_fs_error(sb, __ratelimit(&EXFAT_SB(sb)->ratelimit), \
|
||||
+ fmt, ## args)
|
||||
+void exfat_msg(struct super_block *sb, const char *lv, const char *fmt, ...)
|
||||
+ __printf(3, 4) __cold;
|
||||
+void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
|
||||
+ u8 tz, __le16 time, __le16 date, u8 time_ms);
|
||||
+void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
|
||||
+ u8 *tz, __le16 *time, __le16 *date, u8 *time_ms);
|
||||
+unsigned short exfat_calc_chksum_2byte(void *data, int len,
|
||||
+ unsigned short chksum, int type);
|
||||
+void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int sync);
|
||||
+void exfat_chain_set(struct exfat_chain *ec, unsigned int dir,
|
||||
+ unsigned int size, unsigned char flags);
|
||||
+void exfat_chain_dup(struct exfat_chain *dup, struct exfat_chain *ec);
|
||||
+
|
||||
+#endif /* !_EXFAT_FS_H */
|
||||
diff --git a/fs/exfat/exfat_raw.h b/fs/exfat/exfat_raw.h
|
||||
new file mode 100644
|
||||
index 000000000000..2a841010e649
|
||||
--- /dev/null
|
||||
+++ b/fs/exfat/exfat_raw.h
|
||||
@@ -0,0 +1,184 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
+/*
|
||||
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
|
||||
+ */
|
||||
+
|
||||
+#ifndef _EXFAT_RAW_H
|
||||
+#define _EXFAT_RAW_H
|
||||
+
|
||||
+#include <linux/types.h>
|
||||
+
|
||||
+#define PBR_SIGNATURE 0xAA55
|
||||
+
|
||||
+#define EXFAT_MAX_FILE_LEN 255
|
||||
+
|
||||
+#define VOL_CLEAN 0x0000
|
||||
+#define VOL_DIRTY 0x0002
|
||||
+
|
||||
+#define EXFAT_EOF_CLUSTER 0xFFFFFFFFu
|
||||
+#define EXFAT_BAD_CLUSTER 0xFFFFFFF7u
|
||||
+#define EXFAT_FREE_CLUSTER 0
|
||||
+/* Cluster 0, 1 are reserved, the first cluster is 2 in the cluster heap. */
|
||||
+#define EXFAT_RESERVED_CLUSTERS 2
|
||||
+#define EXFAT_FIRST_CLUSTER 2
|
||||
+#define EXFAT_DATA_CLUSTER_COUNT(sbi) \
|
||||
+ ((sbi)->num_clusters - EXFAT_RESERVED_CLUSTERS)
|
||||
+
|
||||
+/* AllocationPossible and NoFatChain field in GeneralSecondaryFlags Field */
|
||||
+#define ALLOC_FAT_CHAIN 0x01
|
||||
+#define ALLOC_NO_FAT_CHAIN 0x03
|
||||
+
|
||||
+#define DENTRY_SIZE 32 /* directory entry size */
|
||||
+#define DENTRY_SIZE_BITS 5
|
||||
+/* exFAT allows 8388608(256MB) directory entries */
|
||||
+#define MAX_EXFAT_DENTRIES 8388608
|
||||
+
|
||||
+/* dentry types */
|
||||
+#define EXFAT_UNUSED 0x00 /* end of directory */
|
||||
+#define EXFAT_DELETE (~0x80)
|
||||
+#define IS_EXFAT_DELETED(x) ((x) < 0x80) /* deleted file (0x01~0x7F) */
|
||||
+#define EXFAT_INVAL 0x80 /* invalid value */
|
||||
+#define EXFAT_BITMAP 0x81 /* allocation bitmap */
|
||||
+#define EXFAT_UPCASE 0x82 /* upcase table */
|
||||
+#define EXFAT_VOLUME 0x83 /* volume label */
|
||||
+#define EXFAT_FILE 0x85 /* file or dir */
|
||||
+#define EXFAT_GUID 0xA0
|
||||
+#define EXFAT_PADDING 0xA1
|
||||
+#define EXFAT_ACLTAB 0xA2
|
||||
+#define EXFAT_STREAM 0xC0 /* stream entry */
|
||||
+#define EXFAT_NAME 0xC1 /* file name entry */
|
||||
+#define EXFAT_ACL 0xC2 /* stream entry */
|
||||
+
|
||||
+#define IS_EXFAT_CRITICAL_PRI(x) (x < 0xA0)
|
||||
+#define IS_EXFAT_BENIGN_PRI(x) (x < 0xC0)
|
||||
+#define IS_EXFAT_CRITICAL_SEC(x) (x < 0xE0)
|
||||
+
|
||||
+/* checksum types */
|
||||
+#define CS_DIR_ENTRY 0
|
||||
+#define CS_PBR_SECTOR 1
|
||||
+#define CS_DEFAULT 2
|
||||
+
|
||||
+/* file attributes */
|
||||
+#define ATTR_READONLY 0x0001
|
||||
+#define ATTR_HIDDEN 0x0002
|
||||
+#define ATTR_SYSTEM 0x0004
|
||||
+#define ATTR_VOLUME 0x0008
|
||||
+#define ATTR_SUBDIR 0x0010
|
||||
+#define ATTR_ARCHIVE 0x0020
|
||||
+
|
||||
+#define ATTR_RWMASK (ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME | \
|
||||
+ ATTR_SUBDIR | ATTR_ARCHIVE)
|
||||
+
|
||||
+#define PBR64_JUMP_BOOT_LEN 3
|
||||
+#define PBR64_OEM_NAME_LEN 8
|
||||
+#define PBR64_RESERVED_LEN 53
|
||||
+
|
||||
+#define EXFAT_FILE_NAME_LEN 15
|
||||
+
|
||||
+/* EXFAT BIOS parameter block (64 bytes) */
|
||||
+struct bpb64 {
|
||||
+ __u8 jmp_boot[PBR64_JUMP_BOOT_LEN];
|
||||
+ __u8 oem_name[PBR64_OEM_NAME_LEN];
|
||||
+ __u8 res_zero[PBR64_RESERVED_LEN];
|
||||
+} __packed;
|
||||
+
|
||||
+/* EXFAT EXTEND BIOS parameter block (56 bytes) */
|
||||
+struct bsx64 {
|
||||
+ __le64 vol_offset;
|
||||
+ __le64 vol_length;
|
||||
+ __le32 fat_offset;
|
||||
+ __le32 fat_length;
|
||||
+ __le32 clu_offset;
|
||||
+ __le32 clu_count;
|
||||
+ __le32 root_cluster;
|
||||
+ __le32 vol_serial;
|
||||
+ __u8 fs_version[2];
|
||||
+ __le16 vol_flags;
|
||||
+ __u8 sect_size_bits;
|
||||
+ __u8 sect_per_clus_bits;
|
||||
+ __u8 num_fats;
|
||||
+ __u8 phy_drv_no;
|
||||
+ __u8 perc_in_use;
|
||||
+ __u8 reserved2[7];
|
||||
+} __packed;
|
||||
+
|
||||
+/* EXFAT PBR[BPB+BSX] (120 bytes) */
|
||||
+struct pbr64 {
|
||||
+ struct bpb64 bpb;
|
||||
+ struct bsx64 bsx;
|
||||
+} __packed;
|
||||
+
|
||||
+/* Common PBR[Partition Boot Record] (512 bytes) */
|
||||
+struct pbr {
|
||||
+ union {
|
||||
+ __u8 raw[64];
|
||||
+ struct bpb64 f64;
|
||||
+ } bpb;
|
||||
+ union {
|
||||
+ __u8 raw[56];
|
||||
+ struct bsx64 f64;
|
||||
+ } bsx;
|
||||
+ __u8 boot_code[390];
|
||||
+ __le16 signature;
|
||||
+} __packed;
|
||||
+
|
||||
+struct exfat_dentry {
|
||||
+ __u8 type;
|
||||
+ union {
|
||||
+ struct {
|
||||
+ __u8 num_ext;
|
||||
+ __le16 checksum;
|
||||
+ __le16 attr;
|
||||
+ __le16 reserved1;
|
||||
+ __le16 create_time;
|
||||
+ __le16 create_date;
|
||||
+ __le16 modify_time;
|
||||
+ __le16 modify_date;
|
||||
+ __le16 access_time;
|
||||
+ __le16 access_date;
|
||||
+ __u8 create_time_ms;
|
||||
+ __u8 modify_time_ms;
|
||||
+ __u8 create_tz;
|
||||
+ __u8 modify_tz;
|
||||
+ __u8 access_tz;
|
||||
+ __u8 reserved2[7];
|
||||
+ } __packed file; /* file directory entry */
|
||||
+ struct {
|
||||
+ __u8 flags;
|
||||
+ __u8 reserved1;
|
||||
+ __u8 name_len;
|
||||
+ __le16 name_hash;
|
||||
+ __le16 reserved2;
|
||||
+ __le64 valid_size;
|
||||
+ __le32 reserved3;
|
||||
+ __le32 start_clu;
|
||||
+ __le64 size;
|
||||
+ } __packed stream; /* stream extension directory entry */
|
||||
+ struct {
|
||||
+ __u8 flags;
|
||||
+ __le16 unicode_0_14[EXFAT_FILE_NAME_LEN];
|
||||
+ } __packed name; /* file name directory entry */
|
||||
+ struct {
|
||||
+ __u8 flags;
|
||||
+ __u8 reserved[18];
|
||||
+ __le32 start_clu;
|
||||
+ __le64 size;
|
||||
+ } __packed bitmap; /* allocation bitmap directory entry */
|
||||
+ struct {
|
||||
+ __u8 reserved1[3];
|
||||
+ __le32 checksum;
|
||||
+ __u8 reserved2[12];
|
||||
+ __le32 start_clu;
|
||||
+ __le64 size;
|
||||
+ } __packed upcase; /* up-case table directory entry */
|
||||
+ } __packed dentry;
|
||||
+} __packed;
|
||||
+
|
||||
+#define EXFAT_TZ_VALID (1 << 7)
|
||||
+
|
||||
+/* Jan 1 GMT 00:00:00 1980 */
|
||||
+#define EXFAT_MIN_TIMESTAMP_SECS 315532800LL
|
||||
+/* Dec 31 GMT 23:59:59 2107 */
|
||||
+#define EXFAT_MAX_TIMESTAMP_SECS 4354819199LL
|
||||
+
|
||||
+#endif /* !_EXFAT_RAW_H */
|
||||
--
|
||||
2.25.1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,193 @@
|
||||
From 772b29cca528fcb21374bb3e597d848779938d16 Mon Sep 17 00:00:00 2001
|
||||
From: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Date: Mon, 2 Mar 2020 15:21:40 +0900
|
||||
Subject: [PATCH 09/14] exfat: add misc operations
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This adds the implementation of misc operations for exfat.
|
||||
|
||||
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
|
||||
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
|
||||
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
|
||||
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
||||
---
|
||||
fs/exfat/misc.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 163 insertions(+)
|
||||
create mode 100644 fs/exfat/misc.c
|
||||
|
||||
diff --git a/fs/exfat/misc.c b/fs/exfat/misc.c
|
||||
new file mode 100644
|
||||
index 000000000000..14a3300848f6
|
||||
--- /dev/null
|
||||
+++ b/fs/exfat/misc.c
|
||||
@@ -0,0 +1,163 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+/*
|
||||
+ * Written 1992,1993 by Werner Almesberger
|
||||
+ * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980
|
||||
+ * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru)
|
||||
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/time.h>
|
||||
+#include <linux/fs.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/buffer_head.h>
|
||||
+
|
||||
+#include "exfat_raw.h"
|
||||
+#include "exfat_fs.h"
|
||||
+
|
||||
+/*
|
||||
+ * exfat_fs_error reports a file system problem that might indicate fa data
|
||||
+ * corruption/inconsistency. Depending on 'errors' mount option the
|
||||
+ * panic() is called, or error message is printed FAT and nothing is done,
|
||||
+ * or filesystem is remounted read-only (default behavior).
|
||||
+ * In case the file system is remounted read-only, it can be made writable
|
||||
+ * again by remounting it.
|
||||
+ */
|
||||
+void __exfat_fs_error(struct super_block *sb, int report, const char *fmt, ...)
|
||||
+{
|
||||
+ struct exfat_mount_options *opts = &EXFAT_SB(sb)->options;
|
||||
+ va_list args;
|
||||
+ struct va_format vaf;
|
||||
+
|
||||
+ if (report) {
|
||||
+ va_start(args, fmt);
|
||||
+ vaf.fmt = fmt;
|
||||
+ vaf.va = &args;
|
||||
+ exfat_msg(sb, KERN_ERR, "error, %pV\n", &vaf);
|
||||
+ va_end(args);
|
||||
+ }
|
||||
+
|
||||
+ if (opts->errors == EXFAT_ERRORS_PANIC) {
|
||||
+ panic("exFAT-fs (%s): fs panic from previous error\n",
|
||||
+ sb->s_id);
|
||||
+ } else if (opts->errors == EXFAT_ERRORS_RO && !sb_rdonly(sb)) {
|
||||
+ sb->s_flags |= SB_RDONLY;
|
||||
+ exfat_msg(sb, KERN_ERR, "Filesystem has been set read-only");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * exfat_msg() - print preformated EXFAT specific messages.
|
||||
+ * All logs except what uses exfat_fs_error() should be written by exfat_msg()
|
||||
+ */
|
||||
+void exfat_msg(struct super_block *sb, const char *level, const char *fmt, ...)
|
||||
+{
|
||||
+ struct va_format vaf;
|
||||
+ va_list args;
|
||||
+
|
||||
+ va_start(args, fmt);
|
||||
+ vaf.fmt = fmt;
|
||||
+ vaf.va = &args;
|
||||
+ /* level means KERN_ pacility level */
|
||||
+ printk("%sexFAT-fs (%s): %pV\n", level, sb->s_id, &vaf);
|
||||
+ va_end(args);
|
||||
+}
|
||||
+
|
||||
+#define SECS_PER_MIN (60)
|
||||
+#define TIMEZONE_SEC(x) ((x) * 15 * SECS_PER_MIN)
|
||||
+
|
||||
+static void exfat_adjust_tz(struct timespec64 *ts, u8 tz_off)
|
||||
+{
|
||||
+ if (tz_off <= 0x3F)
|
||||
+ ts->tv_sec -= TIMEZONE_SEC(tz_off);
|
||||
+ else /* 0x40 <= (tz_off & 0x7F) <=0x7F */
|
||||
+ ts->tv_sec += TIMEZONE_SEC(0x80 - tz_off);
|
||||
+}
|
||||
+
|
||||
+/* Convert a EXFAT time/date pair to a UNIX date (seconds since 1 1 70). */
|
||||
+void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
|
||||
+ u8 tz, __le16 time, __le16 date, u8 time_ms)
|
||||
+{
|
||||
+ u16 t = le16_to_cpu(time);
|
||||
+ u16 d = le16_to_cpu(date);
|
||||
+
|
||||
+ ts->tv_sec = mktime64(1980 + (d >> 9), d >> 5 & 0x000F, d & 0x001F,
|
||||
+ t >> 11, (t >> 5) & 0x003F, (t & 0x001F) << 1);
|
||||
+
|
||||
+
|
||||
+ /* time_ms field represent 0 ~ 199(1990 ms) */
|
||||
+ if (time_ms) {
|
||||
+ ts->tv_sec += time_ms / 100;
|
||||
+ ts->tv_nsec = (time_ms % 100) * 10 * NSEC_PER_MSEC;
|
||||
+ }
|
||||
+
|
||||
+ if (tz & EXFAT_TZ_VALID)
|
||||
+ /* Adjust timezone to UTC0. */
|
||||
+ exfat_adjust_tz(ts, tz & ~EXFAT_TZ_VALID);
|
||||
+ else
|
||||
+ /* Convert from local time to UTC using time_offset. */
|
||||
+ ts->tv_sec -= sbi->options.time_offset * SECS_PER_MIN;
|
||||
+}
|
||||
+
|
||||
+/* Convert linear UNIX date to a EXFAT time/date pair. */
|
||||
+void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
|
||||
+ u8 *tz, __le16 *time, __le16 *date, u8 *time_ms)
|
||||
+{
|
||||
+ struct tm tm;
|
||||
+ u16 t, d;
|
||||
+
|
||||
+ time64_to_tm(ts->tv_sec, 0, &tm);
|
||||
+ t = (tm.tm_hour << 11) | (tm.tm_min << 5) | (tm.tm_sec >> 1);
|
||||
+ d = ((tm.tm_year - 80) << 9) | ((tm.tm_mon + 1) << 5) | tm.tm_mday;
|
||||
+
|
||||
+ *time = cpu_to_le16(t);
|
||||
+ *date = cpu_to_le16(d);
|
||||
+
|
||||
+ /* time_ms field represent 0 ~ 199(1990 ms) */
|
||||
+ if (time_ms)
|
||||
+ *time_ms = (tm.tm_sec & 1) * 100 +
|
||||
+ ts->tv_nsec / (10 * NSEC_PER_MSEC);
|
||||
+
|
||||
+ /*
|
||||
+ * Record 00h value for OffsetFromUtc field and 1 value for OffsetValid
|
||||
+ * to indicate that local time and UTC are the same.
|
||||
+ */
|
||||
+ *tz = EXFAT_TZ_VALID;
|
||||
+}
|
||||
+
|
||||
+unsigned short exfat_calc_chksum_2byte(void *data, int len,
|
||||
+ unsigned short chksum, int type)
|
||||
+{
|
||||
+ int i;
|
||||
+ unsigned char *c = (unsigned char *)data;
|
||||
+
|
||||
+ for (i = 0; i < len; i++, c++) {
|
||||
+ if (((i == 2) || (i == 3)) && (type == CS_DIR_ENTRY))
|
||||
+ continue;
|
||||
+ chksum = (((chksum & 1) << 15) | ((chksum & 0xFFFE) >> 1)) +
|
||||
+ (unsigned short)*c;
|
||||
+ }
|
||||
+ return chksum;
|
||||
+}
|
||||
+
|
||||
+void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int sync)
|
||||
+{
|
||||
+ set_bit(EXFAT_SB_DIRTY, &EXFAT_SB(sb)->s_state);
|
||||
+ set_buffer_uptodate(bh);
|
||||
+ mark_buffer_dirty(bh);
|
||||
+
|
||||
+ if (sync)
|
||||
+ sync_dirty_buffer(bh);
|
||||
+}
|
||||
+
|
||||
+void exfat_chain_set(struct exfat_chain *ec, unsigned int dir,
|
||||
+ unsigned int size, unsigned char flags)
|
||||
+{
|
||||
+ ec->dir = dir;
|
||||
+ ec->size = size;
|
||||
+ ec->flags = flags;
|
||||
+}
|
||||
+
|
||||
+void exfat_chain_dup(struct exfat_chain *dup, struct exfat_chain *ec)
|
||||
+{
|
||||
+ return exfat_chain_set(dup, ec->dir, ec->size, ec->flags);
|
||||
+}
|
||||
--
|
||||
2.25.1
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
From c37f83b424911f9bb6c9f17a4543c9c77cd73282 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Backlund <tmb@mageia.org>
|
||||
Date: Sat, 4 Apr 2020 23:00:31 +0300
|
||||
Subject: [PATCH v2] exfat: add missing MODULE_ALIAS_FS()
|
||||
|
||||
This adds the necessary MODULE_ALIAS_FS() to exfat so the module gets
|
||||
automatically loaded when an exfat filesystem is mounted.
|
||||
|
||||
Signed-off-by: Thomas Backlund <tmb@mageia.org>
|
||||
Cc: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Cc: Sungjong Seo <sj1557.seo@samsung.com>
|
||||
---
|
||||
fs/exfat/super.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/fs/exfat/super.c b/fs/exfat/super.c
|
||||
index 16ed202ef527..b4a4063a0272 100644
|
||||
--- a/fs/exfat/super.c
|
||||
+++ b/fs/exfat/super.c
|
||||
@@ -717,6 +717,7 @@ static void __exit exit_exfat_fs(void)
|
||||
module_init(init_exfat_fs);
|
||||
module_exit(exit_exfat_fs);
|
||||
|
||||
+MODULE_ALIAS_FS("exfat");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("exFAT filesystem support");
|
||||
MODULE_AUTHOR("Samsung Electronics Co., Ltd.");
|
||||
--
|
||||
2.26.0
|
||||
|
||||
@@ -0,0 +1,860 @@
|
||||
From 370e812b3ec190fa492c9fd5a80c38b086d105c0 Mon Sep 17 00:00:00 2001
|
||||
From: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Date: Mon, 2 Mar 2020 15:21:41 +0900
|
||||
Subject: [PATCH 10/14] exfat: add nls operations
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This adds the implementation of nls operations for exfat.
|
||||
|
||||
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
|
||||
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
|
||||
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
||||
---
|
||||
fs/exfat/nls.c | 831 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 831 insertions(+)
|
||||
create mode 100644 fs/exfat/nls.c
|
||||
|
||||
diff --git a/fs/exfat/nls.c b/fs/exfat/nls.c
|
||||
new file mode 100644
|
||||
index 000000000000..6d1c3ae130ff
|
||||
--- /dev/null
|
||||
+++ b/fs/exfat/nls.c
|
||||
@@ -0,0 +1,831 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+/*
|
||||
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/string.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/buffer_head.h>
|
||||
+#include <asm/unaligned.h>
|
||||
+
|
||||
+#include "exfat_raw.h"
|
||||
+#include "exfat_fs.h"
|
||||
+
|
||||
+/* Upcase tabel macro */
|
||||
+#define EXFAT_NUM_UPCASE (2918)
|
||||
+#define UTBL_COUNT (0x10000)
|
||||
+
|
||||
+/*
|
||||
+ * Upcase table in compressed format (7.2.5.1 Recommended Up-case Table
|
||||
+ * in exfat specification, See:
|
||||
+ * https://docs.microsoft.com/en-us/windows/win32/fileio/exfat-specification).
|
||||
+ */
|
||||
+static const unsigned short uni_def_upcase[EXFAT_NUM_UPCASE] = {
|
||||
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
||||
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
|
||||
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
+ 0x0060, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
+ 0x0058, 0x0059, 0x005a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
|
||||
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
|
||||
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
+ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
|
||||
+ 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
+ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
|
||||
+ 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
+ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
|
||||
+ 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
+ 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
|
||||
+ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
|
||||
+ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
|
||||
+ 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
+ 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00f7,
|
||||
+ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x0178,
|
||||
+ 0x0100, 0x0100, 0x0102, 0x0102, 0x0104, 0x0104, 0x0106, 0x0106,
|
||||
+ 0x0108, 0x0108, 0x010a, 0x010a, 0x010c, 0x010c, 0x010e, 0x010e,
|
||||
+ 0x0110, 0x0110, 0x0112, 0x0112, 0x0114, 0x0114, 0x0116, 0x0116,
|
||||
+ 0x0118, 0x0118, 0x011a, 0x011a, 0x011c, 0x011c, 0x011e, 0x011e,
|
||||
+ 0x0120, 0x0120, 0x0122, 0x0122, 0x0124, 0x0124, 0x0126, 0x0126,
|
||||
+ 0x0128, 0x0128, 0x012a, 0x012a, 0x012c, 0x012c, 0x012e, 0x012e,
|
||||
+ 0x0130, 0x0131, 0x0132, 0x0132, 0x0134, 0x0134, 0x0136, 0x0136,
|
||||
+ 0x0138, 0x0139, 0x0139, 0x013b, 0x013b, 0x013d, 0x013d, 0x013f,
|
||||
+ 0x013f, 0x0141, 0x0141, 0x0143, 0x0143, 0x0145, 0x0145, 0x0147,
|
||||
+ 0x0147, 0x0149, 0x014a, 0x014a, 0x014c, 0x014c, 0x014e, 0x014e,
|
||||
+ 0x0150, 0x0150, 0x0152, 0x0152, 0x0154, 0x0154, 0x0156, 0x0156,
|
||||
+ 0x0158, 0x0158, 0x015a, 0x015a, 0x015c, 0x015c, 0x015e, 0x015e,
|
||||
+ 0x0160, 0x0160, 0x0162, 0x0162, 0x0164, 0x0164, 0x0166, 0x0166,
|
||||
+ 0x0168, 0x0168, 0x016a, 0x016a, 0x016c, 0x016c, 0x016e, 0x016e,
|
||||
+ 0x0170, 0x0170, 0x0172, 0x0172, 0x0174, 0x0174, 0x0176, 0x0176,
|
||||
+ 0x0178, 0x0179, 0x0179, 0x017b, 0x017b, 0x017d, 0x017d, 0x017f,
|
||||
+ 0x0243, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187,
|
||||
+ 0x0187, 0x0189, 0x018a, 0x018b, 0x018b, 0x018d, 0x018e, 0x018f,
|
||||
+ 0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01f6, 0x0196, 0x0197,
|
||||
+ 0x0198, 0x0198, 0x023d, 0x019b, 0x019c, 0x019d, 0x0220, 0x019f,
|
||||
+ 0x01a0, 0x01a0, 0x01a2, 0x01a2, 0x01a4, 0x01a4, 0x01a6, 0x01a7,
|
||||
+ 0x01a7, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ac, 0x01ae, 0x01af,
|
||||
+ 0x01af, 0x01b1, 0x01b2, 0x01b3, 0x01b3, 0x01b5, 0x01b5, 0x01b7,
|
||||
+ 0x01b8, 0x01b8, 0x01ba, 0x01bb, 0x01bc, 0x01bc, 0x01be, 0x01f7,
|
||||
+ 0x01c0, 0x01c1, 0x01c2, 0x01c3, 0x01c4, 0x01c5, 0x01c4, 0x01c7,
|
||||
+ 0x01c8, 0x01c7, 0x01ca, 0x01cb, 0x01ca, 0x01cd, 0x01cd, 0x01cf,
|
||||
+ 0x01cf, 0x01d1, 0x01d1, 0x01d3, 0x01d3, 0x01d5, 0x01d5, 0x01d7,
|
||||
+ 0x01d7, 0x01d9, 0x01d9, 0x01db, 0x01db, 0x018e, 0x01de, 0x01de,
|
||||
+ 0x01e0, 0x01e0, 0x01e2, 0x01e2, 0x01e4, 0x01e4, 0x01e6, 0x01e6,
|
||||
+ 0x01e8, 0x01e8, 0x01ea, 0x01ea, 0x01ec, 0x01ec, 0x01ee, 0x01ee,
|
||||
+ 0x01f0, 0x01f1, 0x01f2, 0x01f1, 0x01f4, 0x01f4, 0x01f6, 0x01f7,
|
||||
+ 0x01f8, 0x01f8, 0x01fa, 0x01fa, 0x01fc, 0x01fc, 0x01fe, 0x01fe,
|
||||
+ 0x0200, 0x0200, 0x0202, 0x0202, 0x0204, 0x0204, 0x0206, 0x0206,
|
||||
+ 0x0208, 0x0208, 0x020a, 0x020a, 0x020c, 0x020c, 0x020e, 0x020e,
|
||||
+ 0x0210, 0x0210, 0x0212, 0x0212, 0x0214, 0x0214, 0x0216, 0x0216,
|
||||
+ 0x0218, 0x0218, 0x021a, 0x021a, 0x021c, 0x021c, 0x021e, 0x021e,
|
||||
+ 0x0220, 0x0221, 0x0222, 0x0222, 0x0224, 0x0224, 0x0226, 0x0226,
|
||||
+ 0x0228, 0x0228, 0x022a, 0x022a, 0x022c, 0x022c, 0x022e, 0x022e,
|
||||
+ 0x0230, 0x0230, 0x0232, 0x0232, 0x0234, 0x0235, 0x0236, 0x0237,
|
||||
+ 0x0238, 0x0239, 0x2c65, 0x023b, 0x023b, 0x023d, 0x2c66, 0x023f,
|
||||
+ 0x0240, 0x0241, 0x0241, 0x0243, 0x0244, 0x0245, 0x0246, 0x0246,
|
||||
+ 0x0248, 0x0248, 0x024a, 0x024a, 0x024c, 0x024c, 0x024e, 0x024e,
|
||||
+ 0x0250, 0x0251, 0x0252, 0x0181, 0x0186, 0x0255, 0x0189, 0x018a,
|
||||
+ 0x0258, 0x018f, 0x025a, 0x0190, 0x025c, 0x025d, 0x025e, 0x025f,
|
||||
+ 0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267,
|
||||
+ 0x0197, 0x0196, 0x026a, 0x2c62, 0x026c, 0x026d, 0x026e, 0x019c,
|
||||
+ 0x0270, 0x0271, 0x019d, 0x0273, 0x0274, 0x019f, 0x0276, 0x0277,
|
||||
+ 0x0278, 0x0279, 0x027a, 0x027b, 0x027c, 0x2c64, 0x027e, 0x027f,
|
||||
+ 0x01a6, 0x0281, 0x0282, 0x01a9, 0x0284, 0x0285, 0x0286, 0x0287,
|
||||
+ 0x01ae, 0x0244, 0x01b1, 0x01b2, 0x0245, 0x028d, 0x028e, 0x028f,
|
||||
+ 0x0290, 0x0291, 0x01b7, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297,
|
||||
+ 0x0298, 0x0299, 0x029a, 0x029b, 0x029c, 0x029d, 0x029e, 0x029f,
|
||||
+ 0x02a0, 0x02a1, 0x02a2, 0x02a3, 0x02a4, 0x02a5, 0x02a6, 0x02a7,
|
||||
+ 0x02a8, 0x02a9, 0x02aa, 0x02ab, 0x02ac, 0x02ad, 0x02ae, 0x02af,
|
||||
+ 0x02b0, 0x02b1, 0x02b2, 0x02b3, 0x02b4, 0x02b5, 0x02b6, 0x02b7,
|
||||
+ 0x02b8, 0x02b9, 0x02ba, 0x02bb, 0x02bc, 0x02bd, 0x02be, 0x02bf,
|
||||
+ 0x02c0, 0x02c1, 0x02c2, 0x02c3, 0x02c4, 0x02c5, 0x02c6, 0x02c7,
|
||||
+ 0x02c8, 0x02c9, 0x02ca, 0x02cb, 0x02cc, 0x02cd, 0x02ce, 0x02cf,
|
||||
+ 0x02d0, 0x02d1, 0x02d2, 0x02d3, 0x02d4, 0x02d5, 0x02d6, 0x02d7,
|
||||
+ 0x02d8, 0x02d9, 0x02da, 0x02db, 0x02dc, 0x02dd, 0x02de, 0x02df,
|
||||
+ 0x02e0, 0x02e1, 0x02e2, 0x02e3, 0x02e4, 0x02e5, 0x02e6, 0x02e7,
|
||||
+ 0x02e8, 0x02e9, 0x02ea, 0x02eb, 0x02ec, 0x02ed, 0x02ee, 0x02ef,
|
||||
+ 0x02f0, 0x02f1, 0x02f2, 0x02f3, 0x02f4, 0x02f5, 0x02f6, 0x02f7,
|
||||
+ 0x02f8, 0x02f9, 0x02fa, 0x02fb, 0x02fc, 0x02fd, 0x02fe, 0x02ff,
|
||||
+ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
|
||||
+ 0x0308, 0x0309, 0x030a, 0x030b, 0x030c, 0x030d, 0x030e, 0x030f,
|
||||
+ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
|
||||
+ 0x0318, 0x0319, 0x031a, 0x031b, 0x031c, 0x031d, 0x031e, 0x031f,
|
||||
+ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327,
|
||||
+ 0x0328, 0x0329, 0x032a, 0x032b, 0x032c, 0x032d, 0x032e, 0x032f,
|
||||
+ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337,
|
||||
+ 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, 0x033d, 0x033e, 0x033f,
|
||||
+ 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347,
|
||||
+ 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, 0x034d, 0x034e, 0x034f,
|
||||
+ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357,
|
||||
+ 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, 0x035d, 0x035e, 0x035f,
|
||||
+ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
|
||||
+ 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f,
|
||||
+ 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377,
|
||||
+ 0x0378, 0x0379, 0x037a, 0x03fd, 0x03fe, 0x03ff, 0x037e, 0x037f,
|
||||
+ 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387,
|
||||
+ 0x0388, 0x0389, 0x038a, 0x038b, 0x038c, 0x038d, 0x038e, 0x038f,
|
||||
+ 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
|
||||
+ 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
|
||||
+ 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
|
||||
+ 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x0386, 0x0388, 0x0389, 0x038a,
|
||||
+ 0x03b0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
|
||||
+ 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
|
||||
+ 0x03a0, 0x03a1, 0x03a3, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
|
||||
+ 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x038c, 0x038e, 0x038f, 0x03cf,
|
||||
+ 0x03d0, 0x03d1, 0x03d2, 0x03d3, 0x03d4, 0x03d5, 0x03d6, 0x03d7,
|
||||
+ 0x03d8, 0x03d8, 0x03da, 0x03da, 0x03dc, 0x03dc, 0x03de, 0x03de,
|
||||
+ 0x03e0, 0x03e0, 0x03e2, 0x03e2, 0x03e4, 0x03e4, 0x03e6, 0x03e6,
|
||||
+ 0x03e8, 0x03e8, 0x03ea, 0x03ea, 0x03ec, 0x03ec, 0x03ee, 0x03ee,
|
||||
+ 0x03f0, 0x03f1, 0x03f9, 0x03f3, 0x03f4, 0x03f5, 0x03f6, 0x03f7,
|
||||
+ 0x03f7, 0x03f9, 0x03fa, 0x03fa, 0x03fc, 0x03fd, 0x03fe, 0x03ff,
|
||||
+ 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
|
||||
+ 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x040d, 0x040e, 0x040f,
|
||||
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
|
||||
+ 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
|
||||
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
|
||||
+ 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
|
||||
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
|
||||
+ 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
|
||||
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
|
||||
+ 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
|
||||
+ 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
|
||||
+ 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x040d, 0x040e, 0x040f,
|
||||
+ 0x0460, 0x0460, 0x0462, 0x0462, 0x0464, 0x0464, 0x0466, 0x0466,
|
||||
+ 0x0468, 0x0468, 0x046a, 0x046a, 0x046c, 0x046c, 0x046e, 0x046e,
|
||||
+ 0x0470, 0x0470, 0x0472, 0x0472, 0x0474, 0x0474, 0x0476, 0x0476,
|
||||
+ 0x0478, 0x0478, 0x047a, 0x047a, 0x047c, 0x047c, 0x047e, 0x047e,
|
||||
+ 0x0480, 0x0480, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,
|
||||
+ 0x0488, 0x0489, 0x048a, 0x048a, 0x048c, 0x048c, 0x048e, 0x048e,
|
||||
+ 0x0490, 0x0490, 0x0492, 0x0492, 0x0494, 0x0494, 0x0496, 0x0496,
|
||||
+ 0x0498, 0x0498, 0x049a, 0x049a, 0x049c, 0x049c, 0x049e, 0x049e,
|
||||
+ 0x04a0, 0x04a0, 0x04a2, 0x04a2, 0x04a4, 0x04a4, 0x04a6, 0x04a6,
|
||||
+ 0x04a8, 0x04a8, 0x04aa, 0x04aa, 0x04ac, 0x04ac, 0x04ae, 0x04ae,
|
||||
+ 0x04b0, 0x04b0, 0x04b2, 0x04b2, 0x04b4, 0x04b4, 0x04b6, 0x04b6,
|
||||
+ 0x04b8, 0x04b8, 0x04ba, 0x04ba, 0x04bc, 0x04bc, 0x04be, 0x04be,
|
||||
+ 0x04c0, 0x04c1, 0x04c1, 0x04c3, 0x04c3, 0x04c5, 0x04c5, 0x04c7,
|
||||
+ 0x04c7, 0x04c9, 0x04c9, 0x04cb, 0x04cb, 0x04cd, 0x04cd, 0x04c0,
|
||||
+ 0x04d0, 0x04d0, 0x04d2, 0x04d2, 0x04d4, 0x04d4, 0x04d6, 0x04d6,
|
||||
+ 0x04d8, 0x04d8, 0x04da, 0x04da, 0x04dc, 0x04dc, 0x04de, 0x04de,
|
||||
+ 0x04e0, 0x04e0, 0x04e2, 0x04e2, 0x04e4, 0x04e4, 0x04e6, 0x04e6,
|
||||
+ 0x04e8, 0x04e8, 0x04ea, 0x04ea, 0x04ec, 0x04ec, 0x04ee, 0x04ee,
|
||||
+ 0x04f0, 0x04f0, 0x04f2, 0x04f2, 0x04f4, 0x04f4, 0x04f6, 0x04f6,
|
||||
+ 0x04f8, 0x04f8, 0x04fa, 0x04fa, 0x04fc, 0x04fc, 0x04fe, 0x04fe,
|
||||
+ 0x0500, 0x0500, 0x0502, 0x0502, 0x0504, 0x0504, 0x0506, 0x0506,
|
||||
+ 0x0508, 0x0508, 0x050a, 0x050a, 0x050c, 0x050c, 0x050e, 0x050e,
|
||||
+ 0x0510, 0x0510, 0x0512, 0x0512, 0x0514, 0x0515, 0x0516, 0x0517,
|
||||
+ 0x0518, 0x0519, 0x051a, 0x051b, 0x051c, 0x051d, 0x051e, 0x051f,
|
||||
+ 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527,
|
||||
+ 0x0528, 0x0529, 0x052a, 0x052b, 0x052c, 0x052d, 0x052e, 0x052f,
|
||||
+ 0x0530, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537,
|
||||
+ 0x0538, 0x0539, 0x053a, 0x053b, 0x053c, 0x053d, 0x053e, 0x053f,
|
||||
+ 0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547,
|
||||
+ 0x0548, 0x0549, 0x054a, 0x054b, 0x054c, 0x054d, 0x054e, 0x054f,
|
||||
+ 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0557,
|
||||
+ 0x0558, 0x0559, 0x055a, 0x055b, 0x055c, 0x055d, 0x055e, 0x055f,
|
||||
+ 0x0560, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537,
|
||||
+ 0x0538, 0x0539, 0x053a, 0x053b, 0x053c, 0x053d, 0x053e, 0x053f,
|
||||
+ 0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547,
|
||||
+ 0x0548, 0x0549, 0x054a, 0x054b, 0x054c, 0x054d, 0x054e, 0x054f,
|
||||
+ 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0xffff,
|
||||
+ 0x17f6, 0x2c63, 0x1d7e, 0x1d7f, 0x1d80, 0x1d81, 0x1d82, 0x1d83,
|
||||
+ 0x1d84, 0x1d85, 0x1d86, 0x1d87, 0x1d88, 0x1d89, 0x1d8a, 0x1d8b,
|
||||
+ 0x1d8c, 0x1d8d, 0x1d8e, 0x1d8f, 0x1d90, 0x1d91, 0x1d92, 0x1d93,
|
||||
+ 0x1d94, 0x1d95, 0x1d96, 0x1d97, 0x1d98, 0x1d99, 0x1d9a, 0x1d9b,
|
||||
+ 0x1d9c, 0x1d9d, 0x1d9e, 0x1d9f, 0x1da0, 0x1da1, 0x1da2, 0x1da3,
|
||||
+ 0x1da4, 0x1da5, 0x1da6, 0x1da7, 0x1da8, 0x1da9, 0x1daa, 0x1dab,
|
||||
+ 0x1dac, 0x1dad, 0x1dae, 0x1daf, 0x1db0, 0x1db1, 0x1db2, 0x1db3,
|
||||
+ 0x1db4, 0x1db5, 0x1db6, 0x1db7, 0x1db8, 0x1db9, 0x1dba, 0x1dbb,
|
||||
+ 0x1dbc, 0x1dbd, 0x1dbe, 0x1dbf, 0x1dc0, 0x1dc1, 0x1dc2, 0x1dc3,
|
||||
+ 0x1dc4, 0x1dc5, 0x1dc6, 0x1dc7, 0x1dc8, 0x1dc9, 0x1dca, 0x1dcb,
|
||||
+ 0x1dcc, 0x1dcd, 0x1dce, 0x1dcf, 0x1dd0, 0x1dd1, 0x1dd2, 0x1dd3,
|
||||
+ 0x1dd4, 0x1dd5, 0x1dd6, 0x1dd7, 0x1dd8, 0x1dd9, 0x1dda, 0x1ddb,
|
||||
+ 0x1ddc, 0x1ddd, 0x1dde, 0x1ddf, 0x1de0, 0x1de1, 0x1de2, 0x1de3,
|
||||
+ 0x1de4, 0x1de5, 0x1de6, 0x1de7, 0x1de8, 0x1de9, 0x1dea, 0x1deb,
|
||||
+ 0x1dec, 0x1ded, 0x1dee, 0x1def, 0x1df0, 0x1df1, 0x1df2, 0x1df3,
|
||||
+ 0x1df4, 0x1df5, 0x1df6, 0x1df7, 0x1df8, 0x1df9, 0x1dfa, 0x1dfb,
|
||||
+ 0x1dfc, 0x1dfd, 0x1dfe, 0x1dff, 0x1e00, 0x1e00, 0x1e02, 0x1e02,
|
||||
+ 0x1e04, 0x1e04, 0x1e06, 0x1e06, 0x1e08, 0x1e08, 0x1e0a, 0x1e0a,
|
||||
+ 0x1e0c, 0x1e0c, 0x1e0e, 0x1e0e, 0x1e10, 0x1e10, 0x1e12, 0x1e12,
|
||||
+ 0x1e14, 0x1e14, 0x1e16, 0x1e16, 0x1e18, 0x1e18, 0x1e1a, 0x1e1a,
|
||||
+ 0x1e1c, 0x1e1c, 0x1e1e, 0x1e1e, 0x1e20, 0x1e20, 0x1e22, 0x1e22,
|
||||
+ 0x1e24, 0x1e24, 0x1e26, 0x1e26, 0x1e28, 0x1e28, 0x1e2a, 0x1e2a,
|
||||
+ 0x1e2c, 0x1e2c, 0x1e2e, 0x1e2e, 0x1e30, 0x1e30, 0x1e32, 0x1e32,
|
||||
+ 0x1e34, 0x1e34, 0x1e36, 0x1e36, 0x1e38, 0x1e38, 0x1e3a, 0x1e3a,
|
||||
+ 0x1e3c, 0x1e3c, 0x1e3e, 0x1e3e, 0x1e40, 0x1e40, 0x1e42, 0x1e42,
|
||||
+ 0x1e44, 0x1e44, 0x1e46, 0x1e46, 0x1e48, 0x1e48, 0x1e4a, 0x1e4a,
|
||||
+ 0x1e4c, 0x1e4c, 0x1e4e, 0x1e4e, 0x1e50, 0x1e50, 0x1e52, 0x1e52,
|
||||
+ 0x1e54, 0x1e54, 0x1e56, 0x1e56, 0x1e58, 0x1e58, 0x1e5a, 0x1e5a,
|
||||
+ 0x1e5c, 0x1e5c, 0x1e5e, 0x1e5e, 0x1e60, 0x1e60, 0x1e62, 0x1e62,
|
||||
+ 0x1e64, 0x1e64, 0x1e66, 0x1e66, 0x1e68, 0x1e68, 0x1e6a, 0x1e6a,
|
||||
+ 0x1e6c, 0x1e6c, 0x1e6e, 0x1e6e, 0x1e70, 0x1e70, 0x1e72, 0x1e72,
|
||||
+ 0x1e74, 0x1e74, 0x1e76, 0x1e76, 0x1e78, 0x1e78, 0x1e7a, 0x1e7a,
|
||||
+ 0x1e7c, 0x1e7c, 0x1e7e, 0x1e7e, 0x1e80, 0x1e80, 0x1e82, 0x1e82,
|
||||
+ 0x1e84, 0x1e84, 0x1e86, 0x1e86, 0x1e88, 0x1e88, 0x1e8a, 0x1e8a,
|
||||
+ 0x1e8c, 0x1e8c, 0x1e8e, 0x1e8e, 0x1e90, 0x1e90, 0x1e92, 0x1e92,
|
||||
+ 0x1e94, 0x1e94, 0x1e96, 0x1e97, 0x1e98, 0x1e99, 0x1e9a, 0x1e9b,
|
||||
+ 0x1e9c, 0x1e9d, 0x1e9e, 0x1e9f, 0x1ea0, 0x1ea0, 0x1ea2, 0x1ea2,
|
||||
+ 0x1ea4, 0x1ea4, 0x1ea6, 0x1ea6, 0x1ea8, 0x1ea8, 0x1eaa, 0x1eaa,
|
||||
+ 0x1eac, 0x1eac, 0x1eae, 0x1eae, 0x1eb0, 0x1eb0, 0x1eb2, 0x1eb2,
|
||||
+ 0x1eb4, 0x1eb4, 0x1eb6, 0x1eb6, 0x1eb8, 0x1eb8, 0x1eba, 0x1eba,
|
||||
+ 0x1ebc, 0x1ebc, 0x1ebe, 0x1ebe, 0x1ec0, 0x1ec0, 0x1ec2, 0x1ec2,
|
||||
+ 0x1ec4, 0x1ec4, 0x1ec6, 0x1ec6, 0x1ec8, 0x1ec8, 0x1eca, 0x1eca,
|
||||
+ 0x1ecc, 0x1ecc, 0x1ece, 0x1ece, 0x1ed0, 0x1ed0, 0x1ed2, 0x1ed2,
|
||||
+ 0x1ed4, 0x1ed4, 0x1ed6, 0x1ed6, 0x1ed8, 0x1ed8, 0x1eda, 0x1eda,
|
||||
+ 0x1edc, 0x1edc, 0x1ede, 0x1ede, 0x1ee0, 0x1ee0, 0x1ee2, 0x1ee2,
|
||||
+ 0x1ee4, 0x1ee4, 0x1ee6, 0x1ee6, 0x1ee8, 0x1ee8, 0x1eea, 0x1eea,
|
||||
+ 0x1eec, 0x1eec, 0x1eee, 0x1eee, 0x1ef0, 0x1ef0, 0x1ef2, 0x1ef2,
|
||||
+ 0x1ef4, 0x1ef4, 0x1ef6, 0x1ef6, 0x1ef8, 0x1ef8, 0x1efa, 0x1efb,
|
||||
+ 0x1efc, 0x1efd, 0x1efe, 0x1eff, 0x1f08, 0x1f09, 0x1f0a, 0x1f0b,
|
||||
+ 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f, 0x1f08, 0x1f09, 0x1f0a, 0x1f0b,
|
||||
+ 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f, 0x1f18, 0x1f19, 0x1f1a, 0x1f1b,
|
||||
+ 0x1f1c, 0x1f1d, 0x1f16, 0x1f17, 0x1f18, 0x1f19, 0x1f1a, 0x1f1b,
|
||||
+ 0x1f1c, 0x1f1d, 0x1f1e, 0x1f1f, 0x1f28, 0x1f29, 0x1f2a, 0x1f2b,
|
||||
+ 0x1f2c, 0x1f2d, 0x1f2e, 0x1f2f, 0x1f28, 0x1f29, 0x1f2a, 0x1f2b,
|
||||
+ 0x1f2c, 0x1f2d, 0x1f2e, 0x1f2f, 0x1f38, 0x1f39, 0x1f3a, 0x1f3b,
|
||||
+ 0x1f3c, 0x1f3d, 0x1f3e, 0x1f3f, 0x1f38, 0x1f39, 0x1f3a, 0x1f3b,
|
||||
+ 0x1f3c, 0x1f3d, 0x1f3e, 0x1f3f, 0x1f48, 0x1f49, 0x1f4a, 0x1f4b,
|
||||
+ 0x1f4c, 0x1f4d, 0x1f46, 0x1f47, 0x1f48, 0x1f49, 0x1f4a, 0x1f4b,
|
||||
+ 0x1f4c, 0x1f4d, 0x1f4e, 0x1f4f, 0x1f50, 0x1f59, 0x1f52, 0x1f5b,
|
||||
+ 0x1f54, 0x1f5d, 0x1f56, 0x1f5f, 0x1f58, 0x1f59, 0x1f5a, 0x1f5b,
|
||||
+ 0x1f5c, 0x1f5d, 0x1f5e, 0x1f5f, 0x1f68, 0x1f69, 0x1f6a, 0x1f6b,
|
||||
+ 0x1f6c, 0x1f6d, 0x1f6e, 0x1f6f, 0x1f68, 0x1f69, 0x1f6a, 0x1f6b,
|
||||
+ 0x1f6c, 0x1f6d, 0x1f6e, 0x1f6f, 0x1fba, 0x1fbb, 0x1fc8, 0x1fc9,
|
||||
+ 0x1fca, 0x1fcb, 0x1fda, 0x1fdb, 0x1ff8, 0x1ff9, 0x1fea, 0x1feb,
|
||||
+ 0x1ffa, 0x1ffb, 0x1f7e, 0x1f7f, 0x1f88, 0x1f89, 0x1f8a, 0x1f8b,
|
||||
+ 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f, 0x1f88, 0x1f89, 0x1f8a, 0x1f8b,
|
||||
+ 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f, 0x1f98, 0x1f99, 0x1f9a, 0x1f9b,
|
||||
+ 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, 0x1f98, 0x1f99, 0x1f9a, 0x1f9b,
|
||||
+ 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, 0x1fa8, 0x1fa9, 0x1faa, 0x1fab,
|
||||
+ 0x1fac, 0x1fad, 0x1fae, 0x1faf, 0x1fa8, 0x1fa9, 0x1faa, 0x1fab,
|
||||
+ 0x1fac, 0x1fad, 0x1fae, 0x1faf, 0x1fb8, 0x1fb9, 0x1fb2, 0x1fbc,
|
||||
+ 0x1fb4, 0x1fb5, 0x1fb6, 0x1fb7, 0x1fb8, 0x1fb9, 0x1fba, 0x1fbb,
|
||||
+ 0x1fbc, 0x1fbd, 0x1fbe, 0x1fbf, 0x1fc0, 0x1fc1, 0x1fc2, 0x1fc3,
|
||||
+ 0x1fc4, 0x1fc5, 0x1fc6, 0x1fc7, 0x1fc8, 0x1fc9, 0x1fca, 0x1fcb,
|
||||
+ 0x1fc3, 0x1fcd, 0x1fce, 0x1fcf, 0x1fd8, 0x1fd9, 0x1fd2, 0x1fd3,
|
||||
+ 0x1fd4, 0x1fd5, 0x1fd6, 0x1fd7, 0x1fd8, 0x1fd9, 0x1fda, 0x1fdb,
|
||||
+ 0x1fdc, 0x1fdd, 0x1fde, 0x1fdf, 0x1fe8, 0x1fe9, 0x1fe2, 0x1fe3,
|
||||
+ 0x1fe4, 0x1fec, 0x1fe6, 0x1fe7, 0x1fe8, 0x1fe9, 0x1fea, 0x1feb,
|
||||
+ 0x1fec, 0x1fed, 0x1fee, 0x1fef, 0x1ff0, 0x1ff1, 0x1ff2, 0x1ff3,
|
||||
+ 0x1ff4, 0x1ff5, 0x1ff6, 0x1ff7, 0x1ff8, 0x1ff9, 0x1ffa, 0x1ffb,
|
||||
+ 0x1ff3, 0x1ffd, 0x1ffe, 0x1fff, 0x2000, 0x2001, 0x2002, 0x2003,
|
||||
+ 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200a, 0x200b,
|
||||
+ 0x200c, 0x200d, 0x200e, 0x200f, 0x2010, 0x2011, 0x2012, 0x2013,
|
||||
+ 0x2014, 0x2015, 0x2016, 0x2017, 0x2018, 0x2019, 0x201a, 0x201b,
|
||||
+ 0x201c, 0x201d, 0x201e, 0x201f, 0x2020, 0x2021, 0x2022, 0x2023,
|
||||
+ 0x2024, 0x2025, 0x2026, 0x2027, 0x2028, 0x2029, 0x202a, 0x202b,
|
||||
+ 0x202c, 0x202d, 0x202e, 0x202f, 0x2030, 0x2031, 0x2032, 0x2033,
|
||||
+ 0x2034, 0x2035, 0x2036, 0x2037, 0x2038, 0x2039, 0x203a, 0x203b,
|
||||
+ 0x203c, 0x203d, 0x203e, 0x203f, 0x2040, 0x2041, 0x2042, 0x2043,
|
||||
+ 0x2044, 0x2045, 0x2046, 0x2047, 0x2048, 0x2049, 0x204a, 0x204b,
|
||||
+ 0x204c, 0x204d, 0x204e, 0x204f, 0x2050, 0x2051, 0x2052, 0x2053,
|
||||
+ 0x2054, 0x2055, 0x2056, 0x2057, 0x2058, 0x2059, 0x205a, 0x205b,
|
||||
+ 0x205c, 0x205d, 0x205e, 0x205f, 0x2060, 0x2061, 0x2062, 0x2063,
|
||||
+ 0x2064, 0x2065, 0x2066, 0x2067, 0x2068, 0x2069, 0x206a, 0x206b,
|
||||
+ 0x206c, 0x206d, 0x206e, 0x206f, 0x2070, 0x2071, 0x2072, 0x2073,
|
||||
+ 0x2074, 0x2075, 0x2076, 0x2077, 0x2078, 0x2079, 0x207a, 0x207b,
|
||||
+ 0x207c, 0x207d, 0x207e, 0x207f, 0x2080, 0x2081, 0x2082, 0x2083,
|
||||
+ 0x2084, 0x2085, 0x2086, 0x2087, 0x2088, 0x2089, 0x208a, 0x208b,
|
||||
+ 0x208c, 0x208d, 0x208e, 0x208f, 0x2090, 0x2091, 0x2092, 0x2093,
|
||||
+ 0x2094, 0x2095, 0x2096, 0x2097, 0x2098, 0x2099, 0x209a, 0x209b,
|
||||
+ 0x209c, 0x209d, 0x209e, 0x209f, 0x20a0, 0x20a1, 0x20a2, 0x20a3,
|
||||
+ 0x20a4, 0x20a5, 0x20a6, 0x20a7, 0x20a8, 0x20a9, 0x20aa, 0x20ab,
|
||||
+ 0x20ac, 0x20ad, 0x20ae, 0x20af, 0x20b0, 0x20b1, 0x20b2, 0x20b3,
|
||||
+ 0x20b4, 0x20b5, 0x20b6, 0x20b7, 0x20b8, 0x20b9, 0x20ba, 0x20bb,
|
||||
+ 0x20bc, 0x20bd, 0x20be, 0x20bf, 0x20c0, 0x20c1, 0x20c2, 0x20c3,
|
||||
+ 0x20c4, 0x20c5, 0x20c6, 0x20c7, 0x20c8, 0x20c9, 0x20ca, 0x20cb,
|
||||
+ 0x20cc, 0x20cd, 0x20ce, 0x20cf, 0x20d0, 0x20d1, 0x20d2, 0x20d3,
|
||||
+ 0x20d4, 0x20d5, 0x20d6, 0x20d7, 0x20d8, 0x20d9, 0x20da, 0x20db,
|
||||
+ 0x20dc, 0x20dd, 0x20de, 0x20df, 0x20e0, 0x20e1, 0x20e2, 0x20e3,
|
||||
+ 0x20e4, 0x20e5, 0x20e6, 0x20e7, 0x20e8, 0x20e9, 0x20ea, 0x20eb,
|
||||
+ 0x20ec, 0x20ed, 0x20ee, 0x20ef, 0x20f0, 0x20f1, 0x20f2, 0x20f3,
|
||||
+ 0x20f4, 0x20f5, 0x20f6, 0x20f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb,
|
||||
+ 0x20fc, 0x20fd, 0x20fe, 0x20ff, 0x2100, 0x2101, 0x2102, 0x2103,
|
||||
+ 0x2104, 0x2105, 0x2106, 0x2107, 0x2108, 0x2109, 0x210a, 0x210b,
|
||||
+ 0x210c, 0x210d, 0x210e, 0x210f, 0x2110, 0x2111, 0x2112, 0x2113,
|
||||
+ 0x2114, 0x2115, 0x2116, 0x2117, 0x2118, 0x2119, 0x211a, 0x211b,
|
||||
+ 0x211c, 0x211d, 0x211e, 0x211f, 0x2120, 0x2121, 0x2122, 0x2123,
|
||||
+ 0x2124, 0x2125, 0x2126, 0x2127, 0x2128, 0x2129, 0x212a, 0x212b,
|
||||
+ 0x212c, 0x212d, 0x212e, 0x212f, 0x2130, 0x2131, 0x2132, 0x2133,
|
||||
+ 0x2134, 0x2135, 0x2136, 0x2137, 0x2138, 0x2139, 0x213a, 0x213b,
|
||||
+ 0x213c, 0x213d, 0x213e, 0x213f, 0x2140, 0x2141, 0x2142, 0x2143,
|
||||
+ 0x2144, 0x2145, 0x2146, 0x2147, 0x2148, 0x2149, 0x214a, 0x214b,
|
||||
+ 0x214c, 0x214d, 0x2132, 0x214f, 0x2150, 0x2151, 0x2152, 0x2153,
|
||||
+ 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, 0x215b,
|
||||
+ 0x215c, 0x215d, 0x215e, 0x215f, 0x2160, 0x2161, 0x2162, 0x2163,
|
||||
+ 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216a, 0x216b,
|
||||
+ 0x216c, 0x216d, 0x216e, 0x216f, 0x2160, 0x2161, 0x2162, 0x2163,
|
||||
+ 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216a, 0x216b,
|
||||
+ 0x216c, 0x216d, 0x216e, 0x216f, 0x2180, 0x2181, 0x2182, 0x2183,
|
||||
+ 0x2183, 0xffff, 0x034b, 0x24b6, 0x24b7, 0x24b8, 0x24b9, 0x24ba,
|
||||
+ 0x24bb, 0x24bc, 0x24bd, 0x24be, 0x24bf, 0x24c0, 0x24c1, 0x24c2,
|
||||
+ 0x24c3, 0x24c4, 0x24c5, 0x24c6, 0x24c7, 0x24c8, 0x24c9, 0x24ca,
|
||||
+ 0x24cb, 0x24cc, 0x24cd, 0x24ce, 0x24cf, 0xffff, 0x0746, 0x2c00,
|
||||
+ 0x2c01, 0x2c02, 0x2c03, 0x2c04, 0x2c05, 0x2c06, 0x2c07, 0x2c08,
|
||||
+ 0x2c09, 0x2c0a, 0x2c0b, 0x2c0c, 0x2c0d, 0x2c0e, 0x2c0f, 0x2c10,
|
||||
+ 0x2c11, 0x2c12, 0x2c13, 0x2c14, 0x2c15, 0x2c16, 0x2c17, 0x2c18,
|
||||
+ 0x2c19, 0x2c1a, 0x2c1b, 0x2c1c, 0x2c1d, 0x2c1e, 0x2c1f, 0x2c20,
|
||||
+ 0x2c21, 0x2c22, 0x2c23, 0x2c24, 0x2c25, 0x2c26, 0x2c27, 0x2c28,
|
||||
+ 0x2c29, 0x2c2a, 0x2c2b, 0x2c2c, 0x2c2d, 0x2c2e, 0x2c5f, 0x2c60,
|
||||
+ 0x2c60, 0x2c62, 0x2c63, 0x2c64, 0x2c65, 0x2c66, 0x2c67, 0x2c67,
|
||||
+ 0x2c69, 0x2c69, 0x2c6b, 0x2c6b, 0x2c6d, 0x2c6e, 0x2c6f, 0x2c70,
|
||||
+ 0x2c71, 0x2c72, 0x2c73, 0x2c74, 0x2c75, 0x2c75, 0x2c77, 0x2c78,
|
||||
+ 0x2c79, 0x2c7a, 0x2c7b, 0x2c7c, 0x2c7d, 0x2c7e, 0x2c7f, 0x2c80,
|
||||
+ 0x2c80, 0x2c82, 0x2c82, 0x2c84, 0x2c84, 0x2c86, 0x2c86, 0x2c88,
|
||||
+ 0x2c88, 0x2c8a, 0x2c8a, 0x2c8c, 0x2c8c, 0x2c8e, 0x2c8e, 0x2c90,
|
||||
+ 0x2c90, 0x2c92, 0x2c92, 0x2c94, 0x2c94, 0x2c96, 0x2c96, 0x2c98,
|
||||
+ 0x2c98, 0x2c9a, 0x2c9a, 0x2c9c, 0x2c9c, 0x2c9e, 0x2c9e, 0x2ca0,
|
||||
+ 0x2ca0, 0x2ca2, 0x2ca2, 0x2ca4, 0x2ca4, 0x2ca6, 0x2ca6, 0x2ca8,
|
||||
+ 0x2ca8, 0x2caa, 0x2caa, 0x2cac, 0x2cac, 0x2cae, 0x2cae, 0x2cb0,
|
||||
+ 0x2cb0, 0x2cb2, 0x2cb2, 0x2cb4, 0x2cb4, 0x2cb6, 0x2cb6, 0x2cb8,
|
||||
+ 0x2cb8, 0x2cba, 0x2cba, 0x2cbc, 0x2cbc, 0x2cbe, 0x2cbe, 0x2cc0,
|
||||
+ 0x2cc0, 0x2cc2, 0x2cc2, 0x2cc4, 0x2cc4, 0x2cc6, 0x2cc6, 0x2cc8,
|
||||
+ 0x2cc8, 0x2cca, 0x2cca, 0x2ccc, 0x2ccc, 0x2cce, 0x2cce, 0x2cd0,
|
||||
+ 0x2cd0, 0x2cd2, 0x2cd2, 0x2cd4, 0x2cd4, 0x2cd6, 0x2cd6, 0x2cd8,
|
||||
+ 0x2cd8, 0x2cda, 0x2cda, 0x2cdc, 0x2cdc, 0x2cde, 0x2cde, 0x2ce0,
|
||||
+ 0x2ce0, 0x2ce2, 0x2ce2, 0x2ce4, 0x2ce5, 0x2ce6, 0x2ce7, 0x2ce8,
|
||||
+ 0x2ce9, 0x2cea, 0x2ceb, 0x2cec, 0x2ced, 0x2cee, 0x2cef, 0x2cf0,
|
||||
+ 0x2cf1, 0x2cf2, 0x2cf3, 0x2cf4, 0x2cf5, 0x2cf6, 0x2cf7, 0x2cf8,
|
||||
+ 0x2cf9, 0x2cfa, 0x2cfb, 0x2cfc, 0x2cfd, 0x2cfe, 0x2cff, 0x10a0,
|
||||
+ 0x10a1, 0x10a2, 0x10a3, 0x10a4, 0x10a5, 0x10a6, 0x10a7, 0x10a8,
|
||||
+ 0x10a9, 0x10aa, 0x10ab, 0x10ac, 0x10ad, 0x10ae, 0x10af, 0x10b0,
|
||||
+ 0x10b1, 0x10b2, 0x10b3, 0x10b4, 0x10b5, 0x10b6, 0x10b7, 0x10b8,
|
||||
+ 0x10b9, 0x10ba, 0x10bb, 0x10bc, 0x10bd, 0x10be, 0x10bf, 0x10c0,
|
||||
+ 0x10c1, 0x10c2, 0x10c3, 0x10c4, 0x10c5, 0xffff, 0xd21b, 0xff21,
|
||||
+ 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27, 0xff28, 0xff29,
|
||||
+ 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f, 0xff30, 0xff31,
|
||||
+ 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37, 0xff38, 0xff39,
|
||||
+ 0xff3a, 0xff5b, 0xff5c, 0xff5d, 0xff5e, 0xff5f, 0xff60, 0xff61,
|
||||
+ 0xff62, 0xff63, 0xff64, 0xff65, 0xff66, 0xff67, 0xff68, 0xff69,
|
||||
+ 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f, 0xff70, 0xff71,
|
||||
+ 0xff72, 0xff73, 0xff74, 0xff75, 0xff76, 0xff77, 0xff78, 0xff79,
|
||||
+ 0xff7a, 0xff7b, 0xff7c, 0xff7d, 0xff7e, 0xff7f, 0xff80, 0xff81,
|
||||
+ 0xff82, 0xff83, 0xff84, 0xff85, 0xff86, 0xff87, 0xff88, 0xff89,
|
||||
+ 0xff8a, 0xff8b, 0xff8c, 0xff8d, 0xff8e, 0xff8f, 0xff90, 0xff91,
|
||||
+ 0xff92, 0xff93, 0xff94, 0xff95, 0xff96, 0xff97, 0xff98, 0xff99,
|
||||
+ 0xff9a, 0xff9b, 0xff9c, 0xff9d, 0xff9e, 0xff9f, 0xffa0, 0xffa1,
|
||||
+ 0xffa2, 0xffa3, 0xffa4, 0xffa5, 0xffa6, 0xffa7, 0xffa8, 0xffa9,
|
||||
+ 0xffaa, 0xffab, 0xffac, 0xffad, 0xffae, 0xffaf, 0xffb0, 0xffb1,
|
||||
+ 0xffb2, 0xffb3, 0xffb4, 0xffb5, 0xffb6, 0xffb7, 0xffb8, 0xffb9,
|
||||
+ 0xffba, 0xffbb, 0xffbc, 0xffbd, 0xffbe, 0xffbf, 0xffc0, 0xffc1,
|
||||
+ 0xffc2, 0xffc3, 0xffc4, 0xffc5, 0xffc6, 0xffc7, 0xffc8, 0xffc9,
|
||||
+ 0xffca, 0xffcb, 0xffcc, 0xffcd, 0xffce, 0xffcf, 0xffd0, 0xffd1,
|
||||
+ 0xffd2, 0xffd3, 0xffd4, 0xffd5, 0xffd6, 0xffd7, 0xffd8, 0xffd9,
|
||||
+ 0xffda, 0xffdb, 0xffdc, 0xffdd, 0xffde, 0xffdf, 0xffe0, 0xffe1,
|
||||
+ 0xffe2, 0xffe3, 0xffe4, 0xffe5, 0xffe6, 0xffe7, 0xffe8, 0xffe9,
|
||||
+ 0xffea, 0xffeb, 0xffec, 0xffed, 0xffee, 0xffef, 0xfff0, 0xfff1,
|
||||
+ 0xfff2, 0xfff3, 0xfff4, 0xfff5, 0xfff6, 0xfff7, 0xfff8, 0xfff9,
|
||||
+ 0xfffa, 0xfffb, 0xfffc, 0xfffd, 0xfffe, 0xffff,
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * Allow full-width illegal characters :
|
||||
+ * "MS windows 7" supports full-width-invalid-name-characters.
|
||||
+ * So we should check half-width-invalid-name-characters(ASCII) only
|
||||
+ * for compatibility.
|
||||
+ *
|
||||
+ * " * / : < > ? \ |
|
||||
+ */
|
||||
+static unsigned short bad_uni_chars[] = {
|
||||
+ 0x0022, 0x002A, 0x002F, 0x003A,
|
||||
+ 0x003C, 0x003E, 0x003F, 0x005C, 0x007C,
|
||||
+ 0
|
||||
+};
|
||||
+
|
||||
+static int exfat_convert_char_to_ucs2(struct nls_table *nls,
|
||||
+ const unsigned char *ch, int ch_len, unsigned short *ucs2,
|
||||
+ int *lossy)
|
||||
+{
|
||||
+ int len;
|
||||
+
|
||||
+ *ucs2 = 0x0;
|
||||
+
|
||||
+ if (ch[0] < 0x80) {
|
||||
+ *ucs2 = ch[0];
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ len = nls->char2uni(ch, ch_len, ucs2);
|
||||
+ if (len < 0) {
|
||||
+ /* conversion failed */
|
||||
+ if (lossy != NULL)
|
||||
+ *lossy |= NLS_NAME_LOSSY;
|
||||
+ *ucs2 = '_';
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+static int exfat_convert_ucs2_to_char(struct nls_table *nls,
|
||||
+ unsigned short ucs2, unsigned char *ch, int *lossy)
|
||||
+{
|
||||
+ int len;
|
||||
+
|
||||
+ ch[0] = 0x0;
|
||||
+
|
||||
+ if (ucs2 < 0x0080) {
|
||||
+ ch[0] = ucs2;
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ len = nls->uni2char(ucs2, ch, MAX_CHARSET_SIZE);
|
||||
+ if (len < 0) {
|
||||
+ /* conversion failed */
|
||||
+ if (lossy != NULL)
|
||||
+ *lossy |= NLS_NAME_LOSSY;
|
||||
+ ch[0] = '_';
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+unsigned short exfat_toupper(struct super_block *sb, unsigned short a)
|
||||
+{
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+
|
||||
+ return sbi->vol_utbl[a] ? sbi->vol_utbl[a] : a;
|
||||
+}
|
||||
+
|
||||
+static unsigned short *exfat_wstrchr(unsigned short *str, unsigned short wchar)
|
||||
+{
|
||||
+ while (*str) {
|
||||
+ if (*(str++) == wchar)
|
||||
+ return str;
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+int exfat_uniname_ncmp(struct super_block *sb, unsigned short *a,
|
||||
+ unsigned short *b, unsigned int len)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < len; i++, a++, b++)
|
||||
+ if (exfat_toupper(sb, *a) != exfat_toupper(sb, *b))
|
||||
+ return 1;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int exfat_utf16_to_utf8(struct super_block *sb,
|
||||
+ struct exfat_uni_name *p_uniname, unsigned char *p_cstring,
|
||||
+ int buflen)
|
||||
+{
|
||||
+ int len;
|
||||
+ const unsigned short *uniname = p_uniname->name;
|
||||
+
|
||||
+ /* always len >= 0 */
|
||||
+ len = utf16s_to_utf8s(uniname, MAX_NAME_LENGTH, UTF16_HOST_ENDIAN,
|
||||
+ p_cstring, buflen);
|
||||
+ p_cstring[len] = '\0';
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+static int exfat_utf8_to_utf16(struct super_block *sb,
|
||||
+ const unsigned char *p_cstring, const int len,
|
||||
+ struct exfat_uni_name *p_uniname, int *p_lossy)
|
||||
+{
|
||||
+ int i, unilen, lossy = NLS_NAME_NO_LOSSY;
|
||||
+ unsigned short upname[MAX_NAME_LENGTH + 1];
|
||||
+ unsigned short *uniname = p_uniname->name;
|
||||
+
|
||||
+ WARN_ON(!len);
|
||||
+
|
||||
+ unilen = utf8s_to_utf16s(p_cstring, len, UTF16_HOST_ENDIAN,
|
||||
+ (wchar_t *)uniname, MAX_NAME_LENGTH + 2);
|
||||
+ if (unilen < 0) {
|
||||
+ exfat_msg(sb, KERN_ERR,
|
||||
+ "failed to %s (err : %d) nls len : %d",
|
||||
+ __func__, unilen, len);
|
||||
+ return unilen;
|
||||
+ }
|
||||
+
|
||||
+ if (unilen > MAX_NAME_LENGTH) {
|
||||
+ exfat_msg(sb, KERN_ERR,
|
||||
+ "failed to %s (estr:ENAMETOOLONG) nls len : %d, unilen : %d > %d",
|
||||
+ __func__, len, unilen, MAX_NAME_LENGTH);
|
||||
+ return -ENAMETOOLONG;
|
||||
+ }
|
||||
+
|
||||
+ p_uniname->name_len = unilen & 0xFF;
|
||||
+
|
||||
+ for (i = 0; i < unilen; i++) {
|
||||
+ if (*uniname < 0x0020 ||
|
||||
+ exfat_wstrchr(bad_uni_chars, *uniname))
|
||||
+ lossy |= NLS_NAME_LOSSY;
|
||||
+
|
||||
+ upname[i] = exfat_toupper(sb, *uniname);
|
||||
+ uniname++;
|
||||
+ }
|
||||
+
|
||||
+ *uniname = '\0';
|
||||
+ p_uniname->name_len = unilen;
|
||||
+ p_uniname->name_hash = exfat_calc_chksum_2byte(upname, unilen << 1, 0,
|
||||
+ CS_DEFAULT);
|
||||
+
|
||||
+ if (p_lossy)
|
||||
+ *p_lossy = lossy;
|
||||
+ return unilen;
|
||||
+}
|
||||
+
|
||||
+#define PLANE_SIZE 0x00010000
|
||||
+#define SURROGATE_MASK 0xfffff800
|
||||
+#define SURROGATE_PAIR 0x0000d800
|
||||
+#define SURROGATE_LOW 0x00000400
|
||||
+#define SURROGATE_BITS 0x000003ff
|
||||
+
|
||||
+unsigned short exfat_high_surrogate(unicode_t u)
|
||||
+{
|
||||
+ return ((u - PLANE_SIZE) >> 10) + SURROGATE_PAIR;
|
||||
+}
|
||||
+
|
||||
+unsigned short exfat_low_surrogate(unicode_t u)
|
||||
+{
|
||||
+ return ((u - PLANE_SIZE) & SURROGATE_BITS) | SURROGATE_PAIR |
|
||||
+ SURROGATE_LOW;
|
||||
+}
|
||||
+
|
||||
+static int __exfat_utf16_to_nls(struct super_block *sb,
|
||||
+ struct exfat_uni_name *p_uniname, unsigned char *p_cstring,
|
||||
+ int buflen)
|
||||
+{
|
||||
+ int i, j, len, out_len = 0;
|
||||
+ unsigned char buf[MAX_CHARSET_SIZE];
|
||||
+ const unsigned short *uniname = p_uniname->name;
|
||||
+ struct nls_table *nls = EXFAT_SB(sb)->nls_io;
|
||||
+
|
||||
+ i = 0;
|
||||
+ while (i < MAX_NAME_LENGTH && out_len < (buflen - 1)) {
|
||||
+ if (*uniname == '\0')
|
||||
+ break;
|
||||
+ if ((*uniname & SURROGATE_MASK) != SURROGATE_PAIR) {
|
||||
+ len = exfat_convert_ucs2_to_char(nls, *uniname, buf,
|
||||
+ NULL);
|
||||
+ } else {
|
||||
+ /* Process UTF-16 surrogate pair as one character */
|
||||
+ if (!(*uniname & SURROGATE_LOW) &&
|
||||
+ i+1 < MAX_NAME_LENGTH &&
|
||||
+ (*(uniname+1) & SURROGATE_MASK) == SURROGATE_PAIR &&
|
||||
+ (*(uniname+1) & SURROGATE_LOW)) {
|
||||
+ uniname++;
|
||||
+ i++;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * UTF-16 surrogate pair encodes code points above
|
||||
+ * U+FFFF. Code points above U+FFFF are not supported
|
||||
+ * by kernel NLS framework therefore use replacement
|
||||
+ * character
|
||||
+ */
|
||||
+ len = 1;
|
||||
+ buf[0] = '_';
|
||||
+ }
|
||||
+
|
||||
+ if (out_len + len >= buflen)
|
||||
+ len = buflen - 1 - out_len;
|
||||
+ out_len += len;
|
||||
+
|
||||
+ if (len > 1) {
|
||||
+ for (j = 0; j < len; j++)
|
||||
+ *p_cstring++ = buf[j];
|
||||
+ } else { /* len == 1 */
|
||||
+ *p_cstring++ = *buf;
|
||||
+ }
|
||||
+
|
||||
+ uniname++;
|
||||
+ i++;
|
||||
+ }
|
||||
+
|
||||
+ *p_cstring = '\0';
|
||||
+ return out_len;
|
||||
+}
|
||||
+
|
||||
+static int exfat_nls_to_ucs2(struct super_block *sb,
|
||||
+ const unsigned char *p_cstring, const int len,
|
||||
+ struct exfat_uni_name *p_uniname, int *p_lossy)
|
||||
+{
|
||||
+ int i = 0, unilen = 0, lossy = NLS_NAME_NO_LOSSY;
|
||||
+ unsigned short upname[MAX_NAME_LENGTH + 1];
|
||||
+ unsigned short *uniname = p_uniname->name;
|
||||
+ struct nls_table *nls = EXFAT_SB(sb)->nls_io;
|
||||
+
|
||||
+ WARN_ON(!len);
|
||||
+
|
||||
+ while (unilen < MAX_NAME_LENGTH && i < len) {
|
||||
+ i += exfat_convert_char_to_ucs2(nls, p_cstring + i, len - i,
|
||||
+ uniname, &lossy);
|
||||
+
|
||||
+ if (*uniname < 0x0020 ||
|
||||
+ exfat_wstrchr(bad_uni_chars, *uniname))
|
||||
+ lossy |= NLS_NAME_LOSSY;
|
||||
+
|
||||
+ upname[unilen] = exfat_toupper(sb, *uniname);
|
||||
+ uniname++;
|
||||
+ unilen++;
|
||||
+ }
|
||||
+
|
||||
+ if (p_cstring[i] != '\0')
|
||||
+ lossy |= NLS_NAME_OVERLEN;
|
||||
+
|
||||
+ *uniname = '\0';
|
||||
+ p_uniname->name_len = unilen;
|
||||
+ p_uniname->name_hash = exfat_calc_chksum_2byte(upname, unilen << 1, 0,
|
||||
+ CS_DEFAULT);
|
||||
+
|
||||
+ if (p_lossy)
|
||||
+ *p_lossy = lossy;
|
||||
+ return unilen;
|
||||
+}
|
||||
+
|
||||
+int exfat_utf16_to_nls(struct super_block *sb, struct exfat_uni_name *uniname,
|
||||
+ unsigned char *p_cstring, int buflen)
|
||||
+{
|
||||
+ if (EXFAT_SB(sb)->options.utf8)
|
||||
+ return exfat_utf16_to_utf8(sb, uniname, p_cstring,
|
||||
+ buflen);
|
||||
+ return __exfat_utf16_to_nls(sb, uniname, p_cstring, buflen);
|
||||
+}
|
||||
+
|
||||
+int exfat_nls_to_utf16(struct super_block *sb, const unsigned char *p_cstring,
|
||||
+ const int len, struct exfat_uni_name *uniname, int *p_lossy)
|
||||
+{
|
||||
+ if (EXFAT_SB(sb)->options.utf8)
|
||||
+ return exfat_utf8_to_utf16(sb, p_cstring, len,
|
||||
+ uniname, p_lossy);
|
||||
+ return exfat_nls_to_ucs2(sb, p_cstring, len, uniname, p_lossy);
|
||||
+}
|
||||
+
|
||||
+static int exfat_load_upcase_table(struct super_block *sb,
|
||||
+ sector_t sector, unsigned long long num_sectors,
|
||||
+ unsigned int utbl_checksum)
|
||||
+{
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ unsigned int sect_size = sb->s_blocksize;
|
||||
+ unsigned int i, index = 0, checksum = 0;
|
||||
+ int ret;
|
||||
+ unsigned char skip = false;
|
||||
+ unsigned short *upcase_table;
|
||||
+
|
||||
+ upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL);
|
||||
+ if (!upcase_table)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ sbi->vol_utbl = upcase_table;
|
||||
+ num_sectors += sector;
|
||||
+
|
||||
+ while (sector < num_sectors) {
|
||||
+ struct buffer_head *bh;
|
||||
+
|
||||
+ bh = sb_bread(sb, sector);
|
||||
+ if (!bh) {
|
||||
+ exfat_msg(sb, KERN_ERR,
|
||||
+ "failed to read sector(0x%llx)\n",
|
||||
+ (unsigned long long)sector);
|
||||
+ ret = -EIO;
|
||||
+ goto free_table;
|
||||
+ }
|
||||
+ sector++;
|
||||
+ for (i = 0; i < sect_size && index <= 0xFFFF; i += 2) {
|
||||
+ unsigned short uni = get_unaligned_le16(bh->b_data + i);
|
||||
+
|
||||
+ checksum = ((checksum & 1) ? 0x80000000 : 0) +
|
||||
+ (checksum >> 1) +
|
||||
+ *(((unsigned char *)bh->b_data) + i);
|
||||
+ checksum = ((checksum & 1) ? 0x80000000 : 0) +
|
||||
+ (checksum >> 1) +
|
||||
+ *(((unsigned char *)bh->b_data) + (i + 1));
|
||||
+
|
||||
+ if (skip) {
|
||||
+ index += uni;
|
||||
+ skip = false;
|
||||
+ } else if (uni == index) {
|
||||
+ index++;
|
||||
+ } else if (uni == 0xFFFF) {
|
||||
+ skip = true;
|
||||
+ } else { /* uni != index , uni != 0xFFFF */
|
||||
+ upcase_table[index] = uni;
|
||||
+ index++;
|
||||
+ }
|
||||
+ }
|
||||
+ brelse(bh);
|
||||
+ }
|
||||
+
|
||||
+ if (index >= 0xFFFF && utbl_checksum == checksum)
|
||||
+ return 0;
|
||||
+
|
||||
+ exfat_msg(sb, KERN_ERR,
|
||||
+ "failed to load upcase table (idx : 0x%08x, chksum : 0x%08x, utbl_chksum : 0x%08x)\n",
|
||||
+ index, checksum, utbl_checksum);
|
||||
+ ret = -EINVAL;
|
||||
+free_table:
|
||||
+ exfat_free_upcase_table(sbi);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int exfat_load_default_upcase_table(struct super_block *sb)
|
||||
+{
|
||||
+ int i, ret = -EIO;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ unsigned char skip = false;
|
||||
+ unsigned short uni = 0, *upcase_table;
|
||||
+ unsigned int index = 0;
|
||||
+
|
||||
+ upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL);
|
||||
+ if (!upcase_table)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ sbi->vol_utbl = upcase_table;
|
||||
+
|
||||
+ for (i = 0; index <= 0xFFFF && i < EXFAT_NUM_UPCASE; i++) {
|
||||
+ uni = uni_def_upcase[i];
|
||||
+ if (skip) {
|
||||
+ index += uni;
|
||||
+ skip = false;
|
||||
+ } else if (uni == index) {
|
||||
+ index++;
|
||||
+ } else if (uni == 0xFFFF) {
|
||||
+ skip = true;
|
||||
+ } else {
|
||||
+ upcase_table[index] = uni;
|
||||
+ index++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (index >= 0xFFFF)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* FATAL error: default upcase table has error */
|
||||
+ exfat_free_upcase_table(sbi);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int exfat_create_upcase_table(struct super_block *sb)
|
||||
+{
|
||||
+ int i, ret;
|
||||
+ unsigned int tbl_clu, type;
|
||||
+ sector_t sector;
|
||||
+ unsigned long long tbl_size, num_sectors;
|
||||
+ unsigned char blksize_bits = sb->s_blocksize_bits;
|
||||
+ struct exfat_chain clu;
|
||||
+ struct exfat_dentry *ep;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ struct buffer_head *bh;
|
||||
+
|
||||
+ clu.dir = sbi->root_dir;
|
||||
+ clu.flags = ALLOC_FAT_CHAIN;
|
||||
+
|
||||
+ while (clu.dir != EXFAT_EOF_CLUSTER) {
|
||||
+ for (i = 0; i < sbi->dentries_per_clu; i++) {
|
||||
+ ep = exfat_get_dentry(sb, &clu, i, &bh, NULL);
|
||||
+ if (!ep)
|
||||
+ return -EIO;
|
||||
+
|
||||
+ type = exfat_get_entry_type(ep);
|
||||
+ if (type == TYPE_UNUSED) {
|
||||
+ brelse(bh);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (type != TYPE_UPCASE) {
|
||||
+ brelse(bh);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ tbl_clu = le32_to_cpu(ep->dentry.upcase.start_clu);
|
||||
+ tbl_size = le64_to_cpu(ep->dentry.upcase.size);
|
||||
+
|
||||
+ sector = exfat_cluster_to_sector(sbi, tbl_clu);
|
||||
+ num_sectors = ((tbl_size - 1) >> blksize_bits) + 1;
|
||||
+ ret = exfat_load_upcase_table(sb, sector, num_sectors,
|
||||
+ le32_to_cpu(ep->dentry.upcase.checksum));
|
||||
+
|
||||
+ brelse(bh);
|
||||
+ if (ret && ret != -EIO)
|
||||
+ goto load_default;
|
||||
+
|
||||
+ /* load successfully */
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if (exfat_get_next_cluster(sb, &(clu.dir)))
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+load_default:
|
||||
+ /* load default upcase table */
|
||||
+ return exfat_load_default_upcase_table(sb);
|
||||
+}
|
||||
+
|
||||
+void exfat_free_upcase_table(struct exfat_sb_info *sbi)
|
||||
+{
|
||||
+ kfree(sbi->vol_utbl);
|
||||
+}
|
||||
--
|
||||
2.25.1
|
||||
|
||||
+758
@@ -0,0 +1,758 @@
|
||||
From 719c1e1829166da399903b13da6dcc5344e73449 Mon Sep 17 00:00:00 2001
|
||||
From: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Date: Mon, 2 Mar 2020 15:21:33 +0900
|
||||
Subject: [PATCH 02/14] exfat: add super block operations
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This adds the implementation of superblock operations for exfat.
|
||||
|
||||
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
|
||||
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
|
||||
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
|
||||
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
||||
---
|
||||
fs/exfat/super.c | 728 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 728 insertions(+)
|
||||
create mode 100644 fs/exfat/super.c
|
||||
|
||||
diff --git a/fs/exfat/super.c b/fs/exfat/super.c
|
||||
new file mode 100644
|
||||
index 000000000000..f06e0b53e393
|
||||
--- /dev/null
|
||||
+++ b/fs/exfat/super.c
|
||||
@@ -0,0 +1,728 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+/*
|
||||
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/fs_context.h>
|
||||
+#include <linux/fs_parser.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/time.h>
|
||||
+#include <linux/mount.h>
|
||||
+#include <linux/cred.h>
|
||||
+#include <linux/statfs.h>
|
||||
+#include <linux/seq_file.h>
|
||||
+#include <linux/blkdev.h>
|
||||
+#include <linux/fs_struct.h>
|
||||
+#include <linux/iversion.h>
|
||||
+#include <linux/nls.h>
|
||||
+#include <linux/buffer_head.h>
|
||||
+
|
||||
+#include "exfat_raw.h"
|
||||
+#include "exfat_fs.h"
|
||||
+
|
||||
+static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET;
|
||||
+static struct kmem_cache *exfat_inode_cachep;
|
||||
+
|
||||
+static void exfat_free_iocharset(struct exfat_sb_info *sbi)
|
||||
+{
|
||||
+ if (sbi->options.iocharset != exfat_default_iocharset)
|
||||
+ kfree(sbi->options.iocharset);
|
||||
+}
|
||||
+
|
||||
+static void exfat_delayed_free(struct rcu_head *p)
|
||||
+{
|
||||
+ struct exfat_sb_info *sbi = container_of(p, struct exfat_sb_info, rcu);
|
||||
+
|
||||
+ unload_nls(sbi->nls_io);
|
||||
+ exfat_free_iocharset(sbi);
|
||||
+ exfat_free_upcase_table(sbi);
|
||||
+ kfree(sbi);
|
||||
+}
|
||||
+
|
||||
+static void exfat_put_super(struct super_block *sb)
|
||||
+{
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+
|
||||
+ mutex_lock(&sbi->s_lock);
|
||||
+ if (test_and_clear_bit(EXFAT_SB_DIRTY, &sbi->s_state))
|
||||
+ sync_blockdev(sb->s_bdev);
|
||||
+ exfat_set_vol_flags(sb, VOL_CLEAN);
|
||||
+ exfat_free_bitmap(sbi);
|
||||
+ mutex_unlock(&sbi->s_lock);
|
||||
+
|
||||
+ call_rcu(&sbi->rcu, exfat_delayed_free);
|
||||
+}
|
||||
+
|
||||
+static int exfat_sync_fs(struct super_block *sb, int wait)
|
||||
+{
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ int err = 0;
|
||||
+
|
||||
+ /* If there are some dirty buffers in the bdev inode */
|
||||
+ mutex_lock(&sbi->s_lock);
|
||||
+ if (test_and_clear_bit(EXFAT_SB_DIRTY, &sbi->s_state)) {
|
||||
+ sync_blockdev(sb->s_bdev);
|
||||
+ if (exfat_set_vol_flags(sb, VOL_CLEAN))
|
||||
+ err = -EIO;
|
||||
+ }
|
||||
+ mutex_unlock(&sbi->s_lock);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||
+{
|
||||
+ struct super_block *sb = dentry->d_sb;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ unsigned long long id = huge_encode_dev(sb->s_bdev->bd_dev);
|
||||
+
|
||||
+ if (sbi->used_clusters == EXFAT_CLUSTERS_UNTRACKED) {
|
||||
+ mutex_lock(&sbi->s_lock);
|
||||
+ if (exfat_count_used_clusters(sb, &sbi->used_clusters)) {
|
||||
+ mutex_unlock(&sbi->s_lock);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+ mutex_unlock(&sbi->s_lock);
|
||||
+ }
|
||||
+
|
||||
+ buf->f_type = sb->s_magic;
|
||||
+ buf->f_bsize = sbi->cluster_size;
|
||||
+ buf->f_blocks = sbi->num_clusters - 2; /* clu 0 & 1 */
|
||||
+ buf->f_bfree = buf->f_blocks - sbi->used_clusters;
|
||||
+ buf->f_bavail = buf->f_bfree;
|
||||
+ buf->f_fsid.val[0] = (unsigned int)id;
|
||||
+ buf->f_fsid.val[1] = (unsigned int)(id >> 32);
|
||||
+ /* Unicode utf16 255 characters */
|
||||
+ buf->f_namelen = EXFAT_MAX_FILE_LEN * NLS_MAX_CHARSET_SIZE;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag)
|
||||
+{
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ struct pbr64 *bpb;
|
||||
+ bool sync = 0;
|
||||
+
|
||||
+ /* flags are not changed */
|
||||
+ if (sbi->vol_flag == new_flag)
|
||||
+ return 0;
|
||||
+
|
||||
+ sbi->vol_flag = new_flag;
|
||||
+
|
||||
+ /* skip updating volume dirty flag,
|
||||
+ * if this volume has been mounted with read-only
|
||||
+ */
|
||||
+ if (sb_rdonly(sb))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!sbi->pbr_bh) {
|
||||
+ sbi->pbr_bh = sb_bread(sb, 0);
|
||||
+ if (!sbi->pbr_bh) {
|
||||
+ exfat_msg(sb, KERN_ERR, "failed to read boot sector");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ bpb = (struct pbr64 *)sbi->pbr_bh->b_data;
|
||||
+ bpb->bsx.vol_flags = cpu_to_le16(new_flag);
|
||||
+
|
||||
+ if (new_flag == VOL_DIRTY && !buffer_dirty(sbi->pbr_bh))
|
||||
+ sync = true;
|
||||
+ else
|
||||
+ sync = false;
|
||||
+
|
||||
+ set_buffer_uptodate(sbi->pbr_bh);
|
||||
+ mark_buffer_dirty(sbi->pbr_bh);
|
||||
+
|
||||
+ if (sync)
|
||||
+ sync_dirty_buffer(sbi->pbr_bh);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int exfat_show_options(struct seq_file *m, struct dentry *root)
|
||||
+{
|
||||
+ struct super_block *sb = root->d_sb;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ struct exfat_mount_options *opts = &sbi->options;
|
||||
+
|
||||
+ /* Show partition info */
|
||||
+ if (!uid_eq(opts->fs_uid, GLOBAL_ROOT_UID))
|
||||
+ seq_printf(m, ",uid=%u",
|
||||
+ from_kuid_munged(&init_user_ns, opts->fs_uid));
|
||||
+ if (!gid_eq(opts->fs_gid, GLOBAL_ROOT_GID))
|
||||
+ seq_printf(m, ",gid=%u",
|
||||
+ from_kgid_munged(&init_user_ns, opts->fs_gid));
|
||||
+ seq_printf(m, ",fmask=%04o,dmask=%04o", opts->fs_fmask, opts->fs_dmask);
|
||||
+ if (opts->allow_utime)
|
||||
+ seq_printf(m, ",allow_utime=%04o", opts->allow_utime);
|
||||
+ if (opts->utf8)
|
||||
+ seq_puts(m, ",iocharset=utf8");
|
||||
+ else if (sbi->nls_io)
|
||||
+ seq_printf(m, ",iocharset=%s", sbi->nls_io->charset);
|
||||
+ seq_printf(m, ",bps=%ld", sb->s_blocksize);
|
||||
+ if (opts->errors == EXFAT_ERRORS_CONT)
|
||||
+ seq_puts(m, ",errors=continue");
|
||||
+ else if (opts->errors == EXFAT_ERRORS_PANIC)
|
||||
+ seq_puts(m, ",errors=panic");
|
||||
+ else
|
||||
+ seq_puts(m, ",errors=remount-ro");
|
||||
+ if (opts->discard)
|
||||
+ seq_puts(m, ",discard");
|
||||
+ if (opts->time_offset)
|
||||
+ seq_printf(m, ",time_offset=%d", opts->time_offset);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct inode *exfat_alloc_inode(struct super_block *sb)
|
||||
+{
|
||||
+ struct exfat_inode_info *ei;
|
||||
+
|
||||
+ ei = kmem_cache_alloc(exfat_inode_cachep, GFP_NOFS);
|
||||
+ if (!ei)
|
||||
+ return NULL;
|
||||
+
|
||||
+ init_rwsem(&ei->truncate_lock);
|
||||
+ return &ei->vfs_inode;
|
||||
+}
|
||||
+
|
||||
+static void exfat_free_inode(struct inode *inode)
|
||||
+{
|
||||
+ kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode));
|
||||
+}
|
||||
+
|
||||
+static const struct super_operations exfat_sops = {
|
||||
+ .alloc_inode = exfat_alloc_inode,
|
||||
+ .free_inode = exfat_free_inode,
|
||||
+ .write_inode = exfat_write_inode,
|
||||
+ .evict_inode = exfat_evict_inode,
|
||||
+ .put_super = exfat_put_super,
|
||||
+ .sync_fs = exfat_sync_fs,
|
||||
+ .statfs = exfat_statfs,
|
||||
+ .show_options = exfat_show_options,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ Opt_uid,
|
||||
+ Opt_gid,
|
||||
+ Opt_umask,
|
||||
+ Opt_dmask,
|
||||
+ Opt_fmask,
|
||||
+ Opt_allow_utime,
|
||||
+ Opt_charset,
|
||||
+ Opt_errors,
|
||||
+ Opt_discard,
|
||||
+ Opt_time_offset,
|
||||
+};
|
||||
+
|
||||
+static const struct fs_parameter_spec exfat_param_specs[] = {
|
||||
+ fsparam_u32("uid", Opt_uid),
|
||||
+ fsparam_u32("gid", Opt_gid),
|
||||
+ fsparam_u32oct("umask", Opt_umask),
|
||||
+ fsparam_u32oct("dmask", Opt_dmask),
|
||||
+ fsparam_u32oct("fmask", Opt_fmask),
|
||||
+ fsparam_u32oct("allow_utime", Opt_allow_utime),
|
||||
+ fsparam_string("iocharset", Opt_charset),
|
||||
+ fsparam_enum("errors", Opt_errors),
|
||||
+ fsparam_flag("discard", Opt_discard),
|
||||
+ fsparam_s32("time_offset", Opt_time_offset),
|
||||
+ {}
|
||||
+};
|
||||
+
|
||||
+static const struct fs_parameter_enum exfat_param_enums[] = {
|
||||
+ { Opt_errors, "continue", EXFAT_ERRORS_CONT },
|
||||
+ { Opt_errors, "panic", EXFAT_ERRORS_PANIC },
|
||||
+ { Opt_errors, "remount-ro", EXFAT_ERRORS_RO },
|
||||
+ {}
|
||||
+};
|
||||
+
|
||||
+static const struct fs_parameter_description exfat_parameters = {
|
||||
+ .name = "exfat",
|
||||
+ .specs = exfat_param_specs,
|
||||
+ .enums = exfat_param_enums,
|
||||
+};
|
||||
+
|
||||
+static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
|
||||
+{
|
||||
+ struct exfat_sb_info *sbi = fc->s_fs_info;
|
||||
+ struct exfat_mount_options *opts = &sbi->options;
|
||||
+ struct fs_parse_result result;
|
||||
+ int opt;
|
||||
+
|
||||
+ opt = fs_parse(fc, &exfat_parameters, param, &result);
|
||||
+ if (opt < 0)
|
||||
+ return opt;
|
||||
+
|
||||
+ switch (opt) {
|
||||
+ case Opt_uid:
|
||||
+ opts->fs_uid = make_kuid(current_user_ns(), result.uint_32);
|
||||
+ break;
|
||||
+ case Opt_gid:
|
||||
+ opts->fs_gid = make_kgid(current_user_ns(), result.uint_32);
|
||||
+ break;
|
||||
+ case Opt_umask:
|
||||
+ opts->fs_fmask = result.uint_32;
|
||||
+ opts->fs_dmask = result.uint_32;
|
||||
+ break;
|
||||
+ case Opt_dmask:
|
||||
+ opts->fs_dmask = result.uint_32;
|
||||
+ break;
|
||||
+ case Opt_fmask:
|
||||
+ opts->fs_fmask = result.uint_32;
|
||||
+ break;
|
||||
+ case Opt_allow_utime:
|
||||
+ opts->allow_utime = result.uint_32 & 0022;
|
||||
+ break;
|
||||
+ case Opt_charset:
|
||||
+ exfat_free_iocharset(sbi);
|
||||
+ opts->iocharset = kstrdup(param->string, GFP_KERNEL);
|
||||
+ if (!opts->iocharset)
|
||||
+ return -ENOMEM;
|
||||
+ break;
|
||||
+ case Opt_errors:
|
||||
+ opts->errors = result.uint_32;
|
||||
+ break;
|
||||
+ case Opt_discard:
|
||||
+ opts->discard = 1;
|
||||
+ break;
|
||||
+ case Opt_time_offset:
|
||||
+ /*
|
||||
+ * Make the limit 24 just in case someone invents something
|
||||
+ * unusual.
|
||||
+ */
|
||||
+ if (result.int_32 < -24 * 60 || result.int_32 > 24 * 60)
|
||||
+ return -EINVAL;
|
||||
+ opts->time_offset = result.int_32;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void exfat_hash_init(struct super_block *sb)
|
||||
+{
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ int i;
|
||||
+
|
||||
+ spin_lock_init(&sbi->inode_hash_lock);
|
||||
+ for (i = 0; i < EXFAT_HASH_SIZE; i++)
|
||||
+ INIT_HLIST_HEAD(&sbi->inode_hashtable[i]);
|
||||
+}
|
||||
+
|
||||
+static int exfat_read_root(struct inode *inode)
|
||||
+{
|
||||
+ struct super_block *sb = inode->i_sb;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+ struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
+ struct exfat_chain cdir;
|
||||
+ int num_subdirs, num_clu = 0;
|
||||
+
|
||||
+ exfat_chain_set(&ei->dir, sbi->root_dir, 0, ALLOC_FAT_CHAIN);
|
||||
+ ei->entry = -1;
|
||||
+ ei->start_clu = sbi->root_dir;
|
||||
+ ei->flags = ALLOC_FAT_CHAIN;
|
||||
+ ei->type = TYPE_DIR;
|
||||
+ ei->version = 0;
|
||||
+ ei->rwoffset = 0;
|
||||
+ ei->hint_bmap.off = EXFAT_EOF_CLUSTER;
|
||||
+ ei->hint_stat.eidx = 0;
|
||||
+ ei->hint_stat.clu = sbi->root_dir;
|
||||
+ ei->hint_femp.eidx = EXFAT_HINT_NONE;
|
||||
+
|
||||
+ exfat_chain_set(&cdir, sbi->root_dir, 0, ALLOC_FAT_CHAIN);
|
||||
+ if (exfat_count_num_clusters(sb, &cdir, &num_clu))
|
||||
+ return -EIO;
|
||||
+ i_size_write(inode, num_clu << sbi->cluster_size_bits);
|
||||
+
|
||||
+ num_subdirs = exfat_count_dir_entries(sb, &cdir);
|
||||
+ if (num_subdirs < 0)
|
||||
+ return -EIO;
|
||||
+ set_nlink(inode, num_subdirs + EXFAT_MIN_SUBDIR);
|
||||
+
|
||||
+ inode->i_uid = sbi->options.fs_uid;
|
||||
+ inode->i_gid = sbi->options.fs_gid;
|
||||
+ inode_inc_iversion(inode);
|
||||
+ inode->i_generation = 0;
|
||||
+ inode->i_mode = exfat_make_mode(sbi, ATTR_SUBDIR, 0777);
|
||||
+ inode->i_op = &exfat_dir_inode_operations;
|
||||
+ inode->i_fop = &exfat_dir_operations;
|
||||
+
|
||||
+ inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1))
|
||||
+ & ~(sbi->cluster_size - 1)) >> inode->i_blkbits;
|
||||
+ EXFAT_I(inode)->i_pos = ((loff_t)sbi->root_dir << 32) | 0xffffffff;
|
||||
+ EXFAT_I(inode)->i_size_aligned = i_size_read(inode);
|
||||
+ EXFAT_I(inode)->i_size_ondisk = i_size_read(inode);
|
||||
+
|
||||
+ exfat_save_attr(inode, ATTR_SUBDIR);
|
||||
+ inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime =
|
||||
+ current_time(inode);
|
||||
+ exfat_cache_init_inode(inode);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb,
|
||||
+ struct buffer_head **prev_bh)
|
||||
+{
|
||||
+ struct pbr *p_pbr = (struct pbr *) (*prev_bh)->b_data;
|
||||
+ unsigned short logical_sect = 0;
|
||||
+
|
||||
+ logical_sect = 1 << p_pbr->bsx.f64.sect_size_bits;
|
||||
+
|
||||
+ if (!is_power_of_2(logical_sect) ||
|
||||
+ logical_sect < 512 || logical_sect > 4096) {
|
||||
+ exfat_msg(sb, KERN_ERR, "bogus logical sector size %u",
|
||||
+ logical_sect);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (logical_sect < sb->s_blocksize) {
|
||||
+ exfat_msg(sb, KERN_ERR,
|
||||
+ "logical sector size too small for device (logical sector size = %u)",
|
||||
+ logical_sect);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (logical_sect > sb->s_blocksize) {
|
||||
+ struct buffer_head *bh = NULL;
|
||||
+
|
||||
+ __brelse(*prev_bh);
|
||||
+ *prev_bh = NULL;
|
||||
+
|
||||
+ if (!sb_set_blocksize(sb, logical_sect)) {
|
||||
+ exfat_msg(sb, KERN_ERR,
|
||||
+ "unable to set blocksize %u", logical_sect);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ bh = sb_bread(sb, 0);
|
||||
+ if (!bh) {
|
||||
+ exfat_msg(sb, KERN_ERR,
|
||||
+ "unable to read boot sector (logical sector size = %lu)",
|
||||
+ sb->s_blocksize);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ *prev_bh = bh;
|
||||
+ p_pbr = (struct pbr *) bh->b_data;
|
||||
+ }
|
||||
+ return p_pbr;
|
||||
+}
|
||||
+
|
||||
+/* mount the file system volume */
|
||||
+static int __exfat_fill_super(struct super_block *sb)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct pbr *p_pbr;
|
||||
+ struct pbr64 *p_bpb;
|
||||
+ struct buffer_head *bh;
|
||||
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
+
|
||||
+ /* set block size to read super block */
|
||||
+ sb_min_blocksize(sb, 512);
|
||||
+
|
||||
+ /* read boot sector */
|
||||
+ bh = sb_bread(sb, 0);
|
||||
+ if (!bh) {
|
||||
+ exfat_msg(sb, KERN_ERR, "unable to read boot sector");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ /* PRB is read */
|
||||
+ p_pbr = (struct pbr *)bh->b_data;
|
||||
+
|
||||
+ /* check the validity of PBR */
|
||||
+ if (le16_to_cpu((p_pbr->signature)) != PBR_SIGNATURE) {
|
||||
+ exfat_msg(sb, KERN_ERR, "invalid boot record signature");
|
||||
+ ret = -EINVAL;
|
||||
+ goto free_bh;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ /* check logical sector size */
|
||||
+ p_pbr = exfat_read_pbr_with_logical_sector(sb, &bh);
|
||||
+ if (!p_pbr) {
|
||||
+ ret = -EIO;
|
||||
+ goto free_bh;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * res_zero field must be filled with zero to prevent mounting
|
||||
+ * from FAT volume.
|
||||
+ */
|
||||
+ if (memchr_inv(p_pbr->bpb.f64.res_zero, 0,
|
||||
+ sizeof(p_pbr->bpb.f64.res_zero))) {
|
||||
+ ret = -EINVAL;
|
||||
+ goto free_bh;
|
||||
+ }
|
||||
+
|
||||
+ p_bpb = (struct pbr64 *)p_pbr;
|
||||
+ if (!p_bpb->bsx.num_fats) {
|
||||
+ exfat_msg(sb, KERN_ERR, "bogus number of FAT structure");
|
||||
+ ret = -EINVAL;
|
||||
+ goto free_bh;
|
||||
+ }
|
||||
+
|
||||
+ sbi->sect_per_clus = 1 << p_bpb->bsx.sect_per_clus_bits;
|
||||
+ sbi->sect_per_clus_bits = p_bpb->bsx.sect_per_clus_bits;
|
||||
+ sbi->cluster_size_bits = sbi->sect_per_clus_bits + sb->s_blocksize_bits;
|
||||
+ sbi->cluster_size = 1 << sbi->cluster_size_bits;
|
||||
+ sbi->num_FAT_sectors = le32_to_cpu(p_bpb->bsx.fat_length);
|
||||
+ sbi->FAT1_start_sector = le32_to_cpu(p_bpb->bsx.fat_offset);
|
||||
+ sbi->FAT2_start_sector = p_bpb->bsx.num_fats == 1 ?
|
||||
+ sbi->FAT1_start_sector :
|
||||
+ sbi->FAT1_start_sector + sbi->num_FAT_sectors;
|
||||
+ sbi->data_start_sector = le32_to_cpu(p_bpb->bsx.clu_offset);
|
||||
+ sbi->num_sectors = le64_to_cpu(p_bpb->bsx.vol_length);
|
||||
+ /* because the cluster index starts with 2 */
|
||||
+ sbi->num_clusters = le32_to_cpu(p_bpb->bsx.clu_count) +
|
||||
+ EXFAT_RESERVED_CLUSTERS;
|
||||
+
|
||||
+ sbi->root_dir = le32_to_cpu(p_bpb->bsx.root_cluster);
|
||||
+ sbi->dentries_per_clu = 1 <<
|
||||
+ (sbi->cluster_size_bits - DENTRY_SIZE_BITS);
|
||||
+
|
||||
+ sbi->vol_flag = le16_to_cpu(p_bpb->bsx.vol_flags);
|
||||
+ sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER;
|
||||
+ sbi->used_clusters = EXFAT_CLUSTERS_UNTRACKED;
|
||||
+
|
||||
+ if (le16_to_cpu(p_bpb->bsx.vol_flags) & VOL_DIRTY) {
|
||||
+ sbi->vol_flag |= VOL_DIRTY;
|
||||
+ exfat_msg(sb, KERN_WARNING,
|
||||
+ "Volume was not properly unmounted. Some data may be corrupt. Please run fsck.");
|
||||
+ }
|
||||
+
|
||||
+ /* exFAT file size is limited by a disk volume size */
|
||||
+ sb->s_maxbytes = (u64)(sbi->num_clusters - EXFAT_RESERVED_CLUSTERS) <<
|
||||
+ sbi->cluster_size_bits;
|
||||
+
|
||||
+ ret = exfat_create_upcase_table(sb);
|
||||
+ if (ret) {
|
||||
+ exfat_msg(sb, KERN_ERR, "failed to load upcase table");
|
||||
+ goto free_bh;
|
||||
+ }
|
||||
+
|
||||
+ ret = exfat_load_bitmap(sb);
|
||||
+ if (ret) {
|
||||
+ exfat_msg(sb, KERN_ERR, "failed to load alloc-bitmap");
|
||||
+ goto free_upcase_table;
|
||||
+ }
|
||||
+
|
||||
+ ret = exfat_count_used_clusters(sb, &sbi->used_clusters);
|
||||
+ if (ret) {
|
||||
+ exfat_msg(sb, KERN_ERR, "failed to scan clusters");
|
||||
+ goto free_alloc_bitmap;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+free_alloc_bitmap:
|
||||
+ exfat_free_bitmap(sbi);
|
||||
+free_upcase_table:
|
||||
+ exfat_free_upcase_table(sbi);
|
||||
+free_bh:
|
||||
+ brelse(bh);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int exfat_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
+{
|
||||
+ struct exfat_sb_info *sbi = sb->s_fs_info;
|
||||
+ struct exfat_mount_options *opts = &sbi->options;
|
||||
+ struct inode *root_inode;
|
||||
+ int err;
|
||||
+
|
||||
+ if (opts->allow_utime == (unsigned short)-1)
|
||||
+ opts->allow_utime = ~opts->fs_dmask & 0022;
|
||||
+
|
||||
+ if (opts->discard) {
|
||||
+ struct request_queue *q = bdev_get_queue(sb->s_bdev);
|
||||
+
|
||||
+ if (!blk_queue_discard(q))
|
||||
+ exfat_msg(sb, KERN_WARNING,
|
||||
+ "mounting with \"discard\" option, but the device does not support discard");
|
||||
+ opts->discard = 0;
|
||||
+ }
|
||||
+
|
||||
+ sb->s_flags |= SB_NODIRATIME;
|
||||
+ sb->s_magic = EXFAT_SUPER_MAGIC;
|
||||
+ sb->s_op = &exfat_sops;
|
||||
+
|
||||
+ sb->s_time_gran = 1;
|
||||
+ sb->s_time_min = EXFAT_MIN_TIMESTAMP_SECS;
|
||||
+ sb->s_time_max = EXFAT_MAX_TIMESTAMP_SECS;
|
||||
+
|
||||
+ err = __exfat_fill_super(sb);
|
||||
+ if (err) {
|
||||
+ exfat_msg(sb, KERN_ERR, "failed to recognize exfat type");
|
||||
+ goto check_nls_io;
|
||||
+ }
|
||||
+
|
||||
+ /* set up enough so that it can read an inode */
|
||||
+ exfat_hash_init(sb);
|
||||
+
|
||||
+ if (!strcmp(sbi->options.iocharset, "utf8"))
|
||||
+ opts->utf8 = 1;
|
||||
+ else {
|
||||
+ sbi->nls_io = load_nls(sbi->options.iocharset);
|
||||
+ if (!sbi->nls_io) {
|
||||
+ exfat_msg(sb, KERN_ERR, "IO charset %s not found",
|
||||
+ sbi->options.iocharset);
|
||||
+ err = -EINVAL;
|
||||
+ goto free_table;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (sbi->options.utf8)
|
||||
+ sb->s_d_op = &exfat_utf8_dentry_ops;
|
||||
+ else
|
||||
+ sb->s_d_op = &exfat_dentry_ops;
|
||||
+
|
||||
+ root_inode = new_inode(sb);
|
||||
+ if (!root_inode) {
|
||||
+ exfat_msg(sb, KERN_ERR, "failed to allocate root inode.");
|
||||
+ err = -ENOMEM;
|
||||
+ goto free_table;
|
||||
+ }
|
||||
+
|
||||
+ root_inode->i_ino = EXFAT_ROOT_INO;
|
||||
+ inode_set_iversion(root_inode, 1);
|
||||
+ err = exfat_read_root(root_inode);
|
||||
+ if (err) {
|
||||
+ exfat_msg(sb, KERN_ERR, "failed to initialize root inode.");
|
||||
+ goto put_inode;
|
||||
+ }
|
||||
+
|
||||
+ exfat_hash_inode(root_inode, EXFAT_I(root_inode)->i_pos);
|
||||
+ insert_inode_hash(root_inode);
|
||||
+
|
||||
+ sb->s_root = d_make_root(root_inode);
|
||||
+ if (!sb->s_root) {
|
||||
+ exfat_msg(sb, KERN_ERR, "failed to get the root dentry");
|
||||
+ err = -ENOMEM;
|
||||
+ goto put_inode;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+put_inode:
|
||||
+ iput(root_inode);
|
||||
+ sb->s_root = NULL;
|
||||
+
|
||||
+free_table:
|
||||
+ exfat_free_upcase_table(sbi);
|
||||
+ exfat_free_bitmap(sbi);
|
||||
+
|
||||
+check_nls_io:
|
||||
+ unload_nls(sbi->nls_io);
|
||||
+ exfat_free_iocharset(sbi);
|
||||
+ sb->s_fs_info = NULL;
|
||||
+ kfree(sbi);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int exfat_get_tree(struct fs_context *fc)
|
||||
+{
|
||||
+ return get_tree_bdev(fc, exfat_fill_super);
|
||||
+}
|
||||
+
|
||||
+static void exfat_free(struct fs_context *fc)
|
||||
+{
|
||||
+ kfree(fc->s_fs_info);
|
||||
+}
|
||||
+
|
||||
+static const struct fs_context_operations exfat_context_ops = {
|
||||
+ .parse_param = exfat_parse_param,
|
||||
+ .get_tree = exfat_get_tree,
|
||||
+ .free = exfat_free,
|
||||
+};
|
||||
+
|
||||
+static int exfat_init_fs_context(struct fs_context *fc)
|
||||
+{
|
||||
+ struct exfat_sb_info *sbi;
|
||||
+
|
||||
+ sbi = kzalloc(sizeof(struct exfat_sb_info), GFP_KERNEL);
|
||||
+ if (!sbi)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ mutex_init(&sbi->s_lock);
|
||||
+ ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL,
|
||||
+ DEFAULT_RATELIMIT_BURST);
|
||||
+
|
||||
+ sbi->options.fs_uid = current_uid();
|
||||
+ sbi->options.fs_gid = current_gid();
|
||||
+ sbi->options.fs_fmask = current->fs->umask;
|
||||
+ sbi->options.fs_dmask = current->fs->umask;
|
||||
+ sbi->options.allow_utime = -1;
|
||||
+ sbi->options.iocharset = exfat_default_iocharset;
|
||||
+ sbi->options.errors = EXFAT_ERRORS_RO;
|
||||
+
|
||||
+ fc->s_fs_info = sbi;
|
||||
+ fc->ops = &exfat_context_ops;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct file_system_type exfat_fs_type = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .name = "exfat",
|
||||
+ .init_fs_context = exfat_init_fs_context,
|
||||
+ .parameters = &exfat_parameters,
|
||||
+ .kill_sb = kill_block_super,
|
||||
+ .fs_flags = FS_REQUIRES_DEV,
|
||||
+};
|
||||
+
|
||||
+static void exfat_inode_init_once(void *foo)
|
||||
+{
|
||||
+ struct exfat_inode_info *ei = (struct exfat_inode_info *)foo;
|
||||
+
|
||||
+ INIT_HLIST_NODE(&ei->i_hash_fat);
|
||||
+ inode_init_once(&ei->vfs_inode);
|
||||
+}
|
||||
+
|
||||
+static int __init init_exfat_fs(void)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ err = exfat_cache_init();
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ exfat_inode_cachep = kmem_cache_create("exfat_inode_cache",
|
||||
+ sizeof(struct exfat_inode_info),
|
||||
+ 0, SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD,
|
||||
+ exfat_inode_init_once);
|
||||
+ if (!exfat_inode_cachep) {
|
||||
+ err = -ENOMEM;
|
||||
+ goto shutdown_cache;
|
||||
+ }
|
||||
+
|
||||
+ err = register_filesystem(&exfat_fs_type);
|
||||
+ if (err)
|
||||
+ goto destroy_cache;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+destroy_cache:
|
||||
+ kmem_cache_destroy(exfat_inode_cachep);
|
||||
+shutdown_cache:
|
||||
+ exfat_cache_shutdown();
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static void __exit exit_exfat_fs(void)
|
||||
+{
|
||||
+ /*
|
||||
+ * Make sure all delayed rcu free inodes are flushed before we
|
||||
+ * destroy cache.
|
||||
+ */
|
||||
+ rcu_barrier();
|
||||
+ kmem_cache_destroy(exfat_inode_cachep);
|
||||
+ unregister_filesystem(&exfat_fs_type);
|
||||
+ exfat_cache_shutdown();
|
||||
+}
|
||||
+
|
||||
+module_init(init_exfat_fs);
|
||||
+module_exit(exit_exfat_fs);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_DESCRIPTION("exFAT filesystem support");
|
||||
+MODULE_AUTHOR("Samsung Electronics Co., Ltd.");
|
||||
--
|
||||
2.25.1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+84
@@ -0,0 +1,84 @@
|
||||
From 9acd0d53800c55c6e2186e29b6433daf24617451 Mon Sep 17 00:00:00 2001
|
||||
From: Valdis Kletnieks <valdis.kletnieks@vt.edu>
|
||||
Date: Mon, 2 Mar 2020 15:21:45 +0900
|
||||
Subject: [PATCH] exfat: update file system parameter handling
|
||||
|
||||
Al Viro recently reworked the way file system parameters are handled
|
||||
Update super.c to work with it in linux-next 20200203.
|
||||
|
||||
Signed-off-by: Valdis Kletnieks <valdis.kletnieks@vt.edu>
|
||||
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||
Acked-by: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
||||
---
|
||||
fs/exfat/super.c | 28 +++++++++++-----------------
|
||||
1 file changed, 11 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/fs/exfat/super.c b/fs/exfat/super.c
|
||||
index f06e0b53e393..16ed202ef527 100644
|
||||
--- a/fs/exfat/super.c
|
||||
+++ b/fs/exfat/super.c
|
||||
@@ -214,7 +214,14 @@ enum {
|
||||
Opt_time_offset,
|
||||
};
|
||||
|
||||
-static const struct fs_parameter_spec exfat_param_specs[] = {
|
||||
+static const struct constant_table exfat_param_enums[] = {
|
||||
+ { "continue", EXFAT_ERRORS_CONT },
|
||||
+ { "panic", EXFAT_ERRORS_PANIC },
|
||||
+ { "remount-ro", EXFAT_ERRORS_RO },
|
||||
+ {}
|
||||
+};
|
||||
+
|
||||
+static const struct fs_parameter_spec exfat_parameters[] = {
|
||||
fsparam_u32("uid", Opt_uid),
|
||||
fsparam_u32("gid", Opt_gid),
|
||||
fsparam_u32oct("umask", Opt_umask),
|
||||
@@ -222,25 +229,12 @@ static const struct fs_parameter_spec exfat_param_specs[] = {
|
||||
fsparam_u32oct("fmask", Opt_fmask),
|
||||
fsparam_u32oct("allow_utime", Opt_allow_utime),
|
||||
fsparam_string("iocharset", Opt_charset),
|
||||
- fsparam_enum("errors", Opt_errors),
|
||||
+ fsparam_enum("errors", Opt_errors, exfat_param_enums),
|
||||
fsparam_flag("discard", Opt_discard),
|
||||
fsparam_s32("time_offset", Opt_time_offset),
|
||||
{}
|
||||
};
|
||||
|
||||
-static const struct fs_parameter_enum exfat_param_enums[] = {
|
||||
- { Opt_errors, "continue", EXFAT_ERRORS_CONT },
|
||||
- { Opt_errors, "panic", EXFAT_ERRORS_PANIC },
|
||||
- { Opt_errors, "remount-ro", EXFAT_ERRORS_RO },
|
||||
- {}
|
||||
-};
|
||||
-
|
||||
-static const struct fs_parameter_description exfat_parameters = {
|
||||
- .name = "exfat",
|
||||
- .specs = exfat_param_specs,
|
||||
- .enums = exfat_param_enums,
|
||||
-};
|
||||
-
|
||||
static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
|
||||
{
|
||||
struct exfat_sb_info *sbi = fc->s_fs_info;
|
||||
@@ -248,7 +242,7 @@ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
|
||||
struct fs_parse_result result;
|
||||
int opt;
|
||||
|
||||
- opt = fs_parse(fc, &exfat_parameters, param, &result);
|
||||
+ opt = fs_parse(fc, exfat_parameters, param, &result);
|
||||
if (opt < 0)
|
||||
return opt;
|
||||
|
||||
@@ -665,7 +659,7 @@ static struct file_system_type exfat_fs_type = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "exfat",
|
||||
.init_fs_context = exfat_init_fs_context,
|
||||
- .parameters = &exfat_parameters,
|
||||
+ .parameters = exfat_parameters,
|
||||
.kill_sb = kill_block_super,
|
||||
.fs_flags = FS_REQUIRES_DEV,
|
||||
};
|
||||
--
|
||||
2.26.0
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
--- a/Makefile.orig 2019-11-25 03:32:01.000000000 +0300
|
||||
+++ b/Makefile 2019-12-11 03:20:12.876664698 +0300
|
||||
@@ -509,15 +509,6 @@
|
||||
# ignore whole output directory
|
||||
outputmakefile:
|
||||
ifdef building_out_of_srctree
|
||||
- $(Q)if [ -f $(srctree)/.config -o \
|
||||
- -d $(srctree)/include/config -o \
|
||||
- -d $(srctree)/arch/$(SRCARCH)/include/generated ]; then \
|
||||
- echo >&2 "***"; \
|
||||
- echo >&2 "*** The source tree is not clean, please run 'make$(if $(findstring command line, $(origin ARCH)), ARCH=$(ARCH)) mrproper'"; \
|
||||
- echo >&2 "*** in $(abs_srctree)";\
|
||||
- echo >&2 "***"; \
|
||||
- false; \
|
||||
- fi
|
||||
$(Q)ln -fsn $(srctree) source
|
||||
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile $(srctree)
|
||||
$(Q)test -e .gitignore || \
|
||||
@@ -1,780 +0,0 @@
|
||||
--- a/Makefile.orig 2019-11-25 03:32:01.000000000 +0300
|
||||
+++ b/Makefile 2019-12-11 16:59:26.708807035 +0300
|
||||
@@ -3,7 +3,7 @@
|
||||
PATCHLEVEL = 4
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION =
|
||||
-NAME = Kleptomaniac Octopus
|
||||
+NAME = Bobtail Squid
|
||||
|
||||
# *DOCUMENTATION*
|
||||
# To see a list of typical targets execute "make help"
|
||||
@@ -206,16 +206,30 @@
|
||||
KBUILD_CHECKSRC = 0
|
||||
endif
|
||||
|
||||
-# Use make M=dir or set the environment variable KBUILD_EXTMOD to specify the
|
||||
-# directory of external module to build. Setting M= takes precedence.
|
||||
+# Use make M=dir to specify directory of external module to build
|
||||
+# Old syntax make ... SUBDIRS=$PWD is still supported
|
||||
+# Setting the environment variable KBUILD_EXTMOD take precedence
|
||||
+ifdef SUBDIRS
|
||||
+ $(warning ================= WARNING ================)
|
||||
+ $(warning 'SUBDIRS' will be removed after Linux 5.3)
|
||||
+ $(warning )
|
||||
+ $(warning If you are building an individual subdirectory)
|
||||
+ $(warning in the kernel tree, you can do like this:)
|
||||
+ $(warning $$ make path/to/dir/you/want/to/build/)
|
||||
+ $(warning (Do not forget the trailing slash))
|
||||
+ $(warning )
|
||||
+ $(warning If you are building an external module,)
|
||||
+ $(warning Please use 'M=' or 'KBUILD_EXTMOD' instead)
|
||||
+ $(warning ==========================================)
|
||||
+ KBUILD_EXTMOD ?= $(SUBDIRS)
|
||||
+endif
|
||||
+
|
||||
ifeq ("$(origin M)", "command line")
|
||||
KBUILD_EXTMOD := $(M)
|
||||
endif
|
||||
|
||||
export KBUILD_CHECKSRC KBUILD_EXTMOD
|
||||
|
||||
-extmod-prefix = $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)
|
||||
-
|
||||
ifeq ($(abs_srctree),$(abs_objtree))
|
||||
# building in the source tree
|
||||
srctree := .
|
||||
@@ -257,62 +271,52 @@
|
||||
%asm-generic kernelversion %src-pkg
|
||||
no-sync-config-targets := $(no-dot-config-targets) install %install \
|
||||
kernelrelease
|
||||
-single-targets := %.a %.i %.ko %.lds %.ll %.lst %.mod %.o %.s %.symtypes %/
|
||||
|
||||
-config-build :=
|
||||
-mixed-build :=
|
||||
-need-config := 1
|
||||
-may-sync-config := 1
|
||||
-single-build :=
|
||||
+config-targets := 0
|
||||
+mixed-targets := 0
|
||||
+dot-config := 1
|
||||
+may-sync-config := 1
|
||||
|
||||
ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
|
||||
ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
|
||||
- need-config :=
|
||||
+ dot-config := 0
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(no-sync-config-targets), $(MAKECMDGOALS)),)
|
||||
ifeq ($(filter-out $(no-sync-config-targets), $(MAKECMDGOALS)),)
|
||||
- may-sync-config :=
|
||||
+ may-sync-config := 0
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(KBUILD_EXTMOD),)
|
||||
- may-sync-config :=
|
||||
+ may-sync-config := 0
|
||||
endif
|
||||
|
||||
ifeq ($(KBUILD_EXTMOD),)
|
||||
ifneq ($(filter config %config,$(MAKECMDGOALS)),)
|
||||
- config-build := 1
|
||||
+ config-targets := 1
|
||||
ifneq ($(words $(MAKECMDGOALS)),1)
|
||||
- mixed-build := 1
|
||||
+ mixed-targets := 1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
-# We cannot build single targets and the others at the same time
|
||||
-ifneq ($(filter $(single-targets), $(MAKECMDGOALS)),)
|
||||
- single-build := 1
|
||||
- ifneq ($(filter-out $(single-targets), $(MAKECMDGOALS)),)
|
||||
- mixed-build := 1
|
||||
- endif
|
||||
-endif
|
||||
-
|
||||
# For "make -j clean all", "make -j mrproper defconfig all", etc.
|
||||
ifneq ($(filter $(clean-targets),$(MAKECMDGOALS)),)
|
||||
ifneq ($(filter-out $(clean-targets),$(MAKECMDGOALS)),)
|
||||
- mixed-build := 1
|
||||
+ mixed-targets := 1
|
||||
endif
|
||||
endif
|
||||
|
||||
# install and modules_install need also be processed one by one
|
||||
ifneq ($(filter install,$(MAKECMDGOALS)),)
|
||||
ifneq ($(filter modules_install,$(MAKECMDGOALS)),)
|
||||
- mixed-build := 1
|
||||
+ mixed-targets := 1
|
||||
endif
|
||||
endif
|
||||
|
||||
-ifdef mixed-build
|
||||
+ifeq ($(mixed-targets),1)
|
||||
# ===========================================================================
|
||||
# We're called with mixed targets (*config and build targets).
|
||||
# Handle them one by one.
|
||||
@@ -328,7 +332,7 @@
|
||||
$(MAKE) -f $(srctree)/Makefile $$i; \
|
||||
done
|
||||
|
||||
-else # !mixed-build
|
||||
+else
|
||||
|
||||
include scripts/Kbuild.include
|
||||
|
||||
@@ -388,7 +392,9 @@
|
||||
export KCONFIG_CONFIG
|
||||
|
||||
# SHELL used by kbuild
|
||||
-CONFIG_SHELL := sh
|
||||
+CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
|
||||
+ else if [ -x /bin/bash ]; then echo /bin/bash; \
|
||||
+ else echo sh; fi ; fi)
|
||||
|
||||
HOST_LFS_CFLAGS := $(shell getconf LFS_CFLAGS 2>/dev/null)
|
||||
HOST_LFS_LDFLAGS := $(shell getconf LFS_LDFLAGS 2>/dev/null)
|
||||
@@ -425,7 +431,6 @@
|
||||
PYTHON2 = python2
|
||||
PYTHON3 = python3
|
||||
CHECK = sparse
|
||||
-BASH = bash
|
||||
|
||||
CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
|
||||
-Wbitwise -Wno-return-void -Wno-unknown-attribute $(CF)
|
||||
@@ -465,13 +470,12 @@
|
||||
KBUILD_CFLAGS_KERNEL :=
|
||||
KBUILD_AFLAGS_MODULE := -DMODULE
|
||||
KBUILD_CFLAGS_MODULE := -DMODULE
|
||||
-KBUILD_LDFLAGS_MODULE :=
|
||||
-export KBUILD_LDS_MODULE := $(srctree)/scripts/module-common.lds
|
||||
+KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
|
||||
KBUILD_LDFLAGS :=
|
||||
GCC_PLUGINS_CFLAGS :=
|
||||
CLANG_FLAGS :=
|
||||
|
||||
-export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE AS LD CC
|
||||
+export ARCH SRCARCH CONFIG_SHELL HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE AS LD CC
|
||||
export CPP AR NM STRIP OBJCOPY OBJDUMP OBJSIZE PAHOLE LEX YACC AWK INSTALLKERNEL
|
||||
export PERL PYTHON PYTHON2 PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
|
||||
export KBUILD_HOSTCXXFLAGS KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS LDFLAGS_MODULE
|
||||
@@ -482,6 +486,7 @@
|
||||
export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
|
||||
export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
|
||||
export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
|
||||
+export KBUILD_ARFLAGS
|
||||
|
||||
# Files to ignore in find ... statements
|
||||
|
||||
@@ -501,7 +506,6 @@
|
||||
$(Q)rm -f .tmp_quiet_recordmcount
|
||||
|
||||
PHONY += outputmakefile
|
||||
-# Before starting out-of-tree build, make sure the source tree is clean.
|
||||
# outputmakefile generates a Makefile in the output directory, if using a
|
||||
# separate output directory. This allows convenient use of make in the
|
||||
# output directory.
|
||||
@@ -509,15 +513,6 @@
|
||||
# ignore whole output directory
|
||||
outputmakefile:
|
||||
ifdef building_out_of_srctree
|
||||
- $(Q)if [ -f $(srctree)/.config -o \
|
||||
- -d $(srctree)/include/config -o \
|
||||
- -d $(srctree)/arch/$(SRCARCH)/include/generated ]; then \
|
||||
- echo >&2 "***"; \
|
||||
- echo >&2 "*** The source tree is not clean, please run 'make$(if $(findstring command line, $(origin ARCH)), ARCH=$(ARCH)) mrproper'"; \
|
||||
- echo >&2 "*** in $(abs_srctree)";\
|
||||
- echo >&2 "***"; \
|
||||
- false; \
|
||||
- fi
|
||||
$(Q)ln -fsn $(srctree) source
|
||||
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile $(srctree)
|
||||
$(Q)test -e .gitignore || \
|
||||
@@ -549,7 +544,7 @@
|
||||
# and from include/config/auto.conf.cmd to detect the compiler upgrade.
|
||||
CC_VERSION_TEXT = $(shell $(CC) --version 2>/dev/null | head -n 1)
|
||||
|
||||
-ifdef config-build
|
||||
+ifeq ($(config-targets),1)
|
||||
# ===========================================================================
|
||||
# *config targets only - make sure prerequisites are updated, and descend
|
||||
# in scripts/kconfig to make the *config target
|
||||
@@ -560,13 +555,13 @@
|
||||
include arch/$(SRCARCH)/Makefile
|
||||
export KBUILD_DEFCONFIG KBUILD_KCONFIG CC_VERSION_TEXT
|
||||
|
||||
-config: outputmakefile scripts_basic FORCE
|
||||
+config: scripts_basic outputmakefile FORCE
|
||||
$(Q)$(MAKE) $(build)=scripts/kconfig $@
|
||||
|
||||
-%config: outputmakefile scripts_basic FORCE
|
||||
+%config: scripts_basic outputmakefile FORCE
|
||||
$(Q)$(MAKE) $(build)=scripts/kconfig $@
|
||||
|
||||
-else #!config-build
|
||||
+else
|
||||
# ===========================================================================
|
||||
# Build targets only - this includes vmlinux, arch specific targets, clean
|
||||
# targets and others. In general all targets except *config targets.
|
||||
@@ -599,7 +594,7 @@
|
||||
# in addition to whatever we do anyway.
|
||||
# Just "make" or "make all" shall build modules as well
|
||||
|
||||
-ifneq ($(filter all _all modules nsdeps,$(MAKECMDGOALS)),)
|
||||
+ifneq ($(filter all _all modules,$(MAKECMDGOALS)),)
|
||||
KBUILD_MODULES := 1
|
||||
endif
|
||||
|
||||
@@ -609,7 +604,7 @@
|
||||
|
||||
export KBUILD_MODULES KBUILD_BUILTIN
|
||||
|
||||
-ifdef need-config
|
||||
+ifeq ($(dot-config),1)
|
||||
include include/config/auto.conf
|
||||
endif
|
||||
|
||||
@@ -650,10 +645,15 @@
|
||||
export RETPOLINE_CFLAGS
|
||||
export RETPOLINE_VDSO_CFLAGS
|
||||
|
||||
+# The arch Makefile can set ARCH_{CPP,A,C}FLAGS to override the default
|
||||
+# values of the respective KBUILD_* variables
|
||||
+ARCH_CPPFLAGS :=
|
||||
+ARCH_AFLAGS :=
|
||||
+ARCH_CFLAGS :=
|
||||
include arch/$(SRCARCH)/Makefile
|
||||
|
||||
-ifdef need-config
|
||||
-ifdef may-sync-config
|
||||
+ifeq ($(dot-config),1)
|
||||
+ifeq ($(may-sync-config),1)
|
||||
# Read in dependencies to all Kconfig* files, make sure to run syncconfig if
|
||||
# changes are detected. This should be included after arch/$(SRCARCH)/Makefile
|
||||
# because some architectures define CROSS_COMPILE there.
|
||||
@@ -676,7 +676,7 @@
|
||||
# The syncconfig should be executed only once to make all the targets.
|
||||
%/auto.conf %/auto.conf.cmd %/tristate.conf: $(KCONFIG_CONFIG)
|
||||
$(Q)$(MAKE) -f $(srctree)/Makefile syncconfig
|
||||
-else # !may-sync-config
|
||||
+else
|
||||
# External modules and some install targets need include/generated/autoconf.h
|
||||
# and include/config/auto.conf but do not care if they are up-to-date.
|
||||
# Use auto.conf to trigger the test
|
||||
@@ -692,7 +692,7 @@
|
||||
/bin/false)
|
||||
|
||||
endif # may-sync-config
|
||||
-endif # need-config
|
||||
+endif # $(dot-config)
|
||||
|
||||
KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks,)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,)
|
||||
@@ -700,12 +700,10 @@
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
|
||||
|
||||
-ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE
|
||||
-KBUILD_CFLAGS += -O2
|
||||
-else ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3
|
||||
-KBUILD_CFLAGS += -O3
|
||||
-else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
|
||||
-KBUILD_CFLAGS += -Os
|
||||
+ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
|
||||
+KBUILD_CFLAGS += -Os
|
||||
+else
|
||||
+KBUILD_CFLAGS += -O2
|
||||
endif
|
||||
|
||||
ifdef CONFIG_CC_DISABLE_WARN_MAYBE_UNINITIALIZED
|
||||
@@ -753,11 +751,6 @@
|
||||
# These warnings generated too much noise in a regular build.
|
||||
# Use make W=1 to enable them (see scripts/Makefile.extrawarn)
|
||||
KBUILD_CFLAGS += -Wno-unused-but-set-variable
|
||||
-
|
||||
-# Warn about unmarked fall-throughs in switch statement.
|
||||
-# Disabled for clang while comment to attribute conversion happens and
|
||||
-# https://github.com/ClangBuiltLinux/linux/issues/636 is discussed.
|
||||
-KBUILD_CFLAGS += $(call cc-option,-Wimplicit-fallthrough,)
|
||||
endif
|
||||
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, unused-const-variable)
|
||||
@@ -852,6 +845,9 @@
|
||||
# warn about C99 declaration after statement
|
||||
KBUILD_CFLAGS += -Wdeclaration-after-statement
|
||||
|
||||
+# Warn about unmarked fall-throughs in switch statement.
|
||||
+KBUILD_CFLAGS += $(call cc-option,-Wimplicit-fallthrough,)
|
||||
+
|
||||
# Variable Length Arrays (VLAs) should not be used anywhere in the kernel
|
||||
KBUILD_CFLAGS += -Wvla
|
||||
|
||||
@@ -897,14 +893,18 @@
|
||||
KBUILD_CFLAGS += $(call cc-option,-fcf-protection=none)
|
||||
endif
|
||||
|
||||
+# use the deterministic mode of AR if available
|
||||
+KBUILD_ARFLAGS := $(call ar-option,D)
|
||||
+
|
||||
include scripts/Makefile.kasan
|
||||
include scripts/Makefile.extrawarn
|
||||
include scripts/Makefile.ubsan
|
||||
|
||||
-# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
|
||||
-KBUILD_CPPFLAGS += $(KCPPFLAGS)
|
||||
-KBUILD_AFLAGS += $(KAFLAGS)
|
||||
-KBUILD_CFLAGS += $(KCFLAGS)
|
||||
+# Add any arch overrides and user supplied CPPFLAGS, AFLAGS and CFLAGS as the
|
||||
+# last assignments
|
||||
+KBUILD_CPPFLAGS += $(ARCH_CPPFLAGS) $(KCPPFLAGS)
|
||||
+KBUILD_AFLAGS += $(ARCH_AFLAGS) $(KAFLAGS)
|
||||
+KBUILD_CFLAGS += $(ARCH_CFLAGS) $(KCFLAGS)
|
||||
|
||||
KBUILD_LDFLAGS_MODULE += --build-id
|
||||
LDFLAGS_vmlinux += --build-id
|
||||
@@ -913,13 +913,6 @@
|
||||
LDFLAGS_vmlinux += $(call ld-option, -X,)
|
||||
endif
|
||||
|
||||
-ifeq ($(CONFIG_RELR),y)
|
||||
-LDFLAGS_vmlinux += --pack-dyn-relocs=relr
|
||||
-endif
|
||||
-
|
||||
-# make the checker run with the right architecture
|
||||
-CHECKFLAGS += --arch=$(ARCH)
|
||||
-
|
||||
# insure the checker run with the right endianness
|
||||
CHECKFLAGS += $(if $(CONFIG_CPU_BIG_ENDIAN),-mbig-endian,-mlittle-endian)
|
||||
|
||||
@@ -1010,7 +1003,7 @@
|
||||
|
||||
PHONY += prepare0
|
||||
|
||||
-export MODORDER := $(extmod-prefix)modules.order
|
||||
+export MODORDER := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)modules.order
|
||||
|
||||
ifeq ($(KBUILD_EXTMOD),)
|
||||
core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
|
||||
@@ -1023,9 +1016,6 @@
|
||||
$(patsubst %/,%,$(filter %/, $(init-) $(core-) \
|
||||
$(drivers-) $(net-) $(libs-) $(virt-))))
|
||||
|
||||
-build-dirs := $(vmlinux-dirs)
|
||||
-clean-dirs := $(vmlinux-alldirs)
|
||||
-
|
||||
init-y := $(patsubst %/, %/built-in.a, $(init-y))
|
||||
core-y := $(patsubst %/, %/built-in.a, $(core-y))
|
||||
drivers-y := $(patsubst %/, %/built-in.a, $(drivers-y))
|
||||
@@ -1040,7 +1030,7 @@
|
||||
export KBUILD_VMLINUX_LIBS := $(libs-y1)
|
||||
export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds
|
||||
export LDFLAGS_vmlinux
|
||||
-# used by scripts/Makefile.package
|
||||
+# used by scripts/package/Makefile
|
||||
export KBUILD_ALLDIRS := $(sort $(filter-out arch/%,$(vmlinux-alldirs)) LICENSES arch include scripts tools)
|
||||
|
||||
vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_OBJS) $(KBUILD_VMLINUX_LIBS)
|
||||
@@ -1048,7 +1038,7 @@
|
||||
# Recurse until adjust_autoksyms.sh is satisfied
|
||||
PHONY += autoksyms_recursive
|
||||
ifdef CONFIG_TRIM_UNUSED_KSYMS
|
||||
-autoksyms_recursive: descend modules.order
|
||||
+autoksyms_recursive: $(vmlinux-deps) modules.order
|
||||
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/adjust_autoksyms.sh \
|
||||
"$(MAKE) -f $(srctree)/Makefile vmlinux"
|
||||
endif
|
||||
@@ -1080,7 +1070,17 @@
|
||||
|
||||
# The actual objects are generated when descending,
|
||||
# make sure no implicit rule kicks in
|
||||
-$(sort $(vmlinux-deps)): descend ;
|
||||
+$(sort $(vmlinux-deps)): $(vmlinux-dirs) ;
|
||||
+
|
||||
+# Handle descending into subdirectories listed in $(vmlinux-dirs)
|
||||
+# Preset locale variables to speed up the build process. Limit locale
|
||||
+# tweaks to this spot to avoid wrong language settings when running
|
||||
+# make menuconfig etc.
|
||||
+# Error messages still appears in the original language
|
||||
+
|
||||
+PHONY += $(vmlinux-dirs)
|
||||
+$(vmlinux-dirs): prepare
|
||||
+ $(Q)$(MAKE) $(build)=$@ need-builtin=1 need-modorder=1
|
||||
|
||||
filechk_kernel.release = \
|
||||
echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))"
|
||||
@@ -1102,9 +1102,24 @@
|
||||
# archprepare is used in arch Makefiles and when processed asm symlink,
|
||||
# version.h and scripts_basic is processed / created.
|
||||
|
||||
-PHONY += prepare archprepare
|
||||
+PHONY += prepare archprepare prepare3
|
||||
|
||||
-archprepare: outputmakefile archheaders archscripts scripts include/config/kernel.release \
|
||||
+# prepare3 is used to check if we are building in a separate output directory,
|
||||
+# and if so do:
|
||||
+# 1) Check that make has not been executed in the kernel src $(srctree)
|
||||
+prepare3: include/config/kernel.release
|
||||
+ifdef building_out_of_srctree
|
||||
+ @$(kecho) ' Using $(srctree) as source for kernel'
|
||||
+ $(Q)if [ -f $(srctree)/.config -o \
|
||||
+ -d $(srctree)/include/config -o \
|
||||
+ -d $(srctree)/arch/$(SRCARCH)/include/generated ]; then \
|
||||
+ echo >&2 " $(srctree) is not clean, please run 'make ARCH=$(ARCH) mrproper'"; \
|
||||
+ echo >&2 " in the '$(srctree)' directory.";\
|
||||
+ /bin/false; \
|
||||
+ fi;
|
||||
+endif
|
||||
+
|
||||
+archprepare: archheaders archscripts scripts prepare3 outputmakefile \
|
||||
asm-generic $(version_h) $(autoksyms_h) include/generated/utsrelease.h
|
||||
|
||||
prepare0: archprepare
|
||||
@@ -1220,15 +1235,16 @@
|
||||
kselftest:
|
||||
$(Q)$(MAKE) -C $(srctree)/tools/testing/selftests run_tests
|
||||
|
||||
-kselftest-%: FORCE
|
||||
- $(Q)$(MAKE) -C $(srctree)/tools/testing/selftests $*
|
||||
+PHONY += kselftest-clean
|
||||
+kselftest-clean:
|
||||
+ $(Q)$(MAKE) -C $(srctree)/tools/testing/selftests clean
|
||||
|
||||
PHONY += kselftest-merge
|
||||
kselftest-merge:
|
||||
$(if $(wildcard $(objtree)/.config),, $(error No .config exists, config your kernel first!))
|
||||
$(Q)find $(srctree)/tools/testing/selftests -name config | \
|
||||
xargs $(srctree)/scripts/kconfig/merge_config.sh -m $(objtree)/.config
|
||||
- $(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig
|
||||
+ +$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Devicetree files
|
||||
@@ -1239,11 +1255,11 @@
|
||||
|
||||
ifneq ($(dtstree),)
|
||||
|
||||
-%.dtb: include/config/kernel.release scripts_dtc
|
||||
+%.dtb: prepare3 scripts_dtc
|
||||
$(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@
|
||||
|
||||
PHONY += dtbs dtbs_install dt_binding_check
|
||||
-dtbs dtbs_check: include/config/kernel.release scripts_dtc
|
||||
+dtbs dtbs_check: prepare3 scripts_dtc
|
||||
$(Q)$(MAKE) $(build)=$(dtstree)
|
||||
|
||||
dtbs_check: export CHECK_DTBS=1
|
||||
@@ -1282,16 +1298,17 @@
|
||||
|
||||
PHONY += modules
|
||||
modules: $(if $(KBUILD_BUILTIN),vmlinux) modules.order modules.builtin
|
||||
+ @$(kecho) ' Building modules, stage 2.';
|
||||
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
|
||||
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/modules-check.sh
|
||||
|
||||
-modules.order: descend
|
||||
- $(Q)$(AWK) '!x[$$0]++' $(addsuffix /$@, $(build-dirs)) > $@
|
||||
+modules.order: $(vmlinux-dirs)
|
||||
+ $(Q)$(AWK) '!x[$$0]++' $(addsuffix /$@, $(vmlinux-dirs)) > $@
|
||||
|
||||
-modbuiltin-dirs := $(addprefix _modbuiltin_, $(build-dirs))
|
||||
+modbuiltin-dirs := $(addprefix _modbuiltin_, $(vmlinux-dirs))
|
||||
|
||||
modules.builtin: $(modbuiltin-dirs)
|
||||
- $(Q)$(AWK) '!x[$$0]++' $(addsuffix /$@, $(build-dirs)) > $@
|
||||
+ $(Q)$(AWK) '!x[$$0]++' $(addsuffix /$@, $(vmlinux-dirs)) > $@
|
||||
|
||||
PHONY += $(modbuiltin-dirs)
|
||||
# tristate.conf is not included from this Makefile. Add it as a prerequisite
|
||||
@@ -1364,14 +1381,12 @@
|
||||
|
||||
# Directories & files removed with 'make mrproper'
|
||||
MRPROPER_DIRS += include/config include/generated \
|
||||
- arch/$(SRCARCH)/include/generated .tmp_objdiff \
|
||||
- debian/ snap/ tar-install/
|
||||
+ arch/$(SRCARCH)/include/generated .tmp_objdiff
|
||||
MRPROPER_FILES += .config .config.old .version \
|
||||
Module.symvers \
|
||||
signing_key.pem signing_key.priv signing_key.x509 \
|
||||
x509.genkey extra_certificates signing_key.x509.keyid \
|
||||
- signing_key.x509.signer vmlinux-gdb.py \
|
||||
- *.spec
|
||||
+ signing_key.x509.signer vmlinux-gdb.py
|
||||
|
||||
# Directories & files removed with 'make distclean'
|
||||
DISTCLEAN_DIRS +=
|
||||
@@ -1381,8 +1396,11 @@
|
||||
#
|
||||
clean: rm-dirs := $(CLEAN_DIRS)
|
||||
clean: rm-files := $(CLEAN_FILES)
|
||||
+clean-dirs := $(addprefix _clean_, . $(vmlinux-alldirs))
|
||||
|
||||
-PHONY += archclean vmlinuxclean
|
||||
+PHONY += $(clean-dirs) clean archclean vmlinuxclean
|
||||
+$(clean-dirs):
|
||||
+ $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
|
||||
|
||||
vmlinuxclean:
|
||||
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean
|
||||
@@ -1423,11 +1441,13 @@
|
||||
|
||||
# Packaging of the kernel to various formats
|
||||
# ---------------------------------------------------------------------------
|
||||
+package-dir := scripts/package
|
||||
|
||||
%src-pkg: FORCE
|
||||
- $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.package $@
|
||||
+ $(Q)$(MAKE) $(build)=$(package-dir) $@
|
||||
%pkg: include/config/kernel.release FORCE
|
||||
- $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.package $@
|
||||
+ $(Q)$(MAKE) $(build)=$(package-dir) $@
|
||||
+
|
||||
|
||||
# Brief documentation of the typical targets used
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -1480,9 +1500,6 @@
|
||||
@echo ' headerdep - Detect inclusion cycles in headers'
|
||||
@echo ' coccicheck - Check with Coccinelle'
|
||||
@echo ''
|
||||
- @echo 'Tools:'
|
||||
- @echo ' nsdeps - Generate missing symbol namespace dependencies'
|
||||
- @echo ''
|
||||
@echo 'Kernel selftest:'
|
||||
@echo ' kselftest - Build and run kernel selftest (run as root)'
|
||||
@echo ' Build, install, and boot kernel before'
|
||||
@@ -1493,10 +1510,8 @@
|
||||
@echo ''
|
||||
@$(if $(dtstree), \
|
||||
echo 'Devicetree:'; \
|
||||
- echo '* dtbs - Build device tree blobs for enabled boards'; \
|
||||
- echo ' dtbs_install - Install dtbs to $(INSTALL_DTBS_PATH)'; \
|
||||
- echo ' dt_binding_check - Validate device tree binding documents'; \
|
||||
- echo ' dtbs_check - Validate device tree source files';\
|
||||
+ echo '* dtbs - Build device tree blobs for enabled boards'; \
|
||||
+ echo ' dtbs_install - Install dtbs to $(INSTALL_DTBS_PATH)'; \
|
||||
echo '')
|
||||
|
||||
@echo 'Userspace tools targets:'
|
||||
@@ -1504,7 +1519,7 @@
|
||||
@echo ' or "cd tools; make help"'
|
||||
@echo ''
|
||||
@echo 'Kernel packaging:'
|
||||
- @$(MAKE) -f $(srctree)/scripts/Makefile.package help
|
||||
+ @$(MAKE) $(build)=$(package-dir) help
|
||||
@echo ''
|
||||
@echo 'Documentation targets:'
|
||||
@$(MAKE) -f $(srctree)/Documentation/Makefile dochelp
|
||||
@@ -1529,7 +1544,7 @@
|
||||
@echo ' make C=1 [targets] Check re-compiled c source with $$CHECK (sparse by default)'
|
||||
@echo ' make C=2 [targets] Force check of all c source with $$CHECK'
|
||||
@echo ' make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections'
|
||||
- @echo ' make W=n [targets] Enable extra build checks, n=1,2,3 where'
|
||||
+ @echo ' make W=n [targets] Enable extra gcc checks, n=1,2,3 where'
|
||||
@echo ' 1: warnings which may be relevant and do not occur too often'
|
||||
@echo ' 2: warnings which occur quite often but may still be relevant'
|
||||
@echo ' 3: more obscure warnings, can most likely be ignored'
|
||||
@@ -1558,7 +1573,7 @@
|
||||
DOC_TARGETS := xmldocs latexdocs pdfdocs htmldocs epubdocs cleandocs \
|
||||
linkcheckdocs dochelp refcheckdocs
|
||||
PHONY += $(DOC_TARGETS)
|
||||
-$(DOC_TARGETS):
|
||||
+$(DOC_TARGETS): scripts_basic FORCE
|
||||
$(Q)$(MAKE) $(build)=Documentation $@
|
||||
|
||||
# Misc
|
||||
@@ -1603,9 +1618,13 @@
|
||||
echo " is missing; modules will have no dependencies and modversions."; \
|
||||
echo )
|
||||
|
||||
-build-dirs := $(KBUILD_EXTMOD)
|
||||
-PHONY += modules
|
||||
-modules: descend $(objtree)/Module.symvers
|
||||
+module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD))
|
||||
+PHONY += $(module-dirs) modules
|
||||
+$(module-dirs): prepare $(objtree)/Module.symvers
|
||||
+ $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@) need-modorder=1
|
||||
+
|
||||
+modules: $(module-dirs)
|
||||
+ @$(kecho) ' Building modules, stage 2.';
|
||||
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
|
||||
|
||||
PHONY += modules_install
|
||||
@@ -1621,12 +1640,13 @@
|
||||
_emodinst_post: _emodinst_
|
||||
$(call cmd,depmod)
|
||||
|
||||
-clean-dirs := $(KBUILD_EXTMOD)
|
||||
-clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers
|
||||
+clean-dirs := $(addprefix _clean_,$(KBUILD_EXTMOD))
|
||||
|
||||
-PHONY += /
|
||||
-/:
|
||||
- @echo >&2 '"$(MAKE) /" is no longer supported. Please use "$(MAKE) ./" instead.'
|
||||
+PHONY += $(clean-dirs) clean
|
||||
+$(clean-dirs):
|
||||
+ $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
|
||||
+
|
||||
+clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers
|
||||
|
||||
PHONY += help
|
||||
help:
|
||||
@@ -1641,21 +1661,6 @@
|
||||
PHONY += prepare
|
||||
endif # KBUILD_EXTMOD
|
||||
|
||||
-# Handle descending into subdirectories listed in $(build-dirs)
|
||||
-# Preset locale variables to speed up the build process. Limit locale
|
||||
-# tweaks to this spot to avoid wrong language settings when running
|
||||
-# make menuconfig etc.
|
||||
-# Error messages still appears in the original language
|
||||
-PHONY += descend $(build-dirs)
|
||||
-descend: $(build-dirs)
|
||||
-$(build-dirs): prepare
|
||||
- $(Q)$(MAKE) $(build)=$@ single-build=$(single-build) need-builtin=1 need-modorder=1
|
||||
-
|
||||
-clean-dirs := $(addprefix _clean_, $(clean-dirs))
|
||||
-PHONY += $(clean-dirs) clean
|
||||
-$(clean-dirs):
|
||||
- $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
|
||||
-
|
||||
clean: $(clean-dirs)
|
||||
$(call cmd,rmdirs)
|
||||
$(call cmd,rmfiles)
|
||||
@@ -1664,7 +1669,7 @@
|
||||
-o -name '*.ko.*' \
|
||||
-o -name '*.dtb' -o -name '*.dtb.S' -o -name '*.dt.yaml' \
|
||||
-o -name '*.dwo' -o -name '*.lst' \
|
||||
- -o -name '*.su' -o -name '*.mod' -o -name '*.ns_deps' \
|
||||
+ -o -name '*.su' -o -name '*.mod' \
|
||||
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
|
||||
-o -name '*.lex.c' -o -name '*.tab.[ch]' \
|
||||
-o -name '*.asn1.[ch]' \
|
||||
@@ -1677,20 +1682,11 @@
|
||||
# Generate tags for editors
|
||||
# ---------------------------------------------------------------------------
|
||||
quiet_cmd_tags = GEN $@
|
||||
- cmd_tags = $(BASH) $(srctree)/scripts/tags.sh $@
|
||||
+ cmd_tags = $(CONFIG_SHELL) $(srctree)/scripts/tags.sh $@
|
||||
|
||||
tags TAGS cscope gtags: FORCE
|
||||
$(call cmd,tags)
|
||||
|
||||
-# Script to generate missing namespace dependencies
|
||||
-# ---------------------------------------------------------------------------
|
||||
-
|
||||
-PHONY += nsdeps
|
||||
-
|
||||
-nsdeps: modules
|
||||
- $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost nsdeps
|
||||
- $(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@
|
||||
-
|
||||
# Scripts to check various things for consistency
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -1707,7 +1703,7 @@
|
||||
| xargs $(PERL) -w $(srctree)/scripts/checkversion.pl
|
||||
|
||||
coccicheck:
|
||||
- $(Q)$(BASH) $(srctree)/scripts/$@
|
||||
+ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@
|
||||
|
||||
namespacecheck:
|
||||
$(PERL) $(srctree)/scripts/namespace.pl
|
||||
@@ -1755,47 +1751,45 @@
|
||||
|
||||
# Single targets
|
||||
# ---------------------------------------------------------------------------
|
||||
-# To build individual files in subdirectories, you can do like this:
|
||||
-#
|
||||
-# make foo/bar/baz.s
|
||||
-#
|
||||
-# The supported suffixes for single-target are listed in 'single-targets'
|
||||
-#
|
||||
-# To build only under specific subdirectories, you can do like this:
|
||||
-#
|
||||
-# make foo/bar/baz/
|
||||
-
|
||||
-ifdef single-build
|
||||
-
|
||||
-single-all := $(filter $(single-targets), $(MAKECMDGOALS))
|
||||
-
|
||||
-# .ko is special because modpost is needed
|
||||
-single-ko := $(sort $(filter %.ko, $(single-all)))
|
||||
-single-no-ko := $(sort $(patsubst %.ko,%.mod, $(single-all)))
|
||||
-
|
||||
-$(single-ko): single_modpost
|
||||
- @:
|
||||
-$(single-no-ko): descend
|
||||
- @:
|
||||
-
|
||||
+# Single targets are compatible with:
|
||||
+# - build with mixed source and output
|
||||
+# - build with separate output dir 'make O=...'
|
||||
+# - external modules
|
||||
+#
|
||||
+# target-dir => where to store outputfile
|
||||
+# build-dir => directory in kernel source tree to use
|
||||
+
|
||||
+build-target = $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD)/)$@
|
||||
+build-dir = $(patsubst %/,%,$(dir $(build-target)))
|
||||
+
|
||||
+%.i: prepare FORCE
|
||||
+ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
|
||||
+%.ll: prepare FORCE
|
||||
+ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
|
||||
+%.lst: prepare FORCE
|
||||
+ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
|
||||
+%.o: prepare FORCE
|
||||
+ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
|
||||
+%.s: prepare FORCE
|
||||
+ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
|
||||
+%.symtypes: prepare FORCE
|
||||
+ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
|
||||
ifeq ($(KBUILD_EXTMOD),)
|
||||
-# For the single build of in-tree modules, use a temporary file to avoid
|
||||
+# For the single build of an in-tree module, use a temporary file to avoid
|
||||
# the situation of modules_install installing an invalid modules.order.
|
||||
-MODORDER := .modules.tmp
|
||||
+%.ko: MODORDER := .modules.tmp
|
||||
endif
|
||||
-
|
||||
-PHONY += single_modpost
|
||||
-single_modpost: $(single-no-ko)
|
||||
- $(Q){ $(foreach m, $(single-ko), echo $(extmod-prefix)$m;) } > $(MODORDER)
|
||||
+%.ko: prepare FORCE
|
||||
+ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target:.ko=.mod)
|
||||
+ $(Q)echo $(build-target) > $(MODORDER)
|
||||
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
|
||||
|
||||
-KBUILD_MODULES := 1
|
||||
-
|
||||
-export KBUILD_SINGLE_TARGETS := $(addprefix $(extmod-prefix), $(single-no-ko))
|
||||
+# Modules
|
||||
+PHONY += /
|
||||
+/: ./
|
||||
|
||||
-single-build = $(if $(filter-out $@/, $(single-no-ko)),1)
|
||||
-
|
||||
-endif
|
||||
+%/: prepare FORCE
|
||||
+ $(Q)$(MAKE) KBUILD_MODULES=1 $(build)=$(build-dir) need-modorder=1
|
||||
|
||||
# FIXME Should go into a make.lib or something
|
||||
# ===========================================================================
|
||||
@@ -1816,9 +1810,9 @@
|
||||
|
||||
-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)
|
||||
|
||||
-endif # config-targets
|
||||
-endif # mixed-build
|
||||
-endif # need-sub-make
|
||||
+endif # ifeq ($(config-targets),1)
|
||||
+endif # ifeq ($(mixed-targets),1)
|
||||
+endif # need-sub-make
|
||||
|
||||
PHONY += FORCE
|
||||
FORCE:
|
||||
@@ -12,22 +12,33 @@
|
||||
<IsA>app:console</IsA>
|
||||
<Summary>CPU power management tools</Summary>
|
||||
<Description>cpupowertools contains utilities to manage power management and frequency scaling policies of modern CPUs.</Description>
|
||||
<Archive sha1sum="14054f92e11eaedef64d19376de01a9e7b53566a" type="targz">https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.5.tar.gz</Archive>
|
||||
<Archive sha1sum="b34cb9bd928ae41b89aab2b73a2bc3e25a2dc128" type="targz">https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.6.tar.gz</Archive>
|
||||
<BuildDependencies>
|
||||
<Dependency>pciutils-devel</Dependency>
|
||||
</BuildDependencies>
|
||||
<Patches>
|
||||
<!-- Linux patches -->
|
||||
<Patch level="1" compressionType="xz">patches/linux/patch-5.5.15.xz</Patch>
|
||||
<Patch level="1" compressionType="xz">patches/linux/patch-5.6.4.xz</Patch>
|
||||
<!-- Mageia Linux patches-->
|
||||
<Patch level="1">patches/mageia_5_5/fs-aufs-5.5.patch</Patch>
|
||||
<Patch level="1">patches/mageia_5_5/fs-aufs-5.5-modular.patch</Patch>
|
||||
<Patch level="1">patches/mageia_5_5/fs-vboxsf.patch</Patch>
|
||||
<Patch level="1">patches/mageia_5_5/CVE-2019-12379.patch</Patch>
|
||||
<!-- <Patch level="1">patches/mageia_5_4/disable-mrproper-in-devel-rpms.patch</Patch> -->
|
||||
|
||||
<!-- Build fix -->
|
||||
<!-- <Patch level="1">patches/pisilinux/revert-Makefile.patch</Patch> -->
|
||||
<Patch level="1">patches/mageia/fs-aufs-5.6.patch</Patch>
|
||||
<Patch level="1">patches/mageia/fs-aufs-5.6-modular.patch</Patch>
|
||||
<Patch level="1">patches/mageia/fs-aufs-5.6-fix.patch</Patch>
|
||||
<Patch level="1">patches/mageia/fs-exfat-remove-from-staging.patch</Patch>
|
||||
<Patch level="1">patches/mageia/fs-exfat-add-in-memory-and-on-disk-structures-and-heade.patch</Patch>
|
||||
<Patch level="1">patches/mageia/fs-exfat-add-super-block-operations.patch</Patch>
|
||||
<Patch level="1">patches/mageia/fs-exfat-add-inode-operations.patch</Patch>
|
||||
<Patch level="1">patches/mageia/fs-exfat-add-directory-operations.patch</Patch>
|
||||
<Patch level="1">patches/mageia/fs-exfat-add-file-operations.patch</Patch>
|
||||
<Patch level="1">patches/mageia/fs-exfat-add-fat-entry-operations.patch</Patch>
|
||||
<Patch level="1">patches/mageia/fs-exfat-add-bitmap-operations.patch</Patch>
|
||||
<Patch level="1">patches/mageia/fs-exfat-add-exfat-cache.patch</Patch>
|
||||
<Patch level="1">patches/mageia/fs-exfat-add-misc-operations.patch</Patch>
|
||||
<Patch level="1">patches/mageia/fs-exfat-add-nls-operations.patch</Patch>
|
||||
<Patch level="1">patches/mageia/fs-exfat-add-Kconfig-and-Makefile.patch</Patch>
|
||||
<Patch level="1">patches/mageia/fs-MAINTAINERS-add-exfat-filesystem.patch</Patch>
|
||||
<Patch level="1">patches/mageia/fs-exfat-update-file-system-parameter-handling.patch</Patch>
|
||||
<Patch level="1">patches/mageia/fs-exfat-add-module_alias_fs.patch</Patch>
|
||||
<Patch level="1">patches/mageia/CVE-2019-12379.patch</Patch>
|
||||
</Patches>
|
||||
</Source>
|
||||
|
||||
@@ -55,6 +66,13 @@
|
||||
</Package>
|
||||
|
||||
<History>
|
||||
<Update release="33">
|
||||
<Date>2020-04-13</Date>
|
||||
<Version>5.6.4</Version>
|
||||
<Comment>Version bump</Comment>
|
||||
<Name>İdris Kalp</Name>
|
||||
<Email>idriskalp@gmail.com</Email>
|
||||
</Update>
|
||||
<Update release="32">
|
||||
<Date>2020-04-03</Date>
|
||||
<Version>5.5.15</Version>
|
||||
|
||||
Reference in New Issue
Block a user