kernel 5.6.4
This commit is contained in:
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -1,181 +0,0 @@
|
||||
|
||||
3rdparty/mkbuild.pl | 92 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
Documentation/3rdparty.txt | 76 +++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 168 insertions(+)
|
||||
|
||||
diff -Nurp linux-2.6.37/3rdparty/mkbuild.pl linux-2.6.37.3rdparty/3rdparty/mkbuild.pl
|
||||
--- linux-2.6.37/3rdparty/mkbuild.pl 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ linux-2.6.37.3rdparty/3rdparty/mkbuild.pl 2004-04-23 14:59:03.000000000 +0300
|
||||
@@ -0,0 +1,92 @@
|
||||
+#!/usr/bin/perl -w
|
||||
+#
|
||||
+# Version 1.0
|
||||
+#
|
||||
+# Copyright 2001 Jeff Garzik <jgarzik@mandrakesoft.com>
|
||||
+# Copyright 2002 Juan Quintela <quintela@mandrakesoft.com>
|
||||
+# Copyright 2003 Nicolas Planel <nplanel@mandrakesoft.com>
|
||||
+#
|
||||
+# This software may be used and distributed according to the terms
|
||||
+# of the GNU General Public License, incorporated herein by reference.
|
||||
+#
|
||||
+#
|
||||
+# Run "mkbuild.pl"
|
||||
+#
|
||||
+# This program generates the following files
|
||||
+# Makefile
|
||||
+# Makefile.drivers
|
||||
+# Config.in
|
||||
+# using the information in the subdirs of this directory.
|
||||
+#
|
||||
+# subdirs need to have:
|
||||
+# a Config.in file
|
||||
+# a Makefile with a O_TARGET/L_TARGET targets
|
||||
+# The config.in should set a CONFIG_<module_dir_name> to m/y.
|
||||
+
|
||||
+use strict;
|
||||
+
|
||||
+opendir(THISDIR, ".");
|
||||
+# get dirs without . and .. garbage
|
||||
+my (@modules) = grep(!/\.\.?$/,grep(-d, readdir(THISDIR)));
|
||||
+closedir(THISDIR);
|
||||
+
|
||||
+generate_kconfig(@modules);
|
||||
+generate_makefile(@modules);
|
||||
+exit(0);
|
||||
+
|
||||
+##########################################################################
|
||||
+
|
||||
+sub generate_makefile {
|
||||
+ my (@modules) = @_;
|
||||
+
|
||||
+ local *F;
|
||||
+ open F, "> Makefile" or die "Cannot create new Makefile: $!\n";
|
||||
+ print F <<'EOM';
|
||||
+#
|
||||
+# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT.
|
||||
+#
|
||||
+
|
||||
+EOM
|
||||
+ printf F "obj- := 3rdparty.o # Dummy rule to force built-in.o to be made\n";
|
||||
+ printf F "obj-\$(%s) += %s\n", to_CONFIG($_), $_ . '/' foreach @modules;
|
||||
+}
|
||||
+
|
||||
+sub generate_kconfig {
|
||||
+ my (@modules) = @_;
|
||||
+
|
||||
+ local *F;
|
||||
+ open F, "> Kconfig" or die "Cannot create Kconfig: $!\n";
|
||||
+ print F <<"EOM";
|
||||
+#
|
||||
+# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT.
|
||||
+#
|
||||
+
|
||||
+menu "Unofficial 3rd party kernel additions"
|
||||
+
|
||||
+EOM
|
||||
+
|
||||
+ foreach (@modules) {
|
||||
+ die "No Kconfig in $_.\n" if ! -r "$_/Kconfig";
|
||||
+ print F "source 3rdparty/$_/Kconfig\n";
|
||||
+ }
|
||||
+ print F "\n\nendmenu\n";
|
||||
+}
|
||||
+
|
||||
+sub to_CONFIG {
|
||||
+ local $_ = $_[0];
|
||||
+ tr/a-z/A-Z/;
|
||||
+ s/[\-\. ]/_/g;
|
||||
+ "CONFIG_$_";
|
||||
+}
|
||||
+
|
||||
+sub find_target {
|
||||
+ my ($module_dir) = @_;
|
||||
+
|
||||
+ local *F;
|
||||
+ open(F, "$module_dir/Makefile") or die "$module_dir/Makefile: $!\n";
|
||||
+ while (<F>) {
|
||||
+ chomp;
|
||||
+ return $1 if (/[LO]_TARGET.*:=\s+(\S+)/);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
diff -Nurp linux-2.6.37/Documentation/3rdparty.txt linux-2.6.37.3rdparty/Documentation/3rdparty.txt
|
||||
--- linux-2.6.37/Documentation/3rdparty.txt 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ linux-2.6.37.3rdparty/Documentation/3rdparty.txt 2003-11-22 01:07:26.000000000 +0200
|
||||
@@ -0,0 +1,76 @@
|
||||
+
|
||||
+Third-Party Kernel Source Module Support, or
|
||||
+an easy way to add modules to your kernel build.
|
||||
+
|
||||
+
|
||||
+
|
||||
+Vendors quite often add additional drivers and features to the kernel
|
||||
+which require nothing more than modifying Kconfig, Makefile, and
|
||||
+adding one or more files to a sub-directory. As a single discrete task,
|
||||
+this is not a problem. However, using patches to add modules to the
|
||||
+kernel very often results in patch conflicts, resulting in needless time
|
||||
+wastage as developers regenerate an otherwise working kernel patch.
|
||||
+
|
||||
+This is designed as a solution to these problems. It is NOT designed as
|
||||
+a replacement for the kernel build system, but merely as a tool for
|
||||
+vendors and system administrators to ease the pain of patch management.
|
||||
+
|
||||
+The key feature of this system is the distinct lack of patches. Drivers
|
||||
+are installed via unpacking a tarball.
|
||||
+
|
||||
+
|
||||
+
|
||||
+Adding a directory to the build (usually from a tarball)
|
||||
+--------------------------------------------------------
|
||||
+If a directory exists inside the 3rdparty sub-directory that contains a
|
||||
+proper Makefile, it can be added to the build. It also needs a
|
||||
+Kconfig file.
|
||||
+
|
||||
+ cd /usr/src/linux-2.4.3/3rdparty
|
||||
+ bzcat /tmp/my-driver2.tar.bz2 | tar xf - # creates "my2" dir
|
||||
+
|
||||
+
|
||||
+Limitations
|
||||
+-----------
|
||||
+There are some limitations to this system. This system is only
|
||||
+designed to support a very common case. If you find yourself running
|
||||
+into limitations (kernel build experts can spot them right off),
|
||||
+then you should probably be patching the kernel instead of using
|
||||
+mkbuild.pl for that particular module.
|
||||
+
|
||||
+FIXME: actually list the limitations
|
||||
+
|
||||
+
|
||||
+
|
||||
+Other notes
|
||||
+-----------
|
||||
+Link order is controlled by the order of mkbuild.pl executions.
|
||||
+
|
||||
+"make mrproper" will erase Makefile.meta, and empty Kconfig, Makefile,
|
||||
+and Makefile.drivers.
|
||||
+
|
||||
+IMPORTANT NOTE: Because this feature modifies the kernel's makefiles and
|
||||
+configuration system, you MUST complete all mkbuild.pl runs before
|
||||
+running any "make" command.
|
||||
+
|
||||
+Building in the 3rdparty dir
|
||||
+----------------------------
|
||||
+
|
||||
+If you use modules that:
|
||||
+ - are contained in one subdir with the name of the module
|
||||
+ - has a Makefile
|
||||
+ - has a Kconfig file
|
||||
+
|
||||
+The system calls the ./mkbuild.pl script. It will search for
|
||||
+subdirectories, and will try to build each of them as a module.
|
||||
+Things to note:
|
||||
+
|
||||
+ The dependencies will be done in a module called:
|
||||
+
|
||||
+ 3rdparty/<module_dir_name>/<module_name>
|
||||
+
|
||||
+depending of CONFIG_<module_name_in_uppercase>.
|
||||
+
|
||||
+<module_name> is the value of O_TARGET/L_TARGET.
|
||||
+
|
||||
+
|
||||
@@ -1,191 +0,0 @@
|
||||
|
||||
Include 3rdparty directory into the main build-system.
|
||||
|
||||
Original author is unknown.
|
||||
(Was either Juan Quintela or Jeff Garzik)
|
||||
|
||||
Signed-off-by: Luiz Fernando N. Capitulino <lcapitulino@mandriva.com.br>
|
||||
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
|
||||
Signed-off-by: Thomas Backlund <tmb@mageia.org>
|
||||
|
||||
Makefile | 2 +-
|
||||
arch/alpha/Kconfig | 1 +
|
||||
arch/ia64/Kconfig | 2 ++
|
||||
arch/mips/Kconfig | 2 ++
|
||||
arch/powerpc/Kconfig | 2 ++
|
||||
arch/sparc/Kconfig | 2 ++
|
||||
arch/x86/Kconfig | 2 ++
|
||||
scripts/kconfig/Makefile | 33 ++++++++++++++++++---------------
|
||||
8 files changed, 30 insertions(+), 16 deletions(-)
|
||||
|
||||
diff -Nurp linux-4.2.2/arch/alpha/Kconfig linux-4.2.2-3rd/arch/alpha/Kconfig
|
||||
--- linux-4.2.2/arch/alpha/Kconfig 2015-08-30 21:34:09.000000000 +0300
|
||||
+++ linux-4.2.2-3rd/arch/alpha/Kconfig 2015-09-29 23:02:44.024347272 +0300
|
||||
@@ -750,3 +750,4 @@ source "crypto/Kconfig"
|
||||
|
||||
source "lib/Kconfig"
|
||||
|
||||
+source "3rdparty/Kconfig"
|
||||
diff -Nurp linux-4.2.2/arch/ia64/Kconfig linux-4.2.2-3rd/arch/ia64/Kconfig
|
||||
--- linux-4.2.2/arch/ia64/Kconfig 2015-08-30 21:34:09.000000000 +0300
|
||||
+++ linux-4.2.2-3rd/arch/ia64/Kconfig 2015-09-29 23:02:44.024347272 +0300
|
||||
@@ -613,3 +613,5 @@ source "lib/Kconfig"
|
||||
|
||||
config IOMMU_HELPER
|
||||
def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC || SWIOTLB)
|
||||
+
|
||||
+source "3rdparty/Kconfig"
|
||||
diff -Nurp linux-4.2.2/arch/mips/Kconfig linux-4.2.2-3rd/arch/mips/Kconfig
|
||||
--- linux-4.2.2/arch/mips/Kconfig 2015-08-30 21:34:09.000000000 +0300
|
||||
+++ linux-4.2.2-3rd/arch/mips/Kconfig 2015-09-29 23:02:44.024347272 +0300
|
||||
@@ -2944,3 +2944,5 @@ source "crypto/Kconfig"
|
||||
source "lib/Kconfig"
|
||||
|
||||
source "arch/mips/kvm/Kconfig"
|
||||
+
|
||||
+source "3rdparty/Kconfig"
|
||||
diff -Nurp linux-4.2.2/arch/powerpc/Kconfig linux-4.2.2-3rd/arch/powerpc/Kconfig
|
||||
--- linux-4.2.2/arch/powerpc/Kconfig 2015-08-30 21:34:09.000000000 +0300
|
||||
+++ linux-4.2.2-3rd/arch/powerpc/Kconfig 2015-09-29 23:02:44.025347276 +0300
|
||||
@@ -1112,3 +1112,5 @@ config PPC_LIB_RHEAP
|
||||
source "arch/powerpc/kvm/Kconfig"
|
||||
|
||||
source "kernel/livepatch/Kconfig"
|
||||
+
|
||||
+source "3rdparty/Kconfig"
|
||||
diff -Nurp linux-4.2.2/arch/sparc/Kconfig linux-4.2.2-3rd/arch/sparc/Kconfig
|
||||
--- linux-4.2.2/arch/sparc/Kconfig 2015-08-30 21:34:09.000000000 +0300
|
||||
+++ linux-4.2.2-3rd/arch/sparc/Kconfig 2015-09-29 23:02:44.025347276 +0300
|
||||
@@ -569,3 +569,5 @@ source "security/Kconfig"
|
||||
source "crypto/Kconfig"
|
||||
|
||||
source "lib/Kconfig"
|
||||
+
|
||||
+source "3rdparty/Kconfig"
|
||||
diff -Nurp linux-4.2.2/arch/x86/Kconfig linux-4.2.2-3rd/arch/x86/Kconfig
|
||||
--- linux-4.2.2/arch/x86/Kconfig 2015-08-30 21:34:09.000000000 +0300
|
||||
+++ linux-4.2.2-3rd/arch/x86/Kconfig 2015-09-29 23:02:44.025347276 +0300
|
||||
@@ -2601,3 +2601,5 @@ source "crypto/Kconfig"
|
||||
source "arch/x86/kvm/Kconfig"
|
||||
|
||||
source "lib/Kconfig"
|
||||
+
|
||||
+source "3rdparty/Kconfig"
|
||||
diff -Nurp linux-4.2.2/Makefile linux-4.2.2-3rd/Makefile
|
||||
--- linux-4.2.2/Makefile 2015-09-29 22:13:44.743650710 +0300
|
||||
+++ linux-4.2.2-3rd/Makefile 2015-09-29 23:02:44.026347280 +0300
|
||||
@@ -546,7 +546,7 @@ scripts: scripts_basic include/config/au
|
||||
|
||||
# Objects we will link into vmlinux / subdirs we need to visit
|
||||
init-y := init/
|
||||
-drivers-y := drivers/ sound/ firmware/
|
||||
+drivers-y := drivers/ sound/ firmware/ 3rdparty/
|
||||
net-y := net/
|
||||
libs-y := lib/
|
||||
core-y := usr/
|
||||
diff -Nurp linux-4.14/scripts/kconfig/Makefile linux-4.14-3rd/scripts/kconfig/Makefile
|
||||
--- linux-4.14/scripts/kconfig/Makefile
|
||||
+++ linux-4.14-3rd/scripts/kconfig/Makefile
|
||||
@@ -19,28 +19,28 @@ endif
|
||||
# We need this, in case the user has it in its environment
|
||||
unexport CONFIG_
|
||||
|
||||
-xconfig: $(obj)/qconf
|
||||
+xconfig: $(obj)/qconf 3rdparty/Makefile
|
||||
$< $(silent) $(Kconfig)
|
||||
|
||||
-gconfig: $(obj)/gconf
|
||||
+gconfig: $(obj)/gconf 3rdparty/Makefile
|
||||
$< $(silent) $(Kconfig)
|
||||
|
||||
-menuconfig: $(obj)/mconf
|
||||
+menuconfig: $(obj)/mconf 3rdparty/Makefile
|
||||
$< $(silent) $(Kconfig)
|
||||
|
||||
-config: $(obj)/conf
|
||||
+config: $(obj)/conf 3rdparty/Makefile
|
||||
$< $(silent) --oldaskconfig $(Kconfig)
|
||||
|
||||
-nconfig: $(obj)/nconf
|
||||
+nconfig: $(obj)/nconf 3rdparty/Makefile
|
||||
$< $(silent) $(Kconfig)
|
||||
|
||||
-silentoldconfig: $(obj)/conf
|
||||
+silentoldconfig: $(obj)/conf 3rdparty/Makefile
|
||||
$(Q)mkdir -p include/config include/generated
|
||||
$(Q)test -e include/generated/autoksyms.h || \
|
||||
touch include/generated/autoksyms.h
|
||||
$< $(silent) --$@ $(Kconfig)
|
||||
|
||||
-localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
|
||||
+localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf 3rdparty/Makefile
|
||||
$(Q)mkdir -p include/config include/generated
|
||||
$(Q)perl $< --$@ $(srctree) $(Kconfig) > .tmp.config
|
||||
$(Q)if [ -f .config ]; then \
|
||||
@@ -83,7 +83,7 @@ simple-targets := oldconfig allnoconfig
|
||||
alldefconfig randconfig listnewconfig olddefconfig
|
||||
PHONY += $(simple-targets)
|
||||
|
||||
-$(simple-targets): $(obj)/conf
|
||||
+$(simple-targets): $(obj)/conf 3rdparty/Makefile
|
||||
$< $(silent) --$@ $(Kconfig)
|
||||
|
||||
PHONY += oldnoconfig savedefconfig defconfig
|
||||
@@ -91,12 +91,12 @@ PHONY += oldnoconfig savedefconfig defco
|
||||
# oldnoconfig is an alias of olddefconfig, because people already are dependent
|
||||
# on its behavior (sets new symbols to their default value but not 'n') with the
|
||||
# counter-intuitive name.
|
||||
-oldnoconfig: olddefconfig
|
||||
+oldnoconfig: olddefconfig 3rdparty/Makefile
|
||||
|
||||
-savedefconfig: $(obj)/conf
|
||||
+savedefconfig: $(obj)/conf 3rdparty/Makefile
|
||||
$< $(silent) --$@=defconfig $(Kconfig)
|
||||
|
||||
-defconfig: $(obj)/conf
|
||||
+defconfig: $(obj)/conf 3rdparty/Makefile
|
||||
ifeq ($(KBUILD_DEFCONFIG),)
|
||||
$< $(silent) --defconfig $(Kconfig)
|
||||
else
|
||||
@@ -109,26 +109,26 @@ else
|
||||
endif
|
||||
endif
|
||||
|
||||
-%_defconfig: $(obj)/conf
|
||||
+%_defconfig: $(obj)/conf 3rdparty/Makefile
|
||||
$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
|
||||
|
||||
configfiles=$(wildcard $(srctree)/kernel/configs/$@ $(srctree)/arch/$(SRCARCH)/configs/$@)
|
||||
|
||||
-%.config: $(obj)/conf
|
||||
+%.config: $(obj)/conf 3rdparty/Makefile
|
||||
$(if $(call configfiles),, $(error No configuration exists for this target on this architecture))
|
||||
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m .config $(configfiles)
|
||||
+$(Q)yes "" | $(MAKE) -f $(srctree)/Makefile oldconfig
|
||||
|
||||
PHONY += kvmconfig
|
||||
-kvmconfig: kvm_guest.config
|
||||
+kvmconfig: kvm_guest.config 3rdparty/Makefile
|
||||
@:
|
||||
|
||||
PHONY += xenconfig
|
||||
-xenconfig: xen.config
|
||||
+xenconfig: xen.config 3rdparty/Makefile
|
||||
@:
|
||||
|
||||
PHONY += tinyconfig
|
||||
-tinyconfig:
|
||||
+tinyconfig:
|
||||
$(Q)$(MAKE) -f $(srctree)/Makefile allnoconfig tiny.config
|
||||
|
||||
# Help text used by make help
|
||||
@@ -191,6 +191,9 @@ gconf-objs := gconf.o zconf.tab.o
|
||||
|
||||
hostprogs-y := conf nconf mconf kxgettext qconf gconf
|
||||
|
||||
+3rdparty/Makefile:
|
||||
+ pushd $(srctree)/3rdparty ; $(PERL) ./mkbuild.pl ; popd
|
||||
+
|
||||
clean-files := qconf.moc .tmp_qtcheck .tmp_gtkcheck
|
||||
clean-files += zconf.tab.c zconf.lex.c gconf.glade.h
|
||||
clean-files += config.pot linux.pot
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,20 +0,0 @@
|
||||
--- linux-2.6.35/3rdparty/acerhk/acerhk.c.orig 2010-10-03 12:50:33.000000000 +0000
|
||||
+++ linux-2.6.35/3rdparty/acerhk/acerhk.c 2010-10-03 13:13:22.093868410 +0000
|
||||
@@ -2730,7 +2730,7 @@ static void acerhk_proc_cleanup(void)
|
||||
|
||||
/* {{{ file operations */
|
||||
|
||||
-static int acerhk_ioctl( struct inode *inode, struct file *file,
|
||||
+static long acerhk_ioctl( struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
{
|
||||
int retval;
|
||||
@@ -2827,7 +2827,7 @@ static int acerhk_release( struct inode
|
||||
|
||||
static struct file_operations acerhk_fops = {
|
||||
owner: THIS_MODULE,
|
||||
- ioctl: acerhk_ioctl,
|
||||
+ unlocked_ioctl: acerhk_ioctl,
|
||||
open: acerhk_open,
|
||||
#ifdef ACERDEBUG
|
||||
write: acerhk_write,
|
||||
@@ -1,33 +0,0 @@
|
||||
CFLAGS use isn't allowed anymore with 2.6.24, we must use EXTRA_CFLAGS
|
||||
in its place
|
||||
|
||||
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
|
||||
|
||||
--- linux-2.6.23/3rdparty/acerhk/Makefile.orig 2007-11-08 21:32:43.000000000 -0200
|
||||
+++ linux-2.6.23/3rdparty/acerhk/Makefile 2007-11-08 21:33:28.000000000 -0200
|
||||
@@ -14,7 +14,7 @@
|
||||
CONFIG_ACERHK?=m
|
||||
obj-$(CONFIG_ACERHK) += acerhk.o
|
||||
|
||||
-CFLAGS+=-c -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe
|
||||
+EXTRA_CFLAGS+=-c -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe
|
||||
INCLUDE=-I$(KERNELSRC)/include
|
||||
|
||||
ifeq ($(KERNELMAJOR), 2.6)
|
||||
@@ -41,13 +41,13 @@ acerhk.ko: $(SOURCE) acerhk.h
|
||||
$(MAKE) -C $(KERNELSRC) SUBDIRS=$(PWD) modules
|
||||
|
||||
acerhk.o: $(SOURCE) acerhk.h
|
||||
- $(CC) $(INCLUDE) $(CFLAGS) -DMODVERSIONS -DMODULE -D__KERNEL__ -o $(TARGET) $(SOURCE)
|
||||
+ $(CC) $(INCLUDE) $(EXTRA_CFLAGS) -DMODVERSIONS -DMODULE -D__KERNEL__ -o $(TARGET) $(SOURCE)
|
||||
|
||||
asm: $(SOURCE)
|
||||
ifeq ($(KERNELMAJOR), 2.6)
|
||||
- $(CC) $(INCLUDE) $(INCLUDE)/asm-i386/mach-default $(CFLAGS) -fverbose-asm -S -DMODVERSIONS -DMODULE -D__KERNEL__ $(SOURCE)
|
||||
+ $(CC) $(INCLUDE) $(INCLUDE)/asm-i386/mach-default $(EXTRA_CFLAGS) -fverbose-asm -S -DMODVERSIONS -DMODULE -D__KERNEL__ $(SOURCE)
|
||||
else
|
||||
- $(CC) $(INCLUDE) $(CFLAGS) -fverbose-asm -S -DMODVERSIONS -DMODULE -D__KERNEL__ $(SOURCE)
|
||||
+ $(CC) $(INCLUDE) $(EXTRA_CFLAGS) -fverbose-asm -S -DMODVERSIONS -DMODULE -D__KERNEL__ $(SOURCE)
|
||||
endif
|
||||
|
||||
clean:
|
||||
@@ -1,22 +0,0 @@
|
||||
Fix acerhk build with FUNCTION_TRACER enabled.
|
||||
|
||||
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
|
||||
---
|
||||
3rdparty/acerhk/Makefile | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff -p -up linux-2.6.31/3rdparty/acerhk/Makefile.orig linux-2.6.31/3rdparty/acerhk/Makefile
|
||||
--- linux-2.6.31/3rdparty/acerhk/Makefile.orig 2009-10-02 16:39:06.000000000 -0300
|
||||
+++ linux-2.6.31/3rdparty/acerhk/Makefile 2009-10-02 16:45:13.000000000 -0300
|
||||
@@ -14,7 +14,10 @@
|
||||
CONFIG_ACERHK?=m
|
||||
obj-$(CONFIG_ACERHK) += acerhk.o
|
||||
|
||||
-EXTRA_CFLAGS+=-c -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe
|
||||
+CFLAGS_acerhk.o += -c -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe
|
||||
+ifdef CONFIG_FUNCTION_TRACER
|
||||
+CFLAGS_REMOVE_acerhk.o = -pg
|
||||
+endif
|
||||
INCLUDE=-I$(KERNELSRC)/include
|
||||
|
||||
ifeq ($(KERNELMAJOR), 2.6)
|
||||
@@ -1,23 +0,0 @@
|
||||
|
||||
AUTOCONF_INCLUDED is not defined anymore in 2.6.38, so old include got exposed.
|
||||
|
||||
Fix by removing the offending bits.
|
||||
|
||||
Signed-off-by: Thomas Backlund <tmb@mageia.org>
|
||||
|
||||
3rdparty/acerhk/acerhk.c | 4 ----
|
||||
1 file changed, 4 deletions(-)
|
||||
|
||||
--- linux-2.6.38/3rdparty/acerhk/acerhk.c.orig 2011-03-20 13:57:32.000000000 +0200
|
||||
+++ linux-2.6.38/3rdparty/acerhk/acerhk.c 2011-03-20 15:00:45.768659568 +0200
|
||||
@@ -35,10 +35,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
-#ifndef AUTOCONF_INCLUDED
|
||||
-#include <linux/config.h>
|
||||
-#endif
|
||||
-
|
||||
/* This driver is heavily dependent on the architecture, don't let
|
||||
* anyone without an X86 machine use it. On laptops with AMD64
|
||||
* architecture this driver is only useable in 32 bit mode.
|
||||
@@ -1,37 +0,0 @@
|
||||
Fix Makefile and add Kconfig for the acerhk driver
|
||||
---
|
||||
3rdparty/acerhk/Kconfig | 8 8 + 0 - 0 !
|
||||
3rdparty/acerhk/Makefile | 6 3 + 3 - 0 !
|
||||
2 files changed, 11 insertions(+), 3 deletions(-)
|
||||
|
||||
Index: linux-2.6.21/3rdparty/acerhk/Makefile
|
||||
===================================================================
|
||||
--- linux-2.6.21.orig/3rdparty/acerhk/Makefile 2007-05-15 15:34:48.000000000 +0200
|
||||
+++ linux-2.6.21/3rdparty/acerhk/Makefile 2007-05-15 15:37:17.000000000 +0200
|
||||
@@ -1,10 +1,10 @@
|
||||
# change KERNELSRC to the location of your kernel build tree only if
|
||||
# autodetection does not work
|
||||
#KERNELSRC=/usr/src/linux
|
||||
-KERNELSRC?=/lib/modules/`uname -r`/build
|
||||
+#KERNELSRC?=/lib/modules/`uname -r`/build
|
||||
# Starting with 2.6.18, the kernel version is in utsrelease.h instead of version.h, accomodate both cases
|
||||
-KERNELVERSION=$(shell awk -F\" '/REL/ {print $$2}' $(shell grep -s -l REL $(KERNELSRC)/include/linux/version.h $(KERNELSRC)/include/linux/utsrelease.h))
|
||||
-KERNELMAJOR=$(shell echo $(KERNELVERSION)|head -c3)
|
||||
+#KERNELVERSION=$(shell awk -F\" '/REL/ {print $$2}' $(shell grep -s -l REL $(KERNELSRC)/include/linux/version.h $(KERNELSRC)/include/linux/utsrelease.h))
|
||||
+#KERNELMAJOR=$(shell echo $(KERNELVERSION)|head -c3)
|
||||
|
||||
# next line is for kernel 2.6, if you integrate the driver in the kernel tree
|
||||
# /usr/src/linux/drivers/acerhk - or something similar
|
||||
Index: linux-2.6.21/3rdparty/acerhk/Kconfig
|
||||
===================================================================
|
||||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ linux-2.6.21/3rdparty/acerhk/Kconfig 2007-05-15 15:39:30.000000000 +0200
|
||||
@@ -0,0 +1,8 @@
|
||||
+config ACERHK
|
||||
+ tristate "Acerhk driver"
|
||||
+ depends on EXPERIMENTAL && X86
|
||||
+ ---help---
|
||||
+ This is an experimental acer keyboard driver for
|
||||
+ acer laptops. If you have a notebook with a ipw2X00
|
||||
+ wireless card, it allows you to turn off the rf_kill
|
||||
+
|
||||
@@ -1,67 +0,0 @@
|
||||
Updated for owner removal from struct proc_dir_entry (2.6.30)
|
||||
|
||||
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
|
||||
|
||||
---
|
||||
3rdparty/acerhk/acerhk.c | 7 -------
|
||||
1 file changed, 7 deletions(-)
|
||||
|
||||
diff -p -up linux-2.6.29/3rdparty/acerhk/acerhk.c.orig linux-2.6.29/3rdparty/acerhk/acerhk.c
|
||||
--- linux-2.6.29/3rdparty/acerhk/acerhk.c.orig 2009-05-22 02:42:44.000000000 -0300
|
||||
+++ linux-2.6.29/3rdparty/acerhk/acerhk.c 2009-05-22 02:43:45.000000000 -0300
|
||||
@@ -2626,7 +2626,6 @@ static int acerhk_proc_init(void)
|
||||
printk(KERN_INFO"acerhk: could not create /proc/driver/acerhk\n");
|
||||
}
|
||||
else {
|
||||
- proc_acer_dir->owner = THIS_MODULE;
|
||||
/* now create several files, first general info ... */
|
||||
entry = create_proc_read_entry("info",
|
||||
0444, proc_acer_dir, acerhk_proc_info, NULL);
|
||||
@@ -2635,7 +2634,6 @@ static int acerhk_proc_init(void)
|
||||
remove_proc_entry("driver/acerhk", NULL);
|
||||
retval = 0;
|
||||
} else {
|
||||
- entry->owner = THIS_MODULE;
|
||||
/* ... last pressed key ... */
|
||||
entry = create_proc_read_entry("key",
|
||||
0444, proc_acer_dir, acerhk_proc_key, NULL);
|
||||
@@ -2645,7 +2643,6 @@ static int acerhk_proc_init(void)
|
||||
remove_proc_entry("driver/acerhk", NULL);
|
||||
retval = 0;
|
||||
} else {
|
||||
- entry->owner = THIS_MODULE;
|
||||
/* ... and led control file */
|
||||
entry = create_proc_entry("led", 0222, proc_acer_dir);
|
||||
if (entry == NULL) {
|
||||
@@ -2657,7 +2654,6 @@ static int acerhk_proc_init(void)
|
||||
}
|
||||
else {
|
||||
entry->write_proc = acerhk_proc_led;
|
||||
- entry->owner = THIS_MODULE;
|
||||
/* ... and wireless led controll file */
|
||||
entry = create_proc_entry("wirelessled", 0222, proc_acer_dir);
|
||||
if (entry == NULL) {
|
||||
@@ -2670,7 +2666,6 @@ static int acerhk_proc_init(void)
|
||||
}
|
||||
else {
|
||||
entry->write_proc = acerhk_proc_wirelessled;
|
||||
- entry->owner = THIS_MODULE;
|
||||
/* ... and bluetooth led controll file */
|
||||
entry = create_proc_entry("blueled", 0222, proc_acer_dir);
|
||||
if (entry == NULL) {
|
||||
@@ -2683,7 +2678,6 @@ static int acerhk_proc_init(void)
|
||||
retval = 0;
|
||||
} else {
|
||||
entry->write_proc = acerhk_proc_blueled;
|
||||
- entry->owner = THIS_MODULE;
|
||||
retval = 1;
|
||||
#ifdef ACERDEBUG
|
||||
/* add extra file for debugging purposes */
|
||||
@@ -2700,7 +2694,6 @@ static int acerhk_proc_init(void)
|
||||
}
|
||||
else {
|
||||
entry->write_proc = acerhk_proc_debug;
|
||||
- entry->owner = THIS_MODULE;
|
||||
retval = 1;
|
||||
}
|
||||
#endif
|
||||
@@ -1,47 +0,0 @@
|
||||
Fix Makefile and add Kconfig for the aes2501 driver.
|
||||
|
||||
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
|
||||
|
||||
---
|
||||
linux-2.6.23/3rdparty/aes2501/Kconfig | 10 ++++++++++
|
||||
linux-2.6.23/3rdparty/aes2501/Makefile | 19 +------------------
|
||||
2 files changed, 11 insertions(+), 18 deletions(-)
|
||||
|
||||
diff -p -up linux-2.6.23/3rdparty/aes2501/Kconfig.orig linux-2.6.23/3rdparty/aes2501/Kconfig
|
||||
--- linux-2.6.23/3rdparty/aes2501/Kconfig.orig 2008-01-13 23:14:47.000000000 -0200
|
||||
+++ linux-2.6.23/3rdparty/aes2501/Kconfig 2008-01-13 23:35:21.000000000 -0200
|
||||
@@ -0,0 +1,10 @@
|
||||
+config AES2501
|
||||
+ tristate "AuthenTec AES2501 Fingerprint Sensor Driver"
|
||||
+ depends on USB
|
||||
+ default m
|
||||
+ ---help---
|
||||
+ Say Y here if you have a AuthenTec AES2501 Fingerprint
|
||||
+ Sensor device.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the
|
||||
+ module will be called aes2501.
|
||||
diff -p -up linux-2.6.23/3rdparty/aes2501/Makefile.orig linux-2.6.23/3rdparty/aes2501/Makefile
|
||||
--- linux-2.6.23/3rdparty/aes2501/Makefile.orig 2008-01-13 23:14:36.000000000 -0200
|
||||
+++ linux-2.6.23/3rdparty/aes2501/Makefile 2008-01-13 23:21:33.000000000 -0200
|
||||
@@ -1,19 +1,2 @@
|
||||
-
|
||||
-obj-m := aes2501.o
|
||||
-
|
||||
-KERNELDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
-
|
||||
-PWD := $(shell pwd)
|
||||
-
|
||||
-all: usertest
|
||||
- $(MAKE) -C $(KERNELDIR) M=$(PWD)
|
||||
-
|
||||
-usertest:
|
||||
- gcc -I. -o usertest usertest.c
|
||||
-
|
||||
-clean:
|
||||
- rm -f *.o *~ aes2501.ko aes2501.mod.c Module.symvers usertest
|
||||
- rm -rf .tmp_versions
|
||||
- rm -f .*.cmd
|
||||
-
|
||||
+obj-$(CONFIG_AES2501) := aes2501.o
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,21 +0,0 @@
|
||||
Prevent oops on module removal when we don't have the device available.
|
||||
|
||||
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
|
||||
|
||||
---
|
||||
linux-2.6.23/3rdparty/aes2501/aes2501.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff -p -up linux-2.6.23/3rdparty/aes2501/aes2501.c.orig linux-2.6.23/3rdparty/aes2501/aes2501.c
|
||||
--- linux-2.6.23/3rdparty/aes2501/aes2501.c.orig 2008-01-13 23:37:38.000000000 -0200
|
||||
+++ linux-2.6.23/3rdparty/aes2501/aes2501.c 2008-01-13 23:38:26.000000000 -0200
|
||||
@@ -1616,7 +1616,8 @@ static int __init aes2501_init(void)
|
||||
|
||||
static void __exit aes2501_exit(void)
|
||||
{
|
||||
- _dev->stop_scan = 1;
|
||||
+ if (_dev)
|
||||
+ _dev->stop_scan = 1;
|
||||
destroy_workqueue(comm_queue);
|
||||
usb_deregister(&aes2501_driver);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,43 +0,0 @@
|
||||
|
||||
last_rx is gone, most drivers does not really need/use it anyway.
|
||||
|
||||
Also, include signal.h to fix implicit deklaration of function ”signal_pending”
|
||||
|
||||
Signed-off-by: Thomas Backlund <tmb@mageia.org>
|
||||
|
||||
--- linux/3rdparty/ndiswrapper/ndis.c.orig 2016-10-09 18:45:08.027226096 +0300
|
||||
+++ linux/3rdparty/ndiswrapper/ndis.c 2017-08-04 00:09:49.264110609 +0300
|
||||
@@ -2258,7 +2258,6 @@ wstdcall void NdisMIndicateReceivePacket
|
||||
WARNING("empty packet ignored");
|
||||
continue;
|
||||
}
|
||||
- wnd->net_dev->last_rx = jiffies;
|
||||
/* get total number of bytes in packet */
|
||||
NdisGetFirstBufferFromPacketSafe(packet, &buffer, &virt,
|
||||
&length, &total_length,
|
||||
@@ -2346,7 +2345,6 @@ wstdcall void EthRxIndicateHandler(struc
|
||||
ERROR("nmb is NULL");
|
||||
EXIT3(return);
|
||||
}
|
||||
- wnd->net_dev->last_rx = jiffies;
|
||||
|
||||
if (look_ahead_size < packet_size) {
|
||||
struct ndis_packet *packet;
|
||||
@@ -2461,7 +2459,6 @@ wstdcall void NdisMTransferDataComplete(
|
||||
WARNING("illegal packet");
|
||||
EXIT3(return);
|
||||
}
|
||||
- wnd->net_dev->last_rx = jiffies;
|
||||
oob_data = NDIS_PACKET_OOB_DATA(packet);
|
||||
skb_size = sizeof(oob_data->header) + oob_data->look_ahead_size +
|
||||
bytes_txed;
|
||||
--- linux/3rdparty/ndiswrapper/ntoskernel.h.orig 2017-08-03 23:52:29.015367906 +0300
|
||||
+++ linux/3rdparty/ndiswrapper/ntoskernel.h 2017-08-04 00:17:41.334914691 +0300
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/sched.h>
|
||||
+#include <linux/sched/signal.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/mman.h>
|
||||
@@ -1,16 +0,0 @@
|
||||
|
||||
__GFP_REPEAT is now __GFP_RETRY_MAYFAIL
|
||||
|
||||
Signed-off-by: Thomas Backlund <tmb@mageia.org>
|
||||
|
||||
--- linux/3rdparty/ndiswrapper/ntoskernel.h.orig 2017-10-15 01:11:56.041892449 +0300
|
||||
+++ linux/3rdparty/ndiswrapper/ntoskernel.h 2017-10-15 01:11:06.159204294 +0300
|
||||
@@ -122,7 +122,7 @@ static cpumask_t cpumasks[NR_CPUS];
|
||||
|
||||
#define PCI_DMA_ALLOC_COHERENT(pci_dev,size,dma_handle) \
|
||||
dma_alloc_coherent(&pci_dev->dev,size,dma_handle, \
|
||||
- GFP_KERNEL | __GFP_REPEAT)
|
||||
+ GFP_KERNEL | __GFP_RETRY_MAYFAIL)
|
||||
#define PCI_DMA_FREE_COHERENT(pci_dev,size,cpu_addr,dma_handle) \
|
||||
dma_free_coherent(&pci_dev->dev,size,cpu_addr,dma_handle)
|
||||
#define PCI_DMA_MAP_SINGLE(pci_dev,addr,size,direction) \
|
||||
@@ -1,7 +0,0 @@
|
||||
--- linux-2.6.24.orig/3rdparty/ndiswrapper/Kconfig 1969-12-31 21:00:00.000000000 -0300
|
||||
+++ linux-2.6.24/3rdparty/ndiswrapper/Kconfig 2007-11-26 15:11:31.000000000 -0200
|
||||
@@ -0,0 +1,4 @@
|
||||
+
|
||||
+config NDISWRAPPER
|
||||
+ tristate "NDIS driver wrapper support"
|
||||
+ depends on PCI && USB && !X86_64_XEN
|
||||
@@ -1,45 +0,0 @@
|
||||
--- linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/Makefile.orig 2013-11-28 21:42:10.000000000 +0200
|
||||
+++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/Makefile 2013-11-30 21:41:19.550504380 +0200
|
||||
@@ -9,24 +9,10 @@ DISTFILES = \
|
||||
winnt_types.h workqueue.c wrapmem.c wrapmem.h wrapndis.c wrapndis.h \
|
||||
wrapper.c wrapper.h
|
||||
|
||||
-# By default, we try to compile the modules for the currently running
|
||||
-# kernel. But it's the first approximation, as we will re-read the
|
||||
-# version from the kernel sources.
|
||||
-KVERS_UNAME ?= $(shell uname -r)
|
||||
-
|
||||
# KBUILD is the path to the Linux kernel build tree. It is usually the
|
||||
# same as the kernel source tree, except when the kernel was compiled in
|
||||
# a separate directory.
|
||||
-KBUILD ?= $(shell readlink -f /lib/modules/$(KVERS_UNAME)/build)
|
||||
-
|
||||
-ifeq (,$(KBUILD))
|
||||
-$(error Kernel build tree not found - please set KBUILD to configured kernel)
|
||||
-endif
|
||||
-
|
||||
-KCONFIG := $(KBUILD)/.config
|
||||
-ifeq (,$(wildcard $(KCONFIG)))
|
||||
-$(error No .config found in $(KBUILD), please set KBUILD to configured kernel)
|
||||
-endif
|
||||
+KBUILD ?= $(srctree)
|
||||
|
||||
ifneq (,$(wildcard $(KBUILD)/include/linux/version.h))
|
||||
ifneq (,$(wildcard $(KBUILD)/include/generated/uapi/linux/version.h))
|
||||
@@ -43,16 +29,9 @@ endif
|
||||
ifeq (,$(wildcard $(VERSION_H)))
|
||||
VERSION_H := $(KBUILD)/include/linux/version.h
|
||||
endif
|
||||
-ifeq (,$(wildcard $(VERSION_H)))
|
||||
-$(error Please run 'make modules_prepare' in $(KBUILD))
|
||||
-endif
|
||||
|
||||
KVERS := $(shell sed -ne 's/"//g;s/^\#define UTS_RELEASE //p' $(VERSION_H))
|
||||
|
||||
-ifeq (,$(KVERS))
|
||||
-$(error Cannot find UTS_RELEASE in $(VERSION_H), please report)
|
||||
-endif
|
||||
-
|
||||
INST_DIR = /lib/modules/$(KVERS)/misc
|
||||
|
||||
SRC_DIR=$(shell pwd)
|
||||
@@ -1,978 +0,0 @@
|
||||
3rdparty/rfswitch/FILES | 6
|
||||
3rdparty/rfswitch/ISSUES | 28 +++
|
||||
3rdparty/rfswitch/Kconfig | 22 ++
|
||||
3rdparty/rfswitch/LICENSE | 339 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
3rdparty/rfswitch/Makefile | 119 +++++++++++++++
|
||||
3rdparty/rfswitch/README | 44 +++++
|
||||
3rdparty/rfswitch/av5100.c | 174 +++++++++++++++++++++++
|
||||
3rdparty/rfswitch/pbe5.c | 205 +++++++++++++++++++++++++++
|
||||
8 files changed, 937 insertions(+)
|
||||
diff -Nurp linux-2.6.37/3rdparty/rfswitch/av5100.c linux-2.6.37.3rdparty/3rdparty/rfswitch/av5100.c
|
||||
--- linux-2.6.37/3rdparty/rfswitch/av5100.c 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/av5100.c 2008-03-28 05:25:28.000000000 +0200
|
||||
@@ -0,0 +1,174 @@
|
||||
+/*******************************************************************************
|
||||
+
|
||||
+ Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify it
|
||||
+ under the terms of version 2 of the GNU General Public License as
|
||||
+ published by the Free Software Foundation.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
+ more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License along with
|
||||
+ this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
+
|
||||
+ The full GNU General Public License is included in this distribution in the
|
||||
+ file called LICENSE.
|
||||
+
|
||||
+ Contact Information:
|
||||
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
|
||||
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
+
|
||||
+*******************************************************************************/
|
||||
+#include <linux/compiler.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/netdevice.h>
|
||||
+#include <linux/version.h>
|
||||
+#include <linux/proc_fs.h>
|
||||
+#include <linux/ioport.h>
|
||||
+#include <asm/uaccess.h>
|
||||
+#include <asm/io.h>
|
||||
+
|
||||
+
|
||||
+#define DRV_NAME "av5100"
|
||||
+#define DRV_VERSION "1.3"
|
||||
+#define DRV_DESCRIPTION "SW RF kill switch for Averatec 5100P"
|
||||
+#define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation"
|
||||
+
|
||||
+static int radio = 1;
|
||||
+
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
+
|
||||
+MODULE_PARM(radio, "i");
|
||||
+
|
||||
+#else /* LINUX_VERSION_CODE < 2.6.0 */
|
||||
+
|
||||
+#include <linux/moduleparam.h>
|
||||
+module_param(radio, int, 1);
|
||||
+
|
||||
+#endif /* LINUX_VERSION_CODE < 2.6.0 */
|
||||
+
|
||||
+MODULE_PARM_DESC(radio, "controls state of radio (1=on, 0=off)");
|
||||
+
|
||||
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
+MODULE_AUTHOR(DRV_COPYRIGHT);
|
||||
+MODULE_LICENSE("GPL");
|
||||
+
|
||||
+#define AV5100_RADIO_ON (0xe0)
|
||||
+#define AV5100_RADIO_OFF (0xe1)
|
||||
+
|
||||
+static int av5100_radio = AV5100_RADIO_OFF;
|
||||
+
|
||||
+static void av5100_set_radio(int state)
|
||||
+{
|
||||
+ printk(KERN_INFO DRV_NAME ": Radio being turned %s\n",
|
||||
+ (state == AV5100_RADIO_ON) ? "ON" : "OFF");
|
||||
+ outl(0x80020800, 0xcf8);
|
||||
+ outb(0x6f, 0x0072);
|
||||
+ outl(0x1800ffff, 0x1184);
|
||||
+ outb(state, 0x00b2);
|
||||
+ av5100_radio = state;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * proc stuff
|
||||
+ */
|
||||
+static struct proc_dir_entry *dir_base = NULL;
|
||||
+
|
||||
+static int proc_set_radio(struct file *file, const char *buffer,
|
||||
+ unsigned long count, void *data)
|
||||
+{
|
||||
+ av5100_set_radio(buffer[0] == '0' ? AV5100_RADIO_OFF : AV5100_RADIO_ON);
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static int proc_get_radio(char *page, char **start, off_t offset,
|
||||
+ int count, int *eof, void *data)
|
||||
+{
|
||||
+ int len = 0;
|
||||
+
|
||||
+ len += snprintf(page, count, DRV_NAME ": %d\n",
|
||||
+ av5100_radio == AV5100_RADIO_OFF ? 0 : 1);
|
||||
+
|
||||
+ *eof = 1;
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void av5100_proc_cleanup(void)
|
||||
+{
|
||||
+ if (dir_base) {
|
||||
+ remove_proc_entry("radio", dir_base);
|
||||
+ remove_proc_entry(DRV_NAME, &proc_root);
|
||||
+ dir_base = NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int av5100_proc_init(void)
|
||||
+{
|
||||
+ struct proc_dir_entry *ent;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ dir_base = create_proc_entry(DRV_NAME, S_IFDIR, &proc_root);
|
||||
+ if (dir_base == NULL) {
|
||||
+ printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/"
|
||||
+ DRV_NAME "\n");
|
||||
+ err = -ENOMEM;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ ent = create_proc_entry("radio", S_IFREG | S_IRUGO | S_IWUSR,
|
||||
+ dir_base);
|
||||
+ if (ent) {
|
||||
+ ent->read_proc = proc_get_radio;
|
||||
+ ent->write_proc = proc_set_radio;
|
||||
+ } else {
|
||||
+ printk(KERN_ERR
|
||||
+ "Unable to initialize /proc/" DRV_NAME "/radio\n");
|
||||
+ err = -ENOMEM;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+ fail:
|
||||
+ av5100_proc_cleanup();
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * module stuff
|
||||
+ */
|
||||
+static int __init av5100_init(void)
|
||||
+{
|
||||
+ av5100_proc_init();
|
||||
+
|
||||
+ av5100_set_radio((radio == 1) ? AV5100_RADIO_ON : AV5100_RADIO_OFF);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __exit av5100_exit(void)
|
||||
+{
|
||||
+ av5100_set_radio(AV5100_RADIO_OFF);
|
||||
+
|
||||
+ av5100_proc_cleanup();
|
||||
+}
|
||||
+
|
||||
+module_init(av5100_init);
|
||||
+module_exit(av5100_exit);
|
||||
+
|
||||
+/*
|
||||
+ 1 2 3 4 5 6 7
|
||||
+12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
+*/
|
||||
diff -Nurp linux-2.6.37/3rdparty/rfswitch/FILES linux-2.6.37.3rdparty/3rdparty/rfswitch/FILES
|
||||
--- linux-2.6.37/3rdparty/rfswitch/FILES 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/FILES 2004-07-09 07:44:19.000000000 +0300
|
||||
@@ -0,0 +1,6 @@
|
||||
+Makefile Used for building on 2.4, 2.6, internally and exteranlly
|
||||
+
|
||||
+FILES This file
|
||||
+
|
||||
+av5100.c Averatec 5100P SW Switch Module
|
||||
+pbe5.c Packard Bell Easynote SW Switch Module
|
||||
diff -Nurp linux-2.6.37/3rdparty/rfswitch/ISSUES linux-2.6.37.3rdparty/3rdparty/rfswitch/ISSUES
|
||||
--- linux-2.6.37/3rdparty/rfswitch/ISSUES 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/ISSUES 2004-07-09 07:43:22.000000000 +0300
|
||||
@@ -0,0 +1,28 @@
|
||||
+
|
||||
+ISSUES
|
||||
+------------ ----- ----- ---- --- -- -
|
||||
+
|
||||
+No packets! - RF kill switch
|
||||
+
|
||||
+If the module loads, but no packets are transferred you may have a SW based
|
||||
+radio kill switch. All laptops have some capability to disable the radio
|
||||
+via a button or switch. On some laptops that switch is physically tied to the
|
||||
+IPW2100; simply toggling the switch should enable the radio.
|
||||
+
|
||||
+On other laptops, the switch is a button that when pressed requires some
|
||||
+software driver to send some hardware command to some other piece of hardware
|
||||
+on the laptop, that then controls the radio. The driver currently has support
|
||||
+for the Averatec 5100P laptop's SW switch. Support will be added for other
|
||||
+laptop vendors as we become aware of them and figure out how to enable the
|
||||
+radio.
|
||||
+
|
||||
+To know if the radio is being disabled via the RF switch, perform the following:
|
||||
+
|
||||
+% cat /proc/net/ipw2100/eth1/state
|
||||
+Radio is disabled by RF switch
|
||||
+
|
||||
+If it says that, then your RF switch is currently disabling the radio. The
|
||||
+driver doesn't currently support switching back to the on state if you have a
|
||||
+physical RF switch (the radio may turn on and packets will work, but the proc
|
||||
+entry won't be updated)
|
||||
+
|
||||
diff -Nurp linux-2.6.37/3rdparty/rfswitch/Kconfig linux-2.6.37.3rdparty/3rdparty/rfswitch/Kconfig
|
||||
--- linux-2.6.37/3rdparty/rfswitch/Kconfig 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/Kconfig 2008-05-27 23:39:10.000000000 +0300
|
||||
@@ -0,0 +1,22 @@
|
||||
+menu "RF Switch"
|
||||
+ depends on EXPERIMENTAL
|
||||
+
|
||||
+config RFSWITCH
|
||||
+ tristate "RF Switch"
|
||||
+ depends on EXPERIMENTAL
|
||||
+
|
||||
+config AVERATEC_5100P
|
||||
+ tristate "averatec 5100P driver"
|
||||
+ depends on RFSWITCH
|
||||
+ ---help---
|
||||
+ This is an experimental driver for the wireless switch
|
||||
+ of some laptops (usefull with some ipw2x00 cards)
|
||||
+
|
||||
+config PACKARDBELL_E5
|
||||
+ tristate "pbe5 driver"
|
||||
+ depends on RFSWITCH
|
||||
+ ---help---
|
||||
+ This is an experimental driver for the wireless switch
|
||||
+ of some laptops (usefull with some ipw2x00 cards)
|
||||
+
|
||||
+endmenu
|
||||
diff -Nurp linux-2.6.37/3rdparty/rfswitch/LICENSE linux-2.6.37.3rdparty/3rdparty/rfswitch/LICENSE
|
||||
--- linux-2.6.37/3rdparty/rfswitch/LICENSE 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/LICENSE 2004-07-09 07:43:22.000000000 +0300
|
||||
@@ -0,0 +1,339 @@
|
||||
+
|
||||
+"This software program is licensed subject to the GNU General Public License
|
||||
+(GPL). Version 2, June 1991, available at
|
||||
+<http://www.fsf.org/copyleft/gpl.html>"
|
||||
+
|
||||
+GNU General Public License
|
||||
+
|
||||
+Version 2, June 1991
|
||||
+
|
||||
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
+
|
||||
+Everyone is permitted to copy and distribute verbatim copies of this license
|
||||
+document, but changing it is not allowed.
|
||||
+
|
||||
+Preamble
|
||||
+
|
||||
+The licenses for most software are designed to take away your freedom to
|
||||
+share and change it. By contrast, the GNU General Public License is intended
|
||||
+to guarantee your freedom to share and change free software--to make sure
|
||||
+the software is free for all its users. This General Public License applies
|
||||
+to most of the Free Software Foundation's software and to any other program
|
||||
+whose authors commit to using it. (Some other Free Software Foundation
|
||||
+software is covered by the GNU Library General Public License instead.) You
|
||||
+can apply it to your programs, too.
|
||||
+
|
||||
+When we speak of free software, we are referring to freedom, not price. Our
|
||||
+General Public Licenses are designed to make sure that you have the freedom
|
||||
+to distribute copies of free software (and charge for this service if you
|
||||
+wish), that you receive source code or can get it if you want it, that you
|
||||
+can change the software or use pieces of it in new free programs; and that
|
||||
+you know you can do these things.
|
||||
+
|
||||
+To protect your rights, we need to make restrictions that forbid anyone to
|
||||
+deny you these rights or to ask you to surrender the rights. These
|
||||
+restrictions translate to certain responsibilities for you if you distribute
|
||||
+copies of the software, or if you modify it.
|
||||
+
|
||||
+For example, if you distribute copies of such a program, whether gratis or
|
||||
+for a fee, you must give the recipients all the rights that you have. You
|
||||
+must make sure that they, too, receive or can get the source code. And you
|
||||
+must show them these terms so they know their rights.
|
||||
+
|
||||
+We protect your rights with two steps: (1) copyright the software, and (2)
|
||||
+offer you this license which gives you legal permission to copy, distribute
|
||||
+and/or modify the software.
|
||||
+
|
||||
+Also, for each author's protection and ours, we want to make certain that
|
||||
+everyone understands that there is no warranty for this free software. If
|
||||
+the software is modified by someone else and passed on, we want its
|
||||
+recipients to know that what they have is not the original, so that any
|
||||
+problems introduced by others will not reflect on the original authors'
|
||||
+reputations.
|
||||
+
|
||||
+Finally, any free program is threatened constantly by software patents. We
|
||||
+wish to avoid the danger that redistributors of a free program will
|
||||
+individually obtain patent licenses, in effect making the program
|
||||
+proprietary. To prevent this, we have made it clear that any patent must be
|
||||
+licensed for everyone's free use or not licensed at all.
|
||||
+
|
||||
+The precise terms and conditions for copying, distribution and modification
|
||||
+follow.
|
||||
+
|
||||
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
+
|
||||
+0. This License applies to any program or other work which contains a notice
|
||||
+ placed by the copyright holder saying it may be distributed under the
|
||||
+ terms of this General Public License. The "Program", below, refers to any
|
||||
+ such program or work, and a "work based on the Program" means either the
|
||||
+ Program or any derivative work under copyright law: that is to say, a
|
||||
+ work containing the Program or a portion of it, either verbatim or with
|
||||
+ modifications and/or translated into another language. (Hereinafter,
|
||||
+ translation is included without limitation in the term "modification".)
|
||||
+ Each licensee is addressed as "you".
|
||||
+
|
||||
+ Activities other than copying, distribution and modification are not
|
||||
+ covered by this License; they are outside its scope. The act of running
|
||||
+ the Program is not restricted, and the output from the Program is covered
|
||||
+ only if its contents constitute a work based on the Program (independent
|
||||
+ of having been made by running the Program). Whether that is true depends
|
||||
+ on what the Program does.
|
||||
+
|
||||
+1. You may copy and distribute verbatim copies of the Program's source code
|
||||
+ as you receive it, in any medium, provided that you conspicuously and
|
||||
+ appropriately publish on each copy an appropriate copyright notice and
|
||||
+ disclaimer of warranty; keep intact all the notices that refer to this
|
||||
+ License and to the absence of any warranty; and give any other recipients
|
||||
+ of the Program a copy of this License along with the Program.
|
||||
+
|
||||
+ You may charge a fee for the physical act of transferring a copy, and you
|
||||
+ may at your option offer warranty protection in exchange for a fee.
|
||||
+
|
||||
+2. You may modify your copy or copies of the Program or any portion of it,
|
||||
+ thus forming a work based on the Program, and copy and distribute such
|
||||
+ modifications or work under the terms of Section 1 above, provided that
|
||||
+ you also meet all of these conditions:
|
||||
+
|
||||
+ * a) You must cause the modified files to carry prominent notices stating
|
||||
+ that you changed the files and the date of any change.
|
||||
+
|
||||
+ * b) You must cause any work that you distribute or publish, that in
|
||||
+ whole or in part contains or is derived from the Program or any part
|
||||
+ thereof, to be licensed as a whole at no charge to all third parties
|
||||
+ under the terms of this License.
|
||||
+
|
||||
+ * c) If the modified program normally reads commands interactively when
|
||||
+ run, you must cause it, when started running for such interactive
|
||||
+ use in the most ordinary way, to print or display an announcement
|
||||
+ including an appropriate copyright notice and a notice that there is
|
||||
+ no warranty (or else, saying that you provide a warranty) and that
|
||||
+ users may redistribute the program under these conditions, and
|
||||
+ telling the user how to view a copy of this License. (Exception: if
|
||||
+ the Program itself is interactive but does not normally print such
|
||||
+ an announcement, your work based on the Program is not required to
|
||||
+ print an announcement.)
|
||||
+
|
||||
+ These requirements apply to the modified work as a whole. If identifiable
|
||||
+ sections of that work are not derived from the Program, and can be
|
||||
+ reasonably considered independent and separate works in themselves, then
|
||||
+ this License, and its terms, do not apply to those sections when you
|
||||
+ distribute them as separate works. But when you distribute the same
|
||||
+ sections as part of a whole which is a work based on the Program, the
|
||||
+ distribution of the whole must be on the terms of this License, whose
|
||||
+ permissions for other licensees extend to the entire whole, and thus to
|
||||
+ each and every part regardless of who wrote it.
|
||||
+
|
||||
+ Thus, it is not the intent of this section to claim rights or contest
|
||||
+ your rights to work written entirely by you; rather, the intent is to
|
||||
+ exercise the right to control the distribution of derivative or
|
||||
+ collective works based on the Program.
|
||||
+
|
||||
+ In addition, mere aggregation of another work not based on the Program
|
||||
+ with the Program (or with a work based on the Program) on a volume of a
|
||||
+ storage or distribution medium does not bring the other work under the
|
||||
+ scope of this License.
|
||||
+
|
||||
+3. You may copy and distribute the Program (or a work based on it, under
|
||||
+ Section 2) in object code or executable form under the terms of Sections
|
||||
+ 1 and 2 above provided that you also do one of the following:
|
||||
+
|
||||
+ * a) Accompany it with the complete corresponding machine-readable source
|
||||
+ code, which must be distributed under the terms of Sections 1 and 2
|
||||
+ above on a medium customarily used for software interchange; or,
|
||||
+
|
||||
+ * b) Accompany it with a written offer, valid for at least three years,
|
||||
+ to give any third party, for a charge no more than your cost of
|
||||
+ physically performing source distribution, a complete machine-
|
||||
+ readable copy of the corresponding source code, to be distributed
|
||||
+ under the terms of Sections 1 and 2 above on a medium customarily
|
||||
+ used for software interchange; or,
|
||||
+
|
||||
+ * c) Accompany it with the information you received as to the offer to
|
||||
+ distribute corresponding source code. (This alternative is allowed
|
||||
+ only for noncommercial distribution and only if you received the
|
||||
+ program in object code or executable form with such an offer, in
|
||||
+ accord with Subsection b above.)
|
||||
+
|
||||
+ The source code for a work means the preferred form of the work for
|
||||
+ making modifications to it. For an executable work, complete source code
|
||||
+ means all the source code for all modules it contains, plus any
|
||||
+ associated interface definition files, plus the scripts used to control
|
||||
+ compilation and installation of the executable. However, as a special
|
||||
+ exception, the source code distributed need not include anything that is
|
||||
+ normally distributed (in either source or binary form) with the major
|
||||
+ components (compiler, kernel, and so on) of the operating system on which
|
||||
+ the executable runs, unless that component itself accompanies the
|
||||
+ executable.
|
||||
+
|
||||
+ If distribution of executable or object code is made by offering access
|
||||
+ to copy from a designated place, then offering equivalent access to copy
|
||||
+ the source code from the same place counts as distribution of the source
|
||||
+ code, even though third parties are not compelled to copy the source
|
||||
+ along with the object code.
|
||||
+
|
||||
+4. You may not copy, modify, sublicense, or distribute the Program except as
|
||||
+ expressly provided under this License. Any attempt otherwise to copy,
|
||||
+ modify, sublicense or distribute the Program is void, and will
|
||||
+ automatically terminate your rights under this License. However, parties
|
||||
+ who have received copies, or rights, from you under this License will not
|
||||
+ have their licenses terminated so long as such parties remain in full
|
||||
+ compliance.
|
||||
+
|
||||
+5. You are not required to accept this License, since you have not signed
|
||||
+ it. However, nothing else grants you permission to modify or distribute
|
||||
+ the Program or its derivative works. These actions are prohibited by law
|
||||
+ if you do not accept this License. Therefore, by modifying or
|
||||
+ distributing the Program (or any work based on the Program), you
|
||||
+ indicate your acceptance of this License to do so, and all its terms and
|
||||
+ conditions for copying, distributing or modifying the Program or works
|
||||
+ based on it.
|
||||
+
|
||||
+6. Each time you redistribute the Program (or any work based on the
|
||||
+ Program), the recipient automatically receives a license from the
|
||||
+ original licensor to copy, distribute or modify the Program subject to
|
||||
+ these terms and conditions. You may not impose any further restrictions
|
||||
+ on the recipients' exercise of the rights granted herein. You are not
|
||||
+ responsible for enforcing compliance by third parties to this License.
|
||||
+
|
||||
+7. If, as a consequence of a court judgment or allegation of patent
|
||||
+ infringement or for any other reason (not limited to patent issues),
|
||||
+ conditions are imposed on you (whether by court order, agreement or
|
||||
+ otherwise) that contradict the conditions of this License, they do not
|
||||
+ excuse you from the conditions of this License. If you cannot distribute
|
||||
+ so as to satisfy simultaneously your obligations under this License and
|
||||
+ any other pertinent obligations, then as a consequence you may not
|
||||
+ distribute the Program at all. For example, if a patent license would
|
||||
+ not permit royalty-free redistribution of the Program by all those who
|
||||
+ receive copies directly or indirectly through you, then the only way you
|
||||
+ could satisfy both it and this License would be to refrain entirely from
|
||||
+ distribution of the Program.
|
||||
+
|
||||
+ If any portion of this section is held invalid or unenforceable under any
|
||||
+ particular circumstance, the balance of the section is intended to apply
|
||||
+ and the section as a whole is intended to apply in other circumstances.
|
||||
+
|
||||
+ It is not the purpose of this section to induce you to infringe any
|
||||
+ patents or other property right claims or to contest validity of any
|
||||
+ such claims; this section has the sole purpose of protecting the
|
||||
+ integrity of the free software distribution system, which is implemented
|
||||
+ by public license practices. Many people have made generous contributions
|
||||
+ to the wide range of software distributed through that system in
|
||||
+ reliance on consistent application of that system; it is up to the
|
||||
+ author/donor to decide if he or she is willing to distribute software
|
||||
+ through any other system and a licensee cannot impose that choice.
|
||||
+
|
||||
+ This section is intended to make thoroughly clear what is believed to be
|
||||
+ a consequence of the rest of this License.
|
||||
+
|
||||
+8. If the distribution and/or use of the Program is restricted in certain
|
||||
+ countries either by patents or by copyrighted interfaces, the original
|
||||
+ copyright holder who places the Program under this License may add an
|
||||
+ explicit geographical distribution limitation excluding those countries,
|
||||
+ so that distribution is permitted only in or among countries not thus
|
||||
+ excluded. In such case, this License incorporates the limitation as if
|
||||
+ written in the body of this License.
|
||||
+
|
||||
+9. The Free Software Foundation may publish revised and/or new versions of
|
||||
+ the General Public License from time to time. Such new versions will be
|
||||
+ similar in spirit to the present version, but may differ in detail to
|
||||
+ address new problems or concerns.
|
||||
+
|
||||
+ Each version is given a distinguishing version number. If the Program
|
||||
+ specifies a version number of this License which applies to it and "any
|
||||
+ later version", you have the option of following the terms and
|
||||
+ conditions either of that version or of any later version published by
|
||||
+ the Free Software Foundation. If the Program does not specify a version
|
||||
+ number of this License, you may choose any version ever published by the
|
||||
+ Free Software Foundation.
|
||||
+
|
||||
+10. If you wish to incorporate parts of the Program into other free programs
|
||||
+ whose distribution conditions are different, write to the author to ask
|
||||
+ for permission. For software which is copyrighted by the Free Software
|
||||
+ Foundation, write to the Free Software Foundation; we sometimes make
|
||||
+ exceptions for this. Our decision will be guided by the two goals of
|
||||
+ preserving the free status of all derivatives of our free software and
|
||||
+ of promoting the sharing and reuse of software generally.
|
||||
+
|
||||
+ NO WARRANTY
|
||||
+
|
||||
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
|
||||
+ ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
|
||||
+ YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
|
||||
+ NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
+
|
||||
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
|
||||
+ DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
|
||||
+ DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
|
||||
+ (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
|
||||
+ INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
|
||||
+ THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR
|
||||
+ OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
+
|
||||
+END OF TERMS AND CONDITIONS
|
||||
+
|
||||
+How to Apply These Terms to Your New Programs
|
||||
+
|
||||
+If you develop a new program, and you want it to be of the greatest
|
||||
+possible use to the public, the best way to achieve this is to make it free
|
||||
+software which everyone can redistribute and change under these terms.
|
||||
+
|
||||
+To do so, attach the following notices to the program. It is safest to
|
||||
+attach them to the start of each source file to most effectively convey the
|
||||
+exclusion of warranty; and each file should have at least the "copyright"
|
||||
+line and a pointer to where the full notice is found.
|
||||
+
|
||||
+one line to give the program's name and an idea of what it does.
|
||||
+Copyright (C) yyyy name of author
|
||||
+
|
||||
+This program is free software; you can redistribute it and/or modify it
|
||||
+under the terms of the GNU General Public License as published by the Free
|
||||
+Software Foundation; either version 2 of the License, or (at your option)
|
||||
+any later version.
|
||||
+
|
||||
+This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
+more details.
|
||||
+
|
||||
+You should have received a copy of the GNU General Public License along with
|
||||
+this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
+Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
+
|
||||
+Also add information on how to contact you by electronic and paper mail.
|
||||
+
|
||||
+If the program is interactive, make it output a short notice like this when
|
||||
+it starts in an interactive mode:
|
||||
+
|
||||
+Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
|
||||
+with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free
|
||||
+software, and you are welcome to redistribute it under certain conditions;
|
||||
+type 'show c' for details.
|
||||
+
|
||||
+The hypothetical commands 'show w' and 'show c' should show the appropriate
|
||||
+parts of the General Public License. Of course, the commands you use may be
|
||||
+called something other than 'show w' and 'show c'; they could even be
|
||||
+mouse-clicks or menu items--whatever suits your program.
|
||||
+
|
||||
+You should also get your employer (if you work as a programmer) or your
|
||||
+school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
+necessary. Here is a sample; alter the names:
|
||||
+
|
||||
+Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
+'Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
+
|
||||
+signature of Ty Coon, 1 April 1989
|
||||
+Ty Coon, President of Vice
|
||||
+
|
||||
+This General Public License does not permit incorporating your program into
|
||||
+proprietary programs. If your program is a subroutine library, you may
|
||||
+consider it more useful to permit linking proprietary applications with the
|
||||
+library. If this is what you want to do, use the GNU Library General Public
|
||||
+License instead of this License.
|
||||
diff -Nurp linux-2.6.37/3rdparty/rfswitch/Makefile linux-2.6.37.3rdparty/3rdparty/rfswitch/Makefile
|
||||
--- linux-2.6.37/3rdparty/rfswitch/Makefile 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/Makefile 2008-03-28 05:17:16.000000000 +0200
|
||||
@@ -0,0 +1,119 @@
|
||||
+#
|
||||
+# Makefile for the SW RF Switch kernel modules
|
||||
+#
|
||||
+# NOTE: This make file can serve as both an external Makefile (launched
|
||||
+# directly by the user), or as the sub-dir Makefile used by the kernel
|
||||
+# build system.
|
||||
+
|
||||
+
|
||||
+CONFIG_AVERATEC_5100P=m
|
||||
+CONFIG_PACKARDBELL_E5=m
|
||||
+
|
||||
+
|
||||
+
|
||||
+list-m :=
|
||||
+list-$(CONFIG_AVERATEC_5100P) += av5100
|
||||
+list-$(CONFIG_PACKARDBELL_E5) += pbe5
|
||||
+
|
||||
+
|
||||
+obj-$(CONFIG_AVERATEC_5100P) += av5100.o
|
||||
+obj-$(CONFIG_PACKARDBELL_E5) += pbe5.o
|
||||
+
|
||||
+#
|
||||
+# Begin dual Makefile mode here. First we provide support for when we
|
||||
+# are being invoked by the kernel build system
|
||||
+#
|
||||
+ifneq ($(KERNELRELEASE),)
|
||||
+
|
||||
+ifneq ($(PATCHLEVEL),6) # If we are not on a 2.6, then do 2.4 specific things
|
||||
+
|
||||
+O_TARGET := rfswitch.o
|
||||
+
|
||||
+include $(TOPDIR)/Rules.make
|
||||
+
|
||||
+endif # End if 2.4 specific settings
|
||||
+
|
||||
+else
|
||||
+# Here we begin the portion that is executed if the user invoked this Makefile
|
||||
+# directly.
|
||||
+
|
||||
+# KSRC should be set to the path to your sources
|
||||
+# modules are installed into KMISC
|
||||
+KVER := $(shell uname -r)
|
||||
+KSRC := /lib/modules/$(KVER)/build
|
||||
+KMISC := /lib/modules/$(KVER)/kernel/drivers/net/wireless/
|
||||
+
|
||||
+# KSRC_OUTPUT should be overridden if you are using a 2.6 kernel that
|
||||
+# has it's output sent elsewhere via KBUILD_OUTPUT= or O=
|
||||
+KSRC_OUTPUT := $(KSRC)
|
||||
+
|
||||
+# If we find Rules.make, we can assume we're using the old 2.4 style building
|
||||
+OLDMAKE=$(wildcard $(KSRC)/Rules.make)
|
||||
+PWD=$(shell pwd)
|
||||
+
|
||||
+VERFILE := $(KSRC_OUTPUT)/include/linux/version.h
|
||||
+KERNELRELEASE := $(shell \
|
||||
+ if [ -r $(VERFILE) ]; then \
|
||||
+ (cat $(VERFILE); echo UTS_RELEASE) | \
|
||||
+ $(CC) -I$(KSRC_OUTPUT) $(CFLAGS) -E - | \
|
||||
+ tail -n 1 | \
|
||||
+ xargs echo; \
|
||||
+ else \
|
||||
+ uname -r; \
|
||||
+ fi)
|
||||
+
|
||||
+MODPATH := $(DESTDIR)/lib/modules/$(KERNELRELEASE)
|
||||
+
|
||||
+all: modules
|
||||
+
|
||||
+clean:
|
||||
+ rm -f *.mod.c *.mod *.o *.ko .*.cmd .*.flags Modules.symvers
|
||||
+ rm -rf $(PWD)/tmp
|
||||
+
|
||||
+
|
||||
+ifeq ($(OLDMAKE),)
|
||||
+
|
||||
+TMP=$(PWD)/tmp
|
||||
+MODVERDIR=$(TMP)/.tmp_versions
|
||||
+
|
||||
+modules:
|
||||
+ifdef ($(KSRC_OUTPUT)/.tmp_versions)
|
||||
+ mkdir -p $(MODVERDIR)
|
||||
+ -cp $(KSRC_OUTPUT)/.tmp_versions/*.mod $(MODVERDIR)
|
||||
+endif
|
||||
+ifeq ($(KSRC),$(KSRC_OUTPUT)) # We're not outputting elsewhere
|
||||
+ifdef ($(KSRC)/.tmp_versions)
|
||||
+ -cp $(KSRC)/.tmp_versions/*.mod $(MODVERDIR)
|
||||
+endif
|
||||
+ $(MAKE) -C $(KSRC) SUBDIRS=$(PWD) MODVERDIR=$(MODVERDIR) modules
|
||||
+else # We've got a kernel with seperate output, copy the config, and use O=
|
||||
+ mkdir -p $(TMP)
|
||||
+ cp $(KSRC_OUTPUT)/.config $(TMP)
|
||||
+ $(MAKE) -C $(KSRC) SUBDIRS=$(PWD) MODVERDIR=$(MODVERDIR) O=$(PWD)/tmp modules
|
||||
+endif
|
||||
+
|
||||
+install: modules
|
||||
+ install -d $(KMISC)
|
||||
+ install -m 644 -c $(addsuffix .ko,$(list-m)) $(KMISC)
|
||||
+ /sbin/depmod -a
|
||||
+
|
||||
+
|
||||
+else # We're on 2.4, and things are slightly different
|
||||
+
|
||||
+modules:
|
||||
+ $(MAKE) -C $(KSRC) SUBDIRS=$(PWD) BUILD_DIR=$(PWD) modules
|
||||
+
|
||||
+install: modules
|
||||
+ install -d $(KMISC)
|
||||
+ install -m 644 -c $(addsuffix .o,$(list-m)) $(KMISC)
|
||||
+ /sbin/depmod -a
|
||||
+
|
||||
+endif
|
||||
+
|
||||
+uninstall:
|
||||
+ cd $(KMISC)
|
||||
+ rm -rf $(addsuffix .ko,$(list-m))
|
||||
+ cd -
|
||||
+ /sbin/depmod -a
|
||||
+
|
||||
+endif
|
||||
diff -Nurp linux-2.6.37/3rdparty/rfswitch/pbe5.c linux-2.6.37.3rdparty/3rdparty/rfswitch/pbe5.c
|
||||
--- linux-2.6.37/3rdparty/rfswitch/pbe5.c 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/pbe5.c 2008-03-28 05:25:16.000000000 +0200
|
||||
@@ -0,0 +1,205 @@
|
||||
+/*******************************************************************************
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify it
|
||||
+ under the terms of version 2 of the GNU General Public License as
|
||||
+ published by the Free Software Foundation.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
+ more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License along with
|
||||
+ this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
+
|
||||
+ The full GNU General Public License is included in this distribution in the
|
||||
+ file called LICENSE.
|
||||
+
|
||||
+ Author:
|
||||
+ Pedro Ramalhais <pmr09313@students.fct.unl.pt>
|
||||
+
|
||||
+ Based on:
|
||||
+ av5100.c from http://ipw2100.sourceforge.net/
|
||||
+
|
||||
+*******************************************************************************/
|
||||
+
|
||||
+#include <linux/compiler.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/netdevice.h>
|
||||
+#include <linux/version.h>
|
||||
+#include <linux/proc_fs.h>
|
||||
+#include <linux/ioport.h>
|
||||
+#include <asm/uaccess.h>
|
||||
+#include <asm/io.h>
|
||||
+
|
||||
+#define DRV_NAME "pbe5"
|
||||
+#define DRV_VERSION "1.3"
|
||||
+#define DRV_DESCRIPTION "SW RF kill switch for Packard Bell EasyNote E5"
|
||||
+#define DRV_AUTHOR "Pedro Ramalhais"
|
||||
+#define DRV_LICENSE "GPL"
|
||||
+
|
||||
+static int radio = 1;
|
||||
+
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
+
|
||||
+MODULE_PARM(radio, "i");
|
||||
+
|
||||
+#else /* LINUX_VERSION_CODE < 2.6.0 */
|
||||
+
|
||||
+#include <linux/moduleparam.h>
|
||||
+module_param(radio, int, 1);
|
||||
+
|
||||
+#endif /* LINUX_VERSION_CODE < 2.6.0 */
|
||||
+
|
||||
+MODULE_PARM_DESC(radio, "controls state of radio (1=on, 0=off)");
|
||||
+
|
||||
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
+MODULE_AUTHOR(DRV_AUTHOR);
|
||||
+MODULE_LICENSE(DRV_LICENSE);
|
||||
+
|
||||
+/*
|
||||
+ * NOTE: These values were obtained from disassembling the Icon.exe program
|
||||
+ * installed in the Packard Bell EasyNote E5 laptop. The names were guessed,
|
||||
+ * so don't rely on them.
|
||||
+ */
|
||||
+#define PBE5_PORT_TOGGLE 0x0b3
|
||||
+#define PBE5_VALUE_TOGGLE_ON 0x01
|
||||
+#define PBE5_VALUE_TOGGLE_OFF 0x00
|
||||
+#define PBE5_PORT_APPLY 0x0b2
|
||||
+#define PBE5_VALUE_APPLY 0xef
|
||||
+
|
||||
+// Some "booleans" =;-)
|
||||
+#define PBE5_RADIO_OFF 0
|
||||
+#define PBE5_RADIO_ON 1
|
||||
+
|
||||
+static int pbe5_radio_status = PBE5_RADIO_ON;
|
||||
+
|
||||
+unsigned char pbe5_get_radio(void)
|
||||
+{
|
||||
+ unsigned char val = 0x00;
|
||||
+
|
||||
+ val = inb(PBE5_PORT_TOGGLE);
|
||||
+
|
||||
+ return val;
|
||||
+}
|
||||
+
|
||||
+static void pbe5_set_radio(int state_set)
|
||||
+{
|
||||
+ pbe5_radio_status = pbe5_get_radio();
|
||||
+
|
||||
+ if (pbe5_radio_status != state_set) {
|
||||
+ // Set the radio toggle register
|
||||
+ outb(PBE5_VALUE_TOGGLE_ON, PBE5_PORT_TOGGLE);
|
||||
+ // Commit the radio toggle register value
|
||||
+ outb(PBE5_VALUE_APPLY, PBE5_PORT_APPLY);
|
||||
+ // Update the radio status
|
||||
+ pbe5_radio_status = pbe5_get_radio();
|
||||
+
|
||||
+ printk(KERN_INFO DRV_NAME ": Radio turned %s\n",
|
||||
+ (state_set == PBE5_RADIO_ON) ? "ON" : "OFF");
|
||||
+ } else {
|
||||
+ printk(KERN_INFO DRV_NAME ": Radio already %s\n",
|
||||
+ (state_set == PBE5_RADIO_ON) ? "ON" : "OFF");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * proc stuff
|
||||
+ */
|
||||
+static struct proc_dir_entry *dir_base = NULL;
|
||||
+
|
||||
+static int proc_set_radio(struct file *file, const char *buffer,
|
||||
+ unsigned long count, void *data)
|
||||
+{
|
||||
+ pbe5_set_radio(buffer[0] == '0' ? PBE5_RADIO_OFF : PBE5_RADIO_ON);
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static int proc_get_radio(char *page, char **start, off_t offset,
|
||||
+ int count, int *eof, void *data)
|
||||
+{
|
||||
+ int len = 0;
|
||||
+
|
||||
+ len += snprintf(page, count, DRV_NAME ": %d\n",
|
||||
+ pbe5_radio_status == PBE5_RADIO_OFF ? 0 : 1);
|
||||
+
|
||||
+ *eof = 1;
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void pbe5_proc_cleanup(void)
|
||||
+{
|
||||
+ if (dir_base) {
|
||||
+ remove_proc_entry("radio", dir_base);
|
||||
+ remove_proc_entry(DRV_NAME, &proc_root);
|
||||
+ dir_base = NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int pbe5_proc_init(void)
|
||||
+{
|
||||
+ struct proc_dir_entry *ent;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ dir_base = create_proc_entry(DRV_NAME, S_IFDIR, &proc_root);
|
||||
+ if (dir_base == NULL) {
|
||||
+ printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/"
|
||||
+ DRV_NAME "\n");
|
||||
+ err = -ENOMEM;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ ent = create_proc_entry("radio", S_IFREG | S_IRUGO | S_IWUSR,
|
||||
+ dir_base);
|
||||
+ if (ent) {
|
||||
+ ent->read_proc = proc_get_radio;
|
||||
+ ent->write_proc = proc_set_radio;
|
||||
+ } else {
|
||||
+ printk(KERN_ERR
|
||||
+ "Unable to initialize /proc/" DRV_NAME "/radio\n");
|
||||
+ err = -ENOMEM;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+ fail:
|
||||
+ pbe5_proc_cleanup();
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * module stuff
|
||||
+ */
|
||||
+static int __init pbe5_init(void)
|
||||
+{
|
||||
+ pbe5_proc_init();
|
||||
+
|
||||
+ pbe5_set_radio((radio == 1) ? PBE5_RADIO_ON : PBE5_RADIO_OFF);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __exit pbe5_exit(void)
|
||||
+{
|
||||
+ pbe5_set_radio(PBE5_RADIO_OFF);
|
||||
+
|
||||
+ pbe5_proc_cleanup();
|
||||
+}
|
||||
+
|
||||
+module_init(pbe5_init);
|
||||
+module_exit(pbe5_exit);
|
||||
+
|
||||
+/*
|
||||
+ 1 2 3 4 5 6 7
|
||||
+12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
+*/
|
||||
diff -Nurp linux-2.6.37/3rdparty/rfswitch/README linux-2.6.37.3rdparty/3rdparty/rfswitch/README
|
||||
--- linux-2.6.37/3rdparty/rfswitch/README 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/README 2004-07-09 17:26:20.000000000 +0300
|
||||
@@ -0,0 +1,44 @@
|
||||
+Radio Kill Switch
|
||||
+------------ ----- ----- ---- --- -- -
|
||||
+Most laptops provide the ability for the user to physically disable the radio.
|
||||
+Some vendors have implemented this as a physical switch that requires no
|
||||
+software to turn the radio off and on. On other laptops, however, the switch
|
||||
+is controlled through a button being pressed and a software driver then making
|
||||
+calls to turn the radio off and on. This is referred to as a "software based
|
||||
+RF kill switch"
|
||||
+
|
||||
+Currently this project provides modules for controlling the software RF kill
|
||||
+switch on the Averatec 5100P and Packard Bell EasyNote E5. The code may work
|
||||
+on other laptops, but these are the only models on which it has been tested.
|
||||
+
|
||||
+To determine if you have a system that might be compatible with one of the
|
||||
+provided SW RF Kill switch modules, you can run:
|
||||
+
|
||||
+
|
||||
+ To check for the Packard Bell (to use module pbe) --
|
||||
+
|
||||
+ % dd if=/dev/mem bs=1 skip=983040 count=65535 2>/dev/null | strings | egrep "NEW-PC|Insyde Software MobilePRO BIOS"
|
||||
+
|
||||
+ To check for the Averatec (to use module av5100) --
|
||||
+
|
||||
+ % dd if=/dev/mem bs=1 skip=983040 count=65535 2>/dev/null | strings | egrep "AVERATEC"
|
||||
+
|
||||
+If you have one of those laptop models you can imply loading the av5100/pbe5
|
||||
+module and the radio will be toggled on and off. In addition, you can turn
|
||||
+the driver on and off by writing either a 1 or 0 to /proc/av5100/radio or
|
||||
+/proc/pbe5/radio. If you automatically load the av5100/pbe5 module when your
|
||||
+system boots, you may wish to use the radio module parameter to control the
|
||||
+state of the radio upon loading:
|
||||
+
|
||||
+ modprobe av5100 radio=0
|
||||
+ modprobe pbe5 radio=0
|
||||
+
|
||||
+results in the module loading with the radio turned off. You can then turn the
|
||||
+radio on by:
|
||||
+
|
||||
+ echo 1 > /proc/av5100/radio
|
||||
+ echo 1 > /proc/pbe5/radio
|
||||
+
|
||||
+If you have a SW RF kill switch and can not use one of the above modules,
|
||||
+please join us on IRC (irc.freenode.net) on channel #ipw2100 and someone may
|
||||
+be able to help.
|
||||
@@ -1,19 +0,0 @@
|
||||
|
||||
fix build with 3.0
|
||||
|
||||
Signed-off-by: Thomas Backlund <tmb@mageia.org>
|
||||
|
||||
3rdparty/rfswitch/Makefile | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
--- a/3rdparty/rfswitch/Makefile.orig 2011-07-15 02:37:27.000000000 +0300
|
||||
+++ a/3rdparty/rfswitch/Makefile 2011-07-15 13:47:10.463914526 +0300
|
||||
@@ -29,8 +29,6 @@ ifneq ($(PATCHLEVEL),6) # If we are not
|
||||
|
||||
O_TARGET := rfswitch.o
|
||||
|
||||
-include $(TOPDIR)/Rules.make
|
||||
-
|
||||
endif # End if 2.4 specific settings
|
||||
|
||||
else
|
||||
@@ -1,51 +0,0 @@
|
||||
Remove 'proc_root' usage
|
||||
|
||||
Commit c74c120a21d87b0b6925ada5830d8cac21e852d9 (Linus's tree) removed
|
||||
the export of 'proc_root' variable, because you can create on the proc's
|
||||
root directory by passing NULL where you would pass 'proc_root'.
|
||||
|
||||
Signed-off-by: Luiz Fernando N. Capitulino <lcapitulino@mandriva.com.br>
|
||||
Index: linux-2.6.25/3rdparty/rfswitch/av5100.c
|
||||
===================================================================
|
||||
--- linux-2.6.25.orig/3rdparty/rfswitch/av5100.c
|
||||
+++ linux-2.6.25/3rdparty/rfswitch/av5100.c
|
||||
@@ -107,7 +107,7 @@ static void av5100_proc_cleanup(void)
|
||||
{
|
||||
if (dir_base) {
|
||||
remove_proc_entry("radio", dir_base);
|
||||
- remove_proc_entry(DRV_NAME, &proc_root);
|
||||
+ remove_proc_entry(DRV_NAME, NULL);
|
||||
dir_base = NULL;
|
||||
}
|
||||
}
|
||||
@@ -118,7 +118,7 @@ static int av5100_proc_init(void)
|
||||
struct proc_dir_entry *ent;
|
||||
int err = 0;
|
||||
|
||||
- dir_base = create_proc_entry(DRV_NAME, S_IFDIR, &proc_root);
|
||||
+ dir_base = create_proc_entry(DRV_NAME, S_IFDIR, NULL);
|
||||
if (dir_base == NULL) {
|
||||
printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/"
|
||||
DRV_NAME "\n");
|
||||
Index: linux-2.6.25/3rdparty/rfswitch/pbe5.c
|
||||
===================================================================
|
||||
--- linux-2.6.25.orig/3rdparty/rfswitch/pbe5.c
|
||||
+++ linux-2.6.25/3rdparty/rfswitch/pbe5.c
|
||||
@@ -138,7 +138,7 @@ static void pbe5_proc_cleanup(void)
|
||||
{
|
||||
if (dir_base) {
|
||||
remove_proc_entry("radio", dir_base);
|
||||
- remove_proc_entry(DRV_NAME, &proc_root);
|
||||
+ remove_proc_entry(DRV_NAME, NULL);
|
||||
dir_base = NULL;
|
||||
}
|
||||
}
|
||||
@@ -149,7 +149,7 @@ static int pbe5_proc_init(void)
|
||||
struct proc_dir_entry *ent;
|
||||
int err = 0;
|
||||
|
||||
- dir_base = create_proc_entry(DRV_NAME, S_IFDIR, &proc_root);
|
||||
+ dir_base = create_proc_entry(DRV_NAME, S_IFDIR, NULL);
|
||||
if (dir_base == NULL) {
|
||||
printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/"
|
||||
DRV_NAME "\n");
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,189 +0,0 @@
|
||||
3rdparty/viahss/Kconfig | 14 +++++++
|
||||
3rdparty/viahss/Makefile | 3 +
|
||||
3rdparty/viahss/README.html | 68 ++++++++++++++++++++++++++++++++++++
|
||||
3rdparty/viahss/viahss.c | 83 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 168 insertions(+)
|
||||
diff -Nurp linux-2.6.37/3rdparty/viahss/Kconfig linux-2.6.37.3rdparty/3rdparty/viahss/Kconfig
|
||||
--- linux-2.6.37/3rdparty/viahss/Kconfig 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ linux-2.6.37.3rdparty/3rdparty/viahss/Kconfig 2003-12-01 01:53:51.000000000 +0200
|
||||
@@ -0,0 +1,14 @@
|
||||
+config VIAHSS
|
||||
+ tristate "VIA High Speed Serial"
|
||||
+ depends on SERIAL_CORE && m
|
||||
+ ---help---
|
||||
+ VIA High Speed Serial is a little kernel module (1 KB) which enables
|
||||
+ high speed serial port modes of VIA VT82C686A or VT82C686B
|
||||
+ southbridge-equipped motherboards. With this module, you can use the
|
||||
+ serial port at 230400 bit/s so that you can get the full 128000 bit/s
|
||||
+ from ISDN-TA. The module has been tested with both 686A and 686B
|
||||
+ chipsets.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the
|
||||
+ module will be called viahss.
|
||||
+
|
||||
diff -Nurp linux-2.6.37/3rdparty/viahss/Makefile linux-2.6.37.3rdparty/3rdparty/viahss/Makefile
|
||||
--- linux-2.6.37/3rdparty/viahss/Makefile 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ linux-2.6.37.3rdparty/3rdparty/viahss/Makefile 2003-12-01 01:43:23.000000000 +0200
|
||||
@@ -0,0 +1,3 @@
|
||||
+
|
||||
+obj-$(CONFIG_VIAHSS) += viahss.o
|
||||
+
|
||||
diff -Nurp linux-2.6.37/3rdparty/viahss/README.html linux-2.6.37.3rdparty/3rdparty/viahss/README.html
|
||||
--- linux-2.6.37/3rdparty/viahss/README.html 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ linux-2.6.37.3rdparty/3rdparty/viahss/README.html 2003-12-01 01:58:23.000000000 +0200
|
||||
@@ -0,0 +1,68 @@
|
||||
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
+<html>
|
||||
+<head>
|
||||
+ <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
|
||||
+ <title>High speed serial port for VIA VT82C686 chipsets for linux</title>
|
||||
+</head>
|
||||
+<body>
|
||||
+<H3>Setting the serial port speed over 115,200bps</H3>
|
||||
+<br>
|
||||
+If you have motherboard which has VIA VT82C686A or VT82C686B chipset
|
||||
+you can set serial ports in high speed mode with this kernel module.
|
||||
+I use module with external ISDN-TA and haven't had any problems
|
||||
+so far but I cannot guarantee that you won't have buffer overflows if
|
||||
+you use full 230K or 460K speed all the time (FIFO's are still 16550A size).
|
||||
+ISDN with two channels maxes out at 128 Kb which means that it doesn't
|
||||
+really stress serial ports at 230400. Unlike SHSMOD-patches you don't have
|
||||
+to patch serial driver and module takes only 1KB of memory when it's
|
||||
+loaded which should leave enough room for other programs. It should
|
||||
+be also possible to make this work from userspace but accessing
|
||||
+pci devices is so much easier from kernel.
|
||||
+
|
||||
+<H3>How to use module</H3>
|
||||
+Get the <A href=http://www.kati.fi/viahss/viahss-0.92.tar.gz>package</A>
|
||||
+and compile it using included makefiles.
|
||||
+<H3>For 2.4</H3>
|
||||
+If you have kernel in some other location than /usr/src/linux edit Makefile
|
||||
+before compiling. You can also install module with "make install". After
|
||||
+you have loaded module in kernel (use modprobe or insmod) you can set serial
|
||||
+ports to use high speed modes with setserial.<br>
|
||||
+<H3>For 2.5/2.6</H3>
|
||||
+Copy Makefile-2.6 on top of Makefile and do make. After loading module set
|
||||
+serial speed with setserial. (NOTE: This gives a warning on depracated
|
||||
+method).
|
||||
+
|
||||
+<br>
|
||||
+# setserial /dev/ttyS0 spd_cust divisor 0x8002
|
||||
+<br><br>
|
||||
+which sets COM1: speed to 230400. With 0x8001 you should get 460800
|
||||
+but I haven't tested it. If you want to use COM2: use ttyS1 instead of ttyS0.
|
||||
+
|
||||
+After this you should set program which you are using to use 38400 bps
|
||||
+speed which is now actually 230K or 460K. For more information check
|
||||
+setserial man page (spd_cust).
|
||||
+
|
||||
+You can use serial port work as normal if you do<br>
|
||||
+<br>
|
||||
+# setserial /dev/ttyS0 spd_normal <br><br>
|
||||
+After this you can also remove viahss module with rmmod if you need to. Module doesn't intefere with normal serial port usage so you can leave
|
||||
+it loaded if you don't need that extra 1KB which module uses.
|
||||
+<H3>Download</H3>
|
||||
+<A href=http://www.kati.fi/viahss/viahss-0.92.tar.gz>viahss-0.92.tar.gz</A>
|
||||
+
|
||||
+<H3>Acknowledgments</H3>
|
||||
+
|
||||
+Thanks to Kimmo Rintala for help with divisor settings.<br>
|
||||
+I also like to thank Jeff Garzik for help with VIA datasheets.<br>
|
||||
+Port to 2.5/2.6 by Kingsly John with the help of <A href=http://lwn.net>LWN</A>
|
||||
+
|
||||
+<H3>Version History</H3>
|
||||
+0.90 First release<br>
|
||||
+0.91 Fixed Makefile <br>
|
||||
+0.92 Fixed for 2.5/2.6<br>
|
||||
+
|
||||
+<H3>Contact</H3>
|
||||
+
|
||||
+You can reach me by email: <A href=mailto:jrauti@iki.fi>jrauti@iki.fi</A>
|
||||
+</body>
|
||||
+</html>
|
||||
diff -Nurp linux-2.6.37/3rdparty/viahss/viahss.c linux-2.6.37.3rdparty/3rdparty/viahss/viahss.c
|
||||
--- linux-2.6.37/3rdparty/viahss/viahss.c 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ linux-2.6.37.3rdparty/3rdparty/viahss/viahss.c 2003-07-17 09:49:59.000000000 +0300
|
||||
@@ -0,0 +1,83 @@
|
||||
+/*
|
||||
+ * VIA VT 82c686[AB] high speed serial port enabler
|
||||
+ * Version 0.92
|
||||
+ * Copyright (c) 2000-2001 Juhani Rautiainen <jrauti@iki.fi>
|
||||
+ *
|
||||
+ * 0.92:
|
||||
+ * Ported to 2.5/2.6 by Kingsly John
|
||||
+ * - Corrected locking (no more cli() and sti())
|
||||
+ * - New makefile
|
||||
+ *
|
||||
+ * Can be freely distributed and used under the terms of the GNU GPL.
|
||||
+*/
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/config.h>
|
||||
+#include <linux/version.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/pci.h>
|
||||
+
|
||||
+const unsigned short confindex=0x3F0,confdata=0x3F1;
|
||||
+const unsigned char spcidx=0xEE;
|
||||
+
|
||||
+spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
|
||||
+
|
||||
+static int __init viahss_init(void)
|
||||
+{
|
||||
+ struct pci_dev *pcidev = NULL;
|
||||
+ unsigned char confval,val;
|
||||
+ pcidev = pci_find_device (PCI_VENDOR_ID_VIA,PCI_DEVICE_ID_VIA_82C686,NULL);
|
||||
+ if (pcidev) {
|
||||
+ spin_lock_irq(&driver_lock);
|
||||
+ /* start config */
|
||||
+ pci_read_config_byte(pcidev,0x85,&confval);
|
||||
+ confval |= 0x2;
|
||||
+ pci_write_config_byte (pcidev, 0x85,confval);
|
||||
+ /* activate high speed bits */
|
||||
+ outb(spcidx,confindex); /* set index */
|
||||
+ val = (unsigned char) inb(confdata);
|
||||
+ val |= 0xC0; /* both ports on high speed*/
|
||||
+ outb (spcidx,confindex);
|
||||
+ outb (val,confdata);
|
||||
+ /*stop config*/
|
||||
+ confval &= ~0x2;
|
||||
+ pci_write_config_byte(pcidev, 0x85, confval);
|
||||
+ spin_unlock_irq(&driver_lock);
|
||||
+ printk (KERN_INFO "VIA VT82C686[AB] serial port high speed enabled\n");
|
||||
+ }
|
||||
+ else {
|
||||
+ printk (KERN_INFO "Couldn't locate VIA chipset\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __exit viahss_exit(void)
|
||||
+{
|
||||
+ struct pci_dev *pcidev = NULL;
|
||||
+ unsigned char confval,val;
|
||||
+ pcidev = pci_find_device (PCI_VENDOR_ID_VIA,PCI_DEVICE_ID_VIA_82C686,NULL);
|
||||
+ if (pcidev) {
|
||||
+ spin_lock_irq(&driver_lock);
|
||||
+ /* start config */
|
||||
+ pci_read_config_byte(pcidev,0x85,&confval);
|
||||
+ confval |= 0x2;
|
||||
+ pci_write_config_byte (pcidev, 0x85,confval);
|
||||
+ /* activate high speed bits */
|
||||
+ outb(spcidx,confindex); /* set index */
|
||||
+ val = (unsigned char) inb(confdata);
|
||||
+ val &= ~0xC0; /* both ports off high speed*/
|
||||
+ outb (spcidx,confindex);
|
||||
+ outb (val,confdata);
|
||||
+ /*stop config*/
|
||||
+ confval &= ~0x2;
|
||||
+ pci_write_config_byte(pcidev, 0x85, confval);
|
||||
+ spin_unlock_irq(&driver_lock);
|
||||
+ printk (KERN_INFO "VIA VT82C686[AB] serial port high speed disabled\n");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+module_init(viahss_init);
|
||||
+module_exit(viahss_exit);
|
||||
+MODULE_DESCRIPTION("VIA VT82C686[AB] high speed serial port enabler");
|
||||
+MODULE_AUTHOR("Juhani Rautiainen <jrauti@iki.fi>");
|
||||
@@ -1,20 +0,0 @@
|
||||
--- linux-2.6.35-rc6-git-mnb0.1/3rdparty/viahss/viahss.c.orig 2010-07-30 21:17:30.000000000 +0300
|
||||
+++ linux-2.6.35-rc6-git-mnb0.1/3rdparty/viahss/viahss.c 2010-07-30 23:10:21.324978822 +0300
|
||||
@@ -25,7 +25,7 @@ static int __init viahss_init(void)
|
||||
{
|
||||
struct pci_dev *pcidev = NULL;
|
||||
unsigned char confval,val;
|
||||
- pcidev = pci_find_device (PCI_VENDOR_ID_VIA,PCI_DEVICE_ID_VIA_82C686,NULL);
|
||||
+ pcidev = pci_get_device (PCI_VENDOR_ID_VIA,PCI_DEVICE_ID_VIA_82C686,NULL);
|
||||
if (pcidev) {
|
||||
spin_lock_irq(&driver_lock);
|
||||
/* start config */
|
||||
@@ -55,7 +55,7 @@ static void __exit viahss_exit(void)
|
||||
{
|
||||
struct pci_dev *pcidev = NULL;
|
||||
unsigned char confval,val;
|
||||
- pcidev = pci_find_device (PCI_VENDOR_ID_VIA,PCI_DEVICE_ID_VIA_82C686,NULL);
|
||||
+ pcidev = pci_get_device (PCI_VENDOR_ID_VIA,PCI_DEVICE_ID_VIA_82C686,NULL);
|
||||
if (pcidev) {
|
||||
spin_lock_irq(&driver_lock);
|
||||
/* start config */
|
||||
@@ -1,19 +0,0 @@
|
||||
|
||||
fix build with 3.0
|
||||
|
||||
Signed-off-by: Thomas Backlund <tmb@mageia.org>
|
||||
|
||||
3rdparty/viahss/viahss.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/3rdparty/viahss/viahss.c.orig 2011-07-15 02:37:27.000000000 +0300
|
||||
+++ a/3rdparty/viahss/viahss.c 2011-07-15 13:48:13.204291256 +0300
|
||||
@@ -19,7 +19,7 @@
|
||||
const unsigned short confindex=0x3F0,confdata=0x3F1;
|
||||
const unsigned char spcidx=0xEE;
|
||||
|
||||
-spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
|
||||
+DEFINE_SPINLOCK(driver_lock);
|
||||
|
||||
static int __init viahss_init(void)
|
||||
{
|
||||
@@ -1,18 +0,0 @@
|
||||
linux/config.h is gone in 2.6.21
|
||||
|
||||
---
|
||||
3rdparty/viahss/viahss.c | 1 0 + 1 - 0 !
|
||||
1 files changed, 1 deletion(-)
|
||||
|
||||
Index: linux-2.6.21/3rdparty/viahss/viahss.c
|
||||
===================================================================
|
||||
--- linux-2.6.21.orig/3rdparty/viahss/viahss.c 2003-07-17 08:49:59.000000000 +0200
|
||||
+++ linux-2.6.21/3rdparty/viahss/viahss.c 2007-05-14 17:06:56.000000000 +0200
|
||||
@@ -12,7 +12,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
-#include <linux/config.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
@@ -1,7 +0,0 @@
|
||||
--- linux-2.6.25/3rdparty/viahss/viahss.c.orig 2008-06-28 22:50:05.000000000 +0300
|
||||
+++ linux-2.6.25/3rdparty/viahss/viahss.c 2008-06-29 14:26:55.000000000 +0300
|
||||
@@ -80,3 +80,4 @@ module_init(viahss_init);
|
||||
module_exit(viahss_exit);
|
||||
MODULE_DESCRIPTION("VIA VT82C686[AB] high speed serial port enabler");
|
||||
MODULE_AUTHOR("Juhani Rautiainen <jrauti@iki.fi>");
|
||||
+MODULE_LICENSE("GPL");
|
||||
@@ -1,3 +0,0 @@
|
||||
# Mageia SVN does not like binaries in /packages tree
|
||||
# it can still be used for out ov svn builds
|
||||
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
From 61f9738d65094a6b18d22c7beb6bb8c3dc0606b9 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Mon, 26 Oct 2015 15:20:46 +0100
|
||||
Subject: [PATCH] ACPI / video: Add a quirk to force acpi-video backlight on
|
||||
Dell XPS L421X
|
||||
|
||||
Just like the Dell XPS 15 (L521X) the Dell XPS 14 (L421X) needs to use
|
||||
the acpi-video backlight interface rather then the native one for backlight
|
||||
control to work, add a quirk for this.
|
||||
|
||||
Link: https://bugzilla.redhat.com/show_bug.cgi?id=1272633
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||
---
|
||||
drivers/acpi/video_detect.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
|
||||
index 0d3a384..daaf1c4 100644
|
||||
--- a/drivers/acpi/video_detect.c
|
||||
+++ b/drivers/acpi/video_detect.c
|
||||
@@ -233,6 +233,15 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
||||
},
|
||||
},
|
||||
{
|
||||
+ /* https://bugzilla.redhat.com/show_bug.cgi?id=1272633 */
|
||||
+ .callback = video_detect_force_video,
|
||||
+ .ident = "Dell XPS14 L421X",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
/* https://bugzilla.redhat.com/show_bug.cgi?id=1163574 */
|
||||
.callback = video_detect_force_video,
|
||||
.ident = "Dell XPS15 L521X",
|
||||
--
|
||||
2.3.10
|
||||
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Subject: [PATCH 2/2] PCI: Add function 1 DMA alias quirk for Highpoint RocketRAID 644L
|
||||
Date: Fri, 2 Mar 2018 11:36:33 +0100
|
||||
|
||||
The Highpoint RocketRAID 644L uses a Marvel 88SE9235 controller, as with
|
||||
other Marvel controllers this needs a function 1 DMA alias quirk.
|
||||
|
||||
Note the RocketRAID 642L uses the same Marvel 88SE9235 controller and
|
||||
already is listed with a function 1 DMA alias quirk.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1534106
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
drivers/pci/quirks.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
|
||||
index 8b14bd326d4a..46d47bd6ca1f 100644
|
||||
--- a/drivers/pci/quirks.c
|
||||
+++ b/drivers/pci/quirks.c
|
||||
@@ -3908,6 +3908,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9230,
|
||||
quirk_dma_func1_alias);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0642,
|
||||
quirk_dma_func1_alias);
|
||||
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0645,
|
||||
+ quirk_dma_func1_alias);
|
||||
/* https://bugs.gentoo.org/show_bug.cgi?id=497630 */
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_JMICRON,
|
||||
PCI_DEVICE_ID_JMICRON_JMB388_ESD,
|
||||
--
|
||||
2.14.3
|
||||
|
||||
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
From 88299efb05387c2c94120fdc9661aab2ec3a1ad8 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Backlund <tmb@mageia.org>
|
||||
Date: Fri, 3 Apr 2015 00:10:34 +0259
|
||||
Subject: [PATCH] Revert "cpufreq: pcc: Enable autoload of pcc-cpufreq for ACPI
|
||||
processors"
|
||||
|
||||
This reverts commit 7e7e8fe69820c6fa31395dbbd8e348e3c69cd2a9.
|
||||
---
|
||||
drivers/cpufreq/pcc-cpufreq.c | 7 -------
|
||||
1 file changed, 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c
|
||||
index 2a0d589..4d2c8e8 100644
|
||||
--- a/drivers/cpufreq/pcc-cpufreq.c
|
||||
+++ b/drivers/cpufreq/pcc-cpufreq.c
|
||||
@@ -603,13 +603,6 @@ static void __exit pcc_cpufreq_exit(void)
|
||||
free_percpu(pcc_cpu_info);
|
||||
}
|
||||
|
||||
-static const struct acpi_device_id processor_device_ids[] = {
|
||||
- {ACPI_PROCESSOR_OBJECT_HID, },
|
||||
- {ACPI_PROCESSOR_DEVICE_HID, },
|
||||
- {},
|
||||
-};
|
||||
-MODULE_DEVICE_TABLE(acpi, processor_device_ids);
|
||||
-
|
||||
MODULE_AUTHOR("Matthew Garrett, Naga Chumbalkar");
|
||||
MODULE_VERSION(PCC_VERSION);
|
||||
MODULE_DESCRIPTION("Processor Clocking Control interface driver");
|
||||
--
|
||||
2.3.1
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
Subject: CLEVO M360S acpi irq workaround
|
||||
|
||||
Some Hardware vendor use CLEVO M360S Laptop OEM.
|
||||
This acpi IRQ routing is not correct. we use normal IRQ routing for default.
|
||||
|
||||
Signed-off-by: Go Taniguchi <go@turbolinux.co.jp>
|
||||
|
||||
---
|
||||
arch/x86/kernel/acpi/boot.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
--- a/arch/x86/kernel/acpi/boot.c
|
||||
+++ b/arch/x86/kernel/acpi/boot.c
|
||||
@@ -1615,6 +1615,14 @@ static struct dmi_system_id __initdata a
|
||||
},
|
||||
},
|
||||
{
|
||||
+ .callback = disable_acpi_irq,
|
||||
+ .ident = "CLEVO M360S",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "M360S"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
/*
|
||||
* Latest BIOS for IBM 600E (1.16) has bad pcinum
|
||||
* for LPC bridge, which is needed for the PCI
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
From: "Rafael J. Wysocki" <rjw@rjwysocki.net>
|
||||
Subject: [PATCH] ACPI / EC: Restore polling during noirq suspend/resume phases
|
||||
Date: Fri, 09 Feb 2018 22:55:28 +0100
|
||||
|
||||
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||
|
||||
Commit 662591461c4b (ACPI / EC: Drop EC noirq hooks to fix a
|
||||
regression) modified the ACPI EC driver so that it doesn't switch
|
||||
over to busy polling mode during noirq stages of system suspend and
|
||||
resume in an attempt to fix an issue resulting from that behavior.
|
||||
|
||||
However, that modification introduced a system resume regression on
|
||||
Thinkpad X240, so make the EC driver switch over to the polling mode
|
||||
during noirq stages of system suspend and resume again, which
|
||||
effectively reverts the problematic commit.
|
||||
|
||||
Fixes: 662591461c4b (ACPI / EC: Drop EC noirq hooks to fix a regression)
|
||||
Link: https://bugzilla.kernel.org/show_bug.cgi?id=197863
|
||||
Reported-by: Markus Demleitner <m@tfiu.de>
|
||||
Tested-by: Markus Demleitner <m@tfiu.de>
|
||||
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||
---
|
||||
drivers/acpi/ec.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
Index: linux-pm/drivers/acpi/ec.c
|
||||
===================================================================
|
||||
--- linux-pm.orig/drivers/acpi/ec.c
|
||||
+++ linux-pm/drivers/acpi/ec.c
|
||||
@@ -1927,6 +1927,9 @@ static int acpi_ec_suspend_noirq(struct
|
||||
ec->reference_count >= 1)
|
||||
acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE);
|
||||
|
||||
+ if (acpi_sleep_no_ec_events())
|
||||
+ acpi_ec_enter_noirq(ec);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1934,6 +1937,9 @@ static int acpi_ec_resume_noirq(struct d
|
||||
{
|
||||
struct acpi_ec *ec = acpi_driver_data(to_acpi_device(dev));
|
||||
|
||||
+ if (acpi_sleep_no_ec_events())
|
||||
+ acpi_ec_leave_noirq(ec);
|
||||
+
|
||||
if (ec_no_wakeup && test_bit(EC_FLAGS_STARTED, &ec->flags) &&
|
||||
ec->reference_count >= 1)
|
||||
acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE);
|
||||
@@ -1,21 +0,0 @@
|
||||
Limit Clevo M720SR to C2, going to C3 makes the machine freeze. This
|
||||
needs more investigation, sis chipset/bios problem may be?
|
||||
|
||||
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
|
||||
|
||||
---
|
||||
drivers/acpi/processor_idle.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
--- linux-2.6.33-rc8-git4-t2/drivers/acpi/processor_idle.c.orig 2010-02-20 12:45:35.000000000 +0200
|
||||
+++ linux-2.6.33-rc8-git4-t2/drivers/acpi/processor_idle.c 2010-02-20 12:53:39.679099592 +0200
|
||||
@@ -110,6 +110,9 @@ static struct dmi_system_id __cpuinitdat
|
||||
DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
|
||||
DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")},
|
||||
(void *)2},
|
||||
+ { set_max_cstate, "Clevo M720SR", {
|
||||
+ DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME,"M720SR")}, (void *)2},
|
||||
{ set_max_cstate, "Pavilion zv5000", {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME,"Pavilion zv5000 (DS502A#ABA)")},
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
From 863204cfdae98626a92535ac928ad79f4d6b74ff Mon Sep 17 00:00:00 2001
|
||||
From: Arnd Bergmann <arnd@arndb.de>
|
||||
Date: Wed, 6 Dec 2017 14:17:17 +0100
|
||||
Subject: [PATCH] ARM: omap2: hide omap3_save_secure_ram on non-OMAP3 builds
|
||||
|
||||
In configurations without CONFIG_OMAP3 but with secure RAM support,
|
||||
we now run into a link failure:
|
||||
|
||||
arch/arm/mach-omap2/omap-secure.o: In function `omap3_save_secure_ram':
|
||||
omap-secure.c:(.text+0x130): undefined reference to `save_secure_ram_context'
|
||||
|
||||
The omap3_save_secure_ram() function is only called from the OMAP34xx
|
||||
power management code, so we can simply hide that function in the
|
||||
appropriate #ifdef.
|
||||
|
||||
Fixes: d09220a887f7 ("ARM: OMAP2+: Fix SRAM virt to phys translation for save_secure_ram_context")
|
||||
Acked-by: Tony Lindgren <tony@atomide.com>
|
||||
Tested-by: Dan Murphy <dmurphy@ti.com>
|
||||
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
|
||||
---
|
||||
arch/arm/mach-omap2/omap-secure.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap-secure.c b/arch/arm/mach-omap2/omap-secure.c
|
||||
index 9ff92050053c..fa7f308c9027 100644
|
||||
--- a/arch/arm/mach-omap2/omap-secure.c
|
||||
+++ b/arch/arm/mach-omap2/omap-secure.c
|
||||
@@ -73,6 +73,7 @@ phys_addr_t omap_secure_ram_mempool_base(void)
|
||||
return omap_secure_memblock_base;
|
||||
}
|
||||
|
||||
+#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
|
||||
u32 omap3_save_secure_ram(void __iomem *addr, int size)
|
||||
{
|
||||
u32 ret;
|
||||
@@ -91,6 +92,7 @@ u32 omap3_save_secure_ram(void __iomem *addr, int size)
|
||||
|
||||
return ret;
|
||||
}
|
||||
+#endif
|
||||
|
||||
/**
|
||||
* rx51_secure_dispatcher: Routine to dispatch secure PPA API calls
|
||||
--
|
||||
2.16.2
|
||||
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Subject: [PATCH 1/2] ahci: Add PCI-id for the Highpoint Rocketraid 644L card
|
||||
Date: Fri, 2 Mar 2018 11:36:32 +0100
|
||||
|
||||
Like the Highpoint Rocketraid 642L and cards using a Marvel 88SE9235
|
||||
controller in general, this RAID card also supports AHCI mode and short
|
||||
of a custom driver, this is the only way to make it work under Linux.
|
||||
|
||||
Note that even though the card is called to 644L, it has a product-id
|
||||
of 0x0645.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1534106
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
drivers/ata/ahci.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
|
||||
index 355a95a83a34..1ff17799769d 100644
|
||||
--- a/drivers/ata/ahci.c
|
||||
+++ b/drivers/ata/ahci.c
|
||||
@@ -550,7 +550,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
||||
.driver_data = board_ahci_yes_fbs },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
|
||||
.driver_data = board_ahci_yes_fbs },
|
||||
- { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642),
|
||||
+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), /* highpoint rocketraid 642L */
|
||||
+ .driver_data = board_ahci_yes_fbs },
|
||||
+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0645), /* highpoint rocketraid 644L */
|
||||
.driver_data = board_ahci_yes_fbs },
|
||||
|
||||
/* Promise */
|
||||
--
|
||||
2.14.3
|
||||
|
||||
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
>From 9f04e51293b130474504216a477bb2a73cbf59e1 Mon Sep 17 00:00:00 2001
|
||||
From: Anssi Hannula <anssi.hannula@iki.fi>
|
||||
Date: Thu, 22 Mar 2012 22:29:11 +0200
|
||||
Subject: [PATCH] ata: prefer ata drivers over ide drivers when both are built
|
||||
|
||||
Currently the old IDE drivers are preferred over ATA drivers when both
|
||||
are built, since ide/ is listed first in drivers/Makefile and therefore
|
||||
the IDE drivers end up before ATA drivers in modules.order which is used
|
||||
by depmod/modprobe for module ordering.
|
||||
|
||||
Change it so that ATA drivers are preferred over IDE driver by moving
|
||||
the ide/ entry under ata/ in drivers/Makefile.
|
||||
|
||||
Signed-off-by: Anssi Hannula <anssi.hannula@iki.fi>
|
||||
---
|
||||
drivers/Makefile | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/Makefile b/drivers/Makefile
|
||||
index 932e8bf..e8df3d0 100644
|
||||
--- a/drivers/Makefile
|
||||
+++ b/drivers/Makefile
|
||||
@@ -69,10 +69,10 @@ obj-$(CONFIG_LIBNVDIMM) += nvdimm/
|
||||
obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf/
|
||||
obj-$(CONFIG_NUBUS) += nubus/
|
||||
obj-y += macintosh/
|
||||
-obj-$(CONFIG_IDE) += ide/
|
||||
obj-$(CONFIG_SCSI) += scsi/
|
||||
obj-y += nvme/
|
||||
obj-$(CONFIG_ATA) += ata/
|
||||
+obj-$(CONFIG_IDE) += ide/
|
||||
obj-$(CONFIG_TARGET_CORE) += target/
|
||||
obj-$(CONFIG_MTD) += mtd/
|
||||
obj-$(CONFIG_SPI) += spi/
|
||||
-107
@@ -1,107 +0,0 @@
|
||||
From 614822f81f606e0064acdae11d9ec1efd3db4190 Mon Sep 17 00:00:00 2001
|
||||
From: Luca Miccio <lucmiccio@gmail.com>
|
||||
Date: Mon, 13 Nov 2017 07:34:08 +0100
|
||||
Subject: [PATCH] block, bfq: add missing invocations of
|
||||
bfqg_stats_update_io_add/remove
|
||||
|
||||
bfqg_stats_update_io_add and bfqg_stats_update_io_remove are to be
|
||||
invoked, respectively, when an I/O request enters and when an I/O
|
||||
request exits the scheduler. Unfortunately, bfq does not fully comply
|
||||
with this scheme, because it does not invoke these functions for
|
||||
requests that are inserted into or extracted from its priority
|
||||
dispatch list. This commit fixes this mistake.
|
||||
|
||||
Tested-by: Lee Tibbert <lee.tibbert@gmail.com>
|
||||
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Luca Miccio <lucmiccio@gmail.com>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 21 ++++++++++++++++++---
|
||||
1 file changed, 18 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index 889a8549d97f..91703eba63f0 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -1359,7 +1359,6 @@ static void bfq_bfqq_handle_idle_busy_switch(struct bfq_data *bfqd,
|
||||
bfqq->ttime.last_end_request +
|
||||
bfqd->bfq_slice_idle * 3;
|
||||
|
||||
- bfqg_stats_update_io_add(bfqq_group(RQ_BFQQ(rq)), bfqq, rq->cmd_flags);
|
||||
|
||||
/*
|
||||
* bfqq deserves to be weight-raised if:
|
||||
@@ -1633,7 +1632,6 @@ static void bfq_remove_request(struct request_queue *q,
|
||||
if (rq->cmd_flags & REQ_META)
|
||||
bfqq->meta_pending--;
|
||||
|
||||
- bfqg_stats_update_io_remove(bfqq_group(bfqq), rq->cmd_flags);
|
||||
}
|
||||
|
||||
static bool bfq_bio_merge(struct blk_mq_hw_ctx *hctx, struct bio *bio)
|
||||
@@ -1746,6 +1744,7 @@ static void bfq_requests_merged(struct request_queue *q, struct request *rq,
|
||||
bfqq->next_rq = rq;
|
||||
|
||||
bfq_remove_request(q, next);
|
||||
+ bfqg_stats_update_io_remove(bfqq_group(bfqq), next->cmd_flags);
|
||||
|
||||
spin_unlock_irq(&bfqq->bfqd->lock);
|
||||
end:
|
||||
@@ -3700,6 +3699,9 @@ static struct request *bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
|
||||
spin_lock_irq(&bfqd->lock);
|
||||
|
||||
rq = __bfq_dispatch_request(hctx);
|
||||
+ if (rq && RQ_BFQQ(rq))
|
||||
+ bfqg_stats_update_io_remove(bfqq_group(RQ_BFQQ(rq)),
|
||||
+ rq->cmd_flags);
|
||||
spin_unlock_irq(&bfqd->lock);
|
||||
|
||||
return rq;
|
||||
@@ -4224,6 +4226,7 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
{
|
||||
struct request_queue *q = hctx->queue;
|
||||
struct bfq_data *bfqd = q->elevator->elevator_data;
|
||||
+ struct bfq_queue *bfqq = RQ_BFQQ(rq);
|
||||
|
||||
spin_lock_irq(&bfqd->lock);
|
||||
if (blk_mq_sched_try_insert_merge(q, rq)) {
|
||||
@@ -4243,6 +4246,12 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
list_add_tail(&rq->queuelist, &bfqd->dispatch);
|
||||
} else {
|
||||
__bfq_insert_request(bfqd, rq);
|
||||
+ /*
|
||||
+ * Update bfqq, because, if a queue merge has occurred
|
||||
+ * in __bfq_insert_request, then rq has been
|
||||
+ * redirected into a new queue.
|
||||
+ */
|
||||
+ bfqq = RQ_BFQQ(rq);
|
||||
|
||||
if (rq_mergeable(rq)) {
|
||||
elv_rqhash_add(q, rq);
|
||||
@@ -4251,6 +4260,9 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
}
|
||||
}
|
||||
|
||||
+ if (bfqq)
|
||||
+ bfqg_stats_update_io_add(bfqq_group(bfqq), bfqq, rq->cmd_flags);
|
||||
+
|
||||
spin_unlock_irq(&bfqd->lock);
|
||||
}
|
||||
|
||||
@@ -4428,8 +4440,11 @@ static void bfq_finish_request(struct request *rq)
|
||||
* lock is held.
|
||||
*/
|
||||
|
||||
- if (!RB_EMPTY_NODE(&rq->rb_node))
|
||||
+ if (!RB_EMPTY_NODE(&rq->rb_node)) {
|
||||
bfq_remove_request(rq->q, rq);
|
||||
+ bfqg_stats_update_io_remove(bfqq_group(bfqq),
|
||||
+ rq->cmd_flags);
|
||||
+ }
|
||||
bfq_put_rq_priv_body(bfqq);
|
||||
}
|
||||
|
||||
--
|
||||
2.15.1
|
||||
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
From 05e90283561648301e30232fe0c91bd345ceba03 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@linaro.org>
|
||||
Date: Wed, 20 Dec 2017 12:38:31 +0100
|
||||
Subject: [PATCH] block, bfq: add missing rq_pos_tree update on rq removal
|
||||
|
||||
If two processes do I/O close to each other, then BFQ merges the
|
||||
bfq_queues associated with these processes, to get a more sequential
|
||||
I/O, and thus a higher throughput. In this respect, to detect whether
|
||||
two processes are doing I/O close to each other, BFQ keeps a list of
|
||||
the head-of-line I/O requests of all active bfq_queues. The list is
|
||||
ordered by initial sectors, and implemented through a red-black tree
|
||||
(rq_pos_tree).
|
||||
|
||||
Unfortunately, the update of the rq_pos_tree was incomplete, because
|
||||
the tree was not updated on the removal of the head-of-line I/O
|
||||
request of a bfq_queue, in case the queue did not remain empty. This
|
||||
commit adds the missing update.
|
||||
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Angelo Ruocco <angeloruocco90@gmail.com>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index 0f48583b9380..fa395a260a23 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -1627,6 +1627,8 @@ static void bfq_remove_request(struct request_queue *q,
|
||||
rb_erase(&bfqq->pos_node, bfqq->pos_root);
|
||||
bfqq->pos_root = NULL;
|
||||
}
|
||||
+ } else {
|
||||
+ bfq_pos_tree_add_move(bfqd, bfqq);
|
||||
}
|
||||
|
||||
if (rq->cmd_flags & REQ_META)
|
||||
--
|
||||
2.15.1
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
From a7877390614770965a6925dfed79cbd3eeeb61e0 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@linaro.org>
|
||||
Date: Wed, 7 Feb 2018 22:19:20 +0100
|
||||
Subject: [PATCH] block, bfq: add requeue-request hook
|
||||
|
||||
Commit 'a6a252e64914 ("blk-mq-sched: decide how to handle flush rq via
|
||||
RQF_FLUSH_SEQ")' makes all non-flush re-prepared requests for a device
|
||||
be re-inserted into the active I/O scheduler for that device. As a
|
||||
consequence, I/O schedulers may get the same request inserted again,
|
||||
even several times, without a finish_request invoked on that request
|
||||
before each re-insertion.
|
||||
|
||||
This fact is the cause of the failure reported in [1]. For an I/O
|
||||
scheduler, every re-insertion of the same re-prepared request is
|
||||
equivalent to the insertion of a new request. For schedulers like
|
||||
mq-deadline or kyber, this fact causes no harm. In contrast, it
|
||||
confuses a stateful scheduler like BFQ, which keeps state for an I/O
|
||||
request, until the finish_request hook is invoked on the request. In
|
||||
particular, BFQ may get stuck, waiting forever for the number of
|
||||
request dispatches, of the same request, to be balanced by an equal
|
||||
number of request completions (while there will be one completion for
|
||||
that request). In this state, BFQ may refuse to serve I/O requests
|
||||
from other bfq_queues. The hang reported in [1] then follows.
|
||||
|
||||
However, the above re-prepared requests undergo a requeue, thus the
|
||||
requeue_request hook of the active elevator is invoked for these
|
||||
requests, if set. This commit then addresses the above issue by
|
||||
properly implementing the hook requeue_request in BFQ.
|
||||
|
||||
[1] https://marc.info/?l=linux-block&m=151211117608676
|
||||
|
||||
Reported-by: Ivan Kozik <ivan@ludios.org>
|
||||
Reported-by: Alban Browaeys <alban.browaeys@gmail.com>
|
||||
Tested-by: Mike Galbraith <efault@gmx.de>
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Serena Ziviani <ziviani.serena@gmail.com>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 107 ++++++++++++++++++++++++++++++++++++++++------------
|
||||
1 file changed, 82 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index 47e6ec7427c4..aeca22d91101 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -3823,24 +3823,26 @@ static struct request *__bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
|
||||
}
|
||||
|
||||
/*
|
||||
- * We exploit the bfq_finish_request hook to decrement
|
||||
- * rq_in_driver, but bfq_finish_request will not be
|
||||
- * invoked on this request. So, to avoid unbalance,
|
||||
- * just start this request, without incrementing
|
||||
- * rq_in_driver. As a negative consequence,
|
||||
- * rq_in_driver is deceptively lower than it should be
|
||||
- * while this request is in service. This may cause
|
||||
- * bfq_schedule_dispatch to be invoked uselessly.
|
||||
+ * We exploit the bfq_finish_requeue_request hook to
|
||||
+ * decrement rq_in_driver, but
|
||||
+ * bfq_finish_requeue_request will not be invoked on
|
||||
+ * this request. So, to avoid unbalance, just start
|
||||
+ * this request, without incrementing rq_in_driver. As
|
||||
+ * a negative consequence, rq_in_driver is deceptively
|
||||
+ * lower than it should be while this request is in
|
||||
+ * service. This may cause bfq_schedule_dispatch to be
|
||||
+ * invoked uselessly.
|
||||
*
|
||||
* As for implementing an exact solution, the
|
||||
- * bfq_finish_request hook, if defined, is probably
|
||||
- * invoked also on this request. So, by exploiting
|
||||
- * this hook, we could 1) increment rq_in_driver here,
|
||||
- * and 2) decrement it in bfq_finish_request. Such a
|
||||
- * solution would let the value of the counter be
|
||||
- * always accurate, but it would entail using an extra
|
||||
- * interface function. This cost seems higher than the
|
||||
- * benefit, being the frequency of non-elevator-private
|
||||
+ * bfq_finish_requeue_request hook, if defined, is
|
||||
+ * probably invoked also on this request. So, by
|
||||
+ * exploiting this hook, we could 1) increment
|
||||
+ * rq_in_driver here, and 2) decrement it in
|
||||
+ * bfq_finish_requeue_request. Such a solution would
|
||||
+ * let the value of the counter be always accurate,
|
||||
+ * but it would entail using an extra interface
|
||||
+ * function. This cost seems higher than the benefit,
|
||||
+ * being the frequency of non-elevator-private
|
||||
* requests very low.
|
||||
*/
|
||||
goto start_rq;
|
||||
@@ -4515,6 +4517,8 @@ static inline void bfq_update_insert_stats(struct request_queue *q,
|
||||
unsigned int cmd_flags) {}
|
||||
#endif
|
||||
|
||||
+static void bfq_prepare_request(struct request *rq, struct bio *bio);
|
||||
+
|
||||
static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
bool at_head)
|
||||
{
|
||||
@@ -4541,6 +4545,18 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
else
|
||||
list_add_tail(&rq->queuelist, &bfqd->dispatch);
|
||||
} else {
|
||||
+ if (WARN_ON_ONCE(!bfqq)) {
|
||||
+ /*
|
||||
+ * This should never happen. Most likely rq is
|
||||
+ * a requeued regular request, being
|
||||
+ * re-inserted without being first
|
||||
+ * re-prepared. Do a prepare, to avoid
|
||||
+ * failure.
|
||||
+ */
|
||||
+ bfq_prepare_request(rq, rq->bio);
|
||||
+ bfqq = RQ_BFQQ(rq);
|
||||
+ }
|
||||
+
|
||||
idle_timer_disabled = __bfq_insert_request(bfqd, rq);
|
||||
/*
|
||||
* Update bfqq, because, if a queue merge has occurred
|
||||
@@ -4697,22 +4713,44 @@ static void bfq_completed_request(struct bfq_queue *bfqq, struct bfq_data *bfqd)
|
||||
bfq_schedule_dispatch(bfqd);
|
||||
}
|
||||
|
||||
-static void bfq_finish_request_body(struct bfq_queue *bfqq)
|
||||
+static void bfq_finish_requeue_request_body(struct bfq_queue *bfqq)
|
||||
{
|
||||
bfqq->allocated--;
|
||||
|
||||
bfq_put_queue(bfqq);
|
||||
}
|
||||
|
||||
-static void bfq_finish_request(struct request *rq)
|
||||
+/*
|
||||
+ * Handle either a requeue or a finish for rq. The things to do are
|
||||
+ * the same in both cases: all references to rq are to be dropped. In
|
||||
+ * particular, rq is considered completed from the point of view of
|
||||
+ * the scheduler.
|
||||
+ */
|
||||
+static void bfq_finish_requeue_request(struct request *rq)
|
||||
{
|
||||
- struct bfq_queue *bfqq;
|
||||
+ struct bfq_queue *bfqq = RQ_BFQQ(rq);
|
||||
struct bfq_data *bfqd;
|
||||
|
||||
- if (!rq->elv.icq)
|
||||
+ /*
|
||||
+ * Requeue and finish hooks are invoked in blk-mq without
|
||||
+ * checking whether the involved request is actually still
|
||||
+ * referenced in the scheduler. To handle this fact, the
|
||||
+ * following two checks make this function exit in case of
|
||||
+ * spurious invocations, for which there is nothing to do.
|
||||
+ *
|
||||
+ * First, check whether rq has nothing to do with an elevator.
|
||||
+ */
|
||||
+ if (unlikely(!(rq->rq_flags & RQF_ELVPRIV)))
|
||||
+ return;
|
||||
+
|
||||
+ /*
|
||||
+ * rq either is not associated with any icq, or is an already
|
||||
+ * requeued request that has not (yet) been re-inserted into
|
||||
+ * a bfq_queue.
|
||||
+ */
|
||||
+ if (!rq->elv.icq || !bfqq)
|
||||
return;
|
||||
|
||||
- bfqq = RQ_BFQQ(rq);
|
||||
bfqd = bfqq->bfqd;
|
||||
|
||||
if (rq->rq_flags & RQF_STARTED)
|
||||
@@ -4727,13 +4765,14 @@ static void bfq_finish_request(struct request *rq)
|
||||
spin_lock_irqsave(&bfqd->lock, flags);
|
||||
|
||||
bfq_completed_request(bfqq, bfqd);
|
||||
- bfq_finish_request_body(bfqq);
|
||||
+ bfq_finish_requeue_request_body(bfqq);
|
||||
|
||||
spin_unlock_irqrestore(&bfqd->lock, flags);
|
||||
} else {
|
||||
/*
|
||||
* Request rq may be still/already in the scheduler,
|
||||
- * in which case we need to remove it. And we cannot
|
||||
+ * in which case we need to remove it (this should
|
||||
+ * never happen in case of requeue). And we cannot
|
||||
* defer such a check and removal, to avoid
|
||||
* inconsistencies in the time interval from the end
|
||||
* of this function to the start of the deferred work.
|
||||
@@ -4748,9 +4787,26 @@ static void bfq_finish_request(struct request *rq)
|
||||
bfqg_stats_update_io_remove(bfqq_group(bfqq),
|
||||
rq->cmd_flags);
|
||||
}
|
||||
- bfq_finish_request_body(bfqq);
|
||||
+ bfq_finish_requeue_request_body(bfqq);
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * Reset private fields. In case of a requeue, this allows
|
||||
+ * this function to correctly do nothing if it is spuriously
|
||||
+ * invoked again on this same request (see the check at the
|
||||
+ * beginning of the function). Probably, a better general
|
||||
+ * design would be to prevent blk-mq from invoking the requeue
|
||||
+ * or finish hooks of an elevator, for a request that is not
|
||||
+ * referred by that elevator.
|
||||
+ *
|
||||
+ * Resetting the following fields would break the
|
||||
+ * request-insertion logic if rq is re-inserted into a bfq
|
||||
+ * internal queue, without a re-preparation. Here we assume
|
||||
+ * that re-insertions of requeued requests, without
|
||||
+ * re-preparation, can happen only for pass_through or at_head
|
||||
+ * requests (which are not re-inserted into bfq internal
|
||||
+ * queues).
|
||||
+ */
|
||||
rq->elv.priv[0] = NULL;
|
||||
rq->elv.priv[1] = NULL;
|
||||
}
|
||||
@@ -5426,7 +5482,8 @@ static struct elevator_type iosched_bfq_mq = {
|
||||
.ops.mq = {
|
||||
.limit_depth = bfq_limit_depth,
|
||||
.prepare_request = bfq_prepare_request,
|
||||
- .finish_request = bfq_finish_request,
|
||||
+ .requeue_request = bfq_finish_requeue_request,
|
||||
+ .finish_request = bfq_finish_requeue_request,
|
||||
.exit_icq = bfq_exit_icq,
|
||||
.insert_requests = bfq_insert_requests,
|
||||
.dispatch_request = bfq_dispatch_request,
|
||||
--
|
||||
2.16.1
|
||||
|
||||
-163
@@ -1,163 +0,0 @@
|
||||
From 3e2bdd6dff239afd8386e8758eee69ad61e5a3d6 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@linaro.org>
|
||||
Date: Thu, 21 Sep 2017 11:04:01 +0200
|
||||
Subject: [PATCH] block, bfq: check and switch back to interactive wr also on
|
||||
queue split
|
||||
|
||||
As already explained in the message of commit "block, bfq: fix
|
||||
wrong init of saved start time for weight raising", if a soft
|
||||
real-time weight-raising period happens to be nested in a larger
|
||||
interactive weight-raising period, then BFQ restores the interactive
|
||||
weight raising at the end of the soft real-time weight raising. In
|
||||
particular, BFQ checks whether the latter has ended only on request
|
||||
dispatches.
|
||||
|
||||
Unfortunately, the above scheme fails to restore interactive weight
|
||||
raising in the following corner case: if a bfq_queue, say Q,
|
||||
1) Is merged with another bfq_queue while it is in a nested soft
|
||||
real-time weight-raising period. The weight-raising state of Q is
|
||||
then saved, and not considered any longer until a split occurs.
|
||||
2) Is split from the other bfq_queue(s) at a time instant when its
|
||||
soft real-time weight raising is already finished.
|
||||
On the split, while resuming the previous, soft real-time
|
||||
weight-raised state of the bfq_queue Q, BFQ checks whether the
|
||||
current soft real-time weight-raising period is actually over. If so,
|
||||
BFQ switches weight raising off for Q, *without* checking whether the
|
||||
soft real-time period was actually nested in a non-yet-finished
|
||||
interactive weight-raising period.
|
||||
|
||||
This commit addresses this issue by adding the above missing check in
|
||||
bfq_queue splits, and restoring interactive weight raising if needed.
|
||||
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Tested-by: Angelo Ruocco <angeloruocco90@gmail.com>
|
||||
Tested-by: Mirko Montanari <mirkomontanari91@gmail.com>
|
||||
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
|
||||
Tested-by: Lee Tibbert <lee.tibbert@gmail.com>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 87 ++++++++++++++++++++++++++++++-----------------------
|
||||
1 file changed, 49 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index c25955c25e03..33b63bc4a64b 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -724,6 +724,44 @@ static void bfq_updated_next_req(struct bfq_data *bfqd,
|
||||
}
|
||||
}
|
||||
|
||||
+static unsigned int bfq_wr_duration(struct bfq_data *bfqd)
|
||||
+{
|
||||
+ u64 dur;
|
||||
+
|
||||
+ if (bfqd->bfq_wr_max_time > 0)
|
||||
+ return bfqd->bfq_wr_max_time;
|
||||
+
|
||||
+ dur = bfqd->RT_prod;
|
||||
+ do_div(dur, bfqd->peak_rate);
|
||||
+
|
||||
+ /*
|
||||
+ * Limit duration between 3 and 13 seconds. Tests show that
|
||||
+ * higher values than 13 seconds often yield the opposite of
|
||||
+ * the desired result, i.e., worsen responsiveness by letting
|
||||
+ * non-interactive and non-soft-real-time applications
|
||||
+ * preserve weight raising for a too long time interval.
|
||||
+ *
|
||||
+ * On the other end, lower values than 3 seconds make it
|
||||
+ * difficult for most interactive tasks to complete their jobs
|
||||
+ * before weight-raising finishes.
|
||||
+ */
|
||||
+ if (dur > msecs_to_jiffies(13000))
|
||||
+ dur = msecs_to_jiffies(13000);
|
||||
+ else if (dur < msecs_to_jiffies(3000))
|
||||
+ dur = msecs_to_jiffies(3000);
|
||||
+
|
||||
+ return dur;
|
||||
+}
|
||||
+
|
||||
+/* switch back from soft real-time to interactive weight raising */
|
||||
+static void switch_back_to_interactive_wr(struct bfq_queue *bfqq,
|
||||
+ struct bfq_data *bfqd)
|
||||
+{
|
||||
+ bfqq->wr_coeff = bfqd->bfq_wr_coeff;
|
||||
+ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd);
|
||||
+ bfqq->last_wr_start_finish = bfqq->wr_start_at_switch_to_srt;
|
||||
+}
|
||||
+
|
||||
static void
|
||||
bfq_bfqq_resume_state(struct bfq_queue *bfqq, struct bfq_data *bfqd,
|
||||
struct bfq_io_cq *bic, bool bfq_already_existing)
|
||||
@@ -750,10 +788,16 @@ bfq_bfqq_resume_state(struct bfq_queue *bfqq, struct bfq_data *bfqd,
|
||||
if (bfqq->wr_coeff > 1 && (bfq_bfqq_in_large_burst(bfqq) ||
|
||||
time_is_before_jiffies(bfqq->last_wr_start_finish +
|
||||
bfqq->wr_cur_max_time))) {
|
||||
- bfq_log_bfqq(bfqq->bfqd, bfqq,
|
||||
- "resume state: switching off wr");
|
||||
-
|
||||
- bfqq->wr_coeff = 1;
|
||||
+ if (bfqq->wr_cur_max_time == bfqd->bfq_wr_rt_max_time &&
|
||||
+ !bfq_bfqq_in_large_burst(bfqq) &&
|
||||
+ time_is_after_eq_jiffies(bfqq->wr_start_at_switch_to_srt +
|
||||
+ bfq_wr_duration(bfqd))) {
|
||||
+ switch_back_to_interactive_wr(bfqq, bfqd);
|
||||
+ } else {
|
||||
+ bfqq->wr_coeff = 1;
|
||||
+ bfq_log_bfqq(bfqq->bfqd, bfqq,
|
||||
+ "resume state: switching off wr");
|
||||
+ }
|
||||
}
|
||||
|
||||
/* make sure weight will be updated, however we got here */
|
||||
@@ -1173,35 +1217,6 @@ static bool bfq_bfqq_update_budg_for_activation(struct bfq_data *bfqd,
|
||||
return wr_or_deserves_wr;
|
||||
}
|
||||
|
||||
-static unsigned int bfq_wr_duration(struct bfq_data *bfqd)
|
||||
-{
|
||||
- u64 dur;
|
||||
-
|
||||
- if (bfqd->bfq_wr_max_time > 0)
|
||||
- return bfqd->bfq_wr_max_time;
|
||||
-
|
||||
- dur = bfqd->RT_prod;
|
||||
- do_div(dur, bfqd->peak_rate);
|
||||
-
|
||||
- /*
|
||||
- * Limit duration between 3 and 13 seconds. Tests show that
|
||||
- * higher values than 13 seconds often yield the opposite of
|
||||
- * the desired result, i.e., worsen responsiveness by letting
|
||||
- * non-interactive and non-soft-real-time applications
|
||||
- * preserve weight raising for a too long time interval.
|
||||
- *
|
||||
- * On the other end, lower values than 3 seconds make it
|
||||
- * difficult for most interactive tasks to complete their jobs
|
||||
- * before weight-raising finishes.
|
||||
- */
|
||||
- if (dur > msecs_to_jiffies(13000))
|
||||
- dur = msecs_to_jiffies(13000);
|
||||
- else if (dur < msecs_to_jiffies(3000))
|
||||
- dur = msecs_to_jiffies(3000);
|
||||
-
|
||||
- return dur;
|
||||
-}
|
||||
-
|
||||
/*
|
||||
* Return the farthest future time instant according to jiffies
|
||||
* macros.
|
||||
@@ -3501,11 +3516,7 @@ static void bfq_update_wr_data(struct bfq_data *bfqd, struct bfq_queue *bfqq)
|
||||
bfq_wr_duration(bfqd)))
|
||||
bfq_bfqq_end_wr(bfqq);
|
||||
else {
|
||||
- /* switch back to interactive wr */
|
||||
- bfqq->wr_coeff = bfqd->bfq_wr_coeff;
|
||||
- bfqq->wr_cur_max_time = bfq_wr_duration(bfqd);
|
||||
- bfqq->last_wr_start_finish =
|
||||
- bfqq->wr_start_at_switch_to_srt;
|
||||
+ switch_back_to_interactive_wr(bfqq, bfqd);
|
||||
bfqq->entity.prio_changed = 1;
|
||||
}
|
||||
}
|
||||
--
|
||||
2.15.1
|
||||
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
From 1be6e8a964ee9aa8d4daac523ce29e5f486dd756 Mon Sep 17 00:00:00 2001
|
||||
From: Angelo Ruocco <angeloruocco90@gmail.com>
|
||||
Date: Wed, 20 Dec 2017 12:38:32 +0100
|
||||
Subject: [PATCH] block, bfq: check low_latency flag in bfq_bfqq_save_state()
|
||||
|
||||
A just-created bfq_queue will certainly be deemed as interactive on
|
||||
the arrival of its first I/O request, if the low_latency flag is
|
||||
set. Yet, if the queue is merged with another queue on the arrival of
|
||||
its first I/O request, it will not have the chance to be flagged as
|
||||
interactive. Nevertheless, if the queue is then split soon enough, it
|
||||
has to be flagged as interactive after the split.
|
||||
|
||||
To handle this early-merge scenario correctly, BFQ saves the state of
|
||||
the queue, on the merge, as if the latter had already been deemed
|
||||
interactive. So, if the queue is split soon, it will get
|
||||
weight-raised, because the previous state of the queue is resumed on
|
||||
the split.
|
||||
|
||||
Unfortunately, in the act of saving the state of the newly-created
|
||||
queue, BFQ doesn't check whether the low_latency flag is set, and this
|
||||
causes early-merged queues to be then weight-raised, on queue splits,
|
||||
even if low_latency is off. This commit addresses this problem by
|
||||
adding the missing check.
|
||||
|
||||
Signed-off-by: Angelo Ruocco <angeloruocco90@gmail.com>
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index fa395a260a23..2cf395daee80 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -2064,7 +2064,8 @@ static void bfq_bfqq_save_state(struct bfq_queue *bfqq)
|
||||
bic->saved_in_large_burst = bfq_bfqq_in_large_burst(bfqq);
|
||||
bic->was_in_burst_list = !hlist_unhashed(&bfqq->burst_list_node);
|
||||
if (unlikely(bfq_bfqq_just_created(bfqq) &&
|
||||
- !bfq_bfqq_in_large_burst(bfqq))) {
|
||||
+ !bfq_bfqq_in_large_burst(bfqq) &&
|
||||
+ bfqq->bfqd->low_latency)) {
|
||||
/*
|
||||
* bfqq being merged right after being created: bfqq
|
||||
* would have deserved interactive weight raising, but
|
||||
--
|
||||
2.15.1
|
||||
|
||||
-206
@@ -1,206 +0,0 @@
|
||||
From a34b024448eb71b0e51ad011fa1862236e366034 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@linaro.org>
|
||||
Date: Fri, 15 Dec 2017 07:23:12 +0100
|
||||
Subject: [PATCH] block, bfq: consider also past I/O in soft real-time
|
||||
detection
|
||||
|
||||
BFQ privileges the I/O of soft real-time applications, such as video
|
||||
players, to guarantee to these application a high bandwidth and a low
|
||||
latency. In this respect, it is not easy to correctly detect when an
|
||||
application is soft real-time. A particularly nasty false positive is
|
||||
that of an I/O-bound application that occasionally happens to meet all
|
||||
requirements to be deemed as soft real-time. After being detected as
|
||||
soft real-time, such an application monopolizes the device. Fortunately,
|
||||
BFQ will realize soon that the application is actually not soft
|
||||
real-time and suspend every privilege. Yet, the application may happen
|
||||
again to be wrongly detected as soft real-time, and so on.
|
||||
|
||||
As highlighted by our tests, this problem causes BFQ to occasionally
|
||||
fail to guarantee a high responsiveness, in the presence of heavy
|
||||
background I/O workloads. The reason is that the background workload
|
||||
happens to be detected as soft real-time, more or less frequently,
|
||||
during the execution of the interactive task under test. To give an
|
||||
idea, because of this problem, Libreoffice Writer occasionally takes 8
|
||||
seconds, instead of 3, to start up, if there are sequential reads and
|
||||
writes in the background, on a Kingston SSDNow V300.
|
||||
|
||||
This commit addresses this issue by leveraging the following facts.
|
||||
|
||||
The reason why some applications are detected as soft real-time despite
|
||||
all BFQ checks to avoid false positives, is simply that, during high
|
||||
CPU or storage-device load, I/O-bound applications may happen to do
|
||||
I/O slowly enough to meet all soft real-time requirements, and pass
|
||||
all BFQ extra checks. Yet, this happens only for limited time periods:
|
||||
slow-speed time intervals are usually interspersed between other time
|
||||
intervals during which these applications do I/O at a very high speed.
|
||||
To exploit these facts, this commit introduces a little change, in the
|
||||
detection of soft real-time behavior, to systematically consider also
|
||||
the recent past: the higher the speed was in the recent past, the
|
||||
later next I/O should arrive for the application to be considered as
|
||||
soft real-time. At the beginning of a slow-speed interval, the minimum
|
||||
arrival time allowed for the next I/O usually happens to still be so
|
||||
high, to fall *after* the end of the slow-speed period itself. As a
|
||||
consequence, the application does not risk to be deemed as soft
|
||||
real-time during the slow-speed interval. Then, during the next
|
||||
high-speed interval, the application cannot, evidently, be deemed as
|
||||
soft real-time (exactly because of its speed), and so on.
|
||||
|
||||
This extra filtering proved to be rather effective: in the above test,
|
||||
the frequency of false positives became so low that the start-up time
|
||||
was 3 seconds in all iterations (apart from occasional outliers,
|
||||
caused by page-cache-management issues, which are out of the scope of
|
||||
this commit, and cannot be solved by an I/O scheduler).
|
||||
|
||||
Tested-by: Lee Tibbert <lee.tibbert@gmail.com>
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Angelo Ruocco <angeloruocco90@gmail.com>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 115 ++++++++++++++++++++++++++++++++++++----------------
|
||||
1 file changed, 81 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index 9625550b2f85..e33c5c4c9856 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -2940,45 +2940,87 @@ static bool bfq_bfqq_is_slow(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
* whereas soft_rt_next_start is set to infinity for applications that do
|
||||
* not.
|
||||
*
|
||||
- * Unfortunately, even a greedy application may happen to behave in an
|
||||
- * isochronous way if the CPU load is high. In fact, the application may
|
||||
- * stop issuing requests while the CPUs are busy serving other processes,
|
||||
- * then restart, then stop again for a while, and so on. In addition, if
|
||||
- * the disk achieves a low enough throughput with the request pattern
|
||||
- * issued by the application (e.g., because the request pattern is random
|
||||
- * and/or the device is slow), then the application may meet the above
|
||||
- * bandwidth requirement too. To prevent such a greedy application to be
|
||||
- * deemed as soft real-time, a further rule is used in the computation of
|
||||
- * soft_rt_next_start: soft_rt_next_start must be higher than the current
|
||||
- * time plus the maximum time for which the arrival of a request is waited
|
||||
- * for when a sync queue becomes idle, namely bfqd->bfq_slice_idle.
|
||||
- * This filters out greedy applications, as the latter issue instead their
|
||||
- * next request as soon as possible after the last one has been completed
|
||||
- * (in contrast, when a batch of requests is completed, a soft real-time
|
||||
- * application spends some time processing data).
|
||||
+ * Unfortunately, even a greedy (i.e., I/O-bound) application may
|
||||
+ * happen to meet, occasionally or systematically, both the above
|
||||
+ * bandwidth and isochrony requirements. This may happen at least in
|
||||
+ * the following circumstances. First, if the CPU load is high. The
|
||||
+ * application may stop issuing requests while the CPUs are busy
|
||||
+ * serving other processes, then restart, then stop again for a while,
|
||||
+ * and so on. The other circumstances are related to the storage
|
||||
+ * device: the storage device is highly loaded or reaches a low-enough
|
||||
+ * throughput with the I/O of the application (e.g., because the I/O
|
||||
+ * is random and/or the device is slow). In all these cases, the
|
||||
+ * I/O of the application may be simply slowed down enough to meet
|
||||
+ * the bandwidth and isochrony requirements. To reduce the probability
|
||||
+ * that greedy applications are deemed as soft real-time in these
|
||||
+ * corner cases, a further rule is used in the computation of
|
||||
+ * soft_rt_next_start: the return value of this function is forced to
|
||||
+ * be higher than the maximum between the following two quantities.
|
||||
*
|
||||
- * Unfortunately, the last filter may easily generate false positives if
|
||||
- * only bfqd->bfq_slice_idle is used as a reference time interval and one
|
||||
- * or both the following cases occur:
|
||||
- * 1) HZ is so low that the duration of a jiffy is comparable to or higher
|
||||
- * than bfqd->bfq_slice_idle. This happens, e.g., on slow devices with
|
||||
- * HZ=100.
|
||||
+ * (a) Current time plus: (1) the maximum time for which the arrival
|
||||
+ * of a request is waited for when a sync queue becomes idle,
|
||||
+ * namely bfqd->bfq_slice_idle, and (2) a few extra jiffies. We
|
||||
+ * postpone for a moment the reason for adding a few extra
|
||||
+ * jiffies; we get back to it after next item (b). Lower-bounding
|
||||
+ * the return value of this function with the current time plus
|
||||
+ * bfqd->bfq_slice_idle tends to filter out greedy applications,
|
||||
+ * because the latter issue their next request as soon as possible
|
||||
+ * after the last one has been completed. In contrast, a soft
|
||||
+ * real-time application spends some time processing data, after a
|
||||
+ * batch of its requests has been completed.
|
||||
+ *
|
||||
+ * (b) Current value of bfqq->soft_rt_next_start. As pointed out
|
||||
+ * above, greedy applications may happen to meet both the
|
||||
+ * bandwidth and isochrony requirements under heavy CPU or
|
||||
+ * storage-device load. In more detail, in these scenarios, these
|
||||
+ * applications happen, only for limited time periods, to do I/O
|
||||
+ * slowly enough to meet all the requirements described so far,
|
||||
+ * including the filtering in above item (a). These slow-speed
|
||||
+ * time intervals are usually interspersed between other time
|
||||
+ * intervals during which these applications do I/O at a very high
|
||||
+ * speed. Fortunately, exactly because of the high speed of the
|
||||
+ * I/O in the high-speed intervals, the values returned by this
|
||||
+ * function happen to be so high, near the end of any such
|
||||
+ * high-speed interval, to be likely to fall *after* the end of
|
||||
+ * the low-speed time interval that follows. These high values are
|
||||
+ * stored in bfqq->soft_rt_next_start after each invocation of
|
||||
+ * this function. As a consequence, if the last value of
|
||||
+ * bfqq->soft_rt_next_start is constantly used to lower-bound the
|
||||
+ * next value that this function may return, then, from the very
|
||||
+ * beginning of a low-speed interval, bfqq->soft_rt_next_start is
|
||||
+ * likely to be constantly kept so high that any I/O request
|
||||
+ * issued during the low-speed interval is considered as arriving
|
||||
+ * to soon for the application to be deemed as soft
|
||||
+ * real-time. Then, in the high-speed interval that follows, the
|
||||
+ * application will not be deemed as soft real-time, just because
|
||||
+ * it will do I/O at a high speed. And so on.
|
||||
+ *
|
||||
+ * Getting back to the filtering in item (a), in the following two
|
||||
+ * cases this filtering might be easily passed by a greedy
|
||||
+ * application, if the reference quantity was just
|
||||
+ * bfqd->bfq_slice_idle:
|
||||
+ * 1) HZ is so low that the duration of a jiffy is comparable to or
|
||||
+ * higher than bfqd->bfq_slice_idle. This happens, e.g., on slow
|
||||
+ * devices with HZ=100. The time granularity may be so coarse
|
||||
+ * that the approximation, in jiffies, of bfqd->bfq_slice_idle
|
||||
+ * is rather lower than the exact value.
|
||||
* 2) jiffies, instead of increasing at a constant rate, may stop increasing
|
||||
* for a while, then suddenly 'jump' by several units to recover the lost
|
||||
* increments. This seems to happen, e.g., inside virtual machines.
|
||||
- * To address this issue, we do not use as a reference time interval just
|
||||
- * bfqd->bfq_slice_idle, but bfqd->bfq_slice_idle plus a few jiffies. In
|
||||
- * particular we add the minimum number of jiffies for which the filter
|
||||
- * seems to be quite precise also in embedded systems and KVM/QEMU virtual
|
||||
- * machines.
|
||||
+ * To address this issue, in the filtering in (a) we do not use as a
|
||||
+ * reference time interval just bfqd->bfq_slice_idle, but
|
||||
+ * bfqd->bfq_slice_idle plus a few jiffies. In particular, we add the
|
||||
+ * minimum number of jiffies for which the filter seems to be quite
|
||||
+ * precise also in embedded systems and KVM/QEMU virtual machines.
|
||||
*/
|
||||
static unsigned long bfq_bfqq_softrt_next_start(struct bfq_data *bfqd,
|
||||
struct bfq_queue *bfqq)
|
||||
{
|
||||
- return max(bfqq->last_idle_bklogged +
|
||||
- HZ * bfqq->service_from_backlogged /
|
||||
- bfqd->bfq_wr_max_softrt_rate,
|
||||
- jiffies + nsecs_to_jiffies(bfqq->bfqd->bfq_slice_idle) + 4);
|
||||
+ return max3(bfqq->soft_rt_next_start,
|
||||
+ bfqq->last_idle_bklogged +
|
||||
+ HZ * bfqq->service_from_backlogged /
|
||||
+ bfqd->bfq_wr_max_softrt_rate,
|
||||
+ jiffies + nsecs_to_jiffies(bfqq->bfqd->bfq_slice_idle) + 4);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4014,10 +4056,15 @@ static void bfq_init_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
bfqq->split_time = bfq_smallest_from_now();
|
||||
|
||||
/*
|
||||
- * Set to the value for which bfqq will not be deemed as
|
||||
- * soft rt when it becomes backlogged.
|
||||
+ * To not forget the possibly high bandwidth consumed by a
|
||||
+ * process/queue in the recent past,
|
||||
+ * bfq_bfqq_softrt_next_start() returns a value at least equal
|
||||
+ * to the current value of bfqq->soft_rt_next_start (see
|
||||
+ * comments on bfq_bfqq_softrt_next_start). Set
|
||||
+ * soft_rt_next_start to now, to mean that bfqq has consumed
|
||||
+ * no bandwidth so far.
|
||||
*/
|
||||
- bfqq->soft_rt_next_start = bfq_greatest_from_now();
|
||||
+ bfqq->soft_rt_next_start = jiffies;
|
||||
|
||||
/* first request is almost certainly seeky */
|
||||
bfqq->seek_history = 1;
|
||||
--
|
||||
2.15.1
|
||||
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
From 7cb04004fa371a626c1a5ebe6d977f70285759ed Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@linaro.org>
|
||||
Date: Thu, 21 Sep 2017 11:04:03 +0200
|
||||
Subject: [PATCH] block, bfq: decrease burst size when queues in burst exit
|
||||
|
||||
If many queues belonging to the same group happen to be created
|
||||
shortly after each other, then the concurrent processes associated
|
||||
with these queues have typically a common goal, and they get it done
|
||||
as soon as possible if not hampered by device idling. Examples are
|
||||
processes spawned by git grep, or by systemd during boot. As for
|
||||
device idling, this mechanism is currently necessary for weight
|
||||
raising to succeed in its goal: privileging I/O. In view of these
|
||||
facts, BFQ does not provide the above queues with either weight
|
||||
raising or device idling.
|
||||
|
||||
On the other hand, a burst of queue creations may be caused also by
|
||||
the start-up of a complex application. In this case, these queues need
|
||||
usually to be served one after the other, and as quickly as possible,
|
||||
to maximise responsiveness. Therefore, in this case the best strategy
|
||||
is to weight-raise all the queues created during the burst, i.e., the
|
||||
exact opposite of the strategy for the above case.
|
||||
|
||||
To distinguish between the two cases, BFQ uses an empirical burst-size
|
||||
threshold, found through extensive tests and monitoring of daily
|
||||
usage. Only large bursts, i.e., burst with a size above this
|
||||
threshold, are considered as generated by a high number of parallel
|
||||
processes. In this respect, upstart-based boot proved to be rather
|
||||
hard to detect as generating a large burst of queue creations, because
|
||||
with upstart most of the queues created in a burst exit *before* the
|
||||
next queues in the same burst are created. To address this issue, I
|
||||
changed the burst-detection mechanism so as to not decrease the size
|
||||
of the current burst even if one of the queues in the burst is
|
||||
eliminated.
|
||||
|
||||
Unfortunately, this missing decrease causes false positives on very
|
||||
fast systems: on the start-up of a complex application, such as
|
||||
libreoffice writer, so many queues are created, served and exited
|
||||
shortly after each other, that a large burst of queue creations is
|
||||
wrongly detected as occurring. These false positives just disappear if
|
||||
the size of a burst is decreased when one of the queues in the burst
|
||||
exits. This commit restores the missing burst-size decrease, relying
|
||||
of the fact that upstart is apparently unlikely to be used on systems
|
||||
running this and future versions of the kernel.
|
||||
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Mauro Andreolini <mauro.andreolini@unimore.it>
|
||||
Signed-off-by: Angelo Ruocco <angeloruocco90@gmail.com>
|
||||
Tested-by: Mirko Montanari <mirkomontanari91@gmail.com>
|
||||
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
|
||||
Tested-by: Lee Tibbert <lee.tibbert@gmail.com>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 12 +++---------
|
||||
1 file changed, 3 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index 115747fe43c8..70f9177c4f5b 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -3725,16 +3725,10 @@ void bfq_put_queue(struct bfq_queue *bfqq)
|
||||
if (bfqq->ref)
|
||||
return;
|
||||
|
||||
- if (bfq_bfqq_sync(bfqq))
|
||||
- /*
|
||||
- * The fact that this queue is being destroyed does not
|
||||
- * invalidate the fact that this queue may have been
|
||||
- * activated during the current burst. As a consequence,
|
||||
- * although the queue does not exist anymore, and hence
|
||||
- * needs to be removed from the burst list if there,
|
||||
- * the burst size has not to be decremented.
|
||||
- */
|
||||
+ if (bfq_bfqq_sync(bfqq) && !hlist_unhashed(&bfqq->burst_list_node)) {
|
||||
hlist_del_init(&bfqq->burst_list_node);
|
||||
+ bfqq->bfqd->burst_size--;
|
||||
+ }
|
||||
|
||||
kmem_cache_free(bfq_pool, bfqq);
|
||||
#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
--
|
||||
2.15.1
|
||||
|
||||
-91
@@ -1,91 +0,0 @@
|
||||
From 8993d445df388e3541f48920a2353cfc904b220a Mon Sep 17 00:00:00 2001
|
||||
From: Chiara Bruschi <bruschi.chiara@outlook.it>
|
||||
Date: Mon, 18 Dec 2017 16:21:59 +0000
|
||||
Subject: [PATCH] block, bfq: fix occurrences of request finish method's old
|
||||
name
|
||||
|
||||
Commit '7b9e93616399' ("blk-mq-sched: unify request finished methods")
|
||||
changed the old name of current bfq_finish_request method, but left it
|
||||
unchanged elsewhere in the code (related comments, part of function
|
||||
name bfq_put_rq_priv_body).
|
||||
|
||||
This commit fixes all occurrences of the old name of this method by
|
||||
changing them into the current name.
|
||||
|
||||
Fixes: 7b9e93616399 ("blk-mq-sched: unify request finished methods")
|
||||
Reviewed-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Federico Motta <federico@willer.it>
|
||||
Signed-off-by: Chiara Bruschi <bruschi.chiara@outlook.it>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 26 +++++++++++++-------------
|
||||
1 file changed, 13 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index 5e6f837f663e..f352b1677143 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -3684,8 +3684,8 @@ static struct request *__bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
|
||||
}
|
||||
|
||||
/*
|
||||
- * We exploit the put_rq_private hook to decrement
|
||||
- * rq_in_driver, but put_rq_private will not be
|
||||
+ * We exploit the bfq_finish_request hook to decrement
|
||||
+ * rq_in_driver, but bfq_finish_request will not be
|
||||
* invoked on this request. So, to avoid unbalance,
|
||||
* just start this request, without incrementing
|
||||
* rq_in_driver. As a negative consequence,
|
||||
@@ -3694,14 +3694,14 @@ static struct request *__bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
|
||||
* bfq_schedule_dispatch to be invoked uselessly.
|
||||
*
|
||||
* As for implementing an exact solution, the
|
||||
- * put_request hook, if defined, is probably invoked
|
||||
- * also on this request. So, by exploiting this hook,
|
||||
- * we could 1) increment rq_in_driver here, and 2)
|
||||
- * decrement it in put_request. Such a solution would
|
||||
- * let the value of the counter be always accurate,
|
||||
- * but it would entail using an extra interface
|
||||
- * function. This cost seems higher than the benefit,
|
||||
- * being the frequency of non-elevator-private
|
||||
+ * bfq_finish_request hook, if defined, is probably
|
||||
+ * invoked also on this request. So, by exploiting
|
||||
+ * this hook, we could 1) increment rq_in_driver here,
|
||||
+ * and 2) decrement it in bfq_finish_request. Such a
|
||||
+ * solution would let the value of the counter be
|
||||
+ * always accurate, but it would entail using an extra
|
||||
+ * interface function. This cost seems higher than the
|
||||
+ * benefit, being the frequency of non-elevator-private
|
||||
* requests very low.
|
||||
*/
|
||||
goto start_rq;
|
||||
@@ -4558,7 +4558,7 @@ static void bfq_completed_request(struct bfq_queue *bfqq, struct bfq_data *bfqd)
|
||||
bfq_schedule_dispatch(bfqd);
|
||||
}
|
||||
|
||||
-static void bfq_put_rq_priv_body(struct bfq_queue *bfqq)
|
||||
+static void bfq_finish_request_body(struct bfq_queue *bfqq)
|
||||
{
|
||||
bfqq->allocated--;
|
||||
|
||||
@@ -4588,7 +4588,7 @@ static void bfq_finish_request(struct request *rq)
|
||||
spin_lock_irqsave(&bfqd->lock, flags);
|
||||
|
||||
bfq_completed_request(bfqq, bfqd);
|
||||
- bfq_put_rq_priv_body(bfqq);
|
||||
+ bfq_finish_request_body(bfqq);
|
||||
|
||||
spin_unlock_irqrestore(&bfqd->lock, flags);
|
||||
} else {
|
||||
@@ -4609,7 +4609,7 @@ static void bfq_finish_request(struct request *rq)
|
||||
bfqg_stats_update_io_remove(bfqq_group(bfqq),
|
||||
rq->cmd_flags);
|
||||
}
|
||||
- bfq_put_rq_priv_body(bfqq);
|
||||
+ bfq_finish_request_body(bfqq);
|
||||
}
|
||||
|
||||
rq->elv.priv[0] = NULL;
|
||||
--
|
||||
2.16.1
|
||||
|
||||
-141
@@ -1,141 +0,0 @@
|
||||
From 99fead8d38e5302b1be9403d4de815ce9174a3df Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@linaro.org>
|
||||
Date: Mon, 9 Oct 2017 13:11:23 +0200
|
||||
Subject: [PATCH] block, bfq: fix unbalanced decrements of burst size
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The commit "block, bfq: decrease burst size when queues in burst
|
||||
exit" introduced the decrement of burst_size on the removal of a
|
||||
bfq_queue from the burst list. Unfortunately, this decrement can
|
||||
happen to be performed even when burst size is already equal to 0,
|
||||
because of unbalanced decrements. A description follows of the cause
|
||||
of these unbalanced decrements, namely a wrong assumption, and of the
|
||||
way how this wrong assumption leads to unbalanced decrements.
|
||||
|
||||
The wrong assumption is that a bfq_queue can exit only if the process
|
||||
associated with the bfq_queue has exited. This is false, because a
|
||||
bfq_queue, say Q, may exit also as a consequence of a merge with
|
||||
another bfq_queue. In this case, Q exits because the I/O of its
|
||||
associated process has been redirected to another bfq_queue.
|
||||
|
||||
The decrement unbalance occurs because Q may then be re-created after
|
||||
a split, and added back to the current burst list, *without*
|
||||
incrementing burst_size. burst_size is not incremented because Q is
|
||||
not a new bfq_queue added to the burst list, but a bfq_queue only
|
||||
temporarily removed from the list, and, before the commit "bfq-sq,
|
||||
bfq-mq: decrease burst size when queues in burst exit", burst_size was
|
||||
not decremented when Q was removed.
|
||||
|
||||
This commit addresses this issue by just checking whether the exiting
|
||||
bfq_queue is a merged bfq_queue, and, in that case, not decrementing
|
||||
burst_size. Unfortunately, this still leaves room for unbalanced
|
||||
decrements, in the following rarer case: on a split, the bfq_queue
|
||||
happens to be inserted into a different burst list than that it was
|
||||
removed from when merged. If this happens, the number of elements in
|
||||
the new burst list becomes higher than burst_size (by one). When the
|
||||
bfq_queue then exits, it is of course not in a merged state any
|
||||
longer, thus burst_size is decremented, which results in an unbalanced
|
||||
decrement. To handle this sporadic, unlucky case in a simple way,
|
||||
this commit also checks that burst_size is larger than 0 before
|
||||
decrementing it.
|
||||
|
||||
Finally, this commit removes an useless, extra check: the check that
|
||||
the bfq_queue is sync, performed before checking whether the bfq_queue
|
||||
is in the burst list. This extra check is redundant, because only sync
|
||||
bfq_queues can be inserted into the burst list.
|
||||
|
||||
Fixes: 7cb04004fa37 ("block, bfq: decrease burst size when queues in burst exit")
|
||||
Reported-by: Philip Müller <philm@manjaro.org>
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Angelo Ruocco <angeloruocco90@gmail.com>
|
||||
Tested-by: Philip Müller <philm@manjaro.org>
|
||||
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
|
||||
Tested-by: Lee Tibbert <lee.tibbert@gmail.com>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 57 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index 261f98695910..889a8549d97f 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -3726,9 +3726,36 @@ void bfq_put_queue(struct bfq_queue *bfqq)
|
||||
if (bfqq->ref)
|
||||
return;
|
||||
|
||||
- if (bfq_bfqq_sync(bfqq) && !hlist_unhashed(&bfqq->burst_list_node)) {
|
||||
+ if (!hlist_unhashed(&bfqq->burst_list_node)) {
|
||||
hlist_del_init(&bfqq->burst_list_node);
|
||||
- bfqq->bfqd->burst_size--;
|
||||
+ /*
|
||||
+ * Decrement also burst size after the removal, if the
|
||||
+ * process associated with bfqq is exiting, and thus
|
||||
+ * does not contribute to the burst any longer. This
|
||||
+ * decrement helps filter out false positives of large
|
||||
+ * bursts, when some short-lived process (often due to
|
||||
+ * the execution of commands by some service) happens
|
||||
+ * to start and exit while a complex application is
|
||||
+ * starting, and thus spawning several processes that
|
||||
+ * do I/O (and that *must not* be treated as a large
|
||||
+ * burst, see comments on bfq_handle_burst).
|
||||
+ *
|
||||
+ * In particular, the decrement is performed only if:
|
||||
+ * 1) bfqq is not a merged queue, because, if it is,
|
||||
+ * then this free of bfqq is not triggered by the exit
|
||||
+ * of the process bfqq is associated with, but exactly
|
||||
+ * by the fact that bfqq has just been merged.
|
||||
+ * 2) burst_size is greater than 0, to handle
|
||||
+ * unbalanced decrements. Unbalanced decrements may
|
||||
+ * happen in te following case: bfqq is inserted into
|
||||
+ * the current burst list--without incrementing
|
||||
+ * bust_size--because of a split, but the current
|
||||
+ * burst list is not the burst list bfqq belonged to
|
||||
+ * (see comments on the case of a split in
|
||||
+ * bfq_set_request).
|
||||
+ */
|
||||
+ if (bfqq->bic && bfqq->bfqd->burst_size > 0)
|
||||
+ bfqq->bfqd->burst_size--;
|
||||
}
|
||||
|
||||
kmem_cache_free(bfq_pool, bfqq);
|
||||
@@ -4460,6 +4487,34 @@ static struct bfq_queue *bfq_get_bfqq_handle_split(struct bfq_data *bfqd,
|
||||
else {
|
||||
bfq_clear_bfqq_in_large_burst(bfqq);
|
||||
if (bic->was_in_burst_list)
|
||||
+ /*
|
||||
+ * If bfqq was in the current
|
||||
+ * burst list before being
|
||||
+ * merged, then we have to add
|
||||
+ * it back. And we do not need
|
||||
+ * to increase burst_size, as
|
||||
+ * we did not decrement
|
||||
+ * burst_size when we removed
|
||||
+ * bfqq from the burst list as
|
||||
+ * a consequence of a merge
|
||||
+ * (see comments in
|
||||
+ * bfq_put_queue). In this
|
||||
+ * respect, it would be rather
|
||||
+ * costly to know whether the
|
||||
+ * current burst list is still
|
||||
+ * the same burst list from
|
||||
+ * which bfqq was removed on
|
||||
+ * the merge. To avoid this
|
||||
+ * cost, if bfqq was in a
|
||||
+ * burst list, then we add
|
||||
+ * bfqq to the current burst
|
||||
+ * list without any further
|
||||
+ * check. This can cause
|
||||
+ * inappropriate insertions,
|
||||
+ * but rarely enough to not
|
||||
+ * harm the detection of large
|
||||
+ * bursts significantly.
|
||||
+ */
|
||||
hlist_add_head(&bfqq->burst_list_node,
|
||||
&bfqd->burst_list);
|
||||
}
|
||||
--
|
||||
2.15.1
|
||||
|
||||
-146
@@ -1,146 +0,0 @@
|
||||
From 4baa8bb13f41307f3eb62fe91f93a1a798ebef53 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@linaro.org>
|
||||
Date: Thu, 21 Sep 2017 11:04:00 +0200
|
||||
Subject: [PATCH] block, bfq: fix wrong init of saved start time for weight
|
||||
raising
|
||||
|
||||
This commit fixes a bug that causes bfq to fail to guarantee a high
|
||||
responsiveness on some drives, if there is heavy random read+write I/O
|
||||
in the background. More precisely, such a failure allowed this bug to
|
||||
be found [1], but the bug may well cause other yet unreported
|
||||
anomalies.
|
||||
|
||||
BFQ raises the weight of the bfq_queues associated with soft real-time
|
||||
applications, to privilege the I/O, and thus reduce latency, for these
|
||||
applications. This mechanism is named soft-real-time weight raising in
|
||||
BFQ. A soft real-time period may happen to be nested into an
|
||||
interactive weight raising period, i.e., it may happen that, when a
|
||||
bfq_queue switches to a soft real-time weight-raised state, the
|
||||
bfq_queue is already being weight-raised because deemed interactive
|
||||
too. In this case, BFQ saves in a special variable
|
||||
wr_start_at_switch_to_srt, the time instant when the interactive
|
||||
weight-raising period started for the bfq_queue, i.e., the time
|
||||
instant when BFQ started to deem the bfq_queue interactive. This value
|
||||
is then used to check whether the interactive weight-raising period
|
||||
would still be in progress when the soft real-time weight-raising
|
||||
period ends. If so, interactive weight raising is restored for the
|
||||
bfq_queue. This restore is useful, in particular, because it prevents
|
||||
bfq_queues from losing their interactive weight raising prematurely,
|
||||
as a consequence of spurious, short-lived soft real-time
|
||||
weight-raising periods caused by wrong detections as soft real-time.
|
||||
|
||||
If, instead, a bfq_queue switches to soft-real-time weight raising
|
||||
while it *is not* already in an interactive weight-raising period,
|
||||
then the variable wr_start_at_switch_to_srt has no meaning during the
|
||||
following soft real-time weight-raising period. Unfortunately the
|
||||
handling of this case is wrong in BFQ: not only the variable is not
|
||||
flagged somehow as meaningless, but it is also set to the time when
|
||||
the switch to soft real-time weight-raising occurs. This may cause an
|
||||
interactive weight-raising period to be considered mistakenly as still
|
||||
in progress, and thus a spurious interactive weight-raising period to
|
||||
start for the bfq_queue, at the end of the soft-real-time
|
||||
weight-raising period. In particular the spurious interactive
|
||||
weight-raising period will be considered as still in progress, if the
|
||||
soft-real-time weight-raising period does not last very long. The
|
||||
bfq_queue will then be wrongly privileged and, if I/O bound, will
|
||||
unjustly steal bandwidth to truly interactive or soft real-time
|
||||
bfq_queues, harming responsiveness and low latency.
|
||||
|
||||
This commit fixes this issue by just setting wr_start_at_switch_to_srt
|
||||
to minus infinity (farthest past time instant according to jiffies
|
||||
macros): when the soft-real-time weight-raising period ends, certainly
|
||||
no interactive weight-raising period will be considered as still in
|
||||
progress.
|
||||
|
||||
[1] Background I/O Type: Random - Background I/O mix: Reads and writes
|
||||
- Application to start: LibreOffice Writer in
|
||||
http://www.phoronix.com/scan.php?page=news_item&px=Linux-4.13-IO-Laptop
|
||||
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Angelo Ruocco <angeloruocco90@gmail.com>
|
||||
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
|
||||
Tested-by: Lee Tibbert <lee.tibbert@gmail.com>
|
||||
Tested-by: Mirko Montanari <mirkomontanari91@gmail.com>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 50 +++++++++++++++++++++++++++++++-------------------
|
||||
1 file changed, 31 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index a4783da90ba8..c25955c25e03 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -1202,6 +1202,24 @@ static unsigned int bfq_wr_duration(struct bfq_data *bfqd)
|
||||
return dur;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Return the farthest future time instant according to jiffies
|
||||
+ * macros.
|
||||
+ */
|
||||
+static unsigned long bfq_greatest_from_now(void)
|
||||
+{
|
||||
+ return jiffies + MAX_JIFFY_OFFSET;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Return the farthest past time instant according to jiffies
|
||||
+ * macros.
|
||||
+ */
|
||||
+static unsigned long bfq_smallest_from_now(void)
|
||||
+{
|
||||
+ return jiffies - MAX_JIFFY_OFFSET;
|
||||
+}
|
||||
+
|
||||
static void bfq_update_bfqq_wr_on_rq_arrival(struct bfq_data *bfqd,
|
||||
struct bfq_queue *bfqq,
|
||||
unsigned int old_wr_coeff,
|
||||
@@ -1216,7 +1234,19 @@ static void bfq_update_bfqq_wr_on_rq_arrival(struct bfq_data *bfqd,
|
||||
bfqq->wr_coeff = bfqd->bfq_wr_coeff;
|
||||
bfqq->wr_cur_max_time = bfq_wr_duration(bfqd);
|
||||
} else {
|
||||
- bfqq->wr_start_at_switch_to_srt = jiffies;
|
||||
+ /*
|
||||
+ * No interactive weight raising in progress
|
||||
+ * here: assign minus infinity to
|
||||
+ * wr_start_at_switch_to_srt, to make sure
|
||||
+ * that, at the end of the soft-real-time
|
||||
+ * weight raising periods that is starting
|
||||
+ * now, no interactive weight-raising period
|
||||
+ * may be wrongly considered as still in
|
||||
+ * progress (and thus actually started by
|
||||
+ * mistake).
|
||||
+ */
|
||||
+ bfqq->wr_start_at_switch_to_srt =
|
||||
+ bfq_smallest_from_now();
|
||||
bfqq->wr_coeff = bfqd->bfq_wr_coeff *
|
||||
BFQ_SOFTRT_WEIGHT_FACTOR;
|
||||
bfqq->wr_cur_max_time =
|
||||
@@ -2897,24 +2927,6 @@ static unsigned long bfq_bfqq_softrt_next_start(struct bfq_data *bfqd,
|
||||
jiffies + nsecs_to_jiffies(bfqq->bfqd->bfq_slice_idle) + 4);
|
||||
}
|
||||
|
||||
-/*
|
||||
- * Return the farthest future time instant according to jiffies
|
||||
- * macros.
|
||||
- */
|
||||
-static unsigned long bfq_greatest_from_now(void)
|
||||
-{
|
||||
- return jiffies + MAX_JIFFY_OFFSET;
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * Return the farthest past time instant according to jiffies
|
||||
- * macros.
|
||||
- */
|
||||
-static unsigned long bfq_smallest_from_now(void)
|
||||
-{
|
||||
- return jiffies - MAX_JIFFY_OFFSET;
|
||||
-}
|
||||
-
|
||||
/**
|
||||
* bfq_bfqq_expire - expire a queue.
|
||||
* @bfqd: device owning the queue.
|
||||
--
|
||||
2.15.1
|
||||
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
From f0ba5ea2fe45c0ad24a7dedae84a97f7aa046494 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@linaro.org>
|
||||
Date: Wed, 20 Dec 2017 17:27:36 +0100
|
||||
Subject: [PATCH] block, bfq: increase threshold to deem I/O as random
|
||||
|
||||
If two processes do I/O close to each other, i.e., are cooperating
|
||||
processes in BFQ (and CFQ'S) nomenclature, then BFQ merges their
|
||||
associated bfq_queues, so as to get sequential I/O from the union of
|
||||
the I/O requests of the processes, and thus reach a higher
|
||||
throughput. A merged queue is then split if its I/O stops being
|
||||
sequential. In this respect, BFQ deems the I/O of a bfq_queue as
|
||||
(mostly) sequential only if less than 4 I/O requests are random, out
|
||||
of the last 32 requests inserted into the queue.
|
||||
|
||||
Unfortunately, extensive testing (with the interleaved_io benchmark of
|
||||
the S suite [1], and with real applications spawning cooperating
|
||||
processes) has clearly shown that, with such a low threshold, only a
|
||||
rather low I/O throughput may be reached when several cooperating
|
||||
processes do I/O. In particular, the outcome of each test run was
|
||||
bimodal: if queue merging occurred and was stable during the test,
|
||||
then the throughput was close to the peak rate of the storage device,
|
||||
otherwise the throughput was arbitrarily low (usually around 1/10 of
|
||||
the peak rate with a rotational device). The probability to get the
|
||||
unlucky outcomes grew with the number of cooperating processes: it was
|
||||
already significant with 5 processes, and close to one with 7 or more
|
||||
processes.
|
||||
|
||||
The cause of the low throughput in the unlucky runs was that the
|
||||
merged queues containing the I/O of these cooperating processes were
|
||||
soon split, because they contained more random I/O requests than those
|
||||
tolerated by the 4/32 threshold, but
|
||||
- that I/O would have however allowed the storage device to reach
|
||||
peak throughput or almost peak throughput;
|
||||
- in contrast, the I/O of these processes, if served individually
|
||||
(from separate queues) yielded a rather low throughput.
|
||||
|
||||
So we repeated our tests with increasing values of the threshold,
|
||||
until we found the minimum value (19) for which we obtained maximum
|
||||
throughput, reliably, with at least up to 9 cooperating
|
||||
processes. Then we checked that the use of that higher threshold value
|
||||
did not cause any regression for any other benchmark in the suite [1].
|
||||
This commit raises the threshold to such a higher value.
|
||||
|
||||
[1] https://github.com/Algodev-github/S
|
||||
|
||||
Signed-off-by: Angelo Ruocco <angeloruocco90@gmail.com>
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index bcb6d21baf12..0f48583b9380 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -178,7 +178,7 @@ static struct kmem_cache *bfq_pool;
|
||||
#define BFQQ_SEEK_THR (sector_t)(8 * 100)
|
||||
#define BFQQ_SECT_THR_NONROT (sector_t)(2 * 32)
|
||||
#define BFQQ_CLOSE_THR (sector_t)(8 * 1024)
|
||||
-#define BFQQ_SEEKY(bfqq) (hweight32(bfqq->seek_history) > 32/8)
|
||||
+#define BFQQ_SEEKY(bfqq) (hweight32(bfqq->seek_history) > 19)
|
||||
|
||||
/* Min number of samples required to perform peak-rate update */
|
||||
#define BFQ_RATE_MIN_SAMPLES 32
|
||||
--
|
||||
2.15.1
|
||||
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
From 8abef10b3de1144cfe968f454946f13eb1ac3d0a Mon Sep 17 00:00:00 2001
|
||||
From: Jens Axboe <axboe@kernel.dk>
|
||||
Date: Tue, 9 Jan 2018 12:20:51 -0700
|
||||
Subject: [PATCH] bfq-iosched: don't call bfqg_and_blkg_put for
|
||||
!CONFIG_BFQ_GROUP_IOSCHED
|
||||
|
||||
It's not available if we don't have group io scheduling set, and
|
||||
there's no need to call it.
|
||||
|
||||
Fixes: 0d52af590552 ("block, bfq: release oom-queue ref to root group on exit")
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index 7c0b7f60811c..5e6f837f663e 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -4893,10 +4893,10 @@ static void bfq_exit_queue(struct elevator_queue *e)
|
||||
|
||||
hrtimer_cancel(&bfqd->idle_slice_timer);
|
||||
|
||||
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
/* release oom-queue reference to root group */
|
||||
bfqg_and_blkg_put(bfqd->root_group);
|
||||
|
||||
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
blkcg_deactivate_policy(bfqd->queue, &blkcg_policy_bfq);
|
||||
#else
|
||||
spin_lock_irq(&bfqd->lock);
|
||||
--
|
||||
2.16.1
|
||||
|
||||
-186
@@ -1,186 +0,0 @@
|
||||
From 7b8fa3b900a087bc03b11329a92398fde563ba37 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@linaro.org>
|
||||
Date: Wed, 20 Dec 2017 12:38:33 +0100
|
||||
Subject: [PATCH] block, bfq: let a queue be merged only shortly after starting
|
||||
I/O
|
||||
|
||||
In BFQ and CFQ, two processes are said to be cooperating if they do
|
||||
I/O in such a way that the union of their I/O requests yields a
|
||||
sequential I/O pattern. To get such a sequential I/O pattern out of
|
||||
the non-sequential pattern of each cooperating process, BFQ and CFQ
|
||||
merge the queues associated with these processes. In more detail,
|
||||
cooperating processes, and thus their associated queues, usually
|
||||
start, or restart, to do I/O shortly after each other. This is the
|
||||
case, e.g., for the I/O threads of KVM/QEMU and of the dump
|
||||
utility. Basing on this assumption, this commit allows a bfq_queue to
|
||||
be merged only during a short time interval (100ms) after it starts,
|
||||
or re-starts, to do I/O. This filtering provides two important
|
||||
benefits.
|
||||
|
||||
First, it greatly reduces the probability that two non-cooperating
|
||||
processes have their queues merged by mistake, if they just happen to
|
||||
do I/O close to each other for a short time interval. These spurious
|
||||
merges cause loss of service guarantees. A low-weight bfq_queue may
|
||||
unjustly get more than its expected share of the throughput: if such a
|
||||
low-weight queue is merged with a high-weight queue, then the I/O for
|
||||
the low-weight queue is served as if the queue had a high weight. This
|
||||
may damage other high-weight queues unexpectedly. For instance,
|
||||
because of this issue, lxterminal occasionally took 7.5 seconds to
|
||||
start, instead of 6.5 seconds, when some sequential readers and
|
||||
writers did I/O in the background on a FUJITSU MHX2300BT HDD. The
|
||||
reason is that the bfq_queues associated with some of the readers or
|
||||
the writers were merged with the high-weight queues of some processes
|
||||
that had to do some urgent but little I/O. The readers then exploited
|
||||
the inherited high weight for all or most of their I/O, during the
|
||||
start-up of terminal. The filtering introduced by this commit
|
||||
eliminated any outlier caused by spurious queue merges in our start-up
|
||||
time tests.
|
||||
|
||||
This filtering also provides a little boost of the throughput
|
||||
sustainable by BFQ: 3-4%, depending on the CPU. The reason is that,
|
||||
once a bfq_queue cannot be merged any longer, this commit makes BFQ
|
||||
stop updating the data needed to handle merging for the queue.
|
||||
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Angelo Ruocco <angeloruocco90@gmail.com>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 57 ++++++++++++++++++++++++++++++++++++++++++-----------
|
||||
block/bfq-iosched.h | 2 ++
|
||||
block/bfq-wf2q.c | 4 ++++
|
||||
3 files changed, 52 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index 2cf395daee80..7066d90f09df 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -166,6 +166,20 @@ static const int bfq_async_charge_factor = 10;
|
||||
/* Default timeout values, in jiffies, approximating CFQ defaults. */
|
||||
const int bfq_timeout = HZ / 8;
|
||||
|
||||
+/*
|
||||
+ * Time limit for merging (see comments in bfq_setup_cooperator). Set
|
||||
+ * to the slowest value that, in our tests, proved to be effective in
|
||||
+ * removing false positives, while not causing true positives to miss
|
||||
+ * queue merging.
|
||||
+ *
|
||||
+ * As can be deduced from the low time limit below, queue merging, if
|
||||
+ * successful, happens at the very beggining of the I/O of the involved
|
||||
+ * cooperating processes, as a consequence of the arrival of the very
|
||||
+ * first requests from each cooperator. After that, there is very
|
||||
+ * little chance to find cooperators.
|
||||
+ */
|
||||
+static const unsigned long bfq_merge_time_limit = HZ/10;
|
||||
+
|
||||
static struct kmem_cache *bfq_pool;
|
||||
|
||||
/* Below this threshold (in ns), we consider thinktime immediate. */
|
||||
@@ -444,6 +458,13 @@ bfq_rq_pos_tree_lookup(struct bfq_data *bfqd, struct rb_root *root,
|
||||
return bfqq;
|
||||
}
|
||||
|
||||
+static bool bfq_too_late_for_merging(struct bfq_queue *bfqq)
|
||||
+{
|
||||
+ return bfqq->service_from_backlogged > 0 &&
|
||||
+ time_is_before_jiffies(bfqq->first_IO_time +
|
||||
+ bfq_merge_time_limit);
|
||||
+}
|
||||
+
|
||||
void bfq_pos_tree_add_move(struct bfq_data *bfqd, struct bfq_queue *bfqq)
|
||||
{
|
||||
struct rb_node **p, *parent;
|
||||
@@ -454,6 +475,14 @@ void bfq_pos_tree_add_move(struct bfq_data *bfqd, struct bfq_queue *bfqq)
|
||||
bfqq->pos_root = NULL;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * bfqq cannot be merged any longer (see comments in
|
||||
+ * bfq_setup_cooperator): no point in adding bfqq into the
|
||||
+ * position tree.
|
||||
+ */
|
||||
+ if (bfq_too_late_for_merging(bfqq))
|
||||
+ return;
|
||||
+
|
||||
if (bfq_class_idle(bfqq))
|
||||
return;
|
||||
if (!bfqq->next_rq)
|
||||
@@ -1935,6 +1964,9 @@ bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq)
|
||||
static bool bfq_may_be_close_cooperator(struct bfq_queue *bfqq,
|
||||
struct bfq_queue *new_bfqq)
|
||||
{
|
||||
+ if (bfq_too_late_for_merging(new_bfqq))
|
||||
+ return false;
|
||||
+
|
||||
if (bfq_class_idle(bfqq) || bfq_class_idle(new_bfqq) ||
|
||||
(bfqq->ioprio_class != new_bfqq->ioprio_class))
|
||||
return false;
|
||||
@@ -2003,6 +2035,20 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
{
|
||||
struct bfq_queue *in_service_bfqq, *new_bfqq;
|
||||
|
||||
+ /*
|
||||
+ * Prevent bfqq from being merged if it has been created too
|
||||
+ * long ago. The idea is that true cooperating processes, and
|
||||
+ * thus their associated bfq_queues, are supposed to be
|
||||
+ * created shortly after each other. This is the case, e.g.,
|
||||
+ * for KVM/QEMU and dump I/O threads. Basing on this
|
||||
+ * assumption, the following filtering greatly reduces the
|
||||
+ * probability that two non-cooperating processes, which just
|
||||
+ * happen to do close I/O for some short time interval, have
|
||||
+ * their queues merged by mistake.
|
||||
+ */
|
||||
+ if (bfq_too_late_for_merging(bfqq))
|
||||
+ return NULL;
|
||||
+
|
||||
if (bfqq->new_bfqq)
|
||||
return bfqq->new_bfqq;
|
||||
|
||||
@@ -3002,17 +3048,6 @@ void bfq_bfqq_expire(struct bfq_data *bfqd,
|
||||
*/
|
||||
slow = bfq_bfqq_is_slow(bfqd, bfqq, compensate, reason, &delta);
|
||||
|
||||
- /*
|
||||
- * Increase service_from_backlogged before next statement,
|
||||
- * because the possible next invocation of
|
||||
- * bfq_bfqq_charge_time would likely inflate
|
||||
- * entity->service. In contrast, service_from_backlogged must
|
||||
- * contain real service, to enable the soft real-time
|
||||
- * heuristic to correctly compute the bandwidth consumed by
|
||||
- * bfqq.
|
||||
- */
|
||||
- bfqq->service_from_backlogged += entity->service;
|
||||
-
|
||||
/*
|
||||
* As above explained, charge slow (typically seeky) and
|
||||
* timed-out queues with the time and not the service
|
||||
diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h
|
||||
index 91c4390903a1..5d47b58d5fc8 100644
|
||||
--- a/block/bfq-iosched.h
|
||||
+++ b/block/bfq-iosched.h
|
||||
@@ -344,6 +344,8 @@ struct bfq_queue {
|
||||
unsigned long wr_start_at_switch_to_srt;
|
||||
|
||||
unsigned long split_time; /* time of last split */
|
||||
+
|
||||
+ unsigned long first_IO_time; /* time of first I/O for this queue */
|
||||
};
|
||||
|
||||
/**
|
||||
diff --git a/block/bfq-wf2q.c b/block/bfq-wf2q.c
|
||||
index e495d3f9b4b0..4456eda34e48 100644
|
||||
--- a/block/bfq-wf2q.c
|
||||
+++ b/block/bfq-wf2q.c
|
||||
@@ -835,6 +835,10 @@ void bfq_bfqq_served(struct bfq_queue *bfqq, int served)
|
||||
struct bfq_entity *entity = &bfqq->entity;
|
||||
struct bfq_service_tree *st;
|
||||
|
||||
+ if (!bfqq->service_from_backlogged)
|
||||
+ bfqq->first_IO_time = jiffies;
|
||||
+
|
||||
+ bfqq->service_from_backlogged += served;
|
||||
for_each_entity(entity) {
|
||||
st = bfq_entity_service_tree(entity);
|
||||
|
||||
--
|
||||
2.15.1
|
||||
|
||||
-89
@@ -1,89 +0,0 @@
|
||||
From 894df937e06a56ed6f054a75a416aff84147c5a2 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@linaro.org>
|
||||
Date: Thu, 21 Sep 2017 11:04:02 +0200
|
||||
Subject: [PATCH] block, bfq: let early-merged queues be weight-raised on split
|
||||
too
|
||||
|
||||
A just-created bfq_queue, say Q, may happen to be merged with another
|
||||
bfq_queue on the very first invocation of the function
|
||||
__bfq_insert_request. In such a case, even if Q would clearly deserve
|
||||
interactive weight raising (as it has just been created), the function
|
||||
bfq_add_request does not make it to be invoked for Q, and thus to
|
||||
activate weight raising for Q. As a consequence, when the state of Q
|
||||
is saved for a possible future restore, after a split of Q from the
|
||||
other bfq_queue(s), such a state happens to be (unjustly)
|
||||
non-weight-raised. Then the bfq_queue will not enjoy any weight
|
||||
raising on the split, even if should still be in an interactive
|
||||
weight-raising period when the split occurs.
|
||||
|
||||
This commit solves this problem as follows, for a just-created
|
||||
bfq_queue that is being early-merged: it stores directly, in the saved
|
||||
state of the bfq_queue, the weight-raising state that would have been
|
||||
assigned to the bfq_queue if not early-merged.
|
||||
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Tested-by: Angelo Ruocco <angeloruocco90@gmail.com>
|
||||
Tested-by: Mirko Montanari <mirkomontanari91@gmail.com>
|
||||
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
|
||||
Tested-by: Lee Tibbert <lee.tibbert@gmail.com>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 28 +++++++++++++++++++++++-----
|
||||
1 file changed, 23 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index 33b63bc4a64b..115747fe43c8 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -2061,10 +2061,27 @@ static void bfq_bfqq_save_state(struct bfq_queue *bfqq)
|
||||
bic->saved_IO_bound = bfq_bfqq_IO_bound(bfqq);
|
||||
bic->saved_in_large_burst = bfq_bfqq_in_large_burst(bfqq);
|
||||
bic->was_in_burst_list = !hlist_unhashed(&bfqq->burst_list_node);
|
||||
- bic->saved_wr_coeff = bfqq->wr_coeff;
|
||||
- bic->saved_wr_start_at_switch_to_srt = bfqq->wr_start_at_switch_to_srt;
|
||||
- bic->saved_last_wr_start_finish = bfqq->last_wr_start_finish;
|
||||
- bic->saved_wr_cur_max_time = bfqq->wr_cur_max_time;
|
||||
+ if (unlikely(bfq_bfqq_just_created(bfqq) &&
|
||||
+ !bfq_bfqq_in_large_burst(bfqq))) {
|
||||
+ /*
|
||||
+ * bfqq being merged right after being created: bfqq
|
||||
+ * would have deserved interactive weight raising, but
|
||||
+ * did not make it to be set in a weight-raised state,
|
||||
+ * because of this early merge. Store directly the
|
||||
+ * weight-raising state that would have been assigned
|
||||
+ * to bfqq, so that to avoid that bfqq unjustly fails
|
||||
+ * to enjoy weight raising if split soon.
|
||||
+ */
|
||||
+ bic->saved_wr_coeff = bfqq->bfqd->bfq_wr_coeff;
|
||||
+ bic->saved_wr_cur_max_time = bfq_wr_duration(bfqq->bfqd);
|
||||
+ bic->saved_last_wr_start_finish = jiffies;
|
||||
+ } else {
|
||||
+ bic->saved_wr_coeff = bfqq->wr_coeff;
|
||||
+ bic->saved_wr_start_at_switch_to_srt =
|
||||
+ bfqq->wr_start_at_switch_to_srt;
|
||||
+ bic->saved_last_wr_start_finish = bfqq->last_wr_start_finish;
|
||||
+ bic->saved_wr_cur_max_time = bfqq->wr_cur_max_time;
|
||||
+ }
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -4150,7 +4167,6 @@ static void __bfq_insert_request(struct bfq_data *bfqd, struct request *rq)
|
||||
new_bfqq->allocated++;
|
||||
bfqq->allocated--;
|
||||
new_bfqq->ref++;
|
||||
- bfq_clear_bfqq_just_created(bfqq);
|
||||
/*
|
||||
* If the bic associated with the process
|
||||
* issuing this request still points to bfqq
|
||||
@@ -4162,6 +4178,8 @@ static void __bfq_insert_request(struct bfq_data *bfqd, struct request *rq)
|
||||
if (bic_to_bfqq(RQ_BIC(rq), 1) == bfqq)
|
||||
bfq_merge_bfqqs(bfqd, RQ_BIC(rq),
|
||||
bfqq, new_bfqq);
|
||||
+
|
||||
+ bfq_clear_bfqq_just_created(bfqq);
|
||||
/*
|
||||
* rq is about to be enqueued into new_bfqq,
|
||||
* release rq reference on bfqq
|
||||
--
|
||||
2.15.1
|
||||
|
||||
-202
@@ -1,202 +0,0 @@
|
||||
From 8a8747dc01cee6f92a52c03ba686e9f60cb46c87 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@linaro.org>
|
||||
Date: Sat, 13 Jan 2018 12:05:18 +0100
|
||||
Subject: [PATCH] block, bfq: limit sectors served with interactive weight
|
||||
raising
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
To maximise responsiveness, BFQ raises the weight, and performs device
|
||||
idling, for bfq_queues associated with processes deemed as
|
||||
interactive. In particular, weight raising has a maximum duration,
|
||||
equal to the time needed to start a large application. If a
|
||||
weight-raised process goes on doing I/O beyond this maximum duration,
|
||||
it loses weight-raising.
|
||||
|
||||
This mechanism is evidently vulnerable to the following false
|
||||
positives: I/O-bound applications that will go on doing I/O for much
|
||||
longer than the duration of weight-raising. These applications have
|
||||
basically no benefit from being weight-raised at the beginning of
|
||||
their I/O. On the opposite end, while being weight-raised, these
|
||||
applications
|
||||
a) unjustly steal throughput to applications that may truly need
|
||||
low latency;
|
||||
b) make BFQ uselessly perform device idling; device idling results
|
||||
in loss of device throughput with most flash-based storage, and may
|
||||
increase latencies when used purposelessly.
|
||||
|
||||
This commit adds a countermeasure to reduce both the above
|
||||
problems. To introduce this countermeasure, we provide the following
|
||||
extra piece of information (full details in the comments added by this
|
||||
commit). During the start-up of the large application used as a
|
||||
reference to set the duration of weight-raising, involved processes
|
||||
transfer at most ~110K sectors each. Accordingly, a process initially
|
||||
deemed as interactive has no right to be weight-raised any longer,
|
||||
once transferred 110K sectors or more.
|
||||
|
||||
Basing on this consideration, this commit early-ends weight-raising
|
||||
for a bfq_queue if the latter happens to have received an amount of
|
||||
service at least equal to 110K sectors (actually, a little bit more,
|
||||
to keep a safety margin). I/O-bound applications that reach a high
|
||||
throughput, such as file copy, get to this threshold much before the
|
||||
allowed weight-raising period finishes. Thus this early ending of
|
||||
weight-raising reduces the amount of time during which these
|
||||
applications cause the problems described above.
|
||||
|
||||
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
|
||||
Tested-by: Holger Hoffstätte <holger@applied-asynchrony.com>
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++------
|
||||
block/bfq-iosched.h | 5 ++++
|
||||
block/bfq-wf2q.c | 3 ++
|
||||
3 files changed, 80 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index a7ab0cb50733..47e6ec7427c4 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -209,15 +209,17 @@ static struct kmem_cache *bfq_pool;
|
||||
* interactive applications automatically, using the following formula:
|
||||
* duration = (R / r) * T, where r is the peak rate of the device, and
|
||||
* R and T are two reference parameters.
|
||||
- * In particular, R is the peak rate of the reference device (see below),
|
||||
- * and T is a reference time: given the systems that are likely to be
|
||||
- * installed on the reference device according to its speed class, T is
|
||||
- * about the maximum time needed, under BFQ and while reading two files in
|
||||
- * parallel, to load typical large applications on these systems.
|
||||
- * In practice, the slower/faster the device at hand is, the more/less it
|
||||
- * takes to load applications with respect to the reference device.
|
||||
- * Accordingly, the longer/shorter BFQ grants weight raising to interactive
|
||||
- * applications.
|
||||
+ * In particular, R is the peak rate of the reference device (see
|
||||
+ * below), and T is a reference time: given the systems that are
|
||||
+ * likely to be installed on the reference device according to its
|
||||
+ * speed class, T is about the maximum time needed, under BFQ and
|
||||
+ * while reading two files in parallel, to load typical large
|
||||
+ * applications on these systems (see the comments on
|
||||
+ * max_service_from_wr below, for more details on how T is obtained).
|
||||
+ * In practice, the slower/faster the device at hand is, the more/less
|
||||
+ * it takes to load applications with respect to the reference device.
|
||||
+ * Accordingly, the longer/shorter BFQ grants weight raising to
|
||||
+ * interactive applications.
|
||||
*
|
||||
* BFQ uses four different reference pairs (R, T), depending on:
|
||||
* . whether the device is rotational or non-rotational;
|
||||
@@ -254,6 +256,60 @@ static int T_slow[2];
|
||||
static int T_fast[2];
|
||||
static int device_speed_thresh[2];
|
||||
|
||||
+/*
|
||||
+ * BFQ uses the above-detailed, time-based weight-raising mechanism to
|
||||
+ * privilege interactive tasks. This mechanism is vulnerable to the
|
||||
+ * following false positives: I/O-bound applications that will go on
|
||||
+ * doing I/O for much longer than the duration of weight
|
||||
+ * raising. These applications have basically no benefit from being
|
||||
+ * weight-raised at the beginning of their I/O. On the opposite end,
|
||||
+ * while being weight-raised, these applications
|
||||
+ * a) unjustly steal throughput to applications that may actually need
|
||||
+ * low latency;
|
||||
+ * b) make BFQ uselessly perform device idling; device idling results
|
||||
+ * in loss of device throughput with most flash-based storage, and may
|
||||
+ * increase latencies when used purposelessly.
|
||||
+ *
|
||||
+ * BFQ tries to reduce these problems, by adopting the following
|
||||
+ * countermeasure. To introduce this countermeasure, we need first to
|
||||
+ * finish explaining how the duration of weight-raising for
|
||||
+ * interactive tasks is computed.
|
||||
+ *
|
||||
+ * For a bfq_queue deemed as interactive, the duration of weight
|
||||
+ * raising is dynamically adjusted, as a function of the estimated
|
||||
+ * peak rate of the device, so as to be equal to the time needed to
|
||||
+ * execute the 'largest' interactive task we benchmarked so far. By
|
||||
+ * largest task, we mean the task for which each involved process has
|
||||
+ * to do more I/O than for any of the other tasks we benchmarked. This
|
||||
+ * reference interactive task is the start-up of LibreOffice Writer,
|
||||
+ * and in this task each process/bfq_queue needs to have at most ~110K
|
||||
+ * sectors transferred.
|
||||
+ *
|
||||
+ * This last piece of information enables BFQ to reduce the actual
|
||||
+ * duration of weight-raising for at least one class of I/O-bound
|
||||
+ * applications: those doing sequential or quasi-sequential I/O. An
|
||||
+ * example is file copy. In fact, once started, the main I/O-bound
|
||||
+ * processes of these applications usually consume the above 110K
|
||||
+ * sectors in much less time than the processes of an application that
|
||||
+ * is starting, because these I/O-bound processes will greedily devote
|
||||
+ * almost all their CPU cycles only to their target,
|
||||
+ * throughput-friendly I/O operations. This is even more true if BFQ
|
||||
+ * happens to be underestimating the device peak rate, and thus
|
||||
+ * overestimating the duration of weight raising. But, according to
|
||||
+ * our measurements, once transferred 110K sectors, these processes
|
||||
+ * have no right to be weight-raised any longer.
|
||||
+ *
|
||||
+ * Basing on the last consideration, BFQ ends weight-raising for a
|
||||
+ * bfq_queue if the latter happens to have received an amount of
|
||||
+ * service at least equal to the following constant. The constant is
|
||||
+ * set to slightly more than 110K, to have a minimum safety margin.
|
||||
+ *
|
||||
+ * This early ending of weight-raising reduces the amount of time
|
||||
+ * during which interactive false positives cause the two problems
|
||||
+ * described at the beginning of these comments.
|
||||
+ */
|
||||
+static const unsigned long max_service_from_wr = 120000;
|
||||
+
|
||||
#define RQ_BIC(rq) icq_to_bic((rq)->elv.priv[0])
|
||||
#define RQ_BFQQ(rq) ((rq)->elv.priv[1])
|
||||
|
||||
@@ -1352,6 +1408,7 @@ static void bfq_update_bfqq_wr_on_rq_arrival(struct bfq_data *bfqd,
|
||||
if (old_wr_coeff == 1 && wr_or_deserves_wr) {
|
||||
/* start a weight-raising period */
|
||||
if (interactive) {
|
||||
+ bfqq->service_from_wr = 0;
|
||||
bfqq->wr_coeff = bfqd->bfq_wr_coeff;
|
||||
bfqq->wr_cur_max_time = bfq_wr_duration(bfqd);
|
||||
} else {
|
||||
@@ -3665,6 +3722,12 @@ static void bfq_update_wr_data(struct bfq_data *bfqd, struct bfq_queue *bfqq)
|
||||
bfqq->entity.prio_changed = 1;
|
||||
}
|
||||
}
|
||||
+ if (bfqq->wr_coeff > 1 &&
|
||||
+ bfqq->wr_cur_max_time != bfqd->bfq_wr_rt_max_time &&
|
||||
+ bfqq->service_from_wr > max_service_from_wr) {
|
||||
+ /* see comments on max_service_from_wr */
|
||||
+ bfq_bfqq_end_wr(bfqq);
|
||||
+ }
|
||||
}
|
||||
/*
|
||||
* To improve latency (for this or other queues), immediately
|
||||
diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h
|
||||
index fcd941008127..350c39ae2896 100644
|
||||
--- a/block/bfq-iosched.h
|
||||
+++ b/block/bfq-iosched.h
|
||||
@@ -337,6 +337,11 @@ struct bfq_queue {
|
||||
* last transition from idle to backlogged.
|
||||
*/
|
||||
unsigned long service_from_backlogged;
|
||||
+ /*
|
||||
+ * Cumulative service received from the @bfq_queue since its
|
||||
+ * last transition to weight-raised state.
|
||||
+ */
|
||||
+ unsigned long service_from_wr;
|
||||
|
||||
/*
|
||||
* Value of wr start time when switching to soft rt
|
||||
diff --git a/block/bfq-wf2q.c b/block/bfq-wf2q.c
|
||||
index 4456eda34e48..4498c43245e2 100644
|
||||
--- a/block/bfq-wf2q.c
|
||||
+++ b/block/bfq-wf2q.c
|
||||
@@ -838,6 +838,9 @@ void bfq_bfqq_served(struct bfq_queue *bfqq, int served)
|
||||
if (!bfqq->service_from_backlogged)
|
||||
bfqq->first_IO_time = jiffies;
|
||||
|
||||
+ if (bfqq->wr_coeff > 1)
|
||||
+ bfqq->service_from_wr += served;
|
||||
+
|
||||
bfqq->service_from_backlogged += served;
|
||||
for_each_entity(entity) {
|
||||
st = bfq_entity_service_tree(entity);
|
||||
--
|
||||
2.16.1
|
||||
|
||||
-162
@@ -1,162 +0,0 @@
|
||||
From a52a69ea89dc12e6f4572f554940789c1ab23c7a Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@linaro.org>
|
||||
Date: Sat, 13 Jan 2018 12:05:17 +0100
|
||||
Subject: [PATCH] block, bfq: limit tags for writes and async I/O
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Asynchronous I/O can easily starve synchronous I/O (both sync reads
|
||||
and sync writes), by consuming all request tags. Similarly, storms of
|
||||
synchronous writes, such as those that sync(2) may trigger, can starve
|
||||
synchronous reads. In their turn, these two problems may also cause
|
||||
BFQ to loose control on latency for interactive and soft real-time
|
||||
applications. For example, on a PLEXTOR PX-256M5S SSD, LibreOffice
|
||||
Writer takes 0.6 seconds to start if the device is idle, but it takes
|
||||
more than 45 seconds (!) if there are sequential writes in the
|
||||
background.
|
||||
|
||||
This commit addresses this issue by limiting the maximum percentage of
|
||||
tags that asynchronous I/O requests and synchronous write requests can
|
||||
consume. In particular, this commit grants a higher threshold to
|
||||
synchronous writes, to prevent the latter from being starved by
|
||||
asynchronous I/O.
|
||||
|
||||
According to the above test, LibreOffice Writer now starts in about
|
||||
1.2 seconds on average, regardless of the background workload, and
|
||||
apart from some rare outlier. To check this improvement, run, e.g.,
|
||||
sudo ./comm_startup_lat.sh bfq 5 5 seq 10 "lowriter --terminate_after_init"
|
||||
for the comm_startup_lat benchmark in the S suite [1].
|
||||
|
||||
[1] https://github.com/Algodev-github/S
|
||||
|
||||
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
|
||||
Tested-by: Holger Hoffstätte <holger@applied-asynchrony.com>
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
block/bfq-iosched.h | 12 +++++++++
|
||||
2 files changed, 89 insertions(+)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index f352b1677143..a7ab0cb50733 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -417,6 +417,82 @@ static struct request *bfq_choose_req(struct bfq_data *bfqd,
|
||||
}
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * See the comments on bfq_limit_depth for the purpose of
|
||||
+ * the depths set in the function.
|
||||
+ */
|
||||
+static void bfq_update_depths(struct bfq_data *bfqd, struct sbitmap_queue *bt)
|
||||
+{
|
||||
+ bfqd->sb_shift = bt->sb.shift;
|
||||
+
|
||||
+ /*
|
||||
+ * In-word depths if no bfq_queue is being weight-raised:
|
||||
+ * leaving 25% of tags only for sync reads.
|
||||
+ *
|
||||
+ * In next formulas, right-shift the value
|
||||
+ * (1U<<bfqd->sb_shift), instead of computing directly
|
||||
+ * (1U<<(bfqd->sb_shift - something)), to be robust against
|
||||
+ * any possible value of bfqd->sb_shift, without having to
|
||||
+ * limit 'something'.
|
||||
+ */
|
||||
+ /* no more than 50% of tags for async I/O */
|
||||
+ bfqd->word_depths[0][0] = max((1U<<bfqd->sb_shift)>>1, 1U);
|
||||
+ /*
|
||||
+ * no more than 75% of tags for sync writes (25% extra tags
|
||||
+ * w.r.t. async I/O, to prevent async I/O from starving sync
|
||||
+ * writes)
|
||||
+ */
|
||||
+ bfqd->word_depths[0][1] = max(((1U<<bfqd->sb_shift) * 3)>>2, 1U);
|
||||
+
|
||||
+ /*
|
||||
+ * In-word depths in case some bfq_queue is being weight-
|
||||
+ * raised: leaving ~63% of tags for sync reads. This is the
|
||||
+ * highest percentage for which, in our tests, application
|
||||
+ * start-up times didn't suffer from any regression due to tag
|
||||
+ * shortage.
|
||||
+ */
|
||||
+ /* no more than ~18% of tags for async I/O */
|
||||
+ bfqd->word_depths[1][0] = max(((1U<<bfqd->sb_shift) * 3)>>4, 1U);
|
||||
+ /* no more than ~37% of tags for sync writes (~20% extra tags) */
|
||||
+ bfqd->word_depths[1][1] = max(((1U<<bfqd->sb_shift) * 6)>>4, 1U);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Async I/O can easily starve sync I/O (both sync reads and sync
|
||||
+ * writes), by consuming all tags. Similarly, storms of sync writes,
|
||||
+ * such as those that sync(2) may trigger, can starve sync reads.
|
||||
+ * Limit depths of async I/O and sync writes so as to counter both
|
||||
+ * problems.
|
||||
+ */
|
||||
+static void bfq_limit_depth(unsigned int op, struct blk_mq_alloc_data *data)
|
||||
+{
|
||||
+ struct blk_mq_tags *tags = blk_mq_tags_from_data(data);
|
||||
+ struct bfq_data *bfqd = data->q->elevator->elevator_data;
|
||||
+ struct sbitmap_queue *bt;
|
||||
+
|
||||
+ if (op_is_sync(op) && !op_is_write(op))
|
||||
+ return;
|
||||
+
|
||||
+ if (data->flags & BLK_MQ_REQ_RESERVED) {
|
||||
+ if (unlikely(!tags->nr_reserved_tags)) {
|
||||
+ WARN_ON_ONCE(1);
|
||||
+ return;
|
||||
+ }
|
||||
+ bt = &tags->breserved_tags;
|
||||
+ } else
|
||||
+ bt = &tags->bitmap_tags;
|
||||
+
|
||||
+ if (unlikely(bfqd->sb_shift != bt->sb.shift))
|
||||
+ bfq_update_depths(bfqd, bt);
|
||||
+
|
||||
+ data->shallow_depth =
|
||||
+ bfqd->word_depths[!!bfqd->wr_busy_queues][op_is_sync(op)];
|
||||
+
|
||||
+ bfq_log(bfqd, "[%s] wr_busy %d sync %d depth %u",
|
||||
+ __func__, bfqd->wr_busy_queues, op_is_sync(op),
|
||||
+ data->shallow_depth);
|
||||
+}
|
||||
+
|
||||
static struct bfq_queue *
|
||||
bfq_rq_pos_tree_lookup(struct bfq_data *bfqd, struct rb_root *root,
|
||||
sector_t sector, struct rb_node **ret_parent,
|
||||
@@ -5285,6 +5361,7 @@ static struct elv_fs_entry bfq_attrs[] = {
|
||||
|
||||
static struct elevator_type iosched_bfq_mq = {
|
||||
.ops.mq = {
|
||||
+ .limit_depth = bfq_limit_depth,
|
||||
.prepare_request = bfq_prepare_request,
|
||||
.finish_request = bfq_finish_request,
|
||||
.exit_icq = bfq_exit_icq,
|
||||
diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h
|
||||
index 5d47b58d5fc8..fcd941008127 100644
|
||||
--- a/block/bfq-iosched.h
|
||||
+++ b/block/bfq-iosched.h
|
||||
@@ -629,6 +629,18 @@ struct bfq_data {
|
||||
struct bfq_io_cq *bio_bic;
|
||||
/* bfqq associated with the task issuing current bio for merging */
|
||||
struct bfq_queue *bio_bfqq;
|
||||
+
|
||||
+ /*
|
||||
+ * Cached sbitmap shift, used to compute depth limits in
|
||||
+ * bfq_update_depths.
|
||||
+ */
|
||||
+ unsigned int sb_shift;
|
||||
+
|
||||
+ /*
|
||||
+ * Depth limits used in bfq_limit_depth (see comments on the
|
||||
+ * function)
|
||||
+ */
|
||||
+ unsigned int word_depths[2][2];
|
||||
};
|
||||
|
||||
enum bfqq_state_flags {
|
||||
--
|
||||
2.16.1
|
||||
|
||||
-467
@@ -1,467 +0,0 @@
|
||||
From a33801e8b4735b8d473f963e5854172f9cde3e8b Mon Sep 17 00:00:00 2001
|
||||
From: Luca Miccio <lucmiccio@gmail.com>
|
||||
Date: Mon, 13 Nov 2017 07:34:10 +0100
|
||||
Subject: [PATCH] block, bfq: move debug blkio stats behind
|
||||
CONFIG_DEBUG_BLK_CGROUP
|
||||
|
||||
BFQ currently creates, and updates, its own instance of the whole
|
||||
set of blkio statistics that cfq creates. Yet, from the comments
|
||||
of Tejun Heo in [1], it turned out that most of these statistics
|
||||
are meant/useful only for debugging. This commit makes BFQ create
|
||||
the latter, debugging statistics only if the option
|
||||
CONFIG_DEBUG_BLK_CGROUP is set.
|
||||
|
||||
By doing so, this commit also enables BFQ to enjoy a high perfomance
|
||||
boost. The reason is that, if CONFIG_DEBUG_BLK_CGROUP is not set, then
|
||||
BFQ has to update far fewer statistics, and, in particular, not the
|
||||
heaviest to update. To give an idea of the benefits, if
|
||||
CONFIG_DEBUG_BLK_CGROUP is not set, then, on an Intel i7-4850HQ, and
|
||||
with 8 threads doing random I/O in parallel on null_blk (configured
|
||||
with 0 latency), the throughput of BFQ grows from 310 to 400 KIOPS
|
||||
(+30%). We have measured similar or even much higher boosts with other
|
||||
CPUs: e.g., +45% with an ARM CortexTM-A53 Octa-core. Our results have
|
||||
been obtained and can be reproduced very easily with the script in [1].
|
||||
|
||||
[1] https://www.spinics.net/lists/linux-block/msg18943.html
|
||||
|
||||
Suggested-by: Tejun Heo <tj@kernel.org>
|
||||
Suggested-by: Ulf Hansson <ulf.hansson@linaro.org>
|
||||
Tested-by: Lee Tibbert <lee.tibbert@gmail.com>
|
||||
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
|
||||
Signed-off-by: Luca Miccio <lucmiccio@gmail.com>
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
Documentation/block/bfq-iosched.txt | 38 +++++++--
|
||||
block/bfq-cgroup.c | 148 ++++++++++++++++++++----------------
|
||||
block/bfq-iosched.c | 14 ++--
|
||||
block/bfq-iosched.h | 4 +-
|
||||
4 files changed, 125 insertions(+), 79 deletions(-)
|
||||
|
||||
diff --git a/Documentation/block/bfq-iosched.txt b/Documentation/block/bfq-iosched.txt
|
||||
index 7fad6c061470..8d8d8f06cab2 100644
|
||||
--- a/Documentation/block/bfq-iosched.txt
|
||||
+++ b/Documentation/block/bfq-iosched.txt
|
||||
@@ -20,12 +20,22 @@ for that device, by setting low_latency to 0. See Section 3 for
|
||||
details on how to configure BFQ for the desired tradeoff between
|
||||
latency and throughput, or on how to maximize throughput.
|
||||
|
||||
-BFQ has a non-null overhead, which limits the maximum IOPS that the
|
||||
-CPU can process for a device scheduled with BFQ. To give an idea of
|
||||
-the limits on slow or average CPUs, here are BFQ limits for three
|
||||
-different CPUs, on, respectively, an average laptop, an old desktop,
|
||||
-and a cheap embedded system, in case full hierarchical support is
|
||||
-enabled (i.e., CONFIG_BFQ_GROUP_IOSCHED is set):
|
||||
+BFQ has a non-null overhead, which limits the maximum IOPS that a CPU
|
||||
+can process for a device scheduled with BFQ. To give an idea of the
|
||||
+limits on slow or average CPUs, here are, first, the limits of BFQ for
|
||||
+three different CPUs, on, respectively, an average laptop, an old
|
||||
+desktop, and a cheap embedded system, in case full hierarchical
|
||||
+support is enabled (i.e., CONFIG_BFQ_GROUP_IOSCHED is set), but
|
||||
+CONFIG_DEBUG_BLK_CGROUP is not set (Section 4-2):
|
||||
+- Intel i7-4850HQ: 400 KIOPS
|
||||
+- AMD A8-3850: 250 KIOPS
|
||||
+- ARM CortexTM-A53 Octa-core: 80 KIOPS
|
||||
+
|
||||
+If CONFIG_DEBUG_BLK_CGROUP is set (and of course full hierarchical
|
||||
+support is enabled), then the sustainable throughput with BFQ
|
||||
+decreases, because all blkio.bfq* statistics are created and updated
|
||||
+(Section 4-2). For BFQ, this leads to the following maximum
|
||||
+sustainable throughputs, on the same systems as above:
|
||||
- Intel i7-4850HQ: 310 KIOPS
|
||||
- AMD A8-3850: 200 KIOPS
|
||||
- ARM CortexTM-A53 Octa-core: 56 KIOPS
|
||||
@@ -505,6 +515,22 @@ BFQ-specific files is "blkio.bfq." or "io.bfq." For example, the group
|
||||
parameter to set the weight of a group with BFQ is blkio.bfq.weight
|
||||
or io.bfq.weight.
|
||||
|
||||
+As for cgroups-v1 (blkio controller), the exact set of stat files
|
||||
+created, and kept up-to-date by bfq, depends on whether
|
||||
+CONFIG_DEBUG_BLK_CGROUP is set. If it is set, then bfq creates all
|
||||
+the stat files documented in
|
||||
+Documentation/cgroup-v1/blkio-controller.txt. If, instead,
|
||||
+CONFIG_DEBUG_BLK_CGROUP is not set, then bfq creates only the files
|
||||
+blkio.bfq.io_service_bytes
|
||||
+blkio.bfq.io_service_bytes_recursive
|
||||
+blkio.bfq.io_serviced
|
||||
+blkio.bfq.io_serviced_recursive
|
||||
+
|
||||
+The value of CONFIG_DEBUG_BLK_CGROUP greatly influences the maximum
|
||||
+throughput sustainable with bfq, because updating the blkio.bfq.*
|
||||
+stats is rather costly, especially for some of the stats enabled by
|
||||
+CONFIG_DEBUG_BLK_CGROUP.
|
||||
+
|
||||
Parameters to set
|
||||
-----------------
|
||||
|
||||
diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
|
||||
index ceefb9a706d6..da1525ec4c87 100644
|
||||
--- a/block/bfq-cgroup.c
|
||||
+++ b/block/bfq-cgroup.c
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include "bfq-iosched.h"
|
||||
|
||||
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
+#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
|
||||
|
||||
/* bfqg stats flags */
|
||||
enum bfqg_stats_flags {
|
||||
@@ -152,6 +152,57 @@ void bfqg_stats_update_avg_queue_size(struct bfq_group *bfqg)
|
||||
bfqg_stats_update_group_wait_time(stats);
|
||||
}
|
||||
|
||||
+void bfqg_stats_update_io_add(struct bfq_group *bfqg, struct bfq_queue *bfqq,
|
||||
+ unsigned int op)
|
||||
+{
|
||||
+ blkg_rwstat_add(&bfqg->stats.queued, op, 1);
|
||||
+ bfqg_stats_end_empty_time(&bfqg->stats);
|
||||
+ if (!(bfqq == ((struct bfq_data *)bfqg->bfqd)->in_service_queue))
|
||||
+ bfqg_stats_set_start_group_wait_time(bfqg, bfqq_group(bfqq));
|
||||
+}
|
||||
+
|
||||
+void bfqg_stats_update_io_remove(struct bfq_group *bfqg, unsigned int op)
|
||||
+{
|
||||
+ blkg_rwstat_add(&bfqg->stats.queued, op, -1);
|
||||
+}
|
||||
+
|
||||
+void bfqg_stats_update_io_merged(struct bfq_group *bfqg, unsigned int op)
|
||||
+{
|
||||
+ blkg_rwstat_add(&bfqg->stats.merged, op, 1);
|
||||
+}
|
||||
+
|
||||
+void bfqg_stats_update_completion(struct bfq_group *bfqg, uint64_t start_time,
|
||||
+ uint64_t io_start_time, unsigned int op)
|
||||
+{
|
||||
+ struct bfqg_stats *stats = &bfqg->stats;
|
||||
+ unsigned long long now = sched_clock();
|
||||
+
|
||||
+ if (time_after64(now, io_start_time))
|
||||
+ blkg_rwstat_add(&stats->service_time, op,
|
||||
+ now - io_start_time);
|
||||
+ if (time_after64(io_start_time, start_time))
|
||||
+ blkg_rwstat_add(&stats->wait_time, op,
|
||||
+ io_start_time - start_time);
|
||||
+}
|
||||
+
|
||||
+#else /* CONFIG_BFQ_GROUP_IOSCHED && CONFIG_DEBUG_BLK_CGROUP */
|
||||
+
|
||||
+void bfqg_stats_update_io_add(struct bfq_group *bfqg, struct bfq_queue *bfqq,
|
||||
+ unsigned int op) { }
|
||||
+void bfqg_stats_update_io_remove(struct bfq_group *bfqg, unsigned int op) { }
|
||||
+void bfqg_stats_update_io_merged(struct bfq_group *bfqg, unsigned int op) { }
|
||||
+void bfqg_stats_update_completion(struct bfq_group *bfqg, uint64_t start_time,
|
||||
+ uint64_t io_start_time, unsigned int op) { }
|
||||
+void bfqg_stats_update_dequeue(struct bfq_group *bfqg) { }
|
||||
+void bfqg_stats_set_start_empty_time(struct bfq_group *bfqg) { }
|
||||
+void bfqg_stats_update_idle_time(struct bfq_group *bfqg) { }
|
||||
+void bfqg_stats_set_start_idle_time(struct bfq_group *bfqg) { }
|
||||
+void bfqg_stats_update_avg_queue_size(struct bfq_group *bfqg) { }
|
||||
+
|
||||
+#endif /* CONFIG_BFQ_GROUP_IOSCHED && CONFIG_DEBUG_BLK_CGROUP */
|
||||
+
|
||||
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
+
|
||||
/*
|
||||
* blk-cgroup policy-related handlers
|
||||
* The following functions help in converting between blk-cgroup
|
||||
@@ -229,42 +280,10 @@ void bfqg_and_blkg_put(struct bfq_group *bfqg)
|
||||
blkg_put(bfqg_to_blkg(bfqg));
|
||||
}
|
||||
|
||||
-void bfqg_stats_update_io_add(struct bfq_group *bfqg, struct bfq_queue *bfqq,
|
||||
- unsigned int op)
|
||||
-{
|
||||
- blkg_rwstat_add(&bfqg->stats.queued, op, 1);
|
||||
- bfqg_stats_end_empty_time(&bfqg->stats);
|
||||
- if (!(bfqq == ((struct bfq_data *)bfqg->bfqd)->in_service_queue))
|
||||
- bfqg_stats_set_start_group_wait_time(bfqg, bfqq_group(bfqq));
|
||||
-}
|
||||
-
|
||||
-void bfqg_stats_update_io_remove(struct bfq_group *bfqg, unsigned int op)
|
||||
-{
|
||||
- blkg_rwstat_add(&bfqg->stats.queued, op, -1);
|
||||
-}
|
||||
-
|
||||
-void bfqg_stats_update_io_merged(struct bfq_group *bfqg, unsigned int op)
|
||||
-{
|
||||
- blkg_rwstat_add(&bfqg->stats.merged, op, 1);
|
||||
-}
|
||||
-
|
||||
-void bfqg_stats_update_completion(struct bfq_group *bfqg, uint64_t start_time,
|
||||
- uint64_t io_start_time, unsigned int op)
|
||||
-{
|
||||
- struct bfqg_stats *stats = &bfqg->stats;
|
||||
- unsigned long long now = sched_clock();
|
||||
-
|
||||
- if (time_after64(now, io_start_time))
|
||||
- blkg_rwstat_add(&stats->service_time, op,
|
||||
- now - io_start_time);
|
||||
- if (time_after64(io_start_time, start_time))
|
||||
- blkg_rwstat_add(&stats->wait_time, op,
|
||||
- io_start_time - start_time);
|
||||
-}
|
||||
-
|
||||
/* @stats = 0 */
|
||||
static void bfqg_stats_reset(struct bfqg_stats *stats)
|
||||
{
|
||||
+#ifdef CONFIG_DEBUG_BLK_CGROUP
|
||||
/* queued stats shouldn't be cleared */
|
||||
blkg_rwstat_reset(&stats->merged);
|
||||
blkg_rwstat_reset(&stats->service_time);
|
||||
@@ -276,6 +295,7 @@ static void bfqg_stats_reset(struct bfqg_stats *stats)
|
||||
blkg_stat_reset(&stats->group_wait_time);
|
||||
blkg_stat_reset(&stats->idle_time);
|
||||
blkg_stat_reset(&stats->empty_time);
|
||||
+#endif
|
||||
}
|
||||
|
||||
/* @to += @from */
|
||||
@@ -284,6 +304,7 @@ static void bfqg_stats_add_aux(struct bfqg_stats *to, struct bfqg_stats *from)
|
||||
if (!to || !from)
|
||||
return;
|
||||
|
||||
+#ifdef CONFIG_DEBUG_BLK_CGROUP
|
||||
/* queued stats shouldn't be cleared */
|
||||
blkg_rwstat_add_aux(&to->merged, &from->merged);
|
||||
blkg_rwstat_add_aux(&to->service_time, &from->service_time);
|
||||
@@ -296,6 +317,7 @@ static void bfqg_stats_add_aux(struct bfqg_stats *to, struct bfqg_stats *from)
|
||||
blkg_stat_add_aux(&to->group_wait_time, &from->group_wait_time);
|
||||
blkg_stat_add_aux(&to->idle_time, &from->idle_time);
|
||||
blkg_stat_add_aux(&to->empty_time, &from->empty_time);
|
||||
+#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -342,6 +364,7 @@ void bfq_init_entity(struct bfq_entity *entity, struct bfq_group *bfqg)
|
||||
|
||||
static void bfqg_stats_exit(struct bfqg_stats *stats)
|
||||
{
|
||||
+#ifdef CONFIG_DEBUG_BLK_CGROUP
|
||||
blkg_rwstat_exit(&stats->merged);
|
||||
blkg_rwstat_exit(&stats->service_time);
|
||||
blkg_rwstat_exit(&stats->wait_time);
|
||||
@@ -353,10 +376,12 @@ static void bfqg_stats_exit(struct bfqg_stats *stats)
|
||||
blkg_stat_exit(&stats->group_wait_time);
|
||||
blkg_stat_exit(&stats->idle_time);
|
||||
blkg_stat_exit(&stats->empty_time);
|
||||
+#endif
|
||||
}
|
||||
|
||||
static int bfqg_stats_init(struct bfqg_stats *stats, gfp_t gfp)
|
||||
{
|
||||
+#ifdef CONFIG_DEBUG_BLK_CGROUP
|
||||
if (blkg_rwstat_init(&stats->merged, gfp) ||
|
||||
blkg_rwstat_init(&stats->service_time, gfp) ||
|
||||
blkg_rwstat_init(&stats->wait_time, gfp) ||
|
||||
@@ -371,6 +396,7 @@ static int bfqg_stats_init(struct bfqg_stats *stats, gfp_t gfp)
|
||||
bfqg_stats_exit(stats);
|
||||
return -ENOMEM;
|
||||
}
|
||||
+#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -887,6 +913,7 @@ static ssize_t bfq_io_set_weight(struct kernfs_open_file *of,
|
||||
return bfq_io_set_weight_legacy(of_css(of), NULL, weight);
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_DEBUG_BLK_CGROUP
|
||||
static int bfqg_print_stat(struct seq_file *sf, void *v)
|
||||
{
|
||||
blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)), blkg_prfill_stat,
|
||||
@@ -991,6 +1018,7 @@ static int bfqg_print_avg_queue_size(struct seq_file *sf, void *v)
|
||||
0, false);
|
||||
return 0;
|
||||
}
|
||||
+#endif /* CONFIG_DEBUG_BLK_CGROUP */
|
||||
|
||||
struct bfq_group *bfq_create_group_hierarchy(struct bfq_data *bfqd, int node)
|
||||
{
|
||||
@@ -1028,15 +1056,6 @@ struct cftype bfq_blkcg_legacy_files[] = {
|
||||
},
|
||||
|
||||
/* statistics, covers only the tasks in the bfqg */
|
||||
- {
|
||||
- .name = "bfq.time",
|
||||
- .private = offsetof(struct bfq_group, stats.time),
|
||||
- .seq_show = bfqg_print_stat,
|
||||
- },
|
||||
- {
|
||||
- .name = "bfq.sectors",
|
||||
- .seq_show = bfqg_print_stat_sectors,
|
||||
- },
|
||||
{
|
||||
.name = "bfq.io_service_bytes",
|
||||
.private = (unsigned long)&blkcg_policy_bfq,
|
||||
@@ -1047,6 +1066,16 @@ struct cftype bfq_blkcg_legacy_files[] = {
|
||||
.private = (unsigned long)&blkcg_policy_bfq,
|
||||
.seq_show = blkg_print_stat_ios,
|
||||
},
|
||||
+#ifdef CONFIG_DEBUG_BLK_CGROUP
|
||||
+ {
|
||||
+ .name = "bfq.time",
|
||||
+ .private = offsetof(struct bfq_group, stats.time),
|
||||
+ .seq_show = bfqg_print_stat,
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "bfq.sectors",
|
||||
+ .seq_show = bfqg_print_stat_sectors,
|
||||
+ },
|
||||
{
|
||||
.name = "bfq.io_service_time",
|
||||
.private = offsetof(struct bfq_group, stats.service_time),
|
||||
@@ -1067,17 +1096,9 @@ struct cftype bfq_blkcg_legacy_files[] = {
|
||||
.private = offsetof(struct bfq_group, stats.queued),
|
||||
.seq_show = bfqg_print_rwstat,
|
||||
},
|
||||
+#endif /* CONFIG_DEBUG_BLK_CGROUP */
|
||||
|
||||
/* the same statictics which cover the bfqg and its descendants */
|
||||
- {
|
||||
- .name = "bfq.time_recursive",
|
||||
- .private = offsetof(struct bfq_group, stats.time),
|
||||
- .seq_show = bfqg_print_stat_recursive,
|
||||
- },
|
||||
- {
|
||||
- .name = "bfq.sectors_recursive",
|
||||
- .seq_show = bfqg_print_stat_sectors_recursive,
|
||||
- },
|
||||
{
|
||||
.name = "bfq.io_service_bytes_recursive",
|
||||
.private = (unsigned long)&blkcg_policy_bfq,
|
||||
@@ -1088,6 +1109,16 @@ struct cftype bfq_blkcg_legacy_files[] = {
|
||||
.private = (unsigned long)&blkcg_policy_bfq,
|
||||
.seq_show = blkg_print_stat_ios_recursive,
|
||||
},
|
||||
+#ifdef CONFIG_DEBUG_BLK_CGROUP
|
||||
+ {
|
||||
+ .name = "bfq.time_recursive",
|
||||
+ .private = offsetof(struct bfq_group, stats.time),
|
||||
+ .seq_show = bfqg_print_stat_recursive,
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "bfq.sectors_recursive",
|
||||
+ .seq_show = bfqg_print_stat_sectors_recursive,
|
||||
+ },
|
||||
{
|
||||
.name = "bfq.io_service_time_recursive",
|
||||
.private = offsetof(struct bfq_group, stats.service_time),
|
||||
@@ -1132,6 +1163,7 @@ struct cftype bfq_blkcg_legacy_files[] = {
|
||||
.private = offsetof(struct bfq_group, stats.dequeue),
|
||||
.seq_show = bfqg_print_stat,
|
||||
},
|
||||
+#endif /* CONFIG_DEBUG_BLK_CGROUP */
|
||||
{ } /* terminate */
|
||||
};
|
||||
|
||||
@@ -1147,18 +1179,6 @@ struct cftype bfq_blkg_files[] = {
|
||||
|
||||
#else /* CONFIG_BFQ_GROUP_IOSCHED */
|
||||
|
||||
-void bfqg_stats_update_io_add(struct bfq_group *bfqg, struct bfq_queue *bfqq,
|
||||
- unsigned int op) { }
|
||||
-void bfqg_stats_update_io_remove(struct bfq_group *bfqg, unsigned int op) { }
|
||||
-void bfqg_stats_update_io_merged(struct bfq_group *bfqg, unsigned int op) { }
|
||||
-void bfqg_stats_update_completion(struct bfq_group *bfqg, uint64_t start_time,
|
||||
- uint64_t io_start_time, unsigned int op) { }
|
||||
-void bfqg_stats_update_dequeue(struct bfq_group *bfqg) { }
|
||||
-void bfqg_stats_set_start_empty_time(struct bfq_group *bfqg) { }
|
||||
-void bfqg_stats_update_idle_time(struct bfq_group *bfqg) { }
|
||||
-void bfqg_stats_set_start_idle_time(struct bfq_group *bfqg) { }
|
||||
-void bfqg_stats_update_avg_queue_size(struct bfq_group *bfqg) { }
|
||||
-
|
||||
void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
struct bfq_group *bfqg) {}
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index 69e05f861daf..bcb6d21baf12 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -3693,14 +3693,14 @@ static struct request *bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
|
||||
{
|
||||
struct bfq_data *bfqd = hctx->queue->elevator->elevator_data;
|
||||
struct request *rq;
|
||||
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
+#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
|
||||
struct bfq_queue *in_serv_queue, *bfqq;
|
||||
bool waiting_rq, idle_timer_disabled;
|
||||
#endif
|
||||
|
||||
spin_lock_irq(&bfqd->lock);
|
||||
|
||||
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
+#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
|
||||
in_serv_queue = bfqd->in_service_queue;
|
||||
waiting_rq = in_serv_queue && bfq_bfqq_wait_request(in_serv_queue);
|
||||
|
||||
@@ -3714,7 +3714,7 @@ static struct request *bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
|
||||
#endif
|
||||
spin_unlock_irq(&bfqd->lock);
|
||||
|
||||
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
+#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
|
||||
bfqq = rq ? RQ_BFQQ(rq) : NULL;
|
||||
if (!idle_timer_disabled && !bfqq)
|
||||
return rq;
|
||||
@@ -4281,7 +4281,7 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
{
|
||||
struct request_queue *q = hctx->queue;
|
||||
struct bfq_data *bfqd = q->elevator->elevator_data;
|
||||
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
+#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
|
||||
struct bfq_queue *bfqq = RQ_BFQQ(rq);
|
||||
bool idle_timer_disabled = false;
|
||||
unsigned int cmd_flags;
|
||||
@@ -4304,7 +4304,7 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
else
|
||||
list_add_tail(&rq->queuelist, &bfqd->dispatch);
|
||||
} else {
|
||||
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
+#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
|
||||
idle_timer_disabled = __bfq_insert_request(bfqd, rq);
|
||||
/*
|
||||
* Update bfqq, because, if a queue merge has occurred
|
||||
@@ -4323,7 +4323,7 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
}
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
+#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
|
||||
/*
|
||||
* Cache cmd_flags before releasing scheduler lock, because rq
|
||||
* may disappear afterwards (for example, because of a request
|
||||
@@ -4333,7 +4333,7 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
#endif
|
||||
spin_unlock_irq(&bfqd->lock);
|
||||
|
||||
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
+#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
|
||||
if (!bfqq)
|
||||
return;
|
||||
/*
|
||||
diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h
|
||||
index ac0809c72c98..91c4390903a1 100644
|
||||
--- a/block/bfq-iosched.h
|
||||
+++ b/block/bfq-iosched.h
|
||||
@@ -689,7 +689,7 @@ enum bfqq_expiration {
|
||||
};
|
||||
|
||||
struct bfqg_stats {
|
||||
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
+#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
|
||||
/* number of ios merged */
|
||||
struct blkg_rwstat merged;
|
||||
/* total time spent on device in ns, may not be accurate w/ queueing */
|
||||
@@ -717,7 +717,7 @@ struct bfqg_stats {
|
||||
uint64_t start_idle_time;
|
||||
uint64_t start_empty_time;
|
||||
uint16_t flags;
|
||||
-#endif /* CONFIG_BFQ_GROUP_IOSCHED */
|
||||
+#endif /* CONFIG_BFQ_GROUP_IOSCHED && CONFIG_DEBUG_BLK_CGROUP */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
--
|
||||
2.15.1
|
||||
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
From 52257ffbfcaf58d247b13fb148e27ed17c33e526 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@linaro.org>
|
||||
Date: Tue, 9 Jan 2018 10:27:58 +0100
|
||||
Subject: [PATCH] block, bfq: put async queues for root bfq groups too
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
For each pair [device for which bfq is selected as I/O scheduler,
|
||||
group in blkio/io], bfq maintains a corresponding bfq group. Each such
|
||||
bfq group contains a set of async queues, with each async queue
|
||||
created on demand, i.e., when some I/O request arrives for it. On
|
||||
creation, an async queue gets an extra reference, to make sure that
|
||||
the queue is not freed as long as its bfq group exists. Accordingly,
|
||||
to allow the queue to be freed after the group exited, this extra
|
||||
reference must released on group exit.
|
||||
|
||||
The above holds also for a bfq root group, i.e., for the bfq group
|
||||
corresponding to the root blkio/io root for a given device. Yet, by
|
||||
mistake, the references to the existing async queues of a root group
|
||||
are not released when the latter exits. This causes a memory leak when
|
||||
the instance of bfq for a given device exits. In a similar vein,
|
||||
bfqg_stats_xfer_dead is not executed for a root group.
|
||||
|
||||
This commit fixes bfq_pd_offline so that the latter executes the above
|
||||
missing operations for a root group too.
|
||||
|
||||
Reported-by: Holger Hoffstätte <holger@applied-asynchrony.com>
|
||||
Reported-by: Guoqing Jiang <gqjiang@suse.com>
|
||||
Tested-by: Holger Hoffstätte <holger@applied-asynchrony.com>
|
||||
Signed-off-by: Davide Ferrari <davideferrari8@gmail.com>
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-cgroup.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
|
||||
index da1525ec4c87..d819dc77fe65 100644
|
||||
--- a/block/bfq-cgroup.c
|
||||
+++ b/block/bfq-cgroup.c
|
||||
@@ -775,10 +775,11 @@ static void bfq_pd_offline(struct blkg_policy_data *pd)
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
+ spin_lock_irqsave(&bfqd->lock, flags);
|
||||
+
|
||||
if (!entity) /* root group */
|
||||
- return;
|
||||
+ goto put_async_queues;
|
||||
|
||||
- spin_lock_irqsave(&bfqd->lock, flags);
|
||||
/*
|
||||
* Empty all service_trees belonging to this group before
|
||||
* deactivating the group itself.
|
||||
@@ -809,6 +810,8 @@ static void bfq_pd_offline(struct blkg_policy_data *pd)
|
||||
}
|
||||
|
||||
__bfq_deactivate_entity(entity, false);
|
||||
+
|
||||
+put_async_queues:
|
||||
bfq_put_async_queues(bfqd, bfqg);
|
||||
|
||||
spin_unlock_irqrestore(&bfqd->lock, flags);
|
||||
--
|
||||
2.16.1
|
||||
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
From 0d52af590552473666da5b6111e7182d6cd23f92 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@linaro.org>
|
||||
Date: Tue, 9 Jan 2018 10:27:59 +0100
|
||||
Subject: [PATCH] block, bfq: release oom-queue ref to root group on exit
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
On scheduler init, a reference to the root group, and a reference to
|
||||
its corresponding blkg are taken for the oom queue. Yet these
|
||||
references are not released on scheduler exit, which prevents these
|
||||
objects from be freed. This commit adds the missing reference
|
||||
releases.
|
||||
|
||||
Reported-by: Davide Ferrari <davideferrari8@gmail.com>
|
||||
Tested-by: Holger Hoffstätte <holger@applied-asynchrony.com>
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index 7bd789da7a29..7c0b7f60811c 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -4893,6 +4893,9 @@ static void bfq_exit_queue(struct elevator_queue *e)
|
||||
|
||||
hrtimer_cancel(&bfqd->idle_slice_timer);
|
||||
|
||||
+ /* release oom-queue reference to root group */
|
||||
+ bfqg_and_blkg_put(bfqd->root_group);
|
||||
+
|
||||
#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
blkcg_deactivate_policy(bfqd->queue, &blkcg_policy_bfq);
|
||||
#else
|
||||
--
|
||||
2.16.1
|
||||
|
||||
-225
@@ -1,225 +0,0 @@
|
||||
From 9b25bd0368d562d1929059e8eb9de4102567b923 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@linaro.org>
|
||||
Date: Mon, 4 Dec 2017 11:42:05 +0100
|
||||
Subject: [PATCH] block, bfq: remove batches of confusing ifdefs
|
||||
|
||||
Commit a33801e8b473 ("block, bfq: move debug blkio stats behind
|
||||
CONFIG_DEBUG_BLK_CGROUP") introduced two batches of confusing ifdefs:
|
||||
one reported in [1], plus a similar one in another function. This
|
||||
commit removes both batches, in the way suggested in [1].
|
||||
|
||||
[1] https://www.spinics.net/lists/linux-block/msg20043.html
|
||||
|
||||
Fixes: a33801e8b473 ("block, bfq: move debug blkio stats behind CONFIG_DEBUG_BLK_CGROUP")
|
||||
Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Tested-by: Luca Miccio <lucmiccio@gmail.com>
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 127 +++++++++++++++++++++++++++++-----------------------
|
||||
1 file changed, 72 insertions(+), 55 deletions(-)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index e33c5c4c9856..7bd789da7a29 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -3743,35 +3743,16 @@ static struct request *__bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
|
||||
return rq;
|
||||
}
|
||||
|
||||
-static struct request *bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
|
||||
-{
|
||||
- struct bfq_data *bfqd = hctx->queue->elevator->elevator_data;
|
||||
- struct request *rq;
|
||||
#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
|
||||
- struct bfq_queue *in_serv_queue, *bfqq;
|
||||
- bool waiting_rq, idle_timer_disabled;
|
||||
-#endif
|
||||
-
|
||||
- spin_lock_irq(&bfqd->lock);
|
||||
-
|
||||
-#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
|
||||
- in_serv_queue = bfqd->in_service_queue;
|
||||
- waiting_rq = in_serv_queue && bfq_bfqq_wait_request(in_serv_queue);
|
||||
-
|
||||
- rq = __bfq_dispatch_request(hctx);
|
||||
-
|
||||
- idle_timer_disabled =
|
||||
- waiting_rq && !bfq_bfqq_wait_request(in_serv_queue);
|
||||
-
|
||||
-#else
|
||||
- rq = __bfq_dispatch_request(hctx);
|
||||
-#endif
|
||||
- spin_unlock_irq(&bfqd->lock);
|
||||
+static void bfq_update_dispatch_stats(struct request_queue *q,
|
||||
+ struct request *rq,
|
||||
+ struct bfq_queue *in_serv_queue,
|
||||
+ bool idle_timer_disabled)
|
||||
+{
|
||||
+ struct bfq_queue *bfqq = rq ? RQ_BFQQ(rq) : NULL;
|
||||
|
||||
-#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
|
||||
- bfqq = rq ? RQ_BFQQ(rq) : NULL;
|
||||
if (!idle_timer_disabled && !bfqq)
|
||||
- return rq;
|
||||
+ return;
|
||||
|
||||
/*
|
||||
* rq and bfqq are guaranteed to exist until this function
|
||||
@@ -3786,7 +3767,7 @@ static struct request *bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
|
||||
* In addition, the following queue lock guarantees that
|
||||
* bfqq_group(bfqq) exists as well.
|
||||
*/
|
||||
- spin_lock_irq(hctx->queue->queue_lock);
|
||||
+ spin_lock_irq(q->queue_lock);
|
||||
if (idle_timer_disabled)
|
||||
/*
|
||||
* Since the idle timer has been disabled,
|
||||
@@ -3805,9 +3786,37 @@ static struct request *bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
|
||||
bfqg_stats_set_start_empty_time(bfqg);
|
||||
bfqg_stats_update_io_remove(bfqg, rq->cmd_flags);
|
||||
}
|
||||
- spin_unlock_irq(hctx->queue->queue_lock);
|
||||
+ spin_unlock_irq(q->queue_lock);
|
||||
+}
|
||||
+#else
|
||||
+static inline void bfq_update_dispatch_stats(struct request_queue *q,
|
||||
+ struct request *rq,
|
||||
+ struct bfq_queue *in_serv_queue,
|
||||
+ bool idle_timer_disabled) {}
|
||||
#endif
|
||||
|
||||
+static struct request *bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
|
||||
+{
|
||||
+ struct bfq_data *bfqd = hctx->queue->elevator->elevator_data;
|
||||
+ struct request *rq;
|
||||
+ struct bfq_queue *in_serv_queue;
|
||||
+ bool waiting_rq, idle_timer_disabled;
|
||||
+
|
||||
+ spin_lock_irq(&bfqd->lock);
|
||||
+
|
||||
+ in_serv_queue = bfqd->in_service_queue;
|
||||
+ waiting_rq = in_serv_queue && bfq_bfqq_wait_request(in_serv_queue);
|
||||
+
|
||||
+ rq = __bfq_dispatch_request(hctx);
|
||||
+
|
||||
+ idle_timer_disabled =
|
||||
+ waiting_rq && !bfq_bfqq_wait_request(in_serv_queue);
|
||||
+
|
||||
+ spin_unlock_irq(&bfqd->lock);
|
||||
+
|
||||
+ bfq_update_dispatch_stats(hctx->queue, rq, in_serv_queue,
|
||||
+ idle_timer_disabled);
|
||||
+
|
||||
return rq;
|
||||
}
|
||||
|
||||
@@ -4335,16 +4344,46 @@ static bool __bfq_insert_request(struct bfq_data *bfqd, struct request *rq)
|
||||
return idle_timer_disabled;
|
||||
}
|
||||
|
||||
+#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
|
||||
+static void bfq_update_insert_stats(struct request_queue *q,
|
||||
+ struct bfq_queue *bfqq,
|
||||
+ bool idle_timer_disabled,
|
||||
+ unsigned int cmd_flags)
|
||||
+{
|
||||
+ if (!bfqq)
|
||||
+ return;
|
||||
+
|
||||
+ /*
|
||||
+ * bfqq still exists, because it can disappear only after
|
||||
+ * either it is merged with another queue, or the process it
|
||||
+ * is associated with exits. But both actions must be taken by
|
||||
+ * the same process currently executing this flow of
|
||||
+ * instructions.
|
||||
+ *
|
||||
+ * In addition, the following queue lock guarantees that
|
||||
+ * bfqq_group(bfqq) exists as well.
|
||||
+ */
|
||||
+ spin_lock_irq(q->queue_lock);
|
||||
+ bfqg_stats_update_io_add(bfqq_group(bfqq), bfqq, cmd_flags);
|
||||
+ if (idle_timer_disabled)
|
||||
+ bfqg_stats_update_idle_time(bfqq_group(bfqq));
|
||||
+ spin_unlock_irq(q->queue_lock);
|
||||
+}
|
||||
+#else
|
||||
+static inline void bfq_update_insert_stats(struct request_queue *q,
|
||||
+ struct bfq_queue *bfqq,
|
||||
+ bool idle_timer_disabled,
|
||||
+ unsigned int cmd_flags) {}
|
||||
+#endif
|
||||
+
|
||||
static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
bool at_head)
|
||||
{
|
||||
struct request_queue *q = hctx->queue;
|
||||
struct bfq_data *bfqd = q->elevator->elevator_data;
|
||||
-#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
|
||||
struct bfq_queue *bfqq = RQ_BFQQ(rq);
|
||||
bool idle_timer_disabled = false;
|
||||
unsigned int cmd_flags;
|
||||
-#endif
|
||||
|
||||
spin_lock_irq(&bfqd->lock);
|
||||
if (blk_mq_sched_try_insert_merge(q, rq)) {
|
||||
@@ -4363,7 +4402,6 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
else
|
||||
list_add_tail(&rq->queuelist, &bfqd->dispatch);
|
||||
} else {
|
||||
-#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
|
||||
idle_timer_disabled = __bfq_insert_request(bfqd, rq);
|
||||
/*
|
||||
* Update bfqq, because, if a queue merge has occurred
|
||||
@@ -4371,9 +4409,6 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
* redirected into a new queue.
|
||||
*/
|
||||
bfqq = RQ_BFQQ(rq);
|
||||
-#else
|
||||
- __bfq_insert_request(bfqd, rq);
|
||||
-#endif
|
||||
|
||||
if (rq_mergeable(rq)) {
|
||||
elv_rqhash_add(q, rq);
|
||||
@@ -4382,35 +4417,17 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
}
|
||||
}
|
||||
|
||||
-#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
|
||||
/*
|
||||
* Cache cmd_flags before releasing scheduler lock, because rq
|
||||
* may disappear afterwards (for example, because of a request
|
||||
* merge).
|
||||
*/
|
||||
cmd_flags = rq->cmd_flags;
|
||||
-#endif
|
||||
+
|
||||
spin_unlock_irq(&bfqd->lock);
|
||||
|
||||
-#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
|
||||
- if (!bfqq)
|
||||
- return;
|
||||
- /*
|
||||
- * bfqq still exists, because it can disappear only after
|
||||
- * either it is merged with another queue, or the process it
|
||||
- * is associated with exits. But both actions must be taken by
|
||||
- * the same process currently executing this flow of
|
||||
- * instruction.
|
||||
- *
|
||||
- * In addition, the following queue lock guarantees that
|
||||
- * bfqq_group(bfqq) exists as well.
|
||||
- */
|
||||
- spin_lock_irq(q->queue_lock);
|
||||
- bfqg_stats_update_io_add(bfqq_group(bfqq), bfqq, cmd_flags);
|
||||
- if (idle_timer_disabled)
|
||||
- bfqg_stats_update_idle_time(bfqq_group(bfqq));
|
||||
- spin_unlock_irq(q->queue_lock);
|
||||
-#endif
|
||||
+ bfq_update_insert_stats(q, bfqq, idle_timer_disabled,
|
||||
+ cmd_flags);
|
||||
}
|
||||
|
||||
static void bfq_insert_requests(struct blk_mq_hw_ctx *hctx,
|
||||
--
|
||||
2.15.1
|
||||
|
||||
-112
@@ -1,112 +0,0 @@
|
||||
From 4403e4e467c365b4189e3e3d3ad35cf67b8c36ed Mon Sep 17 00:00:00 2001
|
||||
From: Angelo Ruocco <angeloruocco90@gmail.com>
|
||||
Date: Wed, 20 Dec 2017 12:38:34 +0100
|
||||
Subject: [PATCH] block, bfq: remove superfluous check in queue-merging setup
|
||||
|
||||
When two or more processes do I/O in a way that the their requests are
|
||||
sequential in respect to one another, BFQ merges the bfq_queues associated
|
||||
with the processes. This way the overall I/O pattern becomes sequential,
|
||||
and thus there is a boost in througput.
|
||||
These cooperating processes usually start or restart to do I/O shortly
|
||||
after each other. So, in order to avoid merging non-cooperating processes,
|
||||
BFQ ensures that none of these queues has been in weight raising for too
|
||||
long.
|
||||
|
||||
In this respect, from commit "block, bfq-sq, bfq-mq: let a queue be merged
|
||||
only shortly after being created", BFQ checks whether any queue (and not
|
||||
only weight-raised ones) is doing I/O continuously from too long to be
|
||||
merged.
|
||||
|
||||
This new additional check makes the first one useless: a queue doing
|
||||
I/O from long enough, if being weight-raised, is also a queue in
|
||||
weight raising for too long to be merged. Accordingly, this commit
|
||||
removes the first check.
|
||||
|
||||
Signed-off-by: Angelo Ruocco <angeloruocco90@gmail.com>
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.com>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/bfq-iosched.c | 36 +++++-------------------------------
|
||||
1 file changed, 5 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index 7066d90f09df..9625550b2f85 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -1990,20 +1990,6 @@ static bool bfq_may_be_close_cooperator(struct bfq_queue *bfqq,
|
||||
return true;
|
||||
}
|
||||
|
||||
-/*
|
||||
- * If this function returns true, then bfqq cannot be merged. The idea
|
||||
- * is that true cooperation happens very early after processes start
|
||||
- * to do I/O. Usually, late cooperations are just accidental false
|
||||
- * positives. In case bfqq is weight-raised, such false positives
|
||||
- * would evidently degrade latency guarantees for bfqq.
|
||||
- */
|
||||
-static bool wr_from_too_long(struct bfq_queue *bfqq)
|
||||
-{
|
||||
- return bfqq->wr_coeff > 1 &&
|
||||
- time_is_before_jiffies(bfqq->last_wr_start_finish +
|
||||
- msecs_to_jiffies(100));
|
||||
-}
|
||||
-
|
||||
/*
|
||||
* Attempt to schedule a merge of bfqq with the currently in-service
|
||||
* queue or with a close queue among the scheduled queues. Return
|
||||
@@ -2017,11 +2003,6 @@ static bool wr_from_too_long(struct bfq_queue *bfqq)
|
||||
* to maintain. Besides, in such a critical condition as an out of memory,
|
||||
* the benefits of queue merging may be little relevant, or even negligible.
|
||||
*
|
||||
- * Weight-raised queues can be merged only if their weight-raising
|
||||
- * period has just started. In fact cooperating processes are usually
|
||||
- * started together. Thus, with this filter we avoid false positives
|
||||
- * that would jeopardize low-latency guarantees.
|
||||
- *
|
||||
* WARNING: queue merging may impair fairness among non-weight raised
|
||||
* queues, for at least two reasons: 1) the original weight of a
|
||||
* merged queue may change during the merged state, 2) even being the
|
||||
@@ -2052,9 +2033,7 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
if (bfqq->new_bfqq)
|
||||
return bfqq->new_bfqq;
|
||||
|
||||
- if (!io_struct ||
|
||||
- wr_from_too_long(bfqq) ||
|
||||
- unlikely(bfqq == &bfqd->oom_bfqq))
|
||||
+ if (!io_struct || unlikely(bfqq == &bfqd->oom_bfqq))
|
||||
return NULL;
|
||||
|
||||
/* If there is only one backlogged queue, don't search. */
|
||||
@@ -2063,12 +2042,9 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
|
||||
in_service_bfqq = bfqd->in_service_queue;
|
||||
|
||||
- if (!in_service_bfqq || in_service_bfqq == bfqq
|
||||
- || wr_from_too_long(in_service_bfqq) ||
|
||||
- unlikely(in_service_bfqq == &bfqd->oom_bfqq))
|
||||
- goto check_scheduled;
|
||||
-
|
||||
- if (bfq_rq_close_to_sector(io_struct, request, bfqd->last_position) &&
|
||||
+ if (in_service_bfqq && in_service_bfqq != bfqq &&
|
||||
+ likely(in_service_bfqq != &bfqd->oom_bfqq) &&
|
||||
+ bfq_rq_close_to_sector(io_struct, request, bfqd->last_position) &&
|
||||
bfqq->entity.parent == in_service_bfqq->entity.parent &&
|
||||
bfq_may_be_close_cooperator(bfqq, in_service_bfqq)) {
|
||||
new_bfqq = bfq_setup_merge(bfqq, in_service_bfqq);
|
||||
@@ -2080,12 +2056,10 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
* queues. The only thing we need is that the bio/request is not
|
||||
* NULL, as we need it to establish whether a cooperator exists.
|
||||
*/
|
||||
-check_scheduled:
|
||||
new_bfqq = bfq_find_close_cooperator(bfqd, bfqq,
|
||||
bfq_io_struct_pos(io_struct, request));
|
||||
|
||||
- if (new_bfqq && !wr_from_too_long(new_bfqq) &&
|
||||
- likely(new_bfqq != &bfqd->oom_bfqq) &&
|
||||
+ if (new_bfqq && likely(new_bfqq != &bfqd->oom_bfqq) &&
|
||||
bfq_may_be_close_cooperator(bfqq, new_bfqq))
|
||||
return bfq_setup_merge(bfqq, new_bfqq);
|
||||
|
||||
--
|
||||
2.15.1
|
||||
|
||||
-283
@@ -1,283 +0,0 @@
|
||||
From 24bfd19bb7890255693ee5cb6dc100d8d215d00b Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@linaro.org>
|
||||
Date: Mon, 13 Nov 2017 07:34:09 +0100
|
||||
Subject: [PATCH] block, bfq: update blkio stats outside the scheduler lock
|
||||
|
||||
bfq invokes various blkg_*stats_* functions to update the statistics
|
||||
contained in the special files blkio.bfq.* in the blkio controller
|
||||
groups, i.e., the I/O accounting related to the proportional-share
|
||||
policy provided by bfq. The execution of these functions takes a
|
||||
considerable percentage, about 40%, of the total per-request execution
|
||||
time of bfq (i.e., of the sum of the execution time of all the bfq
|
||||
functions that have to be executed to process an I/O request from its
|
||||
creation to its destruction). This reduces the request-processing
|
||||
rate sustainable by bfq noticeably, even on a multicore CPU. In fact,
|
||||
the bfq functions that invoke blkg_*stats_* functions cannot be
|
||||
executed in parallel with the rest of the code of bfq, because both
|
||||
are executed under the same same per-device scheduler lock.
|
||||
|
||||
To reduce this slowdown, this commit moves, wherever possible, the
|
||||
invocation of these functions (more precisely, of the bfq functions
|
||||
that invoke blkg_*stats_* functions) outside the critical sections
|
||||
protected by the scheduler lock.
|
||||
|
||||
With this change, and with all blkio.bfq.* statistics enabled, the
|
||||
throughput grows, e.g., from 250 to 310 KIOPS (+25%) on an Intel
|
||||
i7-4850HQ, in case of 8 threads doing random I/O in parallel on
|
||||
null_blk, with the latter configured with 0 latency. We obtained the
|
||||
same or higher throughput boosts, up to +30%, with other processors
|
||||
(some figures are reported in the documentation). For our tests, we
|
||||
used the script [1], with which our results can be easily reproduced.
|
||||
|
||||
NOTE. This commit still protects the invocation of blkg_*stats_*
|
||||
functions with the request_queue lock, because the group these
|
||||
functions are invoked on may otherwise disappear before or while these
|
||||
functions are executed. Fortunately, tests without even this lock
|
||||
show, by difference, that the serialization caused by this lock has a
|
||||
little impact (at most ~5% of throughput reduction).
|
||||
|
||||
[1] https://github.com/Algodev-github/IOSpeed
|
||||
|
||||
Tested-by: Lee Tibbert <lee.tibbert@gmail.com>
|
||||
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Luca Miccio <lucmiccio@gmail.com>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
Documentation/block/bfq-iosched.txt | 6 +-
|
||||
block/bfq-iosched.c | 110 ++++++++++++++++++++++++++++++++----
|
||||
block/bfq-wf2q.c | 1 -
|
||||
3 files changed, 102 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/Documentation/block/bfq-iosched.txt b/Documentation/block/bfq-iosched.txt
|
||||
index 7a9361508157..7fad6c061470 100644
|
||||
--- a/Documentation/block/bfq-iosched.txt
|
||||
+++ b/Documentation/block/bfq-iosched.txt
|
||||
@@ -26,9 +26,9 @@ the limits on slow or average CPUs, here are BFQ limits for three
|
||||
different CPUs, on, respectively, an average laptop, an old desktop,
|
||||
and a cheap embedded system, in case full hierarchical support is
|
||||
enabled (i.e., CONFIG_BFQ_GROUP_IOSCHED is set):
|
||||
-- Intel i7-4850HQ: 250 KIOPS
|
||||
-- AMD A8-3850: 170 KIOPS
|
||||
-- ARM CortexTM-A53 Octa-core: 45 KIOPS
|
||||
+- Intel i7-4850HQ: 310 KIOPS
|
||||
+- AMD A8-3850: 200 KIOPS
|
||||
+- ARM CortexTM-A53 Octa-core: 56 KIOPS
|
||||
|
||||
BFQ works for multi-queue devices too.
|
||||
|
||||
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
||||
index 91703eba63f0..69e05f861daf 100644
|
||||
--- a/block/bfq-iosched.c
|
||||
+++ b/block/bfq-iosched.c
|
||||
@@ -2228,7 +2228,6 @@ static void __bfq_set_in_service_queue(struct bfq_data *bfqd,
|
||||
struct bfq_queue *bfqq)
|
||||
{
|
||||
if (bfqq) {
|
||||
- bfqg_stats_update_avg_queue_size(bfqq_group(bfqq));
|
||||
bfq_clear_bfqq_fifo_expire(bfqq);
|
||||
|
||||
bfqd->budgets_assigned = (bfqd->budgets_assigned * 7 + 256) / 8;
|
||||
@@ -3469,7 +3468,6 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd)
|
||||
*/
|
||||
bfq_clear_bfqq_wait_request(bfqq);
|
||||
hrtimer_try_to_cancel(&bfqd->idle_slice_timer);
|
||||
- bfqg_stats_update_idle_time(bfqq_group(bfqq));
|
||||
}
|
||||
goto keep_queue;
|
||||
}
|
||||
@@ -3695,15 +3693,67 @@ static struct request *bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
|
||||
{
|
||||
struct bfq_data *bfqd = hctx->queue->elevator->elevator_data;
|
||||
struct request *rq;
|
||||
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
+ struct bfq_queue *in_serv_queue, *bfqq;
|
||||
+ bool waiting_rq, idle_timer_disabled;
|
||||
+#endif
|
||||
|
||||
spin_lock_irq(&bfqd->lock);
|
||||
|
||||
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
+ in_serv_queue = bfqd->in_service_queue;
|
||||
+ waiting_rq = in_serv_queue && bfq_bfqq_wait_request(in_serv_queue);
|
||||
+
|
||||
+ rq = __bfq_dispatch_request(hctx);
|
||||
+
|
||||
+ idle_timer_disabled =
|
||||
+ waiting_rq && !bfq_bfqq_wait_request(in_serv_queue);
|
||||
+
|
||||
+#else
|
||||
rq = __bfq_dispatch_request(hctx);
|
||||
- if (rq && RQ_BFQQ(rq))
|
||||
- bfqg_stats_update_io_remove(bfqq_group(RQ_BFQQ(rq)),
|
||||
- rq->cmd_flags);
|
||||
+#endif
|
||||
spin_unlock_irq(&bfqd->lock);
|
||||
|
||||
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
+ bfqq = rq ? RQ_BFQQ(rq) : NULL;
|
||||
+ if (!idle_timer_disabled && !bfqq)
|
||||
+ return rq;
|
||||
+
|
||||
+ /*
|
||||
+ * rq and bfqq are guaranteed to exist until this function
|
||||
+ * ends, for the following reasons. First, rq can be
|
||||
+ * dispatched to the device, and then can be completed and
|
||||
+ * freed, only after this function ends. Second, rq cannot be
|
||||
+ * merged (and thus freed because of a merge) any longer,
|
||||
+ * because it has already started. Thus rq cannot be freed
|
||||
+ * before this function ends, and, since rq has a reference to
|
||||
+ * bfqq, the same guarantee holds for bfqq too.
|
||||
+ *
|
||||
+ * In addition, the following queue lock guarantees that
|
||||
+ * bfqq_group(bfqq) exists as well.
|
||||
+ */
|
||||
+ spin_lock_irq(hctx->queue->queue_lock);
|
||||
+ if (idle_timer_disabled)
|
||||
+ /*
|
||||
+ * Since the idle timer has been disabled,
|
||||
+ * in_serv_queue contained some request when
|
||||
+ * __bfq_dispatch_request was invoked above, which
|
||||
+ * implies that rq was picked exactly from
|
||||
+ * in_serv_queue. Thus in_serv_queue == bfqq, and is
|
||||
+ * therefore guaranteed to exist because of the above
|
||||
+ * arguments.
|
||||
+ */
|
||||
+ bfqg_stats_update_idle_time(bfqq_group(in_serv_queue));
|
||||
+ if (bfqq) {
|
||||
+ struct bfq_group *bfqg = bfqq_group(bfqq);
|
||||
+
|
||||
+ bfqg_stats_update_avg_queue_size(bfqg);
|
||||
+ bfqg_stats_set_start_empty_time(bfqg);
|
||||
+ bfqg_stats_update_io_remove(bfqg, rq->cmd_flags);
|
||||
+ }
|
||||
+ spin_unlock_irq(hctx->queue->queue_lock);
|
||||
+#endif
|
||||
+
|
||||
return rq;
|
||||
}
|
||||
|
||||
@@ -4161,7 +4211,6 @@ static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
*/
|
||||
bfq_clear_bfqq_wait_request(bfqq);
|
||||
hrtimer_try_to_cancel(&bfqd->idle_slice_timer);
|
||||
- bfqg_stats_update_idle_time(bfqq_group(bfqq));
|
||||
|
||||
/*
|
||||
* The queue is not empty, because a new request just
|
||||
@@ -4176,10 +4225,12 @@ static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
}
|
||||
}
|
||||
|
||||
-static void __bfq_insert_request(struct bfq_data *bfqd, struct request *rq)
|
||||
+/* returns true if it causes the idle timer to be disabled */
|
||||
+static bool __bfq_insert_request(struct bfq_data *bfqd, struct request *rq)
|
||||
{
|
||||
struct bfq_queue *bfqq = RQ_BFQQ(rq),
|
||||
*new_bfqq = bfq_setup_cooperator(bfqd, bfqq, rq, true);
|
||||
+ bool waiting, idle_timer_disabled = false;
|
||||
|
||||
if (new_bfqq) {
|
||||
if (bic_to_bfqq(RQ_BIC(rq), 1) != bfqq)
|
||||
@@ -4213,12 +4264,16 @@ static void __bfq_insert_request(struct bfq_data *bfqd, struct request *rq)
|
||||
bfqq = new_bfqq;
|
||||
}
|
||||
|
||||
+ waiting = bfqq && bfq_bfqq_wait_request(bfqq);
|
||||
bfq_add_request(rq);
|
||||
+ idle_timer_disabled = waiting && !bfq_bfqq_wait_request(bfqq);
|
||||
|
||||
rq->fifo_time = ktime_get_ns() + bfqd->bfq_fifo_expire[rq_is_sync(rq)];
|
||||
list_add_tail(&rq->queuelist, &bfqq->fifo);
|
||||
|
||||
bfq_rq_enqueued(bfqd, bfqq, rq);
|
||||
+
|
||||
+ return idle_timer_disabled;
|
||||
}
|
||||
|
||||
static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
@@ -4226,7 +4281,11 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
{
|
||||
struct request_queue *q = hctx->queue;
|
||||
struct bfq_data *bfqd = q->elevator->elevator_data;
|
||||
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
struct bfq_queue *bfqq = RQ_BFQQ(rq);
|
||||
+ bool idle_timer_disabled = false;
|
||||
+ unsigned int cmd_flags;
|
||||
+#endif
|
||||
|
||||
spin_lock_irq(&bfqd->lock);
|
||||
if (blk_mq_sched_try_insert_merge(q, rq)) {
|
||||
@@ -4245,13 +4304,17 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
else
|
||||
list_add_tail(&rq->queuelist, &bfqd->dispatch);
|
||||
} else {
|
||||
- __bfq_insert_request(bfqd, rq);
|
||||
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
+ idle_timer_disabled = __bfq_insert_request(bfqd, rq);
|
||||
/*
|
||||
* Update bfqq, because, if a queue merge has occurred
|
||||
* in __bfq_insert_request, then rq has been
|
||||
* redirected into a new queue.
|
||||
*/
|
||||
bfqq = RQ_BFQQ(rq);
|
||||
+#else
|
||||
+ __bfq_insert_request(bfqd, rq);
|
||||
+#endif
|
||||
|
||||
if (rq_mergeable(rq)) {
|
||||
elv_rqhash_add(q, rq);
|
||||
@@ -4260,10 +4323,35 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
}
|
||||
}
|
||||
|
||||
- if (bfqq)
|
||||
- bfqg_stats_update_io_add(bfqq_group(bfqq), bfqq, rq->cmd_flags);
|
||||
-
|
||||
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
+ /*
|
||||
+ * Cache cmd_flags before releasing scheduler lock, because rq
|
||||
+ * may disappear afterwards (for example, because of a request
|
||||
+ * merge).
|
||||
+ */
|
||||
+ cmd_flags = rq->cmd_flags;
|
||||
+#endif
|
||||
spin_unlock_irq(&bfqd->lock);
|
||||
+
|
||||
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
+ if (!bfqq)
|
||||
+ return;
|
||||
+ /*
|
||||
+ * bfqq still exists, because it can disappear only after
|
||||
+ * either it is merged with another queue, or the process it
|
||||
+ * is associated with exits. But both actions must be taken by
|
||||
+ * the same process currently executing this flow of
|
||||
+ * instruction.
|
||||
+ *
|
||||
+ * In addition, the following queue lock guarantees that
|
||||
+ * bfqq_group(bfqq) exists as well.
|
||||
+ */
|
||||
+ spin_lock_irq(q->queue_lock);
|
||||
+ bfqg_stats_update_io_add(bfqq_group(bfqq), bfqq, cmd_flags);
|
||||
+ if (idle_timer_disabled)
|
||||
+ bfqg_stats_update_idle_time(bfqq_group(bfqq));
|
||||
+ spin_unlock_irq(q->queue_lock);
|
||||
+#endif
|
||||
}
|
||||
|
||||
static void bfq_insert_requests(struct blk_mq_hw_ctx *hctx,
|
||||
diff --git a/block/bfq-wf2q.c b/block/bfq-wf2q.c
|
||||
index 414ba686a847..e495d3f9b4b0 100644
|
||||
--- a/block/bfq-wf2q.c
|
||||
+++ b/block/bfq-wf2q.c
|
||||
@@ -843,7 +843,6 @@ void bfq_bfqq_served(struct bfq_queue *bfqq, int served)
|
||||
st->vtime += bfq_delta(served, st->wsum);
|
||||
bfq_forget_idle(st);
|
||||
}
|
||||
- bfqg_stats_set_start_empty_time(bfqq_group(bfqq));
|
||||
bfq_log_bfqq(bfqq->bfqd, bfqq, "bfqq_served %d secs", served);
|
||||
}
|
||||
|
||||
--
|
||||
2.15.1
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
|
||||
Disable floppy autoloading as it makes systems without real hw,
|
||||
but that has the pnp headers hang.
|
||||
|
||||
See https://bugs.mageia.org/show_bug.cgi?id=4696
|
||||
|
||||
Signed-off-by: Thomas Backlund <tmb@mageia.org>
|
||||
|
||||
diff -Nurp linux-3.3.3-rc1/drivers/block/floppy.c.orig linux-3.3.3-rc1/drivers/block/floppy.c
|
||||
--- linux-3.3.3-rc1/drivers/block/floppy.c.orig 2012-03-19 01:15:34.000000000 +0200
|
||||
+++ linux-3.3.3-rc1/drivers/block/floppy.c 2012-04-22 02:58:10.238498303 +0300
|
||||
@@ -4621,8 +4621,7 @@ static const struct pnp_device_id floppy
|
||||
{"PNP0700", 0},
|
||||
{}
|
||||
};
|
||||
-
|
||||
-MODULE_DEVICE_TABLE(pnp, floppy_pnpids);
|
||||
+/* MODULE_DEVICE_TABLE(pnp, floppy_pnpids); */
|
||||
|
||||
#else
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
|
||||
agp/intel: add new host bridge id for Q57 system
|
||||
|
||||
Add new Host Bridge ID found on a Q57 based system from Positivo. I
|
||||
don't know what abbreviation id for this would be best, may be Q_HB
|
||||
instead of UNKNOWN currently used would be better.
|
||||
|
||||
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
|
||||
|
||||
[ rebased for 3.8-rc3 /tmb ]
|
||||
Signed-off-by: Thomas Backlund <tmb@mageia.org>
|
||||
|
||||
Removed the parts of the patch that are already applied in the kernel by
|
||||
the commit 67384fe3fd450536342330f684ea1f7dcaef8130:
|
||||
"char/agp: add another Ironlake host bridge"
|
||||
|
||||
Rediffed for kernel 3.10.24.
|
||||
|
||||
Signed-off-by: Eugene A. Shatokhin <eugene.shatokhin@rosalab.ru>
|
||||
|
||||
drivers/char/agp/intel-gtt.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff -Nurp linux-3.8-rc3/drivers/char/agp/intel-gtt.c linux-3.8-rc3.q57/drivers/char/agp/intel-gtt.c
|
||||
--- linux-3.8-rc3/drivers/char/agp/intel-gtt.c 2013-01-10 08:17:09.690594184 +0200
|
||||
+++ linux-3.8-rc3.q57/drivers/char/agp/intel-gtt.c 2013-01-10 08:38:56.649888839 +0200
|
||||
@@ -1303,6 +1303,8 @@ static const struct intel_gtt_driver_des
|
||||
&g4x_gtt_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG,
|
||||
"HD Graphics", &ironlake_gtt_driver },
|
||||
+ { PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB,
|
||||
+ "HD Graphics", &ironlake_gtt_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
|
||||
"HD Graphics", &ironlake_gtt_driver },
|
||||
{ 0, NULL, NULL }
|
||||
@@ -1,74 +0,0 @@
|
||||
|
||||
Makefile | 18 +++++-------------
|
||||
scripts/kconfig/Makefile | 4 ----
|
||||
2 files changed, 5 insertions(+), 17 deletions(-)
|
||||
|
||||
diff -Nurp linux-5.4.orig/Makefile linux-5.4/Makefile
|
||||
--- linux-5.4.orig/Makefile 2019-11-30 23:06:49.394199628 +0200
|
||||
+++ linux-5.4/Makefile 2019-11-30 23:08:00.927203318 +0200
|
||||
@@ -1093,8 +1093,7 @@ include/config/kernel.release: FORCE
|
||||
# Carefully list dependencies so we do not try to build scripts twice
|
||||
# in parallel
|
||||
PHONY += scripts
|
||||
-scripts: scripts_basic scripts_dtc
|
||||
- $(Q)$(MAKE) $(build)=$(@)
|
||||
+scripts:
|
||||
|
||||
# Things we need to do before we recursively start building the kernel
|
||||
# or the modules are listed in "prepare".
|
||||
@@ -1112,7 +1111,7 @@ prepare0: archprepare
|
||||
$(Q)$(MAKE) $(build)=.
|
||||
|
||||
# All the preparing..
|
||||
-prepare: prepare0 prepare-objtool
|
||||
+prepare:
|
||||
|
||||
# Support for using generic headers in asm-generic
|
||||
asm-generic := -f $(srctree)/scripts/Makefile.asm-generic obj
|
||||
@@ -1363,15 +1362,8 @@ CLEAN_DIRS += include/ksym
|
||||
CLEAN_FILES += modules.builtin.modinfo
|
||||
|
||||
# Directories & files removed with 'make mrproper'
|
||||
-MRPROPER_DIRS += include/config include/generated \
|
||||
- arch/$(SRCARCH)/include/generated .tmp_objdiff \
|
||||
- debian/ snap/ tar-install/
|
||||
-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
|
||||
+MRPROPER_DIRS += ""
|
||||
+MRPROPER_FILES += ""
|
||||
|
||||
# Directories & files removed with 'make distclean'
|
||||
DISTCLEAN_DIRS +=
|
||||
@@ -1394,7 +1386,7 @@ clean: archclean vmlinuxclean
|
||||
#
|
||||
mrproper: rm-dirs := $(wildcard $(MRPROPER_DIRS))
|
||||
mrproper: rm-files := $(wildcard $(MRPROPER_FILES))
|
||||
-mrproper-dirs := $(addprefix _mrproper_,scripts)
|
||||
+mrproper-dirs := $(addprefix _mrproper_,scripts)
|
||||
|
||||
PHONY += $(mrproper-dirs) mrproper
|
||||
$(mrproper-dirs):
|
||||
diff -Nurp linux-5.4.orig/scripts/kconfig/Makefile linux-5.4/scripts/kconfig/Makefile
|
||||
--- linux-5.4.orig/scripts/kconfig/Makefile 2019-11-25 02:32:01.000000000 +0200
|
||||
+++ linux-5.4/scripts/kconfig/Makefile 2019-11-30 23:07:24.957201462 +0200
|
||||
@@ -24,16 +24,12 @@ endif
|
||||
unexport CONFIG_
|
||||
|
||||
xconfig: $(obj)/qconf
|
||||
- $< $(silent) $(Kconfig)
|
||||
|
||||
gconfig: $(obj)/gconf
|
||||
- $< $(silent) $(Kconfig)
|
||||
|
||||
menuconfig: $(obj)/mconf
|
||||
- $< $(silent) $(Kconfig)
|
||||
|
||||
config: $(obj)/conf
|
||||
- $< $(silent) --oldaskconfig $(Kconfig)
|
||||
|
||||
nconfig: $(obj)/nconf
|
||||
$< $(silent) $(Kconfig)
|
||||
@@ -1,21 +0,0 @@
|
||||
|
||||
This patch adds module aliases for matching the old dm-raid45 patch
|
||||
by heinzm@redhat.com carried by kernel-tmb series in order to make
|
||||
sure there is an upgrade path.
|
||||
|
||||
Signed-off-by: Thomas Backlund <tmb@mageia.org>
|
||||
|
||||
drivers/md/dm-raid.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- linux/drivers/md/dm-raid.c.orig
|
||||
+++ linux/drivers/md/dm-raid.c
|
||||
@@ -3689,6 +3689,8 @@ MODULE_ALIAS("dm-raid10");
|
||||
MODULE_ALIAS("dm-raid4");
|
||||
MODULE_ALIAS("dm-raid5");
|
||||
MODULE_ALIAS("dm-raid6");
|
||||
+MODULE_ALIAS("dm-raid45");
|
||||
+MODULE_ALIAS("dm-raid4-5");
|
||||
MODULE_AUTHOR("Neil Brown <dm-devel@redhat.com>");
|
||||
MODULE_AUTHOR("Heinz Mauelshagen <dm-devel@redhat.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
From 68017e5d87a2477d40476f1a0a06f202ee79316b Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Valente <paolo.valente@linaro.org>
|
||||
Date: Mon, 13 Nov 2017 07:34:07 +0100
|
||||
Subject: [PATCH] doc, block, bfq: update max IOPS sustainable with BFQ
|
||||
|
||||
We have investigated more deeply the performance of BFQ, in terms of
|
||||
number of IOPS that can be processed by the CPU when BFQ is used as
|
||||
I/O scheduler. In more detail, using the script [1], we have measured
|
||||
the number of IOPS reached on top of a null block device configured
|
||||
with zero latency, as a function of the workload (sequential read,
|
||||
sequential write, random read, random write) and of the system (we
|
||||
considered desktops, laptops and embedded systems).
|
||||
|
||||
Basing on the resulting figures, with this commit we update the
|
||||
current, conservative IOPS range reported in BFQ documentation. In
|
||||
particular, the documentation now reports, for each of three different
|
||||
systems, the lowest number of IOPS obtained for that system with the
|
||||
above test (namely, the value obtained with the workload leading to
|
||||
the lowest IOPS).
|
||||
|
||||
[1] https://github.com/Algodev-github/IOSpeed
|
||||
|
||||
Reviewed-by: Lee Tibbert <lee.tibbert@gmail.com>
|
||||
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
|
||||
Signed-off-by: Luca Miccio <lucmiccio@gmail.com>
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
Documentation/block/bfq-iosched.txt | 17 +++++++++++------
|
||||
1 file changed, 11 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/Documentation/block/bfq-iosched.txt b/Documentation/block/bfq-iosched.txt
|
||||
index 3d6951d63489..7a9361508157 100644
|
||||
--- a/Documentation/block/bfq-iosched.txt
|
||||
+++ b/Documentation/block/bfq-iosched.txt
|
||||
@@ -20,12 +20,17 @@ for that device, by setting low_latency to 0. See Section 3 for
|
||||
details on how to configure BFQ for the desired tradeoff between
|
||||
latency and throughput, or on how to maximize throughput.
|
||||
|
||||
-On average CPUs, the current version of BFQ can handle devices
|
||||
-performing at most ~30K IOPS; at most ~50 KIOPS on faster CPUs. As a
|
||||
-reference, 30-50 KIOPS correspond to very high bandwidths with
|
||||
-sequential I/O (e.g., 8-12 GB/s if I/O requests are 256 KB large), and
|
||||
-to 120-200 MB/s with 4KB random I/O. BFQ is currently being tested on
|
||||
-multi-queue devices too.
|
||||
+BFQ has a non-null overhead, which limits the maximum IOPS that the
|
||||
+CPU can process for a device scheduled with BFQ. To give an idea of
|
||||
+the limits on slow or average CPUs, here are BFQ limits for three
|
||||
+different CPUs, on, respectively, an average laptop, an old desktop,
|
||||
+and a cheap embedded system, in case full hierarchical support is
|
||||
+enabled (i.e., CONFIG_BFQ_GROUP_IOSCHED is set):
|
||||
+- Intel i7-4850HQ: 250 KIOPS
|
||||
+- AMD A8-3850: 170 KIOPS
|
||||
+- ARM CortexTM-A53 Octa-core: 45 KIOPS
|
||||
+
|
||||
+BFQ works for multi-queue devices too.
|
||||
|
||||
The table of contents follow. Impatients can just jump to Section 3.
|
||||
|
||||
--
|
||||
2.13.6
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
|
||||
This patch adds missing module aliases for the old ieee1394 stack
|
||||
to make it easier for endusers.
|
||||
|
||||
Note: firewire-sbp2 and firewire-ohci already contains the needed aliases.
|
||||
|
||||
Signed-off-by: Thomas Backlund <tmb@mageia.org>
|
||||
|
||||
diff -Nurp linux-2.6.38.4/drivers/firewire/core-transaction.c linux-2.6.38.4.fw/drivers/firewire/core-transaction.c
|
||||
--- linux-2.6.38.4/drivers/firewire/core-transaction.c 2011-03-15 03:20:32.000000000 +0200
|
||||
+++ linux-2.6.38.4.fw/drivers/firewire/core-transaction.c 2011-04-22 16:22:28.461386738 +0300
|
||||
@@ -1174,6 +1174,9 @@ static struct fw_address_handler registe
|
||||
MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
|
||||
MODULE_DESCRIPTION("Core IEEE1394 transaction logic");
|
||||
MODULE_LICENSE("GPL");
|
||||
+MODULE_ALIAS("ieee1394");
|
||||
+MODULE_ALIAS("raw1394");
|
||||
+MODULE_ALIAS("video1394");
|
||||
|
||||
static const u32 vendor_textual_descriptor[] = {
|
||||
/* textual descriptor leaf () */
|
||||
diff -Nurp linux-2.6.38.4/drivers/firewire/net.c linux-2.6.38.4.fw/drivers/firewire/net.c
|
||||
--- linux-2.6.38.4/drivers/firewire/net.c 2011-03-15 03:20:32.000000000 +0200
|
||||
+++ linux-2.6.38.4.fw/drivers/firewire/net.c 2011-04-22 16:20:34.008883920 +0300
|
||||
@@ -1719,3 +1719,4 @@ MODULE_AUTHOR("Jay Fenlason <fenlason@re
|
||||
MODULE_DESCRIPTION("IP over IEEE1394 as per RFC 2734/3146");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DEVICE_TABLE(ieee1394, fwnet_id_table);
|
||||
+MODULE_ALIAS("eth1394");
|
||||
@@ -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
|
||||
@@ -1,431 +0,0 @@
|
||||
|
||||
fs/aufs/Kconfig | 2 +-
|
||||
fs/dcache.c | 2 ++
|
||||
fs/exec.c | 1 +
|
||||
fs/fcntl.c | 1 +
|
||||
fs/file_table.c | 4 ++++
|
||||
fs/inode.c | 1 +
|
||||
fs/namespace.c | 2 ++
|
||||
fs/notify/group.c | 4 ++++
|
||||
fs/notify/mark.c | 4 ++++
|
||||
fs/open.c | 2 ++
|
||||
fs/read_write.c | 4 ++++
|
||||
fs/splice.c | 2 ++
|
||||
fs/sync.c | 1 +
|
||||
fs/xattr.c | 1 +
|
||||
kernel/task_work.c | 1 +
|
||||
security/commoncap.c | 2 ++
|
||||
security/device_cgroup.c | 2 ++
|
||||
security/security.c | 10 ++++++++++
|
||||
18 files changed, 45 insertions(+), 1 deletion(-)
|
||||
|
||||
diff -Nurp linux-4.14.14-aufs/fs/aufs/Kconfig linux-4.14.14-aufs.mod/fs/aufs/Kconfig
|
||||
--- linux-4.14.14-aufs/fs/aufs/Kconfig 2018-01-17 11:17:42.191975391 +0200
|
||||
+++ linux-4.14.14-aufs.mod/fs/aufs/Kconfig 2018-01-17 11:18:22.784556755 +0200
|
||||
@@ -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-4.14.14-aufs/fs/dcache.c linux-4.14.14-aufs.mod/fs/dcache.c
|
||||
--- linux-4.14.14-aufs/fs/dcache.c 2018-01-17 11:17:42.200975519 +0200
|
||||
+++ linux-4.14.14-aufs.mod/fs/dcache.c 2018-01-17 11:18:22.784556755 +0200
|
||||
@@ -1305,6 +1305,7 @@ rename_retry:
|
||||
seq = 1;
|
||||
goto again;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(d_walk);
|
||||
|
||||
struct check_mount {
|
||||
struct vfsmount *mnt;
|
||||
@@ -2894,6 +2895,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-4.14.14-aufs/fs/exec.c linux-4.14.14-aufs.mod/fs/exec.c
|
||||
--- linux-4.14.14-aufs/fs/exec.c 2018-01-17 11:08:18.957908605 +0200
|
||||
+++ linux-4.14.14-aufs.mod/fs/exec.c 2018-01-17 11:18:22.785556770 +0200
|
||||
@@ -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-4.14.14-aufs/fs/fcntl.c linux-4.14.14-aufs.mod/fs/fcntl.c
|
||||
--- linux-4.14.14-aufs/fs/fcntl.c 2018-01-17 11:17:42.200975519 +0200
|
||||
+++ linux-4.14.14-aufs.mod/fs/fcntl.c 2018-01-17 11:18:22.785556770 +0200
|
||||
@@ -85,6 +85,7 @@ int setfl(int fd, struct file * filp, un
|
||||
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-4.14.14-aufs/fs/file_table.c linux-4.14.14-aufs.mod/fs/file_table.c
|
||||
--- linux-4.14.14-aufs/fs/file_table.c 2017-11-12 20:46:13.000000000 +0200
|
||||
+++ linux-4.14.14-aufs.mod/fs/file_table.c 2018-01-17 11:18:22.785556770 +0200
|
||||
@@ -148,6 +148,7 @@ over:
|
||||
}
|
||||
return ERR_PTR(-ENFILE);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(get_empty_filp);
|
||||
|
||||
/**
|
||||
* alloc_file - allocate and initialize a 'struct file'
|
||||
@@ -258,6 +259,7 @@ void flush_delayed_fput(void)
|
||||
{
|
||||
delayed_fput(NULL);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(flush_delayed_fput);
|
||||
|
||||
static DECLARE_DELAYED_WORK(delayed_fput_work, delayed_fput);
|
||||
|
||||
@@ -300,6 +302,7 @@ void __fput_sync(struct file *file)
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(fput);
|
||||
+EXPORT_SYMBOL_GPL(__fput_sync);
|
||||
|
||||
void put_filp(struct file *file)
|
||||
{
|
||||
@@ -308,6 +311,7 @@ void put_filp(struct file *file)
|
||||
file_free(file);
|
||||
}
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(put_filp);
|
||||
|
||||
void __init files_init(void)
|
||||
{
|
||||
diff -Nurp linux-4.14.14-aufs/fs/inode.c linux-4.14.14-aufs.mod/fs/inode.c
|
||||
--- linux-4.14.14-aufs/fs/inode.c 2018-01-17 11:17:42.200975519 +0200
|
||||
+++ linux-4.14.14-aufs.mod/fs/inode.c 2018-01-17 11:18:22.785556770 +0200
|
||||
@@ -1664,6 +1664,7 @@ int update_time(struct inode *inode, str
|
||||
|
||||
return update_time(inode, time, flags);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(update_time);
|
||||
|
||||
/**
|
||||
* touch_atime - update the access time
|
||||
diff -Nurp linux-4.14.14-aufs/fs/namespace.c linux-4.14.14-aufs.mod/fs/namespace.c
|
||||
--- linux-4.14.14-aufs/fs/namespace.c 2018-01-17 11:17:42.201975534 +0200
|
||||
+++ linux-4.14.14-aufs.mod/fs/namespace.c 2018-01-17 11:18:22.785556770 +0200
|
||||
@@ -517,6 +517,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
|
||||
@@ -1887,6 +1888,7 @@ int iterate_mounts(int (*f)(struct vfsmo
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(iterate_mounts);
|
||||
|
||||
static void cleanup_group_ids(struct mount *mnt, struct mount *end)
|
||||
{
|
||||
diff -Nurp linux-4.14.14-aufs/fs/notify/group.c linux-4.14.14-aufs.mod/fs/notify/group.c
|
||||
--- linux-4.14.14-aufs/fs/notify/group.c 2017-11-12 20:46:13.000000000 +0200
|
||||
+++ linux-4.14.14-aufs.mod/fs/notify/group.c 2018-01-17 11:18:22.786556784 +0200
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <linux/srcu.h>
|
||||
#include <linux/rculist.h>
|
||||
#include <linux/wait.h>
|
||||
+#include <linux/module.h>
|
||||
|
||||
#include <linux/fsnotify_backend.h>
|
||||
#include "fsnotify.h"
|
||||
@@ -109,6 +110,7 @@ void fsnotify_get_group(struct fsnotify_
|
||||
{
|
||||
atomic_inc(&group->refcnt);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(fsnotify_get_group);
|
||||
|
||||
/*
|
||||
* Drop a reference to a group. Free it if it's through.
|
||||
@@ -118,6 +120,7 @@ void fsnotify_put_group(struct fsnotify_
|
||||
if (atomic_dec_and_test(&group->refcnt))
|
||||
fsnotify_final_destroy_group(group);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(fsnotify_put_group);
|
||||
|
||||
/*
|
||||
* Create a new fsnotify_group and hold a reference for the group returned.
|
||||
@@ -147,6 +150,7 @@ struct fsnotify_group *fsnotify_alloc_gr
|
||||
|
||||
return group;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(fsnotify_alloc_group);
|
||||
|
||||
int fsnotify_fasync(int fd, struct file *file, int on)
|
||||
{
|
||||
diff -Nurp linux-4.14.14-aufs/fs/notify/mark.c linux-4.14.14-aufs.mod/fs/notify/mark.c
|
||||
--- linux-4.14.14-aufs/fs/notify/mark.c 2018-01-17 11:08:18.963908691 +0200
|
||||
+++ linux-4.14.14-aufs.mod/fs/notify/mark.c 2018-01-17 11:18:22.786556784 +0200
|
||||
@@ -124,6 +124,7 @@ static void __fsnotify_recalc_mask(struc
|
||||
else if (conn->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT)
|
||||
real_mount(conn->mnt)->mnt_fsnotify_mask = new_mask;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(fsnotify_put_mark);
|
||||
|
||||
/*
|
||||
* Calculate mask of events for a list of marks. The caller must make sure
|
||||
@@ -271,6 +272,7 @@ static bool fsnotify_get_mark_safe(struc
|
||||
}
|
||||
return false;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(fsnotify_destroy_mark);
|
||||
|
||||
/*
|
||||
* Puts marks and wakes up group destruction if necessary.
|
||||
@@ -428,6 +430,7 @@ int fsnotify_compare_groups(struct fsnot
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(fsnotify_add_mark);
|
||||
|
||||
static int fsnotify_attach_connector_to_object(
|
||||
struct fsnotify_mark_connector __rcu **connp,
|
||||
@@ -557,6 +560,7 @@ out_err:
|
||||
spin_unlock(&mark->lock);
|
||||
return err;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(fsnotify_init_mark);
|
||||
|
||||
/*
|
||||
* Attach an initialized mark to a given group and fs object.
|
||||
diff -Nurp linux-4.14.14-aufs/fs/open.c linux-4.14.14-aufs.mod/fs/open.c
|
||||
--- linux-4.14.14-aufs/fs/open.c 2017-11-12 20:46:13.000000000 +0200
|
||||
+++ linux-4.14.14-aufs.mod/fs/open.c 2018-01-17 11:18:22.786556784 +0200
|
||||
@@ -64,6 +64,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)
|
||||
{
|
||||
@@ -691,6 +692,7 @@ int open_check_o_direct(struct file *f)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(open_check_o_direct);
|
||||
|
||||
static int do_dentry_open(struct file *f,
|
||||
struct inode *inode,
|
||||
diff -Nurp linux-4.14.14-aufs/fs/read_write.c linux-4.14.14-aufs.mod/fs/read_write.c
|
||||
--- linux-4.14.14-aufs/fs/read_write.c 2018-01-17 11:17:42.201975534 +0200
|
||||
+++ linux-4.14.14-aufs.mod/fs/read_write.c 2018-01-17 11:18:22.790556841 +0200
|
||||
@@ -454,6 +454,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)
|
||||
{
|
||||
@@ -494,6 +495,7 @@ vfs_readf_t vfs_readf(struct file *file)
|
||||
return new_sync_read;
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(vfs_readf);
|
||||
|
||||
vfs_writef_t vfs_writef(struct file *file)
|
||||
{
|
||||
@@ -505,6 +507,7 @@ vfs_writef_t vfs_writef(struct file *fil
|
||||
return new_sync_write;
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(vfs_writef);
|
||||
|
||||
ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
|
||||
{
|
||||
@@ -574,6 +577,7 @@ ssize_t vfs_write(struct file *file, con
|
||||
|
||||
return ret;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(vfs_write);
|
||||
|
||||
static inline loff_t file_pos_read(struct file *file)
|
||||
{
|
||||
diff -Nurp linux-4.14.14-aufs/fs/splice.c linux-4.14.14-aufs.mod/fs/splice.c
|
||||
--- linux-4.14.14-aufs/fs/splice.c 2018-01-17 11:17:42.201975534 +0200
|
||||
+++ linux-4.14.14-aufs.mod/fs/splice.c 2018-01-17 11:18:22.791556855 +0200
|
||||
@@ -850,6 +850,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.
|
||||
@@ -879,6 +880,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-4.14.14-aufs/fs/sync.c linux-4.14.14-aufs.mod/fs/sync.c
|
||||
--- linux-4.14.14-aufs/fs/sync.c 2018-01-17 11:17:42.201975534 +0200
|
||||
+++ linux-4.14.14-aufs.mod/fs/sync.c 2018-01-17 11:18:22.791556855 +0200
|
||||
@@ -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-4.14.14-aufs/fs/xattr.c linux-4.14.14-aufs.mod/fs/xattr.c
|
||||
--- linux-4.14.14-aufs/fs/xattr.c 2017-11-12 20:46:13.000000000 +0200
|
||||
+++ linux-4.14.14-aufs.mod/fs/xattr.c 2018-01-17 11:18:22.791556855 +0200
|
||||
@@ -297,6 +297,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-4.14.14-aufs/kernel/task_work.c linux-4.14.14-aufs.mod/kernel/task_work.c
|
||||
--- linux-4.14.14-aufs/kernel/task_work.c 2018-01-17 11:08:18.979908919 +0200
|
||||
+++ linux-4.14.14-aufs.mod/kernel/task_work.c 2018-01-17 11:18:22.791556855 +0200
|
||||
@@ -116,3 +116,4 @@ void task_work_run(void)
|
||||
} while (work);
|
||||
}
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(task_work_run);
|
||||
diff -Nurp linux-4.14.14-aufs/security/commoncap.c linux-4.14.14-aufs.mod/security/commoncap.c
|
||||
--- linux-4.14.14-aufs/security/commoncap.c 2018-01-17 11:08:18.999909204 +0200
|
||||
+++ linux-4.14.14-aufs.mod/security/commoncap.c 2018-01-17 11:18:22.791556855 +0200
|
||||
@@ -1267,12 +1267,14 @@ int cap_mmap_addr(unsigned long addr)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(cap_mmap_addr);
|
||||
|
||||
int cap_mmap_file(struct file *file, unsigned long reqprot,
|
||||
unsigned long prot, unsigned long flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(cap_mmap_file);
|
||||
|
||||
#ifdef CONFIG_SECURITY
|
||||
|
||||
diff -Nurp linux-4.14.14-aufs/security/device_cgroup.c linux-4.14.14-aufs.mod/security/device_cgroup.c
|
||||
--- linux-4.14.14-aufs/security/device_cgroup.c 2017-11-12 20:46:13.000000000 +0200
|
||||
+++ linux-4.14.14-aufs.mod/security/device_cgroup.c 2018-01-17 11:18:22.791556855 +0200
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <linux/device_cgroup.h>
|
||||
#include <linux/cgroup.h>
|
||||
#include <linux/ctype.h>
|
||||
+#include <linux/export.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/seq_file.h>
|
||||
@@ -850,6 +851,7 @@ int __devcgroup_inode_permission(struct
|
||||
return __devcgroup_check_permission(type, imajor(inode), iminor(inode),
|
||||
access);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(__devcgroup_inode_permission);
|
||||
|
||||
int devcgroup_inode_mknod(int mode, dev_t dev)
|
||||
{
|
||||
diff -Nurp linux-4.14.14-aufs/security/security.c linux-4.14.14-aufs.mod/security/security.c
|
||||
--- linux-4.14.14-aufs/security/security.c 2017-11-12 20:46:13.000000000 +0200
|
||||
+++ linux-4.14.14-aufs.mod/security/security.c 2018-01-17 11:18:22.791556855 +0200
|
||||
@@ -530,6 +530,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)
|
||||
{
|
||||
@@ -546,6 +547,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)
|
||||
@@ -554,6 +556,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,
|
||||
@@ -581,6 +584,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)
|
||||
{
|
||||
@@ -588,6 +592,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)
|
||||
{
|
||||
@@ -595,6 +600,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)
|
||||
{
|
||||
@@ -680,6 +686,7 @@ int security_inode_readlink(struct dentr
|
||||
return 0;
|
||||
return call_int_hook(inode_readlink, 0, dentry);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(security_inode_readlink);
|
||||
|
||||
int security_inode_follow_link(struct dentry *dentry, struct inode *inode,
|
||||
bool rcu)
|
||||
@@ -695,6 +702,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)
|
||||
{
|
||||
@@ -866,6 +874,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)
|
||||
{
|
||||
@@ -925,6 +934,7 @@ int security_mmap_file(struct file *file
|
||||
return ret;
|
||||
return ima_file_mmap(file, prot);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(security_mmap_file);
|
||||
|
||||
int security_mmap_addr(unsigned long addr)
|
||||
{
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +0,0 @@
|
||||
diff -Nurp linux-5.3-aufs/include/uapi/linux/aufs_type.h linux-5.3-aufs-ver/include/uapi/linux/aufs_type.h
|
||||
--- linux-5.3-aufs/include/uapi/linux/aufs_type.h 2019-09-24 16:13:44.012259519 +0300
|
||||
+++ linux-5.3-aufs-ver/include/uapi/linux/aufs_type.h 2019-09-24 20:04:21.924707762 +0300
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#include <linux/limits.h>
|
||||
|
||||
-#define AUFS_VERSION "5.x-rcN"
|
||||
+#define AUFS_VERSION "5.4"
|
||||
|
||||
/* todo? move this to linux-2.6.19/include/magic.h */
|
||||
#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
|
||||
@@ -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);
|
||||
}
|
||||
+69
-78
@@ -14,13 +14,12 @@
|
||||
fs/xattr.c | 1 +
|
||||
kernel/locking/lockdep.c | 1 +
|
||||
kernel/task_work.c | 1 +
|
||||
security/device_cgroup.c | 1 +
|
||||
security/security.c | 8 ++++++++
|
||||
17 files changed, 32 insertions(+), 1 deletion(-)
|
||||
16 files changed, 31 insertions(+), 1 deletion(-)
|
||||
|
||||
diff -Nurp linux-5.4-aufs/fs/aufs/Kconfig linux-5.4-aufs-mod/fs/aufs/Kconfig
|
||||
--- linux-5.4-aufs/fs/aufs/Kconfig 2019-11-28 01:25:59.062925618 +0200
|
||||
+++ linux-5.4-aufs-mod/fs/aufs/Kconfig 2019-11-28 01:38:40.564895255 +0200
|
||||
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
|
||||
@@ -29,10 +28,10 @@ diff -Nurp linux-5.4-aufs/fs/aufs/Kconfig linux-5.4-aufs-mod/fs/aufs/Kconfig
|
||||
help
|
||||
Aufs is a stackable unification filesystem such as Unionfs,
|
||||
which unifies several directories and provides a merged single
|
||||
diff -Nurp linux-5.4-aufs/fs/dcache.c linux-5.4-aufs-mod/fs/dcache.c
|
||||
--- linux-5.4-aufs/fs/dcache.c 2019-11-28 01:25:59.069925618 +0200
|
||||
+++ linux-5.4-aufs-mod/fs/dcache.c 2019-11-28 01:38:40.585895254 +0200
|
||||
@@ -1369,6 +1369,7 @@ rename_retry:
|
||||
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;
|
||||
}
|
||||
@@ -40,7 +39,7 @@ diff -Nurp linux-5.4-aufs/fs/dcache.c linux-5.4-aufs-mod/fs/dcache.c
|
||||
|
||||
struct check_mount {
|
||||
struct vfsmount *mnt;
|
||||
@@ -2914,6 +2915,7 @@ void d_exchange(struct dentry *dentry1,
|
||||
@@ -2916,6 +2917,7 @@ void d_exchange(struct dentry *dentry1,
|
||||
|
||||
write_sequnlock(&rename_lock);
|
||||
}
|
||||
@@ -48,10 +47,10 @@ diff -Nurp linux-5.4-aufs/fs/dcache.c linux-5.4-aufs-mod/fs/dcache.c
|
||||
|
||||
/**
|
||||
* d_ancestor - search for an ancestor
|
||||
diff -Nurp linux-5.4-aufs/fs/exec.c linux-5.4-aufs-mod/fs/exec.c
|
||||
--- linux-5.4-aufs/fs/exec.c 2019-11-25 02:32:01.000000000 +0200
|
||||
+++ linux-5.4-aufs-mod/fs/exec.c 2019-11-28 01:38:40.589895254 +0200
|
||||
@@ -110,6 +110,7 @@ bool path_noexec(const struct path *path
|
||||
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);
|
||||
}
|
||||
@@ -59,10 +58,10 @@ diff -Nurp linux-5.4-aufs/fs/exec.c linux-5.4-aufs-mod/fs/exec.c
|
||||
|
||||
#ifdef CONFIG_USELIB
|
||||
/*
|
||||
diff -Nurp linux-5.4-aufs/fs/fcntl.c linux-5.4-aufs-mod/fs/fcntl.c
|
||||
--- linux-5.4-aufs/fs/fcntl.c 2019-11-28 01:25:59.069925618 +0200
|
||||
+++ linux-5.4-aufs-mod/fs/fcntl.c 2019-11-28 01:38:40.589895254 +0200
|
||||
@@ -85,6 +85,7 @@ int setfl(int fd, struct file * filp, un
|
||||
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;
|
||||
}
|
||||
@@ -70,9 +69,9 @@ diff -Nurp linux-5.4-aufs/fs/fcntl.c linux-5.4-aufs-mod/fs/fcntl.c
|
||||
|
||||
static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
|
||||
int force)
|
||||
diff -Nurp linux-5.4-aufs/fs/file_table.c linux-5.4-aufs-mod/fs/file_table.c
|
||||
--- linux-5.4-aufs/fs/file_table.c 2019-11-25 02:32:01.000000000 +0200
|
||||
+++ linux-5.4-aufs-mod/fs/file_table.c 2019-11-28 01:38:40.589895254 +0200
|
||||
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);
|
||||
@@ -81,7 +80,7 @@ diff -Nurp linux-5.4-aufs/fs/file_table.c linux-5.4-aufs-mod/fs/file_table.c
|
||||
|
||||
/*
|
||||
* Variant of alloc_empty_file() that doesn't check and modify nr_files.
|
||||
@@ -375,6 +377,7 @@ void __fput_sync(struct file *file)
|
||||
@@ -375,6 +376,7 @@ void __fput_sync(struct file *file)
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(fput);
|
||||
@@ -89,20 +88,20 @@ diff -Nurp linux-5.4-aufs/fs/file_table.c linux-5.4-aufs-mod/fs/file_table.c
|
||||
|
||||
void __init files_init(void)
|
||||
{
|
||||
diff -Nurp linux-5.4-aufs/fs/inode.c linux-5.4-aufs-mod/fs/inode.c
|
||||
--- linux-5.4-aufs/fs/inode.c 2019-11-28 01:25:59.070925617 +0200
|
||||
+++ linux-5.4-aufs-mod/fs/inode.c 2019-11-28 01:38:40.589895254 +0200
|
||||
@@ -1682,6 +1682,7 @@ int update_time(struct inode *inode, str
|
||||
|
||||
return update_time(inode, time, flags);
|
||||
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.4-aufs/fs/namespace.c linux-5.4-aufs-mod/fs/namespace.c
|
||||
--- linux-5.4-aufs/fs/namespace.c 2019-11-28 01:25:59.070925617 +0200
|
||||
+++ linux-5.4-aufs-mod/fs/namespace.c 2019-11-28 01:38:40.589895254 +0200
|
||||
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();
|
||||
@@ -127,9 +126,9 @@ diff -Nurp linux-5.4-aufs/fs/namespace.c linux-5.4-aufs-mod/fs/namespace.c
|
||||
|
||||
static void lock_mnt_tree(struct mount *mnt)
|
||||
{
|
||||
diff -Nurp linux-5.4-aufs/fs/notify/group.c linux-5.4-aufs-mod/fs/notify/group.c
|
||||
--- linux-5.4-aufs/fs/notify/group.c 2019-11-25 02:32:01.000000000 +0200
|
||||
+++ linux-5.4-aufs-mod/fs/notify/group.c 2019-11-28 01:38:40.590895253 +0200
|
||||
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);
|
||||
@@ -138,9 +137,9 @@ diff -Nurp linux-5.4-aufs/fs/notify/group.c linux-5.4-aufs-mod/fs/notify/group.c
|
||||
|
||||
/*
|
||||
* Drop a reference to a group. Free it if it's through.
|
||||
diff -Nurp linux-5.4-aufs/fs/open.c linux-5.4-aufs-mod/fs/open.c
|
||||
--- linux-5.4-aufs/fs/open.c 2019-11-25 02:32:01.000000000 +0200
|
||||
+++ linux-5.4-aufs-mod/fs/open.c 2019-11-28 01:38:48.762894928 +0200
|
||||
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;
|
||||
@@ -149,9 +148,9 @@ diff -Nurp linux-5.4-aufs/fs/open.c linux-5.4-aufs-mod/fs/open.c
|
||||
|
||||
long vfs_truncate(const struct path *path, loff_t length)
|
||||
{
|
||||
diff -Nurp linux-5.4-aufs/fs/read_write.c linux-5.4-aufs-mod/fs/read_write.c
|
||||
--- linux-5.4-aufs/fs/read_write.c 2019-11-28 01:25:59.070925617 +0200
|
||||
+++ linux-5.4-aufs-mod/fs/read_write.c 2019-11-28 01:38:48.780894927 +0200
|
||||
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;
|
||||
@@ -162,7 +161,7 @@ diff -Nurp linux-5.4-aufs/fs/read_write.c linux-5.4-aufs-mod/fs/read_write.c
|
||||
{
|
||||
@@ -508,6 +509,7 @@ vfs_readf_t vfs_readf(struct file *file)
|
||||
return new_sync_read;
|
||||
return ERR_PTR(-ENOSYS);
|
||||
return ERR_PTR(-ENOSYS); /* doesn't have ->read(|_iter)() op */
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(vfs_readf);
|
||||
|
||||
@@ -170,7 +169,7 @@ diff -Nurp linux-5.4-aufs/fs/read_write.c linux-5.4-aufs-mod/fs/read_write.c
|
||||
{
|
||||
@@ -519,6 +521,7 @@ vfs_writef_t vfs_writef(struct file *fil
|
||||
return new_sync_write;
|
||||
return ERR_PTR(-ENOSYS);
|
||||
return ERR_PTR(-ENOSYS); /* doesn't have ->write(|_iter)() op */
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(vfs_writef);
|
||||
|
||||
@@ -184,10 +183,10 @@ diff -Nurp linux-5.4-aufs/fs/read_write.c linux-5.4-aufs-mod/fs/read_write.c
|
||||
|
||||
/* 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.4-aufs/fs/splice.c linux-5.4-aufs-mod/fs/splice.c
|
||||
--- linux-5.4-aufs/fs/splice.c 2019-11-28 01:25:59.071925617 +0200
|
||||
+++ linux-5.4-aufs-mod/fs/splice.c 2019-11-28 01:38:48.780894927 +0200
|
||||
@@ -847,6 +847,7 @@ long do_splice_from(struct pipe_inode_in
|
||||
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);
|
||||
}
|
||||
@@ -195,7 +194,7 @@ diff -Nurp linux-5.4-aufs/fs/splice.c linux-5.4-aufs-mod/fs/splice.c
|
||||
|
||||
/*
|
||||
* Attempt to initiate a splice from a file to a pipe.
|
||||
@@ -876,6 +877,7 @@ long do_splice_to(struct file *in, loff_
|
||||
@@ -891,6 +892,7 @@ long do_splice_to(struct file *in, loff_
|
||||
|
||||
return splice_read(in, ppos, pipe, len, flags);
|
||||
}
|
||||
@@ -203,9 +202,9 @@ diff -Nurp linux-5.4-aufs/fs/splice.c linux-5.4-aufs-mod/fs/splice.c
|
||||
|
||||
/**
|
||||
* splice_direct_to_actor - splices data directly between two non-pipes
|
||||
diff -Nurp linux-5.4-aufs/fs/sync.c linux-5.4-aufs-mod/fs/sync.c
|
||||
--- linux-5.4-aufs/fs/sync.c 2019-11-28 01:25:59.071925617 +0200
|
||||
+++ linux-5.4-aufs-mod/fs/sync.c 2019-11-28 01:38:48.780894927 +0200
|
||||
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);
|
||||
@@ -214,9 +213,9 @@ diff -Nurp linux-5.4-aufs/fs/sync.c linux-5.4-aufs-mod/fs/sync.c
|
||||
|
||||
/*
|
||||
* Write out and wait upon all dirty data associated with this
|
||||
diff -Nurp linux-5.4-aufs/fs/xattr.c linux-5.4-aufs-mod/fs/xattr.c
|
||||
--- linux-5.4-aufs/fs/xattr.c 2019-11-25 02:32:01.000000000 +0200
|
||||
+++ linux-5.4-aufs-mod/fs/xattr.c 2019-11-28 01:38:48.780894927 +0200
|
||||
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;
|
||||
@@ -225,9 +224,9 @@ diff -Nurp linux-5.4-aufs/fs/xattr.c linux-5.4-aufs-mod/fs/xattr.c
|
||||
|
||||
ssize_t
|
||||
__vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
|
||||
diff -Nurp linux-5.4-aufs/kernel/locking/lockdep.c linux-5.4-aufs-mod/kernel/locking/lockdep.c
|
||||
--- linux-5.4-aufs/kernel/locking/lockdep.c 2019-11-28 01:25:59.072925617 +0200
|
||||
+++ linux-5.4-aufs-mod/kernel/locking/lockdep.c 2019-11-28 01:38:48.780894927 +0200
|
||||
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;
|
||||
@@ -236,26 +235,18 @@ diff -Nurp linux-5.4-aufs/kernel/locking/lockdep.c linux-5.4-aufs-mod/kernel/loc
|
||||
#define hlock_class(hlock) lockdep_hlock_class(hlock)
|
||||
|
||||
#ifdef CONFIG_LOCK_STAT
|
||||
diff -Nurp linux-5.4-aufs/kernel/task_work.c linux-5.4-aufs-mod/kernel/task_work.c
|
||||
--- linux-5.4-aufs/kernel/task_work.c 2019-11-25 02:32:01.000000000 +0200
|
||||
+++ linux-5.4-aufs-mod/kernel/task_work.c 2019-11-28 01:38:48.786894927 +0200
|
||||
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.4-aufs/security/device_cgroup.c linux-5.4-aufs-mod/security/device_cgroup.c
|
||||
--- linux-5.4-aufs/security/device_cgroup.c 2019-11-25 02:32:01.000000000 +0200
|
||||
+++ linux-5.4-aufs-mod/security/device_cgroup.c 2019-11-28 01:38:48.790894927 +0200
|
||||
@@ -824,3 +824,4 @@ int __devcgroup_check_permission(short t
|
||||
|
||||
return 0;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(__devcgroup_check_permission);
|
||||
diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/security.c
|
||||
--- linux-5.4-aufs/security/security.c 2019-11-25 02:32:01.000000000 +0200
|
||||
+++ linux-5.4-aufs-mod/security/security.c 2019-11-28 01:38:48.794894926 +0200
|
||||
@@ -1036,6 +1036,7 @@ int security_path_rmdir(const struct pat
|
||||
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);
|
||||
}
|
||||
@@ -263,7 +254,7 @@ diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/securi
|
||||
|
||||
int security_path_unlink(const struct path *dir, struct dentry *dentry)
|
||||
{
|
||||
@@ -1052,6 +1053,7 @@ int security_path_symlink(const struct p
|
||||
@@ -1084,6 +1085,7 @@ int security_path_symlink(const struct p
|
||||
return 0;
|
||||
return call_int_hook(path_symlink, 0, dir, dentry, old_name);
|
||||
}
|
||||
@@ -271,7 +262,7 @@ diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/securi
|
||||
|
||||
int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
|
||||
struct dentry *new_dentry)
|
||||
@@ -1060,6 +1062,7 @@ int security_path_link(struct dentry *ol
|
||||
@@ -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);
|
||||
}
|
||||
@@ -279,7 +270,7 @@ diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/securi
|
||||
|
||||
int security_path_rename(const struct path *old_dir, struct dentry *old_dentry,
|
||||
const struct path *new_dir, struct dentry *new_dentry,
|
||||
@@ -1087,6 +1090,7 @@ int security_path_truncate(const struct
|
||||
@@ -1119,6 +1122,7 @@ int security_path_truncate(const struct
|
||||
return 0;
|
||||
return call_int_hook(path_truncate, 0, path);
|
||||
}
|
||||
@@ -287,7 +278,7 @@ diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/securi
|
||||
|
||||
int security_path_chmod(const struct path *path, umode_t mode)
|
||||
{
|
||||
@@ -1094,6 +1098,7 @@ int security_path_chmod(const struct pat
|
||||
@@ -1126,6 +1130,7 @@ int security_path_chmod(const struct pat
|
||||
return 0;
|
||||
return call_int_hook(path_chmod, 0, path, mode);
|
||||
}
|
||||
@@ -295,7 +286,7 @@ diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/securi
|
||||
|
||||
int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
|
||||
{
|
||||
@@ -1101,6 +1106,7 @@ int security_path_chown(const struct pat
|
||||
@@ -1133,6 +1138,7 @@ int security_path_chown(const struct pat
|
||||
return 0;
|
||||
return call_int_hook(path_chown, 0, path, uid, gid);
|
||||
}
|
||||
@@ -303,7 +294,7 @@ diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/securi
|
||||
|
||||
int security_path_chroot(const struct path *path)
|
||||
{
|
||||
@@ -1201,6 +1207,7 @@ int security_inode_permission(struct ino
|
||||
@@ -1233,6 +1239,7 @@ int security_inode_permission(struct ino
|
||||
return 0;
|
||||
return call_int_hook(inode_permission, 0, inode, mask);
|
||||
}
|
||||
@@ -311,7 +302,7 @@ diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/securi
|
||||
|
||||
int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
{
|
||||
@@ -1378,6 +1385,7 @@ int security_file_permission(struct file
|
||||
@@ -1410,6 +1417,7 @@ int security_file_permission(struct file
|
||||
|
||||
return fsnotify_perm(file, mask);
|
||||
}
|
||||
+539
-581
File diff suppressed because it is too large
Load Diff
@@ -1,27 +0,0 @@
|
||||
|
||||
arm build fails with:
|
||||
|
||||
n file included from fs/aufs/aufs.h:31:0,
|
||||
from fs/aufs/module.c:11:
|
||||
fs/aufs/file.h: In function 'au_do_vm_file_reset':
|
||||
fs/aufs/file.h:273:9: error: dereferencing pointer to incomplete type 'struct vm_area_struct'
|
||||
f = vma->vm_file;
|
||||
^
|
||||
|
||||
on x86(64) we seem to get covered by implict inclusion.
|
||||
|
||||
So explicitly include it to avoid subtle breakage
|
||||
|
||||
Signed-off-by: Thomas Backlund <tmb@mageia.org>
|
||||
---
|
||||
|
||||
--- ./fs/aufs/file.h.orig
|
||||
+++ ./fs/aufs/file.h
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mm_types.h>
|
||||
#include <linux/poll.h>
|
||||
+#include <linux/vmalloc.h>
|
||||
#include "rwsem.h"
|
||||
|
||||
struct au_branch;
|
||||
@@ -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
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,100 +0,0 @@
|
||||
Adapt mach64 to build with 2.6.31 series kernels
|
||||
|
||||
Signed-off-by: Thomas Backlund <tmb@mandriva.org>
|
||||
|
||||
diff -urp linux-2.6.31-rc3-git5-mnb1/drivers/gpu/drm/mach64/mach64_dma.c linux-2.6.31-rc3-git5-mnb1/drivers/gpu/drm/mach64.fixed/mach64_dma.c
|
||||
--- linux-2.6.31-rc3-git5-mnb1/drivers/gpu/drm/mach64/mach64_dma.c 2009-07-23 00:24:12.000000000 +0300
|
||||
+++ linux-2.6.31-rc3-git5-mnb1/drivers/gpu/drm/mach64.fixed/mach64_dma.c 2009-07-23 02:28:21.000000000 +0300
|
||||
@@ -1006,7 +1006,7 @@ static int mach64_do_dma_init(struct drm
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
- dev_priv = drm_alloc(sizeof(drm_mach64_private_t), DRM_MEM_DRIVER);
|
||||
+ dev_priv = kmalloc(sizeof(drm_mach64_private_t), GFP_KERNEL);
|
||||
if (dev_priv == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1386,8 +1386,7 @@ int mach64_do_cleanup_dma(struct drm_dev
|
||||
|
||||
mach64_destroy_freelist(dev);
|
||||
|
||||
- drm_free(dev_priv, sizeof(drm_mach64_private_t),
|
||||
- DRM_MEM_DRIVER);
|
||||
+ kfree(dev_priv);
|
||||
dev->dev_private = NULL;
|
||||
}
|
||||
|
||||
@@ -1476,8 +1475,8 @@ int mach64_init_freelist(struct drm_devi
|
||||
for (i = 0; i < dma->buf_count; i++) {
|
||||
if ((entry =
|
||||
(drm_mach64_freelist_t *)
|
||||
- drm_alloc(sizeof(drm_mach64_freelist_t),
|
||||
- DRM_MEM_BUFLISTS)) == NULL)
|
||||
+ kmalloc(sizeof(drm_mach64_freelist_t),
|
||||
+ GFP_KERNEL)) == NULL)
|
||||
return -ENOMEM;
|
||||
memset(entry, 0, sizeof(drm_mach64_freelist_t));
|
||||
entry->buf = dma->buflist[i];
|
||||
@@ -1500,18 +1499,18 @@ void mach64_destroy_freelist(struct drm_
|
||||
list_for_each_safe(ptr, tmp, &dev_priv->pending) {
|
||||
list_del(ptr);
|
||||
entry = list_entry(ptr, drm_mach64_freelist_t, list);
|
||||
- drm_free(entry, sizeof(*entry), DRM_MEM_BUFLISTS);
|
||||
+ kfree(entry);
|
||||
}
|
||||
list_for_each_safe(ptr, tmp, &dev_priv->placeholders) {
|
||||
list_del(ptr);
|
||||
entry = list_entry(ptr, drm_mach64_freelist_t, list);
|
||||
- drm_free(entry, sizeof(*entry), DRM_MEM_BUFLISTS);
|
||||
+ kfree(entry);
|
||||
}
|
||||
|
||||
list_for_each_safe(ptr, tmp, &dev_priv->free_list) {
|
||||
list_del(ptr);
|
||||
entry = list_entry(ptr, drm_mach64_freelist_t, list);
|
||||
- drm_free(entry, sizeof(*entry), DRM_MEM_BUFLISTS);
|
||||
+ kfree(entry);
|
||||
}
|
||||
}
|
||||
|
||||
diff -urp linux-2.6.31-rc3-git5-mnb1/drivers/gpu/drm/mach64/mach64_state.c linux-2.6.31-rc3-git5-mnb1/drivers/gpu/drm/mach64.fixed/mach64_state.c
|
||||
--- linux-2.6.31-rc3-git5-mnb1/drivers/gpu/drm/mach64/mach64_state.c 2009-07-23 00:24:12.000000000 +0300
|
||||
+++ linux-2.6.31-rc3-git5-mnb1/drivers/gpu/drm/mach64.fixed/mach64_state.c 2009-07-23 02:29:24.000000000 +0300
|
||||
@@ -490,12 +490,12 @@ static __inline__ int copy_from_user_ver
|
||||
unsigned long n = bytes; /* dwords remaining in buffer */
|
||||
u32 *from, *orig_from;
|
||||
|
||||
- from = drm_alloc(bytes, DRM_MEM_DRIVER);
|
||||
+ from = kmalloc(bytes, GFP_KERNEL);
|
||||
if (from == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
if (DRM_COPY_FROM_USER(from, ufrom, bytes)) {
|
||||
- drm_free(from, bytes, DRM_MEM_DRIVER);
|
||||
+ kfree(from);
|
||||
return -EFAULT;
|
||||
}
|
||||
orig_from = from; /* we'll be modifying the "from" ptr, so save it */
|
||||
@@ -526,19 +526,19 @@ static __inline__ int copy_from_user_ver
|
||||
to += count;
|
||||
} else {
|
||||
DRM_ERROR("Got bad command: 0x%04x\n", reg);
|
||||
- drm_free(orig_from, bytes, DRM_MEM_DRIVER);
|
||||
+ kfree(orig_from);
|
||||
return -EACCES;
|
||||
}
|
||||
} else {
|
||||
DRM_ERROR
|
||||
("Got bad command count(=%u) dwords remaining=%lu\n",
|
||||
count, n);
|
||||
- drm_free(orig_from, bytes, DRM_MEM_DRIVER);
|
||||
+ kfree(orig_from);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
- drm_free(orig_from, bytes, DRM_MEM_DRIVER);
|
||||
+ kfree(orig_from);
|
||||
if (n == 0)
|
||||
return 0;
|
||||
else {
|
||||
@@ -1,27 +0,0 @@
|
||||
--- linux-2.6.35/drivers/gpu/drm/mach64/mach64_state.c.orig 2010-10-03 13:29:10.000000000 +0300
|
||||
+++ linux-2.6.35/drivers/gpu/drm/mach64/mach64_state.c 2010-10-03 14:04:45.991164007 +0300
|
||||
@@ -41,15 +41,15 @@
|
||||
*
|
||||
*/
|
||||
struct drm_ioctl_desc mach64_ioctls[] = {
|
||||
- DRM_IOCTL_DEF(DRM_MACH64_INIT, mach64_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
- DRM_IOCTL_DEF(DRM_MACH64_CLEAR, mach64_dma_clear, DRM_AUTH),
|
||||
- DRM_IOCTL_DEF(DRM_MACH64_SWAP, mach64_dma_swap, DRM_AUTH),
|
||||
- DRM_IOCTL_DEF(DRM_MACH64_IDLE, mach64_dma_idle, DRM_AUTH),
|
||||
- DRM_IOCTL_DEF(DRM_MACH64_RESET, mach64_engine_reset, DRM_AUTH),
|
||||
- DRM_IOCTL_DEF(DRM_MACH64_VERTEX, mach64_dma_vertex, DRM_AUTH),
|
||||
- DRM_IOCTL_DEF(DRM_MACH64_BLIT, mach64_dma_blit, DRM_AUTH),
|
||||
- DRM_IOCTL_DEF(DRM_MACH64_FLUSH, mach64_dma_flush, DRM_AUTH),
|
||||
- DRM_IOCTL_DEF(DRM_MACH64_GETPARAM, mach64_get_param, DRM_AUTH),
|
||||
+ DRM_IOCTL_DEF_DRV(MACH64_INIT, mach64_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
+ DRM_IOCTL_DEF_DRV(MACH64_CLEAR, mach64_dma_clear, DRM_AUTH),
|
||||
+ DRM_IOCTL_DEF_DRV(MACH64_SWAP, mach64_dma_swap, DRM_AUTH),
|
||||
+ DRM_IOCTL_DEF_DRV(MACH64_IDLE, mach64_dma_idle, DRM_AUTH),
|
||||
+ DRM_IOCTL_DEF_DRV(MACH64_RESET, mach64_engine_reset, DRM_AUTH),
|
||||
+ DRM_IOCTL_DEF_DRV(MACH64_VERTEX, mach64_dma_vertex, DRM_AUTH),
|
||||
+ DRM_IOCTL_DEF_DRV(MACH64_BLIT, mach64_dma_blit, DRM_AUTH),
|
||||
+ DRM_IOCTL_DEF_DRV(MACH64_FLUSH, mach64_dma_flush, DRM_AUTH),
|
||||
+ DRM_IOCTL_DEF_DRV(MACH64_GETPARAM, mach64_get_param, DRM_AUTH),
|
||||
};
|
||||
|
||||
int mach64_max_ioctl = DRM_ARRAY_SIZE(mach64_ioctls);
|
||||
@@ -1,24 +0,0 @@
|
||||
|
||||
Fix build for 2.6.37
|
||||
|
||||
Signed-off-by: Thomas Backlund <tmb@mandriva.org>
|
||||
|
||||
--- a/drivers/gpu/drm/mach64/mach64_drv.c.orig 2011-01-02 16:55:48.000000000 +0200
|
||||
+++ a/drivers/gpu/drm/mach64/mach64_drv.c 2011-01-02 17:53:54.808775632 +0200
|
||||
@@ -51,8 +51,6 @@ static struct drm_driver driver = {
|
||||
.irq_uninstall = mach64_driver_irq_uninstall,
|
||||
.irq_handler = mach64_driver_irq_handler,
|
||||
.reclaim_buffers = drm_core_reclaim_buffers,
|
||||
- .get_map_ofs = drm_core_get_map_ofs,
|
||||
- .get_reg_ofs = drm_core_get_reg_ofs,
|
||||
.ioctls = mach64_ioctls,
|
||||
.dma_ioctl = mach64_dma_buffers,
|
||||
.fops = {
|
||||
@@ -63,6 +61,7 @@ static struct drm_driver driver = {
|
||||
.mmap = drm_mmap,
|
||||
.poll = drm_poll,
|
||||
.fasync = drm_fasync,
|
||||
+ .llseek = noop_llseek,
|
||||
},
|
||||
.pci_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
@@ -1,44 +0,0 @@
|
||||
|
||||
fix build with linux-3.0
|
||||
|
||||
Signed-off-by: Thomas Backlund <tmb@mageia.org>
|
||||
|
||||
drivers/gpu/drm/mach64/mach64_drv.c | 13 +++++++------
|
||||
1 file changed, 7 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/gpu/drm/mach64/mach64_drv.c.orig 2011-07-15 02:48:40.000000000 +0300
|
||||
+++ a/drivers/gpu/drm/mach64/mach64_drv.c 2011-07-15 13:24:41.454753025 +0300
|
||||
@@ -63,10 +63,6 @@ static struct drm_driver driver = {
|
||||
.fasync = drm_fasync,
|
||||
.llseek = noop_llseek,
|
||||
},
|
||||
- .pci_driver = {
|
||||
- .name = DRIVER_NAME,
|
||||
- .id_table = pciidlist,
|
||||
- },
|
||||
|
||||
.name = DRIVER_NAME,
|
||||
.desc = DRIVER_DESC,
|
||||
@@ -76,15 +72,20 @@ static struct drm_driver driver = {
|
||||
.patchlevel = DRIVER_PATCHLEVEL,
|
||||
};
|
||||
|
||||
+static struct pci_driver mach64_pci_driver = {
|
||||
+ .name = DRIVER_NAME,
|
||||
+ .id_table = pciidlist,
|
||||
+};
|
||||
+
|
||||
static int __init mach64_init(void)
|
||||
{
|
||||
driver.num_ioctls = mach64_max_ioctl;
|
||||
- return drm_init(&driver);
|
||||
+ return drm_pci_init(&driver, &mach64_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit mach64_exit(void)
|
||||
{
|
||||
- drm_exit(&driver);
|
||||
+ drm_pci_exit(&driver, &mach64_pci_driver);
|
||||
}
|
||||
|
||||
module_init(mach64_init);
|
||||
@@ -1,17 +0,0 @@
|
||||
--- linux/drivers/gpu/drm/mach64/mach64_drv.c.orig 2013-10-13 12:19:41.000000000 +0300
|
||||
+++ linux/drivers/gpu/drm/mach64/mach64_drv.c 2013-10-13 14:27:25.684247911 +0300
|
||||
@@ -46,13 +46,12 @@ static const struct file_operations mach
|
||||
.unlocked_ioctl = drm_ioctl,
|
||||
.mmap = drm_mmap,
|
||||
.poll = drm_poll,
|
||||
- .fasync = drm_fasync,
|
||||
.llseek = noop_llseek,
|
||||
};
|
||||
|
||||
static struct drm_driver driver = {
|
||||
.driver_features =
|
||||
- DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_HAVE_DMA
|
||||
+ DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_HAVE_DMA
|
||||
| DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
|
||||
.lastclose = mach64_driver_lastclose,
|
||||
.get_vblank_counter = mach64_get_vblank_counter,
|
||||
@@ -1,31 +0,0 @@
|
||||
|
||||
Adapt for kernel-3.17
|
||||
|
||||
DRM_ARRAY_SIZE is a duplicate of ARRAY_SIZE and have been dropped.
|
||||
|
||||
drm_dev_to_irq has been dropped, so call dev->pdev->irq directly
|
||||
for code simplicity.
|
||||
|
||||
Signed-off-by: Thomas Backlund <tmb@mageia.org>
|
||||
|
||||
diff -urp linux/drivers/gpu/drm/mach64/mach64_state.c.orig linux/drivers/gpu/drm/mach64/mach64_state.c
|
||||
--- linux/drivers/gpu/drm/mach64/mach64_state.c.orig
|
||||
+++ linux/drivers/gpu/drm/mach64/mach64_state.c
|
||||
@@ -52,7 +52,7 @@ struct drm_ioctl_desc mach64_ioctls[] =
|
||||
DRM_IOCTL_DEF_DRV(MACH64_GETPARAM, mach64_get_param, DRM_AUTH),
|
||||
};
|
||||
|
||||
-int mach64_max_ioctl = DRM_ARRAY_SIZE(mach64_ioctls);
|
||||
+int mach64_max_ioctl = ARRAY_SIZE(mach64_ioctls);
|
||||
|
||||
/* ================================================================
|
||||
* DMA hardware state programming functions
|
||||
@@ -895,7 +895,7 @@ int mach64_get_param(struct drm_device *
|
||||
value = mach64_do_get_frames_queued(dev_priv);
|
||||
break;
|
||||
case MACH64_PARAM_IRQ_NR:
|
||||
- value = drm_dev_to_irq(dev);
|
||||
+ value = dev->pdev->irq;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -1,142 +0,0 @@
|
||||
|
||||
Fix build with kernel 3.18
|
||||
|
||||
Signed-off-by: Thomas Backlund <tmb@mageia.org>
|
||||
|
||||
diff -urp linux/drivers/gpu/drm/mach64.orig/mach64_dma.c linux/drivers/gpu/drm/mach64/mach64_dma.c
|
||||
--- linux/drivers/gpu/drm/mach64.orig/mach64_dma.c 2014-11-29 22:01:54.000000000 +0200
|
||||
+++ linux/drivers/gpu/drm/mach64/mach64_dma.c 2014-11-30 00:02:06.906821818 +0200
|
||||
@@ -1038,21 +1038,21 @@ static int mach64_do_dma_init(struct drm
|
||||
INIT_LIST_HEAD(&dev_priv->placeholders);
|
||||
INIT_LIST_HEAD(&dev_priv->pending);
|
||||
|
||||
- dev_priv->sarea = drm_getsarea(dev);
|
||||
+ dev_priv->sarea = drm_legacy_getsarea(dev);
|
||||
if (!dev_priv->sarea) {
|
||||
DRM_ERROR("can not find sarea!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
mach64_do_cleanup_dma(dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
- dev_priv->fb = drm_core_findmap(dev, init->fb_offset);
|
||||
+ dev_priv->fb = drm_legacy_findmap(dev, init->fb_offset);
|
||||
if (!dev_priv->fb) {
|
||||
DRM_ERROR("can not find frame buffer map!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
mach64_do_cleanup_dma(dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
- dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
|
||||
+ dev_priv->mmio = drm_legacy_findmap(dev, init->mmio_offset);
|
||||
if (!dev_priv->mmio) {
|
||||
DRM_ERROR("can not find mmio map!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
@@ -1060,7 +1060,7 @@ static int mach64_do_dma_init(struct drm
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- dev_priv->ring_map = drm_core_findmap(dev, init->ring_offset);
|
||||
+ dev_priv->ring_map = drm_legacy_findmap(dev, init->ring_offset);
|
||||
if (!dev_priv->ring_map) {
|
||||
DRM_ERROR("can not find ring map!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
@@ -1072,7 +1072,7 @@ static int mach64_do_dma_init(struct drm
|
||||
((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
|
||||
|
||||
if (!dev_priv->is_pci) {
|
||||
- drm_core_ioremap(dev_priv->ring_map, dev);
|
||||
+ drm_legacy_ioremap(dev_priv->ring_map, dev);
|
||||
if (!dev_priv->ring_map->handle) {
|
||||
DRM_ERROR("can not ioremap virtual address for"
|
||||
" descriptor ring\n");
|
||||
@@ -1082,7 +1082,7 @@ static int mach64_do_dma_init(struct drm
|
||||
}
|
||||
dev->agp_buffer_token = init->buffers_offset;
|
||||
dev->agp_buffer_map =
|
||||
- drm_core_findmap(dev, init->buffers_offset);
|
||||
+ drm_legacy_findmap(dev, init->buffers_offset);
|
||||
if (!dev->agp_buffer_map) {
|
||||
DRM_ERROR("can not find dma buffer map!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
@@ -1093,7 +1093,7 @@ static int mach64_do_dma_init(struct drm
|
||||
dev isn't passed all the way though the mach64 - DA */
|
||||
dev_priv->dev_buffers = dev->agp_buffer_map;
|
||||
|
||||
- drm_core_ioremap(dev->agp_buffer_map, dev);
|
||||
+ drm_legacy_ioremap(dev->agp_buffer_map, dev);
|
||||
if (!dev->agp_buffer_map->handle) {
|
||||
DRM_ERROR("can not ioremap virtual address for"
|
||||
" dma buffer\n");
|
||||
@@ -1102,7 +1102,7 @@ static int mach64_do_dma_init(struct drm
|
||||
return -ENOMEM;
|
||||
}
|
||||
dev_priv->agp_textures =
|
||||
- drm_core_findmap(dev, init->agp_textures_offset);
|
||||
+ drm_legacy_findmap(dev, init->agp_textures_offset);
|
||||
if (!dev_priv->agp_textures) {
|
||||
DRM_ERROR("can not find agp texture region!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
@@ -1376,10 +1376,10 @@ int mach64_do_cleanup_dma(struct drm_dev
|
||||
|
||||
if (!dev_priv->is_pci) {
|
||||
if (dev_priv->ring_map)
|
||||
- drm_core_ioremapfree(dev_priv->ring_map, dev);
|
||||
+ drm_legacy_ioremapfree(dev_priv->ring_map, dev);
|
||||
|
||||
if (dev->agp_buffer_map) {
|
||||
- drm_core_ioremapfree(dev->agp_buffer_map, dev);
|
||||
+ drm_legacy_ioremapfree(dev->agp_buffer_map, dev);
|
||||
dev->agp_buffer_map = NULL;
|
||||
}
|
||||
}
|
||||
diff -urp linux/drivers/gpu/drm/mach64.orig/mach64_drv.c linux/drivers/gpu/drm/mach64/mach64_drv.c
|
||||
--- linux/drivers/gpu/drm/mach64.orig/mach64_drv.c 2014-11-29 22:01:54.000000000 +0200
|
||||
+++ linux/drivers/gpu/drm/mach64/mach64_drv.c 2014-11-29 23:14:21.918009653 +0200
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "mach64_drv.h"
|
||||
|
||||
#include <drm/drm_pciids.h>
|
||||
+#include <drm/drm_legacy.h>
|
||||
|
||||
static struct pci_device_id pciidlist[] = {
|
||||
mach64_PCI_IDS
|
||||
@@ -44,7 +45,7 @@ static const struct file_operations mach
|
||||
.open = drm_open,
|
||||
.release = drm_release,
|
||||
.unlocked_ioctl = drm_ioctl,
|
||||
- .mmap = drm_mmap,
|
||||
+ .mmap = drm_legacy_mmap,
|
||||
.poll = drm_poll,
|
||||
.llseek = noop_llseek,
|
||||
};
|
||||
diff -urp linux/drivers/gpu/drm/mach64.orig/mach64_drv.h linux/drivers/gpu/drm/mach64/mach64_drv.h
|
||||
--- linux/drivers/gpu/drm/mach64.orig/mach64_drv.h 2014-11-29 22:01:54.000000000 +0200
|
||||
+++ linux/drivers/gpu/drm/mach64/mach64_drv.h 2014-11-29 23:58:20.111491646 +0200
|
||||
@@ -35,6 +35,8 @@
|
||||
#ifndef __MACH64_DRV_H__
|
||||
#define __MACH64_DRV_H__
|
||||
|
||||
+#include <drm/drm_legacy.h>
|
||||
+
|
||||
/* General customization:
|
||||
*/
|
||||
|
||||
@@ -102,12 +104,12 @@ typedef struct drm_mach64_private {
|
||||
u32 back_offset_pitch;
|
||||
u32 depth_offset_pitch;
|
||||
|
||||
- drm_local_map_t *sarea;
|
||||
- drm_local_map_t *fb;
|
||||
- drm_local_map_t *mmio;
|
||||
- drm_local_map_t *ring_map;
|
||||
- drm_local_map_t *dev_buffers; /* this is a pointer to a structure in dev */
|
||||
- drm_local_map_t *agp_textures;
|
||||
+ struct drm_local_map *sarea;
|
||||
+ struct drm_local_map *fb;
|
||||
+ struct drm_local_map *mmio;
|
||||
+ struct drm_local_map *ring_map;
|
||||
+ struct drm_local_map *dev_buffers; /* this is a pointer to a structure in dev */
|
||||
+ struct drm_local_map *agp_textures;
|
||||
} drm_mach64_private_t;
|
||||
|
||||
extern struct drm_ioctl_desc mach64_ioctls[];
|
||||
@@ -1,47 +0,0 @@
|
||||
|
||||
This moves the .fops to a separate struct as required by kernel-3.3
|
||||
|
||||
Signed-off-by: Thomas Backlund <tmb@mageia.org>
|
||||
|
||||
b/drivers/gpu/drm/mach64/mach64_drv.c | 23 ++++++++++++-----------
|
||||
1 file changed, 12 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/gpu/drm/mach64/mach64_drv.c
|
||||
+++ b/drivers/gpu/drm/mach64/mach64_drv.c
|
||||
@@ -39,6 +39,17 @@ static struct pci_device_id pciidlist[]
|
||||
mach64_PCI_IDS
|
||||
};
|
||||
|
||||
+static const struct file_operations mach64_driver_fops = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .open = drm_open,
|
||||
+ .release = drm_release,
|
||||
+ .unlocked_ioctl = drm_ioctl,
|
||||
+ .mmap = drm_mmap,
|
||||
+ .poll = drm_poll,
|
||||
+ .fasync = drm_fasync,
|
||||
+ .llseek = noop_llseek,
|
||||
+};
|
||||
+
|
||||
static struct drm_driver driver = {
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_HAVE_DMA
|
||||
@@ -54,17 +65,7 @@ static struct drm_driver driver = {
|
||||
.reclaim_buffers = drm_core_reclaim_buffers,
|
||||
.ioctls = mach64_ioctls,
|
||||
.dma_ioctl = mach64_dma_buffers,
|
||||
- .fops = {
|
||||
- .owner = THIS_MODULE,
|
||||
- .open = drm_open,
|
||||
- .release = drm_release,
|
||||
- .unlocked_ioctl = drm_ioctl,
|
||||
- .mmap = drm_mmap,
|
||||
- .poll = drm_poll,
|
||||
- .fasync = drm_fasync,
|
||||
- .llseek = noop_llseek,
|
||||
- },
|
||||
-
|
||||
+ .fops = &mach64_driver_fops,
|
||||
.name = DRIVER_NAME,
|
||||
.desc = DRIVER_DESC,
|
||||
.date = DRIVER_DATE,
|
||||
@@ -1,15 +0,0 @@
|
||||
|
||||
reclaim_buffers is gone in 3.6
|
||||
|
||||
Signed-off-by: Thomas Backlund <tmb@mageia.org>
|
||||
|
||||
--- linux/drivers/gpu/drm/mach64/mach64_drv.c.orig 2012-10-17 22:26:58.000000000 +0300
|
||||
+++ linux/drivers/gpu/drm/mach64/mach64_drv.c 2012-10-17 23:05:10.212566630 +0300
|
||||
@@ -62,7 +62,6 @@ static struct drm_driver driver = {
|
||||
.irq_postinstall = mach64_driver_irq_postinstall,
|
||||
.irq_uninstall = mach64_driver_irq_uninstall,
|
||||
.irq_handler = mach64_driver_irq_handler,
|
||||
- .reclaim_buffers = drm_core_reclaim_buffers,
|
||||
.ioctls = mach64_ioctls,
|
||||
.dma_ioctl = mach64_dma_buffers,
|
||||
.fops = &mach64_driver_fops,
|
||||
@@ -1,61 +0,0 @@
|
||||
diff -Nurp linux-3.7-rc8/drivers/gpu/drm/mach64.orig/mach64_dma.c linux-3.7-rc8/drivers/gpu/drm/mach64/mach64_dma.c
|
||||
--- linux-3.7-rc8/drivers/gpu/drm/mach64.orig/mach64_dma.c 2012-12-06 19:50:10.000000000 +0200
|
||||
+++ linux-3.7-rc8/drivers/gpu/drm/mach64/mach64_dma.c 2012-12-06 20:19:10.590681644 +0200
|
||||
@@ -34,8 +34,8 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
-#include "drmP.h"
|
||||
-#include "drm.h"
|
||||
+#include <drm/drmP.h>
|
||||
+#include <drm/drm.h>
|
||||
#include "mach64_drm.h"
|
||||
#include "mach64_drv.h"
|
||||
|
||||
diff -Nurp linux-3.7-rc8/drivers/gpu/drm/mach64.orig/mach64_drv.c linux-3.7-rc8/drivers/gpu/drm/mach64/mach64_drv.c
|
||||
--- linux-3.7-rc8/drivers/gpu/drm/mach64.orig/mach64_drv.c 2012-12-06 19:50:10.000000000 +0200
|
||||
+++ linux-3.7-rc8/drivers/gpu/drm/mach64/mach64_drv.c 2012-12-06 20:20:13.062073838 +0200
|
||||
@@ -28,12 +28,12 @@
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
-#include "drmP.h"
|
||||
-#include "drm.h"
|
||||
+#include <drm/drmP.h>
|
||||
+#include <drm/drm.h>
|
||||
#include "mach64_drm.h"
|
||||
#include "mach64_drv.h"
|
||||
|
||||
-#include "drm_pciids.h"
|
||||
+#include <drm/drm_pciids.h>
|
||||
|
||||
static struct pci_device_id pciidlist[] = {
|
||||
mach64_PCI_IDS
|
||||
diff -Nurp linux-3.7-rc8/drivers/gpu/drm/mach64.orig/mach64_irq.c linux-3.7-rc8/drivers/gpu/drm/mach64/mach64_irq.c
|
||||
--- linux-3.7-rc8/drivers/gpu/drm/mach64.orig/mach64_irq.c 2012-12-06 19:50:10.000000000 +0200
|
||||
+++ linux-3.7-rc8/drivers/gpu/drm/mach64/mach64_irq.c 2012-12-06 20:20:40.192678476 +0200
|
||||
@@ -35,8 +35,8 @@
|
||||
* Leif Delgass <ldelgass@retinalburn.net>
|
||||
*/
|
||||
|
||||
-#include "drmP.h"
|
||||
-#include "drm.h"
|
||||
+#include <drm/drmP.h>
|
||||
+#include <drm/drm.h>
|
||||
#include "mach64_drm.h"
|
||||
#include "mach64_drv.h"
|
||||
|
||||
diff -Nurp linux-3.7-rc8/drivers/gpu/drm/mach64.orig/mach64_state.c linux-3.7-rc8/drivers/gpu/drm/mach64/mach64_state.c
|
||||
--- linux-3.7-rc8/drivers/gpu/drm/mach64.orig/mach64_state.c 2012-12-06 19:50:10.000000000 +0200
|
||||
+++ linux-3.7-rc8/drivers/gpu/drm/mach64/mach64_state.c 2012-12-06 20:21:00.783137370 +0200
|
||||
@@ -30,8 +30,8 @@
|
||||
* José Fonseca <j_r_fonseca@yahoo.co.uk>
|
||||
*/
|
||||
|
||||
-#include "drmP.h"
|
||||
-#include "drm.h"
|
||||
+#include <drm/drmP.h>
|
||||
+#include <drm/drm.h>
|
||||
#include "mach64_drm.h"
|
||||
#include "mach64_drv.h"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user